def find_key_files(results): ''' PackagedPrivateKey ------------------ Summary: Packaged private key Priority: 8 / 10 Severity: Fatal Category: Security In general, you should not package private key files inside your app. ''' if len(common.keyFiles)>0: possibleKeyFiles=common.text_scan(common.keyFiles,r'PRIVATE\sKEY') if len(possibleKeyFiles)>0: for f in possibleKeyFiles: common.logger.debug("It appears there is a private key embedded in your application: " + str(f)) issue = ReportIssue() issue.setCategory(ExploitType.CRYPTO) issue.setDetails("It appears there is a private key embedded in your application in the following file:") issue.setFile(str(f)) issue.setSeverity(Severity.VULNERABILITY) results.append(issue) issue = terminalPrint() issue.setLevel(Severity.VULNERABILITY) issue.setData("It appears there is a private key embedded in your application in the following file:") results.append(issue) return
def find_key_files(results): ''' PackagedPrivateKey ------------------ Summary: Packaged private key Priority: 8 / 10 Severity: Fatal Category: Security In general, you should not package private key files inside your app. ''' if len(common.keyFiles) > 0: possibleKeyFiles = common.text_scan(common.keyFiles, r'PRIVATE\sKEY') if len(possibleKeyFiles) > 0: for f in possibleKeyFiles: common.logger.debug( "It appears there is a private key embedded in your application: " + str(f)) issue = ReportIssue() issue.setCategory(ExploitType.CRYPTO) issue.setDetails( "It appears there is a private key embedded in your application in the following file:" ) issue.setFile(str(f)) issue.setSeverity(Severity.VULNERABILITY) results.append(issue) issue = terminalPrint() issue.setLevel(Severity.VULNERABILITY) issue.setData( "It appears there is a private key embedded in your application in the following file:" ) results.append(issue) return
def find_intent_files(): """ Find all files declaring or using intents in the application """ common.logger.info("Attempting to trace Intent Sources to Sinks") int_files = [] int_dec_list = [] int_dec_list.append([]) int_rex = r"import\sandroid\.content\.Intent" # This syntax is deprecated int_assign_rex1 = r"Intent\s*[A-Za-z0-9_$]+\s*[=;]\s+getIntent\(" int_assign_rex2 = r"[A-Za-z0-9_$]+\s*[=;]\s*Intent\.parseUri\(" int_assign_rex3 = r"Intent\s*[A-Za-z0-9_$]+\s*[=;]\s*new\s+Intent\(" int_files += common.text_scan(common.java_files, int_rex) for i in int_files: if len(i) > 0: tmp = [i[1]] int_dec_list += common.text_scan(tmp, int_assign_rex1) int_dec_list += common.text_scan(tmp, int_assign_rex2) int_dec_list += common.text_scan(tmp, int_assign_rex3) common.logger.info("Intent Declarations:") int_dec_list = filter(None, int_dec_list) for d in int_dec_list: if len(d) > 0: d[0] = re.sub(r"\s*[=;]\s*new\s*Intent\(.*", "", str(d[0])) d[0] = re.sub(r"(final)?\s*Intent\s+", "", str(d[0])) d[0] = re.sub(r"[=;]\s*getIntent\(.*", "", str(d[0])) d[0] = re.sub(r"\'", "", str(d[0])) d[0] = re.sub(r"\"", "", str(d[0])) d[0] = re.sub(r"\s+", "", str(d[0])) d[0] = re.sub(r"\[", "", str(d[0])) d[0] = re.sub(r"\\\\\t", "", str(d[0])) d[0] = re.sub(r"\\\t", "", str(d[0])) d[0] = re.sub(r"\\t", "", str(d[0])) d[0] = str(d[0]).strip("\t\n\r") common.logger.info(int_dec_list) return
def find_intent_files(): """ Find all files declaring or using intents in the application """ common.logger.info("Attempting to trace Intent Sources to Sinks") int_files = [] int_dec_list = [] int_dec_list.append([]) int_rex = r'import\sandroid\.content\.Intent' #This syntax is deprecated int_assign_rex1 = r'Intent\s*[A-Za-z0-9_$]+\s*[=;]\s+getIntent\(' int_assign_rex2 = r'[A-Za-z0-9_$]+\s*[=;]\s*Intent\.parseUri\(' int_assign_rex3 = r'Intent\s*[A-Za-z0-9_$]+\s*[=;]\s*new\s+Intent\(' int_files += common.text_scan(common.java_files, int_rex) for i in int_files: if len(i) > 0: tmp = [i[1]] int_dec_list += common.text_scan(tmp, int_assign_rex1) int_dec_list += common.text_scan(tmp, int_assign_rex2) int_dec_list += common.text_scan(tmp, int_assign_rex3) common.logger.info("Intent Declarations:") int_dec_list = filter(None, int_dec_list) for d in int_dec_list: if len(d) > 0: d[0] = re.sub(r'\s*[=;]\s*new\s*Intent\(.*', '', str(d[0])) d[0] = re.sub(r'(final)?\s*Intent\s+', '', str(d[0])) d[0] = re.sub(r'[=;]\s*getIntent\(.*', '', str(d[0])) d[0] = re.sub(r'\'', '', str(d[0])) d[0] = re.sub(r'\"', '', str(d[0])) d[0] = re.sub(r'\s+', '', str(d[0])) d[0] = re.sub(r'\[', '', str(d[0])) d[0] = re.sub(r'\\\\\t', '', str(d[0])) d[0] = re.sub(r'\\\t', '', str(d[0])) d[0] = re.sub(r'\\t', '', str(d[0])) d[0] = str(d[0]).strip('\t\n\r') common.logger.info(int_dec_list) return
def find_gradle(): version=0 files=[] for (dirpath,dirname, filenames) in os.walk(common.sourceDirectory): for filename in filenames: if filename=='build.gradle': files.append(os.path.join(dirpath,filename)) if len(files)>0: matches=common.text_scan(files,r'def\s_compileSdkVersion\s*=\s*[0-9]+') #TODO - fix this so we don't have to account for the empty first element #We skip it if there are multiple build.gradle files, since manual input is unavoidable at that point if len(matches)==2: for m in matches: if len(m)>0: version=re.compile('\d+') version=version.findall(str(m[0]))[0] return version
def find_content_providers(): """ Find all content providers and return the list """ cp_list = common.find_ext('ContentProvider') growing = 1 #TODO - This is ugly and needs to be re-written #The intention here is to loop endlessly until all extensions are found while growing: cp_list_count_old = len(cp_list) cp_list += common.tree(cp_list) if len(cp_list) == cp_list_count_old: growing = 0 cp_list.append(['ContentProvider', '']) cp_decs = [] cp_decs.append([]) for x in cp_list: if len(x) > 0: tmp = r'' + re.escape(str(x[0])) + r'\s\w+[;=]' cp_decs += common.text_scan(common.java_files, tmp) tmp = r'(private .*|protected.*)' + re.escape(str( x[0])) + r'\s\w+;' cp_decs += common.text_scan(common.java_files, tmp) tmp = r'\w+\s[;=]\snew\s' + re.escape(str(x[0])) + r'\(' cp_decs += common.text_scan(common.java_files, tmp) tmp = r'\(.*' + re.escape( str(x[0]) ) + r'\s\w+.*\)' # Need to ensure this is working properly tmp_list2 = [] tmp_list2.append([]) for z in cp_decs: if len(z) > 0: #conditional declarations will cause conditional positives #BUG sometimes Z[0] is a list, rather than just a list element. Need to separate, remove and re-parse if (len(z[0]) > 1 and not isinstance(z[0], str)): for x in z[0]: foo = [x, z[1]] tmp_list2.append(foo) cp_decs.pop() continue else: tmp_list2.append(z) else: tmp_list2.append(z) tmp_list2 = filter(None, tmp_list2) for y in tmp_list2: if len(y) > 0: y[0] = re.sub(r';\\n', '', str(y[0]).strip('[]\'')) y[0] = re.sub(r'\\t*', '', y[0]) y[0] = re.sub(r'\s*private\b', '', y[0]) y[0] = re.sub(r'\s*protected\b', '', y[0]) y[0] = re.sub(r'\s*static\b', '', y[0]) y[0] = re.sub(r'^\s*ContentProvider\b', '', y[0]) y[0] = re.sub(r'\s*[;=]\s*new\sContentProvider\s.*', '', y[0]) y[0] = re.sub(r'\s*[;=]\s*new\s\w+\(.*\)', '', y[0]) y[0] = re.sub(r'^\s*', '', y[0]) y[0] = re.sub(r'\s*$', '', y[0]) y[0] = re.sub(r'^\w+\s', '', y[0]) y[0] = re.sub(r';$', '', y[0]) #remove whitespace y[0] = y[0].strip(' \t\r\n') tmp_list2 = common.dedup(tmp_list2) return tmp_list2
def find_extras(stub_file_name, path): """ Find all extras given a filename """ #TODO - This needs to be gutted and re-writtten extras = [] filename = re.search(r'\w+$', stub_file_name) filename = filename.group() fname = common.grep(path, r'' + str(filename) + '\.java') rextras = [] rextras.append(r'getExtras\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getStringExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getIntExtra\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getIntArrayExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getFloatExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getFloatArrayExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getDoubleExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getDoubleArrayExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getCharExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getCharArrayExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getByteExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getByteArrayExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getBundleExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getBooleanExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getBooleanArrayExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getCharSequenceArrayExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getCharSequenceArrayListExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getCharSequenceExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getInterArrayListExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getLongArrayExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getLongExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getParcelableArrayExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getParcelableArrayListExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getParcelableExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getSeriablizableExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getShortArrayExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getShortExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getStringArrayExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getStringArrayListExtra\(\s*[0-9A-Za-z_\"\'.]+') #These are not necessarily Intent extras, but may contain them rextras.append(r'getString\(\s*[0-9A-Za-z_\"\'.]+') #TODO add data types to the extras, so we can provide better suggestions if len(fname) > 0: x_tmp = [] x_tmp.append([]) for r in rextras: x_tmp = common.text_scan(fname, r) for m in x_tmp: if len(m) > 0: i = 0 for l in m: if type(l) is list: sigh = [] for s in l: sigh.append(re.sub(r'.*\(', '', str(s))) sigh[i] = re.sub(r'\).*', '', sigh[i]) sigh[i] = re.sub(r'\s*,.*', '', sigh[i]) extras += sigh i += 1 extras = common.dedup(extras) if len(extras) < 1: common.logger.debug("No extras found in " + str(fname[0]) + " to suggest.\n") common.parsingerrors.add(str(fname[0])) else: #BUG - seems like a flow can come here without the fname; Ex: Flagship S - 4 common.logger.error( "Sorry, we could not find a filename while looking for extras\n") #Trying to get rid of empty first element return extras
def find_webviews(): """ Finds all webviews in the decompiled source code """ #1. Look for classes that extend WebView #Find classes that extend Web View wv_list = find_ext('WebView') #2. Look for classes that extend classes that extend WebView while len(common.tree(wv_list)) > 1: wv_list += common.tree(wv_list) wv_list.append(['WebView', '']) #3. Cleanup? #4. Look for all declaration of WebViews using normal and extended class names #BUG sometimes multiple declarations are coming back for z[0], need to figure out what is going on there #Currently there may be false negatives #BUG - Need to review this for optional/multiple spaces wv_decs = [] wv_decs.append([]) for x in wv_list: if len(x) > 0: tmp = r'' + re.escape(str(x[0])) + r'\s\w+[;=]' wv_decs += common.text_scan(common.java_files, tmp) tmp = r'(private .*|protected.*)' + re.escape(str( x[0])) + r'\s\w+;' wv_decs += common.text_scan(common.java_files, tmp) tmp = r'\w+\s[;=]\snew\s' + re.escape(str(x[0])) + r'\(' wv_decs += common.text_scan(common.java_files, tmp) tmp = r'\(.*' + re.escape( str(x[0]) ) + r'\s\w+.*\)' # Need to ensure this is working properly tmp_list2 = [] tmp_list2.append([]) for z in wv_decs: if len(z) > 0: #conditional declarations will cause conditional positives #BUG sometimes Z[0] is a list, rather than just a list element. Need to separate, remove and re-parse if (len(z[0]) > 1 and not isinstance(z[0], str)): for x in z[0]: foo = [x, z[1]] tmp_list2.append(foo) wv_decs.pop() continue else: tmp_list2.append(z) else: tmp_list2.append(z) tmp_list2 = filter(None, tmp_list2) for y in tmp_list2: if len(y) > 0: y[0] = re.sub(r';\\n', '', str(y[0]).strip('[]\'')) y[0] = re.sub(r'\\t*', '', y[0]) y[0] = re.sub(r'\s*private\b', '', y[0]) y[0] = re.sub(r'\s*protected\b', '', y[0]) y[0] = re.sub(r'\s*static\b', '', y[0]) y[0] = re.sub(r'^\s*WebView\b', '', y[0]) y[0] = re.sub(r'\s*[;=]\s*new\sWebView\s.*', '', y[0]) y[0] = re.sub(r'\s*[;=]\s*new\s\w+\(.*\)', '', y[0]) y[0] = re.sub(r'^\s*', '', y[0]) y[0] = re.sub(r'\s*$', '', y[0]) y[0] = re.sub(r'^\w+\s', '', y[0]) y[0] = re.sub(r';$', '', y[0]) #remove whitespace y[0] = y[0].strip(' \t\r\n') tmp_list2 = common.dedup(tmp_list2) return tmp_list2
def find_content_providers(): """ Find all content providers and return the list """ cp_list=common.find_ext('ContentProvider') growing=1 #TODO - This is ugly and needs to be re-written #The intention here is to loop endlessly until all extensions are found while growing: cp_list_count_old=len(cp_list) cp_list+=common.tree(cp_list) if len(cp_list) == cp_list_count_old: growing=0 cp_list.append(['ContentProvider','']) cp_decs=[] cp_decs.append([]) for x in cp_list: if len(x)>0: tmp=r''+re.escape(str(x[0]))+r'\s\w+[;=]' cp_decs+=common.text_scan(common.java_files,tmp) tmp=r'(private .*|protected.*)'+ re.escape(str(x[0]))+r'\s\w+;' cp_decs+=common.text_scan(common.java_files,tmp) tmp=r'\w+\s[;=]\snew\s'+re.escape(str(x[0]))+r'\(' cp_decs+=common.text_scan(common.java_files,tmp) tmp=r'\(.*'+re.escape(str(x[0]))+r'\s\w+.*\)' # Need to ensure this is working properly tmp_list2=[] tmp_list2.append([]) for z in cp_decs: if len(z)>0: #conditional declarations will cause conditional positives #BUG sometimes Z[0] is a list, rather than just a list element. Need to separate, remove and re-parse if (len(z[0])>1 and not isinstance(z[0],str)): for x in z[0]: foo=[x,z[1]] tmp_list2.append(foo) cp_decs.pop() continue else: tmp_list2.append(z) else: tmp_list2.append(z) tmp_list2=filter(None,tmp_list2) for y in tmp_list2: if len(y)>0: y[0]=re.sub(r';\\n','',str(y[0]).strip('[]\'')) y[0]=re.sub(r'\\t*','',y[0]) y[0]=re.sub(r'\s*private\b','',y[0]) y[0]=re.sub(r'\s*protected\b','',y[0]) y[0]=re.sub(r'\s*static\b','',y[0]) y[0]=re.sub(r'^\s*ContentProvider\b','',y[0]) y[0]=re.sub(r'\s*[;=]\s*new\sContentProvider\s.*','',y[0]) y[0]=re.sub(r'\s*[;=]\s*new\s\w+\(.*\)','',y[0]) y[0]=re.sub(r'^\s*','',y[0]) y[0]=re.sub(r'\s*$','',y[0]) y[0]=re.sub(r'^\w+\s','',y[0]) y[0]=re.sub(r';$','',y[0]) #remove whitespace y[0]=y[0].strip(' \t\r\n') tmp_list2=common.dedup(tmp_list2) return tmp_list2
def find_extras(stub_file_name,path): """ Find all extras given a filename """ #TODO - This needs to be gutted and re-writtten extras=[] filename=re.search(r'\w+$',stub_file_name) filename=filename.group() fname=common.grep(path,r''+str(filename)+'\.java') rextras=[] rextras.append(r'getExtras\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getStringExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getIntExtra\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getIntArrayExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getFloatExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getFloatArrayExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getDoubleExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getDoubleArrayExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getCharExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getCharArrayExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getByteExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getByteArrayExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getBundleExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getBooleanExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getBooleanArrayExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getCharSequenceArrayExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getCharSequenceArrayListExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getCharSequenceExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getInterArrayListExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getLongArrayExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getLongExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getParcelableArrayExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getParcelableArrayListExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getParcelableExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getSeriablizableExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getShortArrayExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getShortExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getStringArrayExtra\(\s*[0-9A-Za-z_\"\'.]+') rextras.append(r'getStringArrayListExtra\(\s*[0-9A-Za-z_\"\'.]+') #These are not necessarily Intent extras, but may contain them rextras.append(r'getString\(\s*[0-9A-Za-z_\"\'.]+') #TODO add data types to the extras, so we can provide better suggestions if len(fname)>0: x_tmp=[] x_tmp.append([]) for r in rextras: x_tmp=common.text_scan(fname,r) for m in x_tmp: if len(m)>0: i=0 for l in m: if type(l) is list: sigh=[] for s in l: sigh.append(re.sub(r'.*\(','',str(s))) sigh[i]=re.sub(r'\).*','',sigh[i]) sigh[i]=re.sub(r'\s*,.*','',sigh[i]) extras+=sigh i+=1 extras=common.dedup(extras) if len(extras)<1: common.logger.debug("No extras found in " + str(fname[0]) + " to suggest.\n") common.parsingerrors.add(str(fname[0])) else: #BUG - seems like a flow can come here without the fname; Ex: Flagship S - 4 common.logger.error("Sorry, we could not find a filename while looking for extras\n") #Trying to get rid of empty first element return extras
def find_webviews(): """ Finds all webviews in the decompiled source code """ #1. Look for classes that extend WebView #Find classes that extend Web View wv_list=find_ext('WebView') #2. Look for classes that extend classes that extend WebView while len(common.tree(wv_list)) > 1: wv_list+=common.tree(wv_list) wv_list.append(['WebView','']) #3. Cleanup? #4. Look for all declaration of WebViews using normal and extended class names #BUG sometimes multiple declarations are coming back for z[0], need to figure out what is going on there #Currently there may be false negatives #BUG - Need to review this for optional/multiple spaces wv_decs=[] wv_decs.append([]) for x in wv_list: if len(x)>0: tmp=r''+re.escape(str(x[0]))+r'\s\w+[;=]' wv_decs+=common.text_scan(common.java_files,tmp) tmp=r'(private .*|protected.*)'+ re.escape(str(x[0]))+r'\s\w+;' wv_decs+=common.text_scan(common.java_files,tmp) tmp=r'\w+\s[;=]\snew\s'+re.escape(str(x[0]))+r'\(' wv_decs+=common.text_scan(common.java_files,tmp) tmp=r'\(.*'+re.escape(str(x[0]))+r'\s\w+.*\)' # Need to ensure this is working properly tmp_list2=[] tmp_list2.append([]) for z in wv_decs: if len(z)>0: #conditional declarations will cause conditional positives #BUG sometimes Z[0] is a list, rather than just a list element. Need to separate, remove and re-parse if (len(z[0])>1 and not isinstance(z[0],str)): for x in z[0]: foo=[x,z[1]] tmp_list2.append(foo) wv_decs.pop() continue else: tmp_list2.append(z) else: tmp_list2.append(z) tmp_list2=filter(None,tmp_list2) for y in tmp_list2: if len(y)>0: y[0]=re.sub(r';\\n','',str(y[0]).strip('[]\'')) y[0]=re.sub(r'\\t*','',y[0]) y[0]=re.sub(r'\s*private\b','',y[0]) y[0]=re.sub(r'\s*protected\b','',y[0]) y[0]=re.sub(r'\s*static\b','',y[0]) y[0]=re.sub(r'^\s*WebView\b','',y[0]) y[0]=re.sub(r'\s*[;=]\s*new\sWebView\s.*','',y[0]) y[0]=re.sub(r'\s*[;=]\s*new\s\w+\(.*\)','',y[0]) y[0]=re.sub(r'^\s*','',y[0]) y[0]=re.sub(r'\s*$','',y[0]) y[0]=re.sub(r'^\w+\s','',y[0]) y[0]=re.sub(r';$','',y[0]) #remove whitespace y[0]=y[0].strip(' \t\r\n') tmp_list2=common.dedup(tmp_list2) return tmp_list2