add "识别到壳后自动进行脱壳处理"

v1.0.9.1
xiaokanghub 2 years ago committed by root
parent 18188fda3b
commit ae2de54c59
  1. 61
      app.py
  2. 53
      libs/core/__init__.py
  3. 352
      libs/task/android_task.py
  4. 2
      requirements.txt
  5. BIN
      tools/unpacker/aapt.exe
  6. BIN
      tools/unpacker/adb.exe
  7. BIN
      tools/unpacker/hexl-server-arm32
  8. BIN
      tools/unpacker/hexl-server-arm64

@ -13,19 +13,28 @@ from libs.task.base_task import BaseTask
def cli():
pass
# 创建Android任务
@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("-r", "--rules", required=False, type=str, default="", help="Please enter a rule for temporary scanning of file contents.")
@click.option("-s", "--sniffer", is_flag=True, default=False, help="Enable the network sniffer function. It is on by default.")
@click.option("-n", '--no-resource', is_flag=True, default=False, help="Ignore all resource files, including network sniffing. It is not enabled by default.")
@click.option("-a", '--all', is_flag=True, default=False, help="Output the string content that conforms to the scan rules.It is on by default.")
@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("-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("-s", "--sniffer", is_flag=True, default=False,
help="Enable the network sniffer function. It is on by default.")
@click.option("-n", '--no-resource', is_flag=True, default=False,
help="Ignore all resource files, including network sniffing. It is not enabled by default.")
@click.option("-a", '--all', is_flag=True, default=False,
help="Output the string content that conforms to the scan rules.It is on by default.")
@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.")
@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:
@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()
@ -36,12 +45,18 @@ def android(inputs: str, rules: str, sniffer: bool, no_resource: bool, all: bool
@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("-r", "--rules", required=False, type=str, default="", help="Please enter a rule for temporary scanning of file contents.")
@click.option("-s", "--sniffer", is_flag=True, default=False, help="Enable the network sniffer function. It is on by default.")
@click.option("-n", '--no-resource', is_flag=True, default=False, help="Ignore all resource files, including network sniffing. It is not enabled by default.")
@click.option("-a", '--all', is_flag=True, default=False, help="Output the string content that conforms to the scan rules.It is on by default.")
@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("-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("-s", "--sniffer", is_flag=True, default=False,
help="Enable the network sniffer function. It is on by default.")
@click.option("-n", '--no-resource', is_flag=True, default=False,
help="Ignore all resource files, including network sniffing. It is not enabled by default.")
@click.option("-a", '--all', is_flag=True, default=False,
help="Output the string content that conforms to the scan rules.It is on by default.")
@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:
@ -54,12 +69,18 @@ def ios(inputs: str, rules: str, sniffer: bool, no_resource: bool, all: bool, th
@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("-r", "--rules", required=False, type=str, default="", help="Please enter a rule for temporary scanning of file contents.")
@click.option("-s", "--sniffer", is_flag=True, default=False, help="Enable the network sniffer function. It is on by default.")
@click.option("-n", '--no-resource', is_flag=True, default=False, help="Ignore all resource files, including network sniffing. It is not enabled by default.")
@click.option("-a", '--all', is_flag=True, default=False, help="Output the string content that conforms to the scan rules.It is on by default.")
@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("-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("-s", "--sniffer", is_flag=True, default=False,
help="Enable the network sniffer function. It is on by default.")
@click.option("-n", '--no-resource', is_flag=True, default=False,
help="Ignore all resource files, including network sniffing. It is not enabled by default.")
@click.option("-a", '--all', is_flag=True, default=False,
help="Output the string content that conforms to the scan rules.It is on by default.")
@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:

@ -16,6 +16,16 @@ backsmali_path = ""
# apktool 所在路径
apktool_path = ""
# adb 所在路径
adb_path = ""
# frida server 所在路径
frida32_path = ""
frida64_path = ""
# aapt 所在路径
aapt_apth = ""
# 系统类型
os_type = ""
@ -28,12 +38,17 @@ download_flag = False
# excel 起始行号
excel_row = 1
class Bootstrapper(object):
def __init__(self, path, out_path, all=False, no_resource= False):
def __init__(self, path, out_path, all=False, no_resource=False):
global smali_path
global backsmali_path
global apktool_path
global adb_path
global frida32_path
global frida64_path
global aapt_apth
global os_type
global output_path
global script_root_dir
@ -59,28 +74,32 @@ class Bootstrapper(object):
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")
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")
if platform.system() == "Windows":
machine2bits = {'AMD64':64, 'x86_64': 64, 'i386': 32, 'x86': 32}
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_path = os.path.join(tools_dir, "strings.exe")
else:
strings_path = os.path.join(tools_dir,"strings64.exe")
strings_path = os.path.join(tools_dir, "strings64.exe")
else:
strings_path ="strings"
strings_path = "strings"
backsmali_path = os.path.join(tools_dir,"baksmali.jar")
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)+".xlsx")
app_history_path = os.path.join(history_path,"app_history.txt")
domain_history_path = os.path.join(history_path,"domain_history.txt")
adb_path = os.path.join(tools_dir + '\\unpacker', "adb.exe")
frida32_path = os.path.join(tools_dir + '\\unpacker', "hexl-server-arm32")
frida64_path = os.path.join(tools_dir + '\\unpacker', "hexl-server-arm64")
aapt_apth = os.path.join(tools_dir + '\\unpacker', "aapt.exe")
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) + ".xlsx")
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):
@ -113,11 +132,11 @@ class Bootstrapper(object):
if os.path.exists(xls_result_path):
os.remove(xls_result_path)
def __removed_dirs_cmd__(self,output_path):
def __removed_dirs_cmd__(self, output_path):
files = os.listdir(output_path)
for file in files:
new_dir = os.path.join(output_path,"newdir")
old_dir = os.path.join(output_path,file)
new_dir = os.path.join(output_path, "newdir")
old_dir = os.path.join(output_path, file)
if not os.path.exists(new_dir):
os.makedirs(new_dir)
os.chdir(output_path)

