- 优化excle文件输出

- 更新项目处理流程
- 添加批量处理操作
v1.0.9
kelvinBen 3 years ago
parent 1f0fa65606
commit acc01c3303
  1. 4
      .gitignore
  2. 47
      app.py
  3. 232
      libs/core/__init__.py
  4. 22
      libs/core/net.py
  5. 2
      libs/core/parses.py
  6. 20
      libs/task/android_task.py
  7. 111
      libs/task/base_task.py
  8. 64
      libs/task/download_task.py
  9. 12
      libs/task/ios_task.py
  10. 32
      libs/task/net_task.py
  11. 2
      requirements.txt
  12. 11
      update.md

4
.gitignore vendored

@ -114,3 +114,7 @@ venv.bak/
# add
.idea/
#
1.py
.vscode/

@ -11,7 +11,13 @@ from libs.task.base_task import BaseTask
@click.group(help="Python script for automatically retrieving key information in app.")
def cli():
pass
try:
LOG_FORMAT = "%(message)s" # 日志格式化输出
fp = logging.FileHandler('info.log', mode='w',encoding='utf-8')
fs = logging.StreamHandler()
logging.basicConfig(level=logging.INFO, format=LOG_FORMAT, handlers=[fp, fs]) # 调用
except Exception as e:
logging.error("{}".format(e))
# 创建Android任务
@cli.command(help="Get the key information of Android system.")
@ -24,13 +30,13 @@ def cli():
@click.option("-o", '--output',required=False, type=str,default=None,help="Specify the result set output directory.")
@click.option("-p", '--package',required=False,type=str,default="",help="Specifies the package name information that needs to be scanned.")
def android(inputs: str, rules: str, sniffer: bool, no_resource:bool, all:bool, threads:int, output, package:str) -> None:
try:
bootstrapper = Bootstrapper(__file__, output, all, no_resource)
bootstrapper.init()
BaseTask("Android", inputs, rules, sniffer, threads, package).start()
except Exception as e:
raise e
bootstrapper = Bootstrapper(rules, sniffer, threads, all ,no_resource)
bootstrapper.init_dir(__file__, output)
BaseTask().start("Android", inputs, package)
@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.")
@ -41,13 +47,12 @@ def android(inputs: str, rules: str, sniffer: bool, no_resource:bool, all:bool,
@click.option("-t", '--threads',required=False, type=int,default=10,help="Set the number of concurrency. The larger the concurrency, the faster the speed. The default value is 10.")
@click.option("-o", '--output',required=False, type=str,default=None,help="Specify the result set output directory.")
def ios(inputs: str, rules: str, sniffer: bool, no_resource:bool, all:bool, threads:int, output:str) -> None:
try:
bootstrapper = Bootstrapper(__file__, output, all, no_resource)
bootstrapper.init()
BaseTask("iOS", inputs, rules, sniffer, threads).start()
except Exception as e:
raise e
bootstrapper = Bootstrapper(rules, sniffer, threads, all ,no_resource)
bootstrapper.init_dir(__file__, output)
BaseTask().start("iOS", inputs)
@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.")
@ -58,20 +63,14 @@ def ios(inputs: str, rules: str, sniffer: bool, no_resource:bool, all:bool, thre
@click.option("-t", '--threads',required=False, type=int,default=10,help="Set the number of concurrency. The larger the concurrency, the faster the speed. The default value is 10.")
@click.option("-o", '--output',required=False, type=str,default=None,help="Specify the result set output directory.")
def web(inputs: str, rules: str, sniffer: bool, no_resource:bool, all:bool, threads:int, output:str) -> None:
try:
bootstrapper = Bootstrapper(__file__, output, all, no_resource)
bootstrapper.init()
BaseTask("Web", inputs, rules, sniffer, threads).start()
except Exception as e:
raise e
bootstrapper = Bootstrapper(rules, sniffer, threads, all ,no_resource)
bootstrapper.init_dir(__file__, output)
BaseTask().start("Web", inputs)
def main():
LOG_FORMAT = "%(levelname)s - %(message)s" # 日志格式化输出
DATE_FORMAT = "%m/%d/%Y %H:%M:%S %p" # 日期格式
fp = logging.FileHandler('info.log', encoding='utf-8')
fs = logging.StreamHandler()
logging.basicConfig(level=logging.INFO, format=LOG_FORMAT, datefmt=DATE_FORMAT, handlers=[fp, fs]) # 调用
cli()
if __name__ == "__main__":

@ -2,118 +2,178 @@
# -*- coding: utf-8 -*-
# Author: kelvinBen
# Github: https://github.com/kelvinBen/AppInfoScanner
import os
import time
import shutil
import platform
import logging
# smali 所在路径
smali_path = ""
# backsmli 所在路径
backsmali_path = ""
# apktool 所在路径
apktool_path = ""
# 系统类型
os_type = ""
# 输出路径
output_path = ""
backsmali_file = None
apktool_file = None
strings_file = None
app_history_file= None
domain_history_file = None
result_dir = None
download_dir = None
decode_dir = None
user_add_rules = None
# 下载完成标记
download_flag = False
net_sniffer_flag = False
all_string_out = False
no_resource_flag = False
excel_row = 1
threads_num = 10
# excel 起始行号
excel_row = 0
class Bootstrapper(object):
def __init__(self, path, out_path, all=False, no_resource= False):
global smali_path
global backsmali_path
global apktool_path
global os_type
global output_path
global script_root_dir
global txt_result_path
global xls_result_path
global strings_path
global history_path
global app_history_path
global domain_history_path
global excel_row
global download_path
def __init__(self, rules, threads, sniffer, all, no_resource):
# backsmali 加载路径
global backsmali_file
# apktool 加载路径
global apktool_file
# string 加载路径
global strings_file
# App 扫描历史文件
global app_history_file
# 域名 扫描历史文件
global domain_history_file
# 结果输出目录
global result_dir
# 临时文件下载目录
global download_dir
# 临时反编译目录
global decode_dir
# 下载完成标记
global download_flag
global out_dir
global all_flag
global resource_flag
# excel 行号
global excel_row
# 用户自定义规则
global user_add_rules
# 用户指定线程数
global threads_num
# 网络嗅探标记
global net_sniffer_flag
# 输出所有字符传
global all_string_out
# 忽略资源标记
global no_resource_flag
user_add_rules = rules
threads_num = threads
net_sniffer_flag = sniffer
all_string_out = all
no_resource_flag = no_resource
# 需要创建的目录列表
self.__create_dir_list__= []
# 需要删除目录的列表
self.__remove_dir_list__= []
logging.info("[*] System env: {}".format(platform.system()))
def init_dir(self, app_input_path, user_out_path):
logging.info("[*] init dir...")
# 脚本执行目录
script_root_dir = os.path.dirname(os.path.abspath(app_input_path))
# 加载集成的工具
self.__tools_loading__(script_root_dir)
# 构建持久化目录
self.__build_persistent_path__(script_root_dir)
# 构建结果输出目录
self.__build_result_out__path__(script_root_dir,user_out_path)
# 统一目录构建中心
self.__build_dir__()
# 加载集成的工具
def __tools_loading__(self,script_root_dir):
tools_dir = os.path.join(script_root_dir,"tools")
all_flag = not all
resource_flag = no_resource
backsmali_file = os.path.join(tools_dir,"baksmali.jar")
logging.info("[*] Backsmali Path: {}".format(backsmali_file))
create_time = time.strftime("%Y%m%d%H%M%S", time.localtime())
script_root_dir = os.path.dirname(os.path.abspath(path))
if out_path:
out_dir = out_path
else:
out_dir = script_root_dir
tools_dir = os.path.join(script_root_dir,"tools")
output_path = os.path.join(out_dir,"out")
history_path = os.path.join(script_root_dir,"history")
apktool_file = os.path.join(tools_dir, "apktool.jar")
logging.info("[*] Apktool Path: {}".format(apktool_file))
if platform.system() == "Windows":
machine2bits = {'AMD64':64, 'x86_64': 64, 'i386': 32, 'x86': 32}
machine2bits.get(platform.machine())
if platform.machine() == 'i386' or platform.machine() == 'x86':
strings_path = os.path.join(tools_dir,"strings.exe")
strings_file = os.path.join(tools_dir,"strings.exe")
else:
strings_path = os.path.join(tools_dir,"strings64.exe")
strings_file = os.path.join(tools_dir,"strings64.exe")
else:
strings_file ="strings"
logging.info("[*] Strings Path: {}".format(strings_file))
# 构建持久化目录
def __build_persistent_path__(self,script_root_dir):
# 当前用户文档目录
doc_path = os.path.join(os.path.expanduser("~"), 'Documents')
if os.path.exists(doc_path):
app_dir = os.path.join(doc_path,"AppInfoScanner")
else:
strings_path ="strings"
backsmali_path = os.path.join(tools_dir,"baksmali.jar")
apktool_path = os.path.join(tools_dir, "apktool.jar")
download_path = os.path.join(out_dir,"download")
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")
app_history_path = os.path.join(history_path,"app_history.txt")
domain_history_path = os.path.join(history_path,"domain_history.txt")
def init(self):
if not os.path.exists(out_dir):
os.makedirs(out_dir)
print("[*] Create directory {}".format(out_dir))
if os.path.exists(output_path):
app_dir = os.path.join(script_root_dir,"AppInfoScanner")
# 历史任务加载目录
history_path = os.path.join(app_dir,"history")
app_history_file = os.path.join(history_path,"app_history.txt")
domain_history_file = os.path.join(history_path,"domain_history.txt")
self.__create_dir_list__.append(app_dir)
self.__create_dir_list__.append(history_path)
# 构建结果输出目录
def __build_result_out__path__(self,script_root_dir,user_out_path):
result_out_dir = script_root_dir
# 用户指定输出目录结果则为输出到指定目录
if user_out_path:
result_out_dir = user_out_path
# 统一输出目录
out_dir = os.path.join(result_out_dir,"out")
# 临时结果输出目录
decode_dir = os.path.join(out_dir,"decode")
# 临时文件下载目录
download_dir = os.path.join(out_dir,"download")
# 最终结果输出目录
result_dir = os.path.join(out_dir,"result")
self.__create_dir_list__.append(out_dir)
self.__create_dir_list__.append(decode_dir)
self.__create_dir_list__.append(download_dir)
self.__create_dir_list__.append(result_dir)
self.__remove_dir_list__.append(decode_dir)
# 统一目录构建中心
def __build_dir__(self):
for dir_path in self.__create_dir_list__:
if (os.path.exists(dir_path)) and (dir_path in self.__remove_dir_list__):
# 删除目录
try:
shutil.rmtree(output_path)
shutil.rmtree(dir_path)
logging.info("[-] Remove Dir: {}".format(dir_path))
except Exception as e:
# 解决windows超长文件名删除问题
if not (platform.system() == "Windows"):
raise e
self.__removed_dirs_cmd__(output_path)
os.makedirs(output_path)
logging.info("[*] Create directory {}".format(output_path))
if not os.path.exists(download_path):
# shutil.rmtree(download_path)
os.makedirs(download_path)
logging.info("[*] Create directory {}".format(download_path))
if not os.path.exists(history_path):
os.makedirs(history_path)
logging.info("[*] Create directory {}".format(history_path))
if os.path.exists(txt_result_path):
os.remove(txt_result_path)
self.__removed_dirs_cmd__(dir_path)
if os.path.exists(xls_result_path):
os.remove(xls_result_path)
# 创建目录
if not os.path.exists(dir_path):
os.makedirs(dir_path)
logging.info("[+] Create Dir: {}".format(dir_path))
def __removed_dirs_cmd__(self,output_path):
files = os.listdir(output_path)
@ -122,8 +182,12 @@ class Bootstrapper(object):
old_dir = os.path.join(output_path,file)
if not os.path.exists(new_dir):
os.makedirs(new_dir)
logging.info("[+] Create Dir: {}".format(new_dir))
os.chdir(output_path)
cmd = ("robocopy %s %s /purge") % (new_dir, old_dir)
logging.debug("[*] cmd : {}".format(cmd))
os.system(cmd)
os.removedirs(new_dir)
os.removedirs(old_dir)
logging.info("[-] Remove Dir: {}".format(new_dir))
logging.info("[-] Remove Dir: {}".format(old_dir))

@ -28,20 +28,22 @@ class NetThreads(threading.Thread):
url_ip = domains["url_ip"]
time.sleep(2)
result = self.__get_request_result__(url_ip)
logging.info("[+] Processing URL address:"+url_ip)
logging.info("[+] " + url_ip)
if result != "error":
if self.lock.acquire(True):
cores.excel_row = cores.excel_row + 1
self.worksheet.write(cores.excel_row, 0, label = cores.excel_row)
self.worksheet.write(cores.excel_row, 1, label = url_ip)
self.worksheet.write(cores.excel_row, 2, label = domain)
self.worksheet.cell(row=cores.excel_row, column=1).value = cores.excel_row
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":
self.worksheet.write(cores.excel_row, 3, label = result["status"])
self.worksheet.write(cores.excel_row, 4, label = result["des_ip"])
self.worksheet.write(cores.excel_row, 5, label = result["server"])
self.worksheet.write(cores.excel_row, 6, label = result["title"])
self.worksheet.write(cores.excel_row, 7, label = result["cdn"])
# self.worksheet.write(cores.excel_row, 8, label = "")
self.worksheet.cell(row=cores.excel_row, column=4).value = result["status"]
self.worksheet.cell(row=cores.excel_row, column=5).value = result["des_ip"]
self.worksheet.cell(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.worksheet.cell(row=cores.excel_row, column=9).value = ""
self.lock.release()
def __get_request_result__(self,url):

@ -81,7 +81,7 @@ class ParsesThreads(threading.Thread):
self.threadLock.acquire()
if cores.all_flag:
logging.info("[+] The string searched for matching rule is: %s" % (resl_str))
logging.info("[+] String : {}".format(resl_str))
self.result_list.append(resl_str)
self.threadLock.release()
continue

@ -38,8 +38,6 @@ class AndroidTask(object):
return {"comp_list":self.comp_list,"shell_flag":self.shell_flag,"file_queue":self.file_queue,"packagename":self.packagename,"file_identifier":self.file_identifier}
def __decode_file__(self,file_path):
apktool_path = str(cores.apktool_path)
backsmali_path = str(cores.backsmali_path)
base_out_path = str(cores.output_path)
filename = os.path.basename(file_path)
suffix_name = filename.split(".")[-1]
@ -47,7 +45,7 @@ class AndroidTask(object):
if suffix_name == "apk":
name = filename.split(".")[0]
output_path = os.path.join(base_out_path,name)
self.__decode_apk__(file_path,apktool_path,output_path)
self.__decode_apk__(file_path,output_path)
elif suffix_name == "dex":
f = open(file_path,'rb')
md5_obj = hashlib.md5()
@ -61,7 +59,7 @@ class AndroidTask(object):
output_path = os.path.join(base_out_path,dex_md5)
if not os.path.exists(output_path):
os.makedirs(output_path)
self.__decode_dex__(file_path,backsmali_path,output_path)
self.__decode_dex__(file_path,output_path)
else:
return "error"
@ -76,23 +74,25 @@ class AndroidTask(object):
continue
# 分解apk
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))
def __decode_apk__(self,file_path,output_path):
cmd_str = ('java -jar "%s" d -f "%s" -o "%s" --only-main-classe') % (cores.apktool_file,str(file_path),str(output_path))
logging.debug("[*] cmd {}".format(cmd_str))
if os.system(cmd_str) == 0:
self.__shell_test__(output_path)
self.__scanner_file_by_apktool__(output_path)
else:
logging.info("[-] Decompilation failed, please submit error information at https://github.com/kelvinBen/AppInfoScanner/issues")
logging.error("[x] Decompilation failed, please submit error information at https://github.com/kelvinBen/AppInfoScanner/issues")
raise Exception(file_path + ", Decompilation failed.")
# 分解dex
def __decode_dex__(self,file_path,backsmali_path,output_path):
cmd_str = ('java -jar "%s" d "%s"') % (str(backsmali_path),str(file_path))
def __decode_dex__(self,file_path,output_path):
cmd_str = ('java -jar "%s" d "%s"') % (cores.backsmali_file,str(file_path))
logging.debug("[*] cmd {}".format(cmd_str))
if os.system(cmd_str) == 0:
self.__get_scanner_file__(output_path)
else:
logging.info("[-] Decompilation failed, please submit error information at https://github.com/kelvinBen/AppInfoScanner/issues")
logging.error("[x] Decompilation failed, please submit error information at https://github.com/kelvinBen/AppInfoScanner/issues")
raise Exception(file_path + ", Decompilation failed.")

@ -17,46 +17,75 @@ from libs.task.android_task import AndroidTask
from libs.task.download_task import DownloadTask
class BaseTask(object):
thread_list =[]
result_dict = {}
app_history_list=[]
domain_history_list=[]
# 统一初始化入口
def __init__(self, types="Android", inputs="", rules="", sniffer=True, threads=10, package=""):
self.types = types
self.path = inputs
if rules:
config.filter_strs.append(r'.*'+str(rules)+'.*')
self.sniffer = not sniffer
self.threads = threads
self.package = package
def __init__(self):
if cores.user_add_rules:
config.filter_strs.append(r'.*'+str(cores.user_add_rules)+'.*')
self.file_queue = Queue()
self.file_path_list = []
self.thread_list = []
self.app_history_list= []
self.domain_history_list = []
self.result_dict = {}
# 统一启动
def start(self, types="Android", user_input_path="", package=""):
# 如果输入路径为目录,则自动检索DEX、IPA、APK等文件
if not(types == "Web") and os.path.isdir(user_input_path):
self.__scanner_specified_file__(self.file_path_list, user_input_path)
# 如果输入的路径为txt, 则加载txt中的内容
elif user_input_path.endswith("txt"):
with open(user_input_path) as f:
lines = f.readlines()
for line in lines:
if line.startswith("http://") or line.startswith("https://") or line.endswith("apk") or line.endswith(".dex") or line.endswith("ipa"):
self.file_path_list.append(line)
f.close()
else:
# 如果是文件则追加到文件列表中
self.file_path_list.append(user_input_path)
# 长度小于1需重新选择目录
if len(self.file_path_list) < 1:
raise Exception('[x] The specified DEX, IPA and APK files are not found. Please re-enter the directory to be scanned!')
# 统一调度平台
def start(self):
# 遍历目录
for file_path in self.file_path_list:
self.__control_center__(file_path,types)
# 控制中心
def __control_center__(self,file_path,types):
logging.info("[*] Processing {}".format(file_path))
logging.info("[*] AI is analyzing filtering rules......")
# 获取历史记录
# 处理历史记录
self.__history_handle__()
logging.info("[*] The filtering rules obtained by AI are as follows: {}".format(set(config.filter_no)))
logging.info("[*] The filtering rules obtained by AI are as follows: %s" % (set(config.filter_no)) )
# AI 修正扫描类型
cache_info = DownloadTask().start(file_path, types)
cacar_path = cache_info["path"]
types = cache_info["type"]
# 任务控制中心
task_info = self.__tast_control__()
task_info = self.__tast_control__(file_path)
if len(task_info) < 1:
return
# 文件队列
file_queue = task_info["file_queue"]
# 是否存在壳
shell_flag = task_info["shell_flag"]
# 组件列表(仅适用于Android)
comp_list = task_info["comp_list"]
# 报名信息(仅适用于Android)
packagename = task_info["packagename"]
# 文件标识符
file_identifier = task_info["file_identifier"]
if shell_flag:
logging.info('[-] \033[3;31m Error: This application has shell, the retrieval results may not be accurate, Please remove the shell and try again!')
return
logging.error('[x] This application has shell, the retrieval results may not be accurate, Please remove the shell and try again!')
continue
# 线程控制中心
logging.info("[*] ========= Searching for strings that match the rules ===============")
@ -70,15 +99,13 @@ class BaseTask(object):
self.__print_control__(packagename,comp_list,file_identifier)
def __tast_control__(self):
# 任务控制中心
def __tast_control__(self,user_input_path):
task_info = {}
# 自动根据文件后缀名称进行修正
cache_info = DownloadTask().start(self.path,self.types)
cacar_path = cache_info["path"]
types = cache_info["type"]
if (not os.path.exists(cacar_path) and cores.download_flag):
logging.info("[-] File download failed! Please download the file manually and try again.")
logging.error("[x] File download failed! Please download the file manually and try again.")
return task_info
# 调用Android 相关处理逻辑
@ -92,21 +119,19 @@ class BaseTask(object):
task_info = WebTask(cacar_path).start()
return task_info
# 线程控制中心
def __threads_control__(self,file_queue):
for threadID in range(1,self.threads):
for threadID in range(1, cores.threads_num):
name = "Thread - " + str(int(threadID))
thread = ParsesThreads(threadID,name,file_queue,self.result_dict,self.types)
thread.start()
self.thread_list.append(thread)
# 信息输出中心
def __print_control__(self,packagename,comp_list,file_identifier):
txt_result_path = cores.txt_result_path
xls_result_path = cores.xls_result_path
all_flag = cores.all_flag
if self.sniffer:
if cores.net_sniffer_flag:
logging.info("[*] ========= Sniffing the URL address of the search ===============")
NetTask(self.result_dict,self.app_history_list,self.domain_history_list,file_identifier,self.threads).start()
NetTask(self.result_dict,self.app_history_list,self.domain_history_list,file_identifier).start()
if packagename:
logging.info("[*] ========= The package name of this APP is: ===============")
@ -117,7 +142,7 @@ class BaseTask(object):
for json in comp_list:
logging.info(json)
if all_flag:
if cores.all_flag:
value_list = []
with open(txt_result_path,"a+",encoding='utf-8',errors='ignore') as f:
for key,value in self.result_dict.items():
@ -128,11 +153,12 @@ class BaseTask(object):
value_list.append(result)
f.write("\t"+result+"\r")
f.close()
logging.info("[*] For more information about the search, see TXT file result: %s" %(txt_result_path))
logging.info("[>] For more information about the search, see TXT file result: {}".format(cores.txt_result_path))
if self.sniffer:
logging.info("[*] For more information about the search, see XLS file result: %s" %(xls_result_path))
if cores.net_sniffer_flag:
logging.info("[>] For more information about the search, see XLS file result: {}".format(cores.xls_result_path))
# 获取历史记录
def __history_handle__(self):
domain_history_path = cores.domain_history_path
app_history_path = cores.app_history_path
@ -160,4 +186,13 @@ class BaseTask(object):
config.filter_no.append(".*" + domain)
f.close()
# 扫描指定后缀文件
def __scanner_specified_file__(self, file_list, root_dir, file_suffix=['dex','ipa','apk']):
dir_or_files = os.listdir(root_dir)
for dir_or_file in dir_or_files:
dir_or_file_path = os.path.join(root_dir,dir_or_file)
if os.path.isdir(dir_or_file_path):
self.__scanner_specified_file__(file_list,dir_or_file_path,file_suffix)
else:
if dir_or_file_path.split(".")[-1] in file_suffix:
file_list.append(dir_or_file_path)

@ -7,40 +7,70 @@ import re
import time
import config
import hashlib
import logging
from queue import Queue
import libs.core as cores
from libs.core.download import DownloadThreads
class DownloadTask(object):
def __init__(self):
self.download_file_queue = Queue()
self.thread_list = []
def start(self, path, types):
self.__local_or_remote__(path, types)
for threadID in range(1, cores.threads_num):
name = "Thread - " + str(int(threadID))
thread = DownloadThreads(threadID,name,self.download_file_queue)
thread.start()
thread.join()
# 判断文件是本地加载还是远程加载
def __local_or_remote__(self,path,types):
# 处理本地文件
if not(path.startswith("http://") or path.startswith("https://")):
if not os.path.isdir(path): # 不是目录
return {"path":path,"type":types}
else: # 目录处理
return {"path":path,"type":types}
else:
self.__net_header__(path,types)
# self.download_file_queue.put(path)
# 处理网络请求
def __net_header__(self, path, types):
create_time = time.strftime("%Y%m%d%H%M%S", time.localtime())
if path.endswith("apk"):
if path.endswith("apk") or types == "Android":
types = "Android"
file_name = create_time+ ".apk"
elif path.endswith("ipa"):
elif path.endswith("ipa") or types == "iOS":
types = "iOS"
file_name = create_time + ".ipa"
else:
if types == "Android":
types = "WEB"
file_name = create_time + ".html"
logging.info("[*] Detected that the task is not local, preparing to download file......")
cache_path = os.path.join(cores.download_dir, file_name)
self.download_file_queue.put({"path":path, "cache_path":cache_path, "types":types})
# thread = DownloadThreads(path,file_name,cache_path,types)
# thread.start()
# thread.join()
return {"path":cache_path,"type":types}
def __update_type__(self, path, types, file_name=None):
create_time = time.strftime("%Y%m%d%H%M%S", time.localtime())
if path.endswith("apk") or types == "Android":
types = "Android"
if not file_name:
file_name = create_time+ ".apk"
elif types == "iOS":
elif path.endswith("ipa") or types == "iOS":
types = "iOS"
if not file_name:
file_name = create_time + ".ipa"
else:
types = "WEB"
if not file_name:
file_name = create_time + ".html"
if not(path.startswith("http://") or path.startswith("https://")):
if not os.path.isdir(path): # 不是目录
return {"path":path,"type":types}
else: # 目录处理
return {"path":path,"type":types}
else:
logging.info("[*] Detected that the task is not local, preparing to download file......")
cache_path = os.path.join(cores.download_path, file_name)
thread = DownloadThreads(path,file_name,cache_path,types)
thread.start()
thread.join()
logging.info()
return {"path":cache_path,"type":types}
return types,file_name

@ -3,8 +3,6 @@
# Author: kelvinBen
# Github: https://github.com/kelvinBen/AppInfoScanner
import os
import re
import shutil
import zipfile
import binascii
import platform
@ -23,7 +21,6 @@ class iOSTask(object):
file_path = self.path
if file_path.split(".")[-1] == 'ipa':
self.__decode_ipa__(cores.output_path)
self.__scanner_file_by_ipa__(cores.output_path)
elif self.__get_file_header__(file_path):
self.file_queue.put(file_path)
else:
@ -50,11 +47,6 @@ class iOSTask(object):
macho_file.close()
return False
def __scanner_file_by_ipa__(self,output):
scanner_file_suffix = ["plist","js","xml","html"]
scanner_dir = os.path.join(output,"Payload")
self.__get_scanner_file__(scanner_dir,scanner_file_suffix)
def __get_scanner_file__(self,scanner_dir,file_suffix):
dir_or_files = os.listdir(scanner_dir)
for dir_file in dir_or_files:
@ -76,6 +68,9 @@ class iOSTask(object):
self.file_queue.put(dir_file_path)
def __decode_ipa__(self,output_path):
scanner_file_suffix = ["plist","js","xml","html"]
scanner_dir = os.path.join(output_path,"Payload")
with zipfile.ZipFile(self.path,"r") as zip_files:
zip_file_names = zip_files.namelist()
for zip_file_name in zip_file_names:
@ -90,6 +85,7 @@ class iOSTask(object):
new_ext_file_path = os.path.join(output_path,new_file_name)
ext_file_path = zip_files.extract(zip_file_name,output_path)
os.rename(ext_file_path,new_ext_file_path)
self.__get_scanner_file__(scanner_dir,scanner_file_suffix)
def __get_parse_dir__(self,output_path,file_path):
start = file_path.index("Payload/")

@ -2,32 +2,29 @@
# -*- coding: utf-8 -*-
# Author: kelvinBen
# Github: https://github.com/kelvinBen/AppInfoScanner
import re
import xlwt
import socket
import config
from queue import Queue
import libs.core as cores
from openpyxl import Workbook
from libs.core.net import NetThreads
import requests
class NetTask(object):
value_list = []
domain_list=[]
def __init__(self,result_dict,app_history_list,domain_history_list,file_identifier,threads):
def __init__(self,result_dict,app_history_list,domain_history_list,file_identifier):
self.result_dict = result_dict
self.app_history_list = app_history_list
self.domain_history_list = domain_history_list
self.file_identifier = file_identifier
self.domain_queue = Queue()
self.threads = int(threads)
self.thread_list = []
self.domain_history_list = domain_history_list
def start(self):
xls_result_path = cores.xls_result_path
workbook = xlwt.Workbook(encoding = 'utf-8')
workbook = Workbook()
worksheet = self.__creating_excel_header__(workbook)
self.__write_result_to_txt__()
@ -40,16 +37,11 @@ class NetTask(object):
workbook.save(xls_result_path)
def __creating_excel_header__(self,workbook):
worksheet = workbook.add_sheet("Result",cell_overwrite_ok=True)
worksheet.write(0,0, label = "Number")
worksheet.write(0,1, label = "IP/URL")
worksheet.write(0,2, label = "Domain")
worksheet.write(0,3, label = "Status")
worksheet.write(0,4, label = "IP")
worksheet.write(0,5, label = "Server")
worksheet.write(0,6, label = "Title")
worksheet.write(0,7, label = "CDN")
# worksheet.write(0,8, label = "Finger")
worksheet = workbook.create_sheet("Result",0)
excel_headers = ["Number","IP/URL","Domain","Status","IP","Server","Title","CDN","Finger"]
for head_cell in excel_headers:
column = excel_headers.index(head_cell) + 1
worksheet.cell(row=1, column=column).value = head_cell
return worksheet
def __write_result_to_txt__(self):
@ -97,7 +89,7 @@ class NetTask(object):
append_file_flag = False
def __start_threads__(self,worksheet):
for threadID in range(0,self.threads) :
for threadID in range(0, cores.threads_num):
name = "Thread - " + str(threadID)
thread = NetThreads(threadID,name,self.domain_queue,worksheet)
thread.start()

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

@ -1,12 +1,15 @@
### V1.0.9
- 新增IPA批量操作
- 优化iOS壳检测速度
- 优化iPA文件效率
- 优化iPA文件解压效率
- 优化日志输出
- 修复内容过长无法输出到excle
### V1.0.8
- 添加AK和SK的检测
- 添加检测规则提交入口
- 添加.gitignore文件
- 新增AK和SK的检测
- 新增检测规则提交入口
- 新增.gitignore文件
- 优化txt结果集输出方式
- 修复目录中包含空格无法解析的问题
- 修复WEB页面或者目录扫描的问题

Loading…
Cancel
Save