@ -2,71 +2,409 @@
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
# Author: kelvinBen
# Author: kelvinBen
# Github: https://github.com/kelvinBen/AppInfoScanner
# Github: https://github.com/kelvinBen/AppInfoScanner
import json
import os
import os
import re
import re
import shutil
import subprocess
import config
import config
import logging
import hashlib
import hashlib
import zipfile
import platform
from queue import Queue
from queue import Queue
import libs . core as cores
import libs . core as cores
class AndroidTask ( object ) :
class AndroidTask ( object ) :
def __init__ ( self , file_ path, package ) :
def __init__ ( self , path , package ) :
self . input_file_ path = file_ path
self . path = path
self . package = package
self . package = package
self . file_queue = Queue ( )
self . file_queue = Queue ( )
self . shell_flag = False
self . shell_flag = False
self . packagename = " "
self . packagename = " "
self . comp_list = [ ]
self . comp_list = [ ]
self . file_identifier = [ ]
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 ) :
def start ( self ) :
# 检查java环境是否存在
# 检查java环境是否存在
if os . system ( " java -version " ) != 0 :
if os . system ( " java -version " ) != 0 :
raise Exception ( " Please install the Java environment! " )
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
input_file_path = self . path
if os . path . isdir ( input_file_path ) :
if os . path . isdir ( input_file_path ) :
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 }
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 \n specific code: {} -> {} \n " . format ( key , zippath , mark ) )
flag + = ( " detect 【 {} 】 protector \n specific 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 \n specific code: {} -> {} \n " . format ( key , zippath , mark ) )
flag + = ( " detect 【 {} 】 protector \n specific code: {} -> {} \n " . format ( key , zippath , mark ) )
if len ( flag ) > 0 :
self . __android_unpack__ ( )
print ( " We can ' t detect protect " )
def __decode_file__ ( self , file_path ) :
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 )
backsmali_path = str ( cores . backsmali_path )
base_out_path = str ( cores . output_path )
base_out_path = str ( cores . output_path )
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 " :
self . __detect_protect__ ( file_path )
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 , output_path )
self . __decode_apk__ ( file_path , apktool_path , output_path )
elif suffix_name == " dex " :
elif suffix_name == " dex " :
f = open ( file_path , ' rb ' )
f = open ( file_path , ' rb ' )
md5_obj = hashlib . md5 ( )
md5_obj = hashlib . md5 ( )
while True :
while True :
r = f . read ( 1024 )
r = f . read ( 1024 )
if not r :
if not r :
break
break
md5_obj . update ( r )
md5_obj . update ( r )
dex_md5 = md5_obj . hexdigest ( ) . lower ( )
dex_md5 = md5_obj . hexdigest ( ) . lower ( )
self . file_identifier . append ( dex_md5 )
self . file_identifier . append ( dex_md5 )
output_path = os . path . join ( base_out_path , dex_md5 )
output_path = os . path . join ( base_out_path , dex_md5 )
if not os . path . exists ( output_path ) :
if not os . path . exists ( output_path ) :
os . makedirs ( output_path )
os . makedirs ( output_path )
self . __decode_dex__ ( file_path , output_path )
self . __decode_dex__ ( file_path , backsmali_path , output_path )
else :
else :
return " error "
return " error "
def __decode_dir__ ( self , root_dir ) :
def __decode_dir__ ( self , root_dir ) :
dir_or_files = os . listdir ( root_dir )
dir_or_files = os . listdir ( root_dir )
for dir_or_file in dir_or_files :
for dir_or_file in dir_or_files :
dir_or_file_path = os . path . join ( root_dir , dir_or_file )
dir_or_file_path = os . path . join ( root_dir , dir_or_file )
if os . path . isdir ( dir_or_file_path ) :
if os . path . isdir ( dir_or_file_path ) :
self . __decode_dir__ ( dir_or_file_path )
self . __decode_dir__ ( dir_or_file_path )
else :
else :
@ -74,73 +412,80 @@ class AndroidTask(object):
continue
continue
# 分解apk
# 分解apk
def __decode_apk__ ( self , file_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 ' ) % ( cores . apktool_file , str ( file_path ) , str ( output_path ) )
cmd_str = ( ' java -jar " %s " d -f " %s " -o " %s " --only-main-classe ' ) % (
logging . debug ( " [*] cmd {} " . format ( cmd_str ) )
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 )
else :
else :
logging . error ( " [x] 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 , output_path ) :
def __decode_dex__ ( self , file_path , backsmali_path , output_path ) :
cmd_str = ( ' java -jar " %s " d " %s " ' ) % ( cores . backsmali_file , str ( file_path ) )
cmd_str = ( ' java -jar " %s " d " %s " ' ) % ( str ( backsmali_path ) ,
logging . debug ( " [*] cmd {} " . format ( cmd_str ) )
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 :
logging . error ( " [x] 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 )
for file_name in file_names :
for file_name in file_names :
file_path = os . path . join ( output_path , file_name )
file_path = os . path . join ( output_path , file_name )
if not os . path . isdir ( file_path ) :
if not os . path . isdir ( file_path ) :
continue
continue
if " smali " in file_name or " assets " in file_name :
if " smali " in file_name or " assets " in file_name :
scanner_file_suffixs = [ " smali " , " js " , " xml " ]
scanner_file_suffixs = [ " smali " , " js " , " xml " ]
if cores . resource_flag :
if cores . resource_flag :
scanner_file_suffixs = [ " smali " ]
scanner_file_suffixs = [ " smali " ]
self . __get_scanner_file__ ( file_path , scanner_file_suffixs )
self . __get_scanner_file__ ( file_path , scanner_file_suffixs )
def __get_scanner_file__ ( self , scanner_dir , scanner_file_suffixs = [ " smali " ] ) :
def __get_scanner_file__ ( self , scanner_dir , scanner_file_suffixs = [ " smali " ] ) :
dir_or_files = os . listdir ( scanner_dir )
dir_or_files = os . listdir ( scanner_dir )
for dir_or_file in dir_or_files :
for dir_or_file in dir_or_files :
dir_file_path = os . path . join ( scanner_dir , dir_or_file )
dir_file_path = os . path . join ( scanner_dir , dir_or_file )
if os . path . isdir ( dir_file_path ) :
if os . path . isdir ( dir_file_path ) :
self . __get_scanner_file__ ( dir_file_path , scanner_file_suffixs )
self . __get_scanner_file__ ( dir_file_path , scanner_file_suffixs )
else :
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
continue
self . file_queue . put ( dir_file_path )
self . file_queue . put ( dir_file_path )
for component in config . filter_components :
for component in config . filter_components :
comp = component . replace ( " . " , " / " )
comp = component . replace ( " . " , " / " )
if ( comp in dir_file_path ) :
if ( comp in dir_file_path ) :
if ( component not in self . comp_list ) :
if ( component not in self . comp_list ) :
self . comp_list . append ( component )
self . comp_list . append ( component )
def __shell_test__ ( self , output ) :
def __shell_test__ ( self , output ) :
am_path = os . path . join ( output , " AndroidManifest.xml " )
am_path = os . path . join ( output , " AndroidManifest.xml " )
with open ( am_path , " r " , encoding = ' utf-8 ' , errors = ' ignore ' ) as f :
with open ( am_path , " r " , encoding = ' utf-8 ' , errors = ' ignore ' ) as f :
am_str = f . read ( )
am_str = f . read ( )
am_package = re . compile ( r ' <manifest.*package= \ " (.*?) \ " .* ' )
am_package = re . compile ( r ' <manifest.*package= \ " (.*?) \ " .* ' )
apackage = am_package . findall ( am_str )
apackage = am_package . findall ( am_str )
if len ( apackage ) > = 1 :
if len ( apackage ) > = 1 :
self . packagename = apackage [ 0 ]
self . packagename = apackage [ 0 ]
self . file_identifier . append ( apackage [ 0 ] )
self . file_identifier . append ( apackage [ 0 ] )
am_name = re . compile ( r ' <application.*android:name= \ " (.*?) \ " .*> ' )
am_name = re . compile ( r ' <application.*android:name= \ " (.*?) \ " .*> ' )
aname = am_name . findall ( am_str )
aname = am_name . findall ( am_str )
if aname and len ( aname ) > = 1 :
if aname and len ( aname ) > = 1 :
if aname [ 0 ] in config . shell_list :
if aname [ 0 ] in config . shell_list :
self . shell_flag = True
self . shell_flag = True
am_permission = re . compile ( r ' <uses-permission android:name= " (.*) " /> ' )
ampermissions = am_permission . findall ( am_str )
for ampermission in ampermissions :
if ampermission in config . apk_permissions :
self . permissions . append ( ampermission )