@ -2,10 +2,16 @@
# -*- coding: utf-8 -*-
# Author: kelvinBen
# Github: https://github.com/kelvinBen/AppInfoScanner
import json
import os
import re
import shutil
import subprocess
import config
import hashlib
import zipfile
import platform
from queue import Queue
import libs.core as cores
@ -21,14 +27,279 @@ class AndroidTask(object):
self.comp_list = []
self.file_identifier = []
self.permissions = []
self.files = []
self.protect_flag = """{
"360加固": [
"assets/.appkey",
"assets/libjiagu.so",
"libjiagu.so",
"libjiagu_art.so",
"libjiagu_x86.so",
"libprotectClass.so",
".appkey",
"1ibjgdtc.so",
"libjgdtc.so",
"libjgdtc_a64.so",
"libjgdtc_art.so",
"libjgdtc_x64.so",
"libjgdtc_x86.so",
"libjiagu_a64.so",
"libjiagu_ls.so",
"libjiagu_x64.so"
],
"APKProtect": [
"libAPKProtect.so"
],
"UU安全": [
"libuusafe.jar.so",
"libuusafe.so",
"libuusafeempty.so",
"assets/libuusafe.jar.so",
"assets/libuusafe.so",
"lib/armeabi/libuusafeempty.so"
],
"apktoolplus": [
"assets/jiagu_data.bin",
"assets/sign.bin",
"jiagu_data.bin",
"lib/armeabi/libapktoolplus_jiagu.so",
"libapktoolplus_jiagu.so",
"sign.bin"
],
"中国移动加固": [
"assets/mogosec_classes",
"assets/mogosec_data",
"assets/mogosec_dexinfo",
"assets/mogosec_march",
"ibmogosecurity.so",
"lib/armeabi/libcmvmp.so",
"lib/armeabi/libmogosec_dex.so",
"lib/armeabi/libmogosec_sodecrypt.so",
"lib/armeabi/libmogosecurity.so",
"libcmvmp.so",
"libmogosec_dex.so",
"libmogosec_sodecrypt.so",
"mogosec_classes",
"mogosec_data",
"mogosec_dexinfo",
"mogosec_march"
],
"几维安全": [
"assets/dex.dat",
"lib/armeabi/kdpdata.so",
"lib/armeabi/libkdp.so",
"lib/armeabi/libkwscmm.so",
"libkwscmm.so",
"libkwscr.so",
"libkwslinker.so"
],
"启明星辰": [
"libvenSec.so",
"libvenustech.so"
],
"网秦加固": [
"libnqshield.so"
],
"娜迦加固": [
"libchaosvmp.so",
"libddog.so",
"libfdog.so"
],
"娜迦加固(新版2022)": [
"assets/maindata/fake_classes.dex",
"lib/armeabi/libxloader.so",
"lib/armeabi-v7a/libxloader.so",
"lib/arm64-v8a/libxloader.so",
"libxloader.so"
],
"娜迦加固(企业版)": [
"libedog.so"
],
"梆梆安全(企业版)": [
"libDexHelper-x86.so",
"libDexHelper.so",
"1ibDexHelper.so"
],
"梆梆安全": [
"libSecShell.so",
"libsecexe.so",
"libsecmain.so",
"libSecShel1.so"
],
"梆梆安全(定制版)": [
"assets/classes.jar",
"lib/armeabi/DexHelper.so"
],
"梆梆安全(免费版)": [
"assets/secData0.jar",
"lib/armeabi/libSecShell-x86.so",
"lib/armeabi/libSecShell.so"
],
"海云安加固": [
"assets/itse",
"lib/armeabi/libitsec.so",
"libitsec.so"
],
"爱加密": [
"assets/af.bin",
"assets/ijiami.ajm",
"assets/ijm_lib/X86/libexec.so",
"assets/ijm_lib/armeabi/libexec.so",
"assets/signed.bin",
"ijiami.dat",
"lib/armeabi/libexecmain.so",
"libexecmain.so"
],
"爱加密企业版": [
"ijiami.ajm"
],
"珊瑚灵御": [
"assets/libreincp.so",
"assets/libreincp_x86.so",
"libreincp.so",
"libreincp_x86.so"
],
"瑞星加固": [
"librsprotect.so"
],
"百度加固": [
"libbaiduprotect.so",
"assets/baiduprotect.jar",
"assets/baiduprotect1.jar",
"baiduprotect1.jar",
"lib/armeabi/libbaiduprotect.so",
"libbaiduprotect_art.so",
"libbaiduprotect_x86.so"
],
"盛大加固": [
"libapssec.so"
],
"网易易盾": [
"libnesec.so"
],
"腾讯": [
"libexec.so",
"libshell.so"
],
"腾讯加固": [
"lib/armeabi/mix.dex",
"lib/armeabi/mixz.dex",
"lib/armeabi/libshella-xxxx.so",
"lib/armeabi/libshellx-xxxx.so",
"tencent_stub"
],
"腾讯乐固(旧版)": [
"libtup.so",
"mix.dex",
"liblegudb.so",
"libshella",
"mixz.dex",
"libshel1x"
],
"腾讯乐固": [
"libshellx"
],
"腾讯乐固(VMP)": [
"lib/arm64-v8a/libxgVipSecurity.so",
"lib/armeabi-v7a/libxgVipSecurity.so",
"libxgVipSecurity.so"
],
"腾讯云": [
"assets/libshellx-super.2021.so",
"lib/armeabi/libshell-super.2019.so",
"lib/armeabi/libshell-super.2020.so",
"lib/armeabi/libshell-super.2021.so",
"lib/armeabi/libshell-super.2022.so",
"lib/armeabi/libshell-super.2023.so",
"tencent_sub"
],
"腾讯云移动应用安全": [
"0000000lllll.dex",
"00000olllll.dex",
"000O00ll111l.dex",
"00O000ll111l.dex",
"0OO00l111l1l",
"o0oooOO0ooOo.dat"
],
"腾讯云移动应用安全(腾讯御安全)": [
"libBugly-yaq.so",
"libshell-super.2019.so",
"libshellx-super.2019.so",
"libzBugly-yaq.so",
"t86",
"tosprotection",
"tosversion",
"000000011111.dex",
"000000111111.dex",
"000001111111",
"00000o11111.dex",
"o0ooo000oo0o.dat"
],
"腾讯御安全": [
"libtosprotection.armeabi-v7a.so",
"libtosprotection.armeabi.so",
"libtosprotection.x86.so",
"assets/libtosprotection.armeabi-v7a.so",
"assets/libtosprotection.armeabi.so",
"assets/libtosprotection.x86.so",
"assets/tosversion",
"lib/armeabi/libTmsdk-xxx-mfr.so",
"lib/armeabi/libtest.so"
],
"腾讯Bugly": [
"lib/arm64-v8a/libBugly.so",
"libBugly.so"
],
"蛮犀": [
"assets/mxsafe.config",
"assets/mxsafe.data",
"assets/mxsafe.jar",
"assets/mxsafe/arm64-v8a/libdSafeShell.so",
"assets/mxsafe/x86_64/libdSafeShell.so",
"libdSafeShell.so"
],
"通付盾": [
"libNSaferOnly.so",
"libegis.so"
],
"阿里加固": [
"assets/armeabi/libfakejni.so",
"assets/armeabi/libzuma.so",
"assets/classes.dex.dat",
"assets/dp.arm-v7.so.dat",
"assets/dp.arm.so.dat",
"assets/libpreverify1.so",
"assets/libzuma.so",
"assets/libzumadata.so",
"dexprotect"
],
"阿里聚安全": [
"aliprotect.dat",
"libdemolish.so",
"libfakejni.so",
"libmobisec.so",
"libsgmain.so",
"libzuma.so",
"libzumadata.so",
"libdemolishdata.so",
"libpreverify1.so",
"libsgsecuritybody.so"
],
"顶像科技": [
"libx3g.so",
"lib/armeabi/libx3g.so"
]
}"""
def start(self):
# 检查java环境是否存在
if os.system("java -version") != 0:
raise Exception("Please install the Java environment!")
# 检查Frida环境是否存在
if os.system("frida --version") != 0:
raise Exception("Please install the Frida environment!")
input_file_path = self.path
if os.path.isdir(input_file_path):
self.__decode_dir__(input_file_path)
else:
@ -36,7 +307,68 @@ class AndroidTask(object):
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}
def __detect_protect__(self, file_path):
markNameMap = json.loads(self.protect_flag)
markNameMap = dict(markNameMap)
zip_stream = zipfile.ZipFile(file_path) # 默认模式r,读
flag = ''
for zippath in zip_stream.namelist():
if 'lib' in zippath:
for key, value in markNameMap.items():
for mark in value:
if mark in zippath:
print("detect 【{}】 protector\nspecific code:{}->{}\n".format(key, zippath, mark))
flag += ("detect 【{}】 protector\nspecific code:{}->{}\n".format(key, zippath, mark))
if len(flag) > 0:
self.__android_unpack__()
# so库文件模式找不到就全量匹配
for zippath in zip_stream.namelist():
for key, value in markNameMap.items():
for mark in value:
if mark in zippath:
print("detect 【{}】 protector\nspecific code:{}->{}\n".format(key, zippath, mark))
flag += ("detect 【{}】 protector\nspecific code:{}->{}\n".format(key, zippath, mark))
if len(flag) > 0:
self.__android_unpack__()
print("We can't detect protect")
def __android_unpack__(self):
print('[*] unpacking')
cmd_str = ('%s install %s') % (str(cores.adb_path), str(self.path))
print('[*] Install the APK')
if os.system(cmd_str) == 0:
print("Push Frida Server")
cmd_str = ('%s push %s /data/local/tmp') % (str(cores.adb_path), str(cores.frida32_path))
cmd_str1 = ('%s push %s /data/local/tmp') % (str(cores.adb_path), str(cores.frida64_path))
cmd_str2 = ('%s shell su -c "chmod 777 /data/local/tmp/hexl-server-arm64"') % (str(cores.adb_path))
cmd_str3 = ('%s shell su -c "setenforce 0"') % (str(cores.adb_path))
cmd_str4 = ('%s shell su -c "./data/local/tmp/hexl-server-arm64 &"') % (str(cores.adb_path))
print("[*] Running Frida Server")
if os.system(cmd_str) == 0 and os.system(cmd_str1) == 0 and os.system(cmd_str2) == 0 \
and os.system(cmd_str3) == 0 and os.system(cmd_str4) == 0:
print("[*] Frida Server started")
else:
print("[-] Running failed, please check the error in terminal")
exit()
else:
print("[-] We can't install the APP")
exit()
get_info_command = "%s dump badging %s" % (cores.aapt_apth, self.path)
pip = os.popen(get_info_command)
output = pip.buffer.read().decode('utf-8', 'ignore')
if output == "":
raise Exception("can't get the app info")
match = re.compile("package: name='(\S+)'").match(
output) # 通过正则匹配,获取包名
print(match.group(1))
cmd_str = ('frida-dexdump -U -f %s') % (str(match.group(1)))
if os.system(cmd_str) != 0:
print("An error occurred in the unpack")
exit()
def __decode_file__(self, file_path):
apktool_path = str(cores.apktool_path)
@ -45,6 +377,9 @@ class AndroidTask(object):
filename = os.path.basename(file_path)
suffix_name = filename.split(".")[-1]
if suffix_name == "apk":
self.__detect_protect__(file_path)
if suffix_name == "apk" or suffix_name == "hpk":
name = filename.split(".")[0]
output_path = os.path.join(base_out_path, name)
@ -84,7 +419,8 @@ class AndroidTask(object):
self.__shell_test__(output_path)
self.__scanner_file_by_apktool__(output_path)
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.")
# 分解dex
@ -94,7 +430,8 @@ class AndroidTask(object):
if os.system(cmd_str) == 0:
self.__get_scanner_file__(output_path)
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.")
# 初始化检测文件信息
@ -119,13 +456,14 @@ class AndroidTask(object):
if os.path.isdir(dir_file_path):
self.__get_scanner_file__(dir_file_path, scanner_file_suffixs)
else:
if ("." not in dir_or_file) or (len(dir_or_file.split(".")) < 1) or (dir_or_file.split(".")[-1] not in scanner_file_suffixs):
if ("." not in dir_or_file) or (len(dir_or_file.split(".")) < 1) or (
dir_or_file.split(".")[-1] not in scanner_file_suffixs):
continue
self.file_queue.put(dir_file_path)
for component in config.filter_components:
comp = component.replace(".", "/")
if(comp in dir_file_path):
if(component not in self.comp_list):
if (comp in dir_file_path):
if (component not in self.comp_list):
self.comp_list.append(component)
def __shell_test__(self, output):

@ -1,3 +1,5 @@
requests
click
openpyxl
frida-tools==11.0.0
frida-dexdump

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.
Loading…
Cancel
Save