逆向工具腳本:命令行使用輪子
前言
輪子腳本,本質為使用subprocess替代大量無謂的交互command,內部方法自由擴展
呃我是有用AndroidKiller,但耐不住常用到adb自定義的臭長命令,例如經常取httpcanary的hcy回本地分析
代碼
usage
-
通常
-
路徑為apk絕對地址,則解包
-
路徑為目錄地址,則嘗試打包
-
-
自定義
- 自定義方法與參數
Usage: python dece.py [-i INSTALL] [-e EXTRA] path
Integrate decompile related complicated command.
Arguments:
path program/apk path | special use "/"
-i INSTALL, --install INSTALL
adb remote install apk
-e EXTRA, --extra EXTRA
use inner func individually, |adb_install(apk_path)
|get_info(apk_path) |jadx(*args) |as_debug
Examples:
dece.py D:\\com.android.unpack_catalog -i true
dece.py / -e func++args1++args2 (params split with ++)
Source code
dece.py(cmd等實際輪子路徑填自己的)
#!/usr/bin/python
__author__ = "jsoneri"
__version__ = "1.0"
import time
import os
import re
import chardet
import shutil
import argparse
import subprocess
from loguru import logger
keystore = r'D:\xxxxx\my-release-key.keystore' # 簽名證書
nickname = 'my_alias' # 簽名證書別稱
keypwd = b'123456' # 簽名證書密碼
device = "FA68H0XXXXXX" # 手機設備號 模擬器則IP端口
cmd = {
'aapt': r'D:\xxxxx\aapt', # 看包信息,與get_info關聯
'apktool': r'D:\xxxxx\apktool.bat',
'jadx': r'D:\xxxxx\bin\jadx-gui.bat'
}
bash = {
'aapt': r'/mnt/d/xxxxx/aapt',
'apktool': r'java -jar -Duser.language=en -Dfile.encoding=UTF8 /mnt/d/xxxxx/apktool.jar',
'jadx': ValueError('在WSL上開gui需要vncsever,xhost等操作較麻煩,本人自禁用') #
}
class DeceUtils:
def packapk(self, path, apk): # 回編譯
command = f'{cmd["apktool"]} b {path}'
subprocess.run(command.split(' '))
return self.signing(path, apk)
def unpack(self, path): # 反編譯
command = f"{cmd['apktool']} d -f {path}"
subprocess.run(command.split(' '))
def jadx(self, *args):
ori = f"{cmd['jadx']}"
if args:
for arg in args:
ori += f' {arg}'
subprocess.run(ori)
@logger.catch
def adb_install(self, apk_path):
subprocess.run(f'adb -s {device} install {apk_path}', stdout=subprocess.PIPE)
logger.debug('-*- apk installation running -*- ')
@logger.catch
def signing(self, path, apk):
"""一般簽名是在打包時才用的,,所以綁定為pack後使用,通常非單獨用"""
dist = f'{path}\\dist'
name = apk.replace('.apk', '')
keyname = keystore.split('\\')[-1]
shutil.copy(keystore, dist)
command = f'jarsigner -verbose -keystore {keyname} -signedjar {name}_signed.apk {apk} {nickname}'
obj = subprocess.Popen(command, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, cwd=dist)
obj.communicate(keypwd)
obj.terminate()
obj.kill()
logger.debug('-*- apk signed -*- ')
return f'{name}_signed.apk'
@logger.catch
def as_debug(self):
"""設備當前窗口進程轉發端口給AS的5005調用"""
command = 'adb shell dumpsys activity activities|grep Resumed'
infos = subprocess.run(command, stdout=subprocess.PIPE)
r = re.search(r'u0 ([\w.]+)/[\w.]+ ', infos.stdout.decode(chardet.detect(infos.stdout)['encoding'])).group(1)
infos = subprocess.run(f'adb shell ps | grep {r}', stdout=subprocess.PIPE)
r = re.search(r' (\d+) ', infos.stdout.decode(chardet.detect(infos.stdout)['encoding'])).group(1)
subprocess.run(f'adb forward tcp:5005 jdwp:{r}', stdout=subprocess.PIPE)
def get_info(self, apk_path):
try:
command2 = f'{cmd["aapt"]} dump badging '
infos = subprocess.run(command2 +apk_path, shell=True, stdout=subprocess.PIPE)
# infos.stdout.decode(_code)
return infos.stdout.decode(chardet.detect(infos.stdout)['encoding'])
except Exception as e:
logger.error(f"occur exception: {str(type(e))}:: {str(e)}")
@staticmethod
def get_apk(path):
if '.apk' in os.path.split(path)[-1]:
logger.info(f'輸入為apk絕對地址,準備解包')
return 'unpack', ''
else:
name = path.split("\\")[-1]
dist = f'{path}\\dist'
apk = f'{name}.apk'
if not os.path.exists(f'{dist}\\{apk}'):
logger.info(f'輸入為目錄且未發現打包痕迹,準備打包此目錄')
return 'pack', apk
else:
logger.info(f'輸入為目錄但發現有打包痕迹,請檢查/刪除再操作')
os.startfile(dist)
return '', ''
def main(self, path, install_flag=False):
flag, apk = self.get_apk(path)
if flag == 'unpack':
self.unpack(path)
elif flag == 'pack':
apk = self.packapk(path, apk)
self.adb_install(f'{path}\\dist\\{apk}') if install_flag else None
info = self.get_info(f'{path}\\dist\\{apk}')
package = re.search(r'package: name=\'(com\.[\w.]+)\'', info).group(1)
mainActivity = re.search(r'activity name=\'(com\.[\w.]+)\'', info).group(1)
print(f'>>> {apk} infos: ↓↓ \npackage: [{package}], mainActivity: [{mainActivity}]')
if __name__ == '__main__':
class ArgParser(argparse.ArgumentParser):
def error(self, message):
print(f"DecompileUtils v{__version__}\nby {__author__}\n\nError: {message}\n")
print(self.format_help().replace("usage:", "Usage:"))
self.exit(0)
parser = ArgParser(
add_help=False,
description="Integrate decompile related complicated command.",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=r"""
Examples:
%(prog)s D:\\com.android.unpack_catalog -i true
%(prog)s / -e func++args1++args2 (params split with ++)
""")
if os.name == 'posix':
cmd = bash
args = parser.add_argument_group("Arguments")
args.add_argument('path', help='program/apk path | special use "/"')
args.add_argument('-i', '--install', type=bool, default=False, help='adb remote install apk')
args.add_argument('-e', '--extra', type=str, required=False, help=r'use inner func individually, '
r'|adb_install(apk_path) |get_info(apk_path) |jadx(*args) |as_debug')
parsed = parser.parse_args()
if parsed.extra:
_args = parsed.extra.split('++')
logger.debug(f'>> extra >> {_args}')
ret = getattr(DeceUtils(), _args[0])(*_args[1:])
print(ret) if ret else None
time.sleep(0.05)
logger.debug(f'func【 {_args[0]} 】 end')
else:
DeceUtils().main(parsed.path, parsed.install)
其他
- 相關地址
- 簽名證書可通過以下命令生成
chcp 936
keytool -genkey -keystore my-release-key.keystore -alias my_alias -keyalg RSA -keysize 4096 -validity 10000
# my-release-key.keystore -> 證書文件名 // my_alias -> 證書別名
# 以下是交互,口令是密碼,其他隨便填,確認y
輸入密鑰庫口令:
再次輸入新口令:
您的名字與姓氏是什麼?
[Unknown]: qw
您的組織單位名稱是什麼?
[Unknown]: qw
您的組織名稱是什麼?
[Unknown]: qw
您所在的城市或區域名稱是什麼?
[Unknown]: qw
您所在的省/市/自治區名稱是什麼?
[Unknown]: qw
該單位的雙字母國家/地區代碼是什麼?
[Unknown]: qw
CN=qw, OU=qw, O=qw, L=qw, ST=qw, C=qw是否正確?
[否]: y
輸入 <my_alias> 的密鑰口令
(如果和密鑰庫口令相同, 按回車):
再次輸入新口令:
Warning:
JKS 密鑰庫使用專用格式。建議使用 "keytool -importkeystore -srckeystore my-release-key.keystore -destkeystore my-release-key.keystore -deststoretype pkcs12" 遷移到行業標準格式 PKCS12。
keytool -importkeystore -srckeystore my-release-key.keystore -destkeystore my-release-key.keystore -deststoretype pkcs12
………………
結
如若對你有用請點個贊給點動力; 代碼並不完美,若有更優的方案還請交流賜教


