- 更新apktool为最新版本

- 优化部分环节流程
- 修复excle文件导出时超时行数限制
- 修复脚本执行时卡顿的问题
- 修复Mac下Playload文件权限不足的问题
v1.0.09 V1.0.9_Releases
kelvinBen 2 years ago
parent 51ca5a0c5b
commit 827ef29e65
  1. 8
      app.py
  2. 8
      config.py
  3. 5
      libs/core/__init__.py
  4. 15
      libs/core/download.py
  5. 30
      libs/core/net.py
  6. 14
      libs/core/parses.py
  7. 13
      libs/task/android_task.py
  8. 42
      libs/task/base_task.py
  9. 4
      libs/task/download_task.py
  10. 26
      libs/task/ios_task.py
  11. 46
      libs/task/net_task.py
  12. 1
      libs/task/web_task.py
  13. 2
      requirements.txt
  14. BIN
      tools/apktool.jar
  15. 7
      update.md

@ -8,11 +8,14 @@ import click
from libs.core import Bootstrapper from libs.core import Bootstrapper
from libs.task.base_task import BaseTask from libs.task.base_task import BaseTask
@click.group(help="Python script for automatically retrieving key information in app.") @click.group(help="Python script for automatically retrieving key information in app.")
def cli(): def cli():
pass pass
# 创建Android任务 # 创建Android任务
@cli.command(help="Get the key information of Android system.") @cli.command(help="Get the key information of Android system.")
@click.option("-i", "--inputs", required=True, type=str, help="Please enter the APK file or DEX file to be scanned or the corresponding APK download address.") @click.option("-i", "--inputs", required=True, type=str, help="Please enter the APK file or DEX file to be scanned or the corresponding APK download address.")
@click.option("-r", "--rules", required=False, type=str, default="", help="Please enter a rule for temporary scanning of file contents.") @click.option("-r", "--rules", required=False, type=str, default="", help="Please enter a rule for temporary scanning of file contents.")
@ -31,6 +34,7 @@ def android(inputs: str, rules: str, sniffer: bool, no_resource:bool, all:bool,
except Exception as e: except Exception as e:
raise e raise e
@cli.command(help="Get the key information of iOS system.") @cli.command(help="Get the key information of iOS system.")
@click.option("-i", "--inputs", required=True, type=str, help="Please enter IPA file or ELF file to scan or corresponding IPA download address. App store is not supported at present.") @click.option("-i", "--inputs", required=True, type=str, help="Please enter IPA file or ELF file to scan or corresponding IPA download address. App store is not supported at present.")
@click.option("-r", "--rules", required=False, type=str, default="", help="Please enter a rule for temporary scanning of file contents.") @click.option("-r", "--rules", required=False, type=str, default="", help="Please enter a rule for temporary scanning of file contents.")
@ -48,6 +52,7 @@ def ios(inputs: str, rules: str, sniffer: bool, no_resource:bool, all:bool, thre
except Exception as e: except Exception as e:
raise e raise e
@cli.command(help="Get the key information of Web system.") @cli.command(help="Get the key information of Web system.")
@click.option("-i", "--inputs", required=True, type=str, help="Please enter the site directory or site file to scan or the corresponding site download address.") @click.option("-i", "--inputs", required=True, type=str, help="Please enter the site directory or site file to scan or the corresponding site download address.")
@click.option("-r", "--rules", required=False, type=str, default="", help="Please enter a rule for temporary scanning of file contents.") @click.option("-r", "--rules", required=False, type=str, default="", help="Please enter a rule for temporary scanning of file contents.")
@ -65,9 +70,10 @@ def web(inputs: str, rules: str, sniffer: bool, no_resource:bool, all:bool, thre
except Exception as e: except Exception as e:
raise e raise e
def main(): def main():
cli() cli()
if __name__ == "__main__": if __name__ == "__main__":
main() main()

@ -50,14 +50,15 @@ filter_no = [
r'.*w3school.com.cn', r'.*w3school.com.cn',
r'.*apple.com', r'.*apple.com',
r'.*.amap.com', r'.*.amap.com',
r'.*slf4j.org',
] ]
# AK集合 # AK集合
filter_ak_map = { filter_ak_map = {
"Aliyun_OSS": [ "Aliyun_OSS": [
r'.*accessKeyId.*".*"', r'.*accessKeyId.*".*?"',
r'.*accessKeySecret.*".*"', r'.*accessKeySecret.*".*?"',
r'.*secret.*".*"' r'.*secret.*".*?"'
], ],
# "Amazon_AWS_Access_Key_ID": r"([^A-Z0-9]|^)(AKIA|A3T|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{12,}", # "Amazon_AWS_Access_Key_ID": r"([^A-Z0-9]|^)(AKIA|A3T|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{12,}",
# "Amazon_AWS_S3_Bucket": [ # "Amazon_AWS_S3_Bucket": [
@ -183,4 +184,3 @@ data = {
# 配置自动下载Apk文件或者缓存HTML的请求方法信息,目前仅支持GET和POST # 配置自动下载Apk文件或者缓存HTML的请求方法信息,目前仅支持GET和POST
method = "GET" method = "GET"

@ -26,7 +26,7 @@ output_path = ""
download_flag = False download_flag = False
# excel 起始行号 # excel 起始行号
excel_row = 0 excel_row = 1
class Bootstrapper(object): class Bootstrapper(object):
@ -78,7 +78,7 @@ class Bootstrapper(object):
apktool_path = os.path.join(tools_dir, "apktool.jar") apktool_path = os.path.join(tools_dir, "apktool.jar")
download_path = os.path.join(out_dir,"download") download_path = os.path.join(out_dir,"download")
txt_result_path = os.path.join(out_dir,"result_"+str(create_time)+".txt") txt_result_path = os.path.join(out_dir,"result_"+str(create_time)+".txt")
xls_result_path = os.path.join(out_dir,"result_"+str(create_time)+".xls") xls_result_path = os.path.join(out_dir,"result_"+str(create_time)+".xlsx")
app_history_path = os.path.join(history_path,"app_history.txt") app_history_path = os.path.join(history_path,"app_history.txt")
domain_history_path = os.path.join(history_path,"domain_history.txt") domain_history_path = os.path.join(history_path,"domain_history.txt")
@ -100,7 +100,6 @@ class Bootstrapper(object):
print("[*] Create directory {}".format(output_path)) print("[*] Create directory {}".format(output_path))
if not os.path.exists(download_path): if not os.path.exists(download_path):
# shutil.rmtree(download_path)
os.makedirs(download_path) os.makedirs(download_path)
print("[*] Create directory {}".format(download_path)) print("[*] Create directory {}".format(download_path))

@ -2,10 +2,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Author: kelvinBen # Author: kelvinBen
# Github: https://github.com/kelvinBen/AppInfoScanner # Github: https://github.com/kelvinBen/AppInfoScanner
import re
import os
import sys import sys
import time
import config import config
import requests import requests
import threading import threading
@ -13,6 +10,7 @@ import libs.core as cores
from requests.packages import urllib3 from requests.packages import urllib3
from requests.adapters import HTTPAdapter from requests.adapters import HTTPAdapter
class DownloadThreads(threading.Thread): class DownloadThreads(threading.Thread):
def __init__(self, input_path, file_name, cache_path, types): def __init__(self, input_path, file_name, cache_path, types):
@ -32,15 +30,16 @@ class DownloadThreads(threading.Thread):
urllib3.disable_warnings() urllib3.disable_warnings()
if config.method.upper() == "POST": if config.method.upper() == "POST":
resp = session.post(url=self.url,params=config.data ,headers=config.headers,timeout=30) resp = session.post(
url=self.url, params=config.data, headers=config.headers, timeout=30)
else: else:
resp = session.get(url=self.url,data=config.data ,headers=config.headers,timeout=30) resp = session.get(url=self.url, data=config.data,
headers=config.headers, timeout=30)
if resp.status_code == requests.codes.ok: if resp.status_code == requests.codes.ok:
if self.types == "Android" or self.types == "iOS": if self.types == "Android" or self.types == "iOS":
count = 0 count = 0
progress_tmp = 0 progress_tmp = 0
time1 = time.time()
length = float(resp.headers['content-length']) length = float(resp.headers['content-length'])
with open(self.cache_path, "wb") as f: with open(self.cache_path, "wb") as f:
for chunk in resp.iter_content(chunk_size=512): for chunk in resp.iter_content(chunk_size=512):
@ -51,7 +50,8 @@ class DownloadThreads(threading.Thread):
if progress != progress_tmp: if progress != progress_tmp:
progress_tmp = progress progress_tmp = progress
print("\r", end="") print("\r", end="")
print("[*] Download progress: {}%: ".format(progress), "" * (progress // 2), end="") print(
"[*] Download progress: {}%: ".format(progress), "" * (progress // 2), end="")
sys.stdout.flush() sys.stdout.flush()
f.close() f.close()
else: else:
@ -62,7 +62,6 @@ class DownloadThreads(threading.Thread):
cores.download_flag = True cores.download_flag = True
except Exception as e: except Exception as e:
raise Exception(e) raise Exception(e)
return
def run(self): def run(self):
threadLock = threading.Lock() threadLock = threading.Lock()

@ -31,20 +31,30 @@ class NetThreads(threading.Thread):
if result != "error": if result != "error":
if self.lock.acquire(True): if self.lock.acquire(True):
cores.excel_row = cores.excel_row + 1 cores.excel_row = cores.excel_row + 1
self.worksheet.write(cores.excel_row, 0, label = cores.excel_row) self.worksheet.cell(row=cores.excel_row,
self.worksheet.write(cores.excel_row, 1, label = url_ip) column=1, value=cores.excel_row-1)
self.worksheet.write(cores.excel_row, 2, label = domain) self.worksheet.cell(row=cores.excel_row,
column=2, value=url_ip)
self.worksheet.cell(row=cores.excel_row,
column=3, value=domain)
if result != "timeout": if result != "timeout":
self.worksheet.write(cores.excel_row, 3, label = result["status"]) self.worksheet.cell(
self.worksheet.write(cores.excel_row, 4, label = result["des_ip"]) row=cores.excel_row, column=4, value=result["status"])
self.worksheet.write(cores.excel_row, 5, label = result["server"]) self.worksheet.cell(
self.worksheet.write(cores.excel_row, 6, label = result["title"]) row=cores.excel_row, column=5, value=result["des_ip"])
self.worksheet.write(cores.excel_row, 7, label = result["cdn"]) self.worksheet.cell(
# self.worksheet.write(cores.excel_row, 8, label = "") row=cores.excel_row, column=6, value=result["server"])
self.worksheet.cell(
row=cores.excel_row, column=7, value=result["title"])
self.worksheet.cell(
row=cores.excel_row, column=8, value=result["cdn"])
self.lock.release() self.lock.release()
def __get_request_result__(self, url): def __get_request_result__(self, url):
result={"status":"","server":"","cookie":"","cdn":"","des_ip":"","sou_ip":"","title":""} result = {"status": "", "server": "", "cookie": "",
"cdn": "", "des_ip": "", "sou_ip": "", "title": ""}
cdn = "" cdn = ""
try: try:
with requests.get(url, timeout=5, stream=True) as rsp: with requests.get(url, timeout=5, stream=True) as rsp:

@ -40,7 +40,8 @@ class ParsesThreads(threading.Thread):
output_path = cores.output_path output_path = cores.output_path
strings_path = cores.strings_path strings_path = cores.strings_path
temp = os.path.join(output_path, "temp.txt") temp = os.path.join(output_path, "temp.txt")
cmd_str = ('"%s" "%s" > "%s"') % (str(strings_path),str(file_path),str(temp)) cmd_str = ('"%s" "%s" > "%s"') % (
str(strings_path), str(file_path), str(temp))
if os.system(cmd_str) == 0: if os.system(cmd_str) == 0:
with open(temp, "r", encoding='utf-8', errors='ignore') as f: with open(temp, "r", encoding='utf-8', errors='ignore') as f:
lines = f.readlines() lines = f.readlines()
@ -56,6 +57,8 @@ class ParsesThreads(threading.Thread):
# 搜素AK和SK信息,由于iOS的逻辑处理效率过慢暂时忽略对iOS的AK检测 # 搜素AK和SK信息,由于iOS的逻辑处理效率过慢暂时忽略对iOS的AK检测
if not (".js" == file_path[-3:] and self.types == "iOS"): if not (".js" == file_path[-3:] and self.types == "iOS"):
# 未包含相关字段不进行ak或者sk信息采集
if "access" in file_content or "secret" in file_content:
for key, values in config.filter_ak_map.items(): for key, values in config.filter_ak_map.items():
if isinstance(values, list): if isinstance(values, list):
for value in values: for value in values:
@ -65,6 +68,8 @@ class ParsesThreads(threading.Thread):
# 遍历所有的字符串 # 遍历所有的字符串
for result in set(results): for result in set(results):
if ("http://" == result) or ("https://" == result) or result.startswith("https://.") or result.startswith("http://.") :
continue
self.__parse_string__(result) self.__parse_string__(result)
def __ak_and_sk__(self, name, ak_rule, content): def __ak_and_sk__(self, name, ak_rule, content):
@ -89,14 +94,16 @@ class ParsesThreads(threading.Thread):
self.threadLock.acquire() self.threadLock.acquire()
if cores.all_flag: if cores.all_flag:
print(("[+] The string searched for matching rule is: %s") % (resl_str)) print(
("[+] The string searched for matching rule is: %s") % (resl_str))
self.result_list.append(resl_str) self.result_list.append(resl_str)
self.threadLock.release() self.threadLock.release()
continue continue
def __filter__(self, resl_str): def __filter__(self, resl_str):
return_flag = 1 return_flag = 1
resl_str = resl_str.replace("\r","").replace("\n","").replace(" ","") resl_str = resl_str.replace("\r", "").replace(
"\n", "").replace(" ", "")
if len(resl_str) == 0: if len(resl_str) == 0:
return 0 return 0
@ -110,6 +117,7 @@ class ParsesThreads(threading.Thread):
if re.match(filte, resl_str): if re.match(filte, resl_str):
return_flag = 0 return_flag = 0
continue continue
return return_flag return return_flag
def run(self): def run(self):

@ -33,7 +33,8 @@ class AndroidTask(object):
self.__decode_dir__(input_file_path) self.__decode_dir__(input_file_path)
else: else:
if self.__decode_file__(input_file_path) == "error": if self.__decode_file__(input_file_path) == "error":
raise Exception("Retrieval of this file type is not supported. Select APK file or DEX file.") raise Exception(
"Retrieval of this file type is not supported. Select APK file or DEX file.")
return {"comp_list": self.comp_list, "shell_flag": self.shell_flag, "file_queue": self.file_queue, "packagename": self.packagename, "file_identifier": self.file_identifier, "permissions": self.permissions} return {"comp_list": self.comp_list, "shell_flag": self.shell_flag, "file_queue": self.file_queue, "packagename": self.packagename, "file_identifier": self.file_identifier, "permissions": self.permissions}
@ -44,7 +45,7 @@ class AndroidTask(object):
filename = os.path.basename(file_path) filename = os.path.basename(file_path)
suffix_name = filename.split(".")[-1] suffix_name = filename.split(".")[-1]
if suffix_name == "apk": if suffix_name == "apk" or suffix_name == "hpk":
name = filename.split(".")[0] name = filename.split(".")[0]
output_path = os.path.join(base_out_path, name) output_path = os.path.join(base_out_path, name)
self.__decode_apk__(file_path, apktool_path, output_path) self.__decode_apk__(file_path, apktool_path, output_path)
@ -77,7 +78,8 @@ class AndroidTask(object):
# 分解apk # 分解apk
def __decode_apk__(self, file_path, apktool_path, output_path): def __decode_apk__(self, file_path, apktool_path, output_path):
cmd_str = ('java -jar "%s" d -f "%s" -o "%s" --only-main-classe') % (str(apktool_path),str(file_path),str(output_path)) cmd_str = ('java -jar "%s" d -f "%s" -o "%s" --only-main-classe') % (
str(apktool_path), str(file_path), str(output_path))
if os.system(cmd_str) == 0: if os.system(cmd_str) == 0:
self.__shell_test__(output_path) self.__shell_test__(output_path)
self.__scanner_file_by_apktool__(output_path) self.__scanner_file_by_apktool__(output_path)
@ -85,17 +87,16 @@ class AndroidTask(object):
print("[-] Decompilation failed, please submit error information at https://github.com/kelvinBen/AppInfoScanner/issues") print("[-] Decompilation failed, please submit error information at https://github.com/kelvinBen/AppInfoScanner/issues")
raise Exception(file_path + ", Decompilation failed.") raise Exception(file_path + ", Decompilation failed.")
# 分解dex # 分解dex
def __decode_dex__(self, file_path, backsmali_path, output_path): def __decode_dex__(self, file_path, backsmali_path, output_path):
cmd_str = ('java -jar "%s" d "%s"') % (str(backsmali_path),str(file_path)) cmd_str = ('java -jar "%s" d "%s"') % (str(backsmali_path),
str(file_path))
if os.system(cmd_str) == 0: if os.system(cmd_str) == 0:
self.__get_scanner_file__(output_path) self.__get_scanner_file__(output_path)
else: else:
print("[-] Decompilation failed, please submit error information at https://github.com/kelvinBen/AppInfoScanner/issues") print("[-] Decompilation failed, please submit error information at https://github.com/kelvinBen/AppInfoScanner/issues")
raise Exception(file_path + ", Decompilation failed.") raise Exception(file_path + ", Decompilation failed.")
# 初始化检测文件信息 # 初始化检测文件信息
def __scanner_file_by_apktool__(self, output_path): def __scanner_file_by_apktool__(self, output_path):
file_names = os.listdir(output_path) file_names = os.listdir(output_path)

@ -3,9 +3,7 @@
# Author: kelvinBen # Author: kelvinBen
# Github: https://github.com/kelvinBen/AppInfoScanner # Github: https://github.com/kelvinBen/AppInfoScanner
import os import os
import re
import config import config
import threading
from queue import Queue from queue import Queue
import libs.core as cores import libs.core as cores
from libs.task.ios_task import iOSTask from libs.task.ios_task import iOSTask
@ -15,12 +13,14 @@ from libs.core.parses import ParsesThreads
from libs.task.android_task import AndroidTask from libs.task.android_task import AndroidTask
from libs.task.download_task import DownloadTask from libs.task.download_task import DownloadTask
class BaseTask(object): class BaseTask(object):
thread_list = [] thread_list = []
result_dict = {} result_dict = {}
app_history_list = [] app_history_list = []
domain_history_list = [] domain_history_list = []
# 统一初始化入口 # 统一初始化入口
def __init__(self, types="Android", inputs="", rules="", sniffer=True, threads=10, package=""): def __init__(self, types="Android", inputs="", rules="", sniffer=True, threads=10, package=""):
self.types = types self.types = types
self.path = inputs self.path = inputs
@ -31,8 +31,8 @@ class BaseTask(object):
self.package = package self.package = package
self.file_queue = Queue() self.file_queue = Queue()
# 统一调度平台 # 统一调度平台
def start(self): def start(self):
print("[*] AI is analyzing filtering rules......") print("[*] AI is analyzing filtering rules......")
@ -40,7 +40,8 @@ class BaseTask(object):
# 获取历史记录 # 获取历史记录
self.__history_handle__() self.__history_handle__()
print("[*] The filtering rules obtained by AI are as follows: %s" % (set(config.filter_no)) ) print("[*] The filtering rules obtained by AI are as follows: %s" %
(set(config.filter_no)))
# 任务控制中心 # 任务控制中心
task_info = self.__tast_control__() task_info = self.__tast_control__()
@ -59,7 +60,8 @@ class BaseTask(object):
return return
# 线程控制中心 # 线程控制中心
print("[*] ========= Searching for strings that match the rules ===============") print(
"[*] ========= Searching for strings that match the rules ===============")
self.__threads_control__(file_queue) self.__threads_control__(file_queue)
# 等待线程结束 # 等待线程结束
@ -67,8 +69,8 @@ class BaseTask(object):
thread.join() thread.join()
# 结果输出中心 # 结果输出中心
self.__print_control__(packagename,comp_list,file_identifier,permissions) self.__print_control__(packagename, comp_list,
file_identifier, permissions)
def __tast_control__(self): def __tast_control__(self):
task_info = {} task_info = {}
@ -78,7 +80,8 @@ class BaseTask(object):
types = cache_info["type"] types = cache_info["type"]
if (not os.path.exists(cacar_path) and cores.download_flag): if (not os.path.exists(cacar_path) and cores.download_flag):
print("[-] File download failed! Please download the file manually and try again.") print(
"[-] File download failed! Please download the file manually and try again.")
return task_info return task_info
# 调用Android 相关处理逻辑 # 调用Android 相关处理逻辑
@ -95,7 +98,8 @@ class BaseTask(object):
def __threads_control__(self, file_queue): def __threads_control__(self, file_queue):
for threadID in range(1, self.threads): for threadID in range(1, self.threads):
name = "Thread - " + str(int(threadID)) name = "Thread - " + str(int(threadID))
thread = ParsesThreads(threadID,name,file_queue,self.result_dict,self.types) thread = ParsesThreads(
threadID, name, file_queue, self.result_dict, self.types)
thread.start() thread.start()
self.thread_list.append(thread) self.thread_list.append(thread)
@ -105,8 +109,10 @@ class BaseTask(object):
all_flag = cores.all_flag all_flag = cores.all_flag
if self.sniffer: if self.sniffer:
print("[*] ========= Sniffing the URL address of the search ===============") print(
NetTask(self.result_dict,self.app_history_list,self.domain_history_list,file_identifier,self.threads).start() "[*] ========= Sniffing the URL address of the search ===============")
NetTask(self.result_dict, self.app_history_list,
self.domain_history_list, file_identifier, self.threads).start()
if packagename: if packagename:
print("[*] ========= The package name of this APP is: ===============") print("[*] ========= The package name of this APP is: ===============")
@ -118,7 +124,8 @@ class BaseTask(object):
print(json) print(json)
if len(permissions) != 0: if len(permissions) != 0:
print("[*] ========= Sensitive permission information is as follows: ===============") print(
"[*] ========= Sensitive permission information is as follows: ===============")
for permission in permissions: for permission in permissions:
print(permission) print(permission)
@ -133,10 +140,12 @@ class BaseTask(object):
value_list.append(result) value_list.append(result)
f.write("\t"+result+"\r") f.write("\t"+result+"\r")
f.close() f.close()
print("[*] For more information about the search, see TXT file result: %s" %(txt_result_path)) print("[*] For more information about the search, see TXT file result: %s" %
(txt_result_path))
if self.sniffer: if self.sniffer:
print("[*] For more information about the search, see XLS file result: %s" %(xls_result_path)) print("[*] For more information about the search, see XLSX file result: %s" %
(xls_result_path))
def __history_handle__(self): def __history_handle__(self):
domain_history_path = cores.domain_history_path domain_history_path = cores.domain_history_path
@ -148,7 +157,8 @@ class BaseTask(object):
lines = f.readlines() lines = f.readlines()
app_size = len(lines) app_size = len(lines)
for line in lines: for line in lines:
self.app_history_list.append(line.replace("\r","").replace("\n","")) self.app_history_list.append(
line.replace("\r", "").replace("\n", ""))
f.close() f.close()
@ -164,5 +174,3 @@ class BaseTask(object):
if domain_count >= cout: if domain_count >= cout:
config.filter_no.append(".*" + domain) config.filter_no.append(".*" + domain)
f.close() f.close()

@ -11,6 +11,7 @@ from queue import Queue
import libs.core as cores import libs.core as cores
from libs.core.download import DownloadThreads from libs.core.download import DownloadThreads
class DownloadTask(object): class DownloadTask(object):
def start(self, path, types): def start(self, path, types):
@ -37,7 +38,8 @@ class DownloadTask(object):
else: # 目录处理 else: # 目录处理
return {"path": path, "type": types} return {"path": path, "type": types}
else: else:
print("[*] Detected that the task is not local, preparing to download file......") print(
"[*] Detected that the task is not local, preparing to download file......")
cache_path = os.path.join(cores.download_path, file_name) cache_path = os.path.join(cores.download_path, file_name)
thread = DownloadThreads(path, file_name, cache_path, types) thread = DownloadThreads(path, file_name, cache_path, types)
thread.start() thread.start()

@ -11,8 +11,10 @@ import platform
import libs.core as cores import libs.core as cores
from queue import Queue from queue import Queue
class iOSTask(object): class iOSTask(object):
elf_file_name = "" elf_file_name = ""
def __init__(self, path): def __init__(self, path):
self.path = path self.path = path
self.file_queue = Queue() self.file_queue = Queue()
@ -28,7 +30,8 @@ class iOSTask(object):
elif self.__get_file_header__(file_path): elif self.__get_file_header__(file_path):
self.file_queue.put(file_path) self.file_queue.put(file_path)
else: else:
raise Exception("Retrieval of this file type is not supported. Select IPA file or Mach-o file.") raise Exception(
"Retrieval of this file type is not supported. Select IPA file or Mach-o file.")
return {"shell_flag": self.shell_flag, "file_queue": self.file_queue, "comp_list": [], "packagename": None, "file_identifier": self.file_identifier, "permissions": self.permissions} return {"shell_flag": self.shell_flag, "file_queue": self.file_queue, "comp_list": [], "packagename": None, "file_identifier": self.file_identifier, "permissions": self.permissions}
def __get_file_header__(self, file_path): def __get_file_header__(self, file_path):
@ -46,14 +49,15 @@ class iOSTask(object):
macho_file.close() macho_file.close()
return False return False
def __shell_test__(self, macho_file, hex_hand): def __shell_test__(self, macho_file, hex_hand):
while True: while True:
magic = binascii.hexlify(macho_file.read(4)).decode().upper() magic = binascii.hexlify(macho_file.read(4)).decode().upper()
if magic == "2C000000": if magic == "2C000000":
macho_file.seek(hex_hand, 0) macho_file.seek(hex_hand, 0)
encryption_info_command = binascii.hexlify(macho_file.read(24)).decode() encryption_info_command = binascii.hexlify(
cryptid = encryption_info_command[-8:len(encryption_info_command)] macho_file.read(24)).decode()
cryptid = encryption_info_command[-8:len(
encryption_info_command)]
if cryptid == "01000000": if cryptid == "01000000":
self.shell_flag = True self.shell_flag = True
break break
@ -89,16 +93,21 @@ class iOSTask(object):
zip_file_names = zip_files.namelist() zip_file_names = zip_files.namelist()
zip_files.extract(zip_file_names[0], output_path) zip_files.extract(zip_file_names[0], output_path)
try: try:
new_zip_file = zip_file_names[0].encode('cp437').decode('utf-8') new_zip_file = zip_file_names[0].encode(
'cp437').decode('utf-8')
except UnicodeEncodeError: except UnicodeEncodeError:
new_zip_file = zip_file_names[0].encode('utf-8').decode('utf-8') new_zip_file = zip_file_names[0].encode(
'utf-8').decode('utf-8')
old_zip_dir = self.__get_parse_dir__(output_path,zip_file_names[0]) old_zip_dir = self.__get_parse_dir__(
output_path, zip_file_names[0])
new_zip_dir = self.__get_parse_dir__(output_path, new_zip_file) new_zip_dir = self.__get_parse_dir__(output_path, new_zip_file)
os.rename(old_zip_dir, new_zip_dir) os.rename(old_zip_dir, new_zip_dir)
for zip_file in zip_file_names: for zip_file in zip_file_names:
old_ext_path = zip_files.extract(zip_file, output_path) old_ext_path = zip_files.extract(zip_file, output_path)
if not "Payload" in old_ext_path:
continue
start = str(old_ext_path).index("Payload") start = str(old_ext_path).index("Payload")
dir_path = old_ext_path[start:len(old_ext_path)] dir_path = old_ext_path[start:len(old_ext_path)]
old_ext_path = os.path.join(output_path, dir_path) old_ext_path = os.path.join(output_path, dir_path)
@ -117,14 +126,13 @@ class iOSTask(object):
if not os.path.exists(dir_path): if not os.path.exists(dir_path):
os.makedirs(dir_path) os.makedirs(dir_path)
shutil.move(old_ext_path, new_ext_path) shutil.move(old_ext_path, new_ext_path)
if os.path.exists(old_ext_path): if os.path.exists(old_ext_path) and (".app" in old_ext_path):
try: try:
# mac发生权限问题的时候做处理 # mac发生权限问题的时候做处理
os.remove(old_ext_path) os.remove(old_ext_path)
except Exception: except Exception:
shutil.rmtree(old_ext_path) shutil.rmtree(old_ext_path)
def __get_parse_dir__(self, output_path, file_path): def __get_parse_dir__(self, output_path, file_path):
start = file_path.index("Payload/") start = file_path.index("Payload/")
end = file_path.index(".app") end = file_path.index(".app")

@ -3,15 +3,13 @@
# Author: kelvinBen # Author: kelvinBen
# Github: https://github.com/kelvinBen/AppInfoScanner # Github: https://github.com/kelvinBen/AppInfoScanner
import re import openpyxl
import xlwt
import socket
import config import config
from queue import Queue from queue import Queue
import libs.core as cores import libs.core as cores
from libs.core.net import NetThreads from libs.core.net import NetThreads
import requests
class NetTask(object): class NetTask(object):
value_list = [] value_list = []
domain_list = [] domain_list = []
@ -27,7 +25,7 @@ class NetTask(object):
def start(self): def start(self):
xls_result_path = cores.xls_result_path xls_result_path = cores.xls_result_path
workbook = xlwt.Workbook(encoding = 'utf-8') workbook = openpyxl.Workbook()
worksheet = self.__creating_excel_header__(workbook) worksheet = self.__creating_excel_header__(workbook)
self.__write_result_to_txt__() self.__write_result_to_txt__()
@ -40,20 +38,19 @@ class NetTask(object):
workbook.save(xls_result_path) workbook.save(xls_result_path)
def __creating_excel_header__(self, workbook): def __creating_excel_header__(self, workbook):
worksheet = workbook.add_sheet("Result",cell_overwrite_ok=True) worksheet = workbook.create_sheet("Result", 0)
worksheet.write(0,0, label = "Number") worksheet.cell(row=1, column=1, value="Number")
worksheet.write(0,1, label = "IP/URL") worksheet.cell(row=1, column=2, value="IP/URL")
worksheet.write(0,2, label = "Domain") worksheet.cell(row=1, column=3, value="Domain")
worksheet.write(0,3, label = "Status") worksheet.cell(row=1, column=4, value="Status")
worksheet.write(0,4, label = "IP") worksheet.cell(row=1, column=5, value="IP")
worksheet.write(0,5, label = "Server") worksheet.cell(row=1, column=6, value="Server")
worksheet.write(0,6, label = "Title") worksheet.cell(row=1, column=7, value="Title")
worksheet.write(0,7, label = "CDN") worksheet.cell(row=1, column=8, value="CDN")
# worksheet.write(0,8, label = "Finger") worksheet.cell(row=1, column=9, value="Finger")
return worksheet return worksheet
def __write_result_to_txt__(self): def __write_result_to_txt__(self):
txt_result_path = cores.txt_result_path
append_file_flag = True append_file_flag = True
for key, value in self.result_dict.items(): for key, value in self.result_dict.items():
@ -63,11 +60,11 @@ class NetTask(object):
self.value_list.append(result) self.value_list.append(result)
if (("http://" in result) or ("https://" in result)) and ("." in result): if (("http://" in result) or ("https://" in result)) and ("." in result):
domain = result.replace("https://","").replace("http://","")
if "{" in result or "}" in result or "[" in result or "]" in result or "\\" in result or "!" in result or "," in result: if "{" in result or "}" in result or "[" in result or "]" in result or "\\" in result or "!" in result or "," in result:
continue continue
domain = result.replace(
"https://", "").replace("http://", "")
if "/" in domain: if "/" in domain:
domain = domain[:domain.index("/")] domain = domain[:domain.index("/")]
@ -79,21 +76,25 @@ class NetTask(object):
url_suffix = result[result.rindex(".")+1:].lower() url_suffix = result[result.rindex(".")+1:].lower()
if not(cores.resource_flag and url_suffix in config.sniffer_filter): if not(cores.resource_flag and url_suffix in config.sniffer_filter):
self.domain_queue.put({"domain":domain,"url_ip":result}) self.domain_queue.put(
{"domain": domain, "url_ip": result})
for identifier in self.file_identifier: for identifier in self.file_identifier:
if identifier in self.app_history_list: if identifier in self.app_history_list:
if not(domain in self.domain_history_list): if not(domain in self.domain_history_list):
self.domain_list.append(domain) self.domain_list.append(domain)
self.__write_content_in_file__(cores.domain_history_path,domain) self.__write_content_in_file__(
cores.domain_history_path, domain)
continue continue
if not(domain in self.domain_list): if not(domain in self.domain_list):
self.domain_list.append(domain) self.domain_list.append(domain)
self.__write_content_in_file__(cores.domain_history_path,domain) self.__write_content_in_file__(
cores.domain_history_path, domain)
if append_file_flag: if append_file_flag:
self.__write_content_in_file__(cores.app_history_path,identifier) self.__write_content_in_file__(
cores.app_history_path, identifier)
append_file_flag = False append_file_flag = False
def __start_threads__(self, worksheet): def __start_threads__(self, worksheet):
@ -107,4 +108,3 @@ class NetTask(object):
with open(file_path, "a+", encoding='utf-8', errors='ignore') as f: with open(file_path, "a+", encoding='utf-8', errors='ignore') as f:
f.write(content+"\r") f.write(content+"\r")
f.close() f.close()

@ -7,6 +7,7 @@ import config
import hashlib import hashlib
from queue import Queue from queue import Queue
class WebTask(object): class WebTask(object):
thread_list = [] thread_list = []
value_list = [] value_list = []

@ -1,3 +1,3 @@
requests requests
click click
xlwt openpyxl

Binary file not shown.

@ -1,3 +1,10 @@
### V1.0.9
- 更新apktool为最新版本
- 优化部分环节流程
- 修复excle文件导出时超时行数限制
- 修复脚本执行时卡顿的问题
- 修复Mac下Playload文件权限不足的问题
### V1.0.8 ### V1.0.8
- 添加AK和SK的检测 - 添加AK和SK的检测
- 添加检测规则提交入口 - 添加检测规则提交入口

Loading…
Cancel
Save