当前位置:
首页 > temp > python入门教程 >
-
逆向工具脚本:命令行使用轮子
前言
轮子脚本,本质为使用subprocess替代大量无谓的交互command,内部方法自由扩展
呃我是有用AndroidKiller,但耐不住常用到adb自定义的臭长命令,例如经常取httpcanary的hcy回本地分析
代码
remarks
- 需要事先吧aapt,apktool加至环境变量
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)
其他
-
相关地址
- jadx
- apktool
- widora的github代下服务
- 签名证书可通过以下命令生成
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
………………
结
欢迎交流赐教
__EOF__
本文作者:JsonEri
本文链接:https://www.cnblogs.com/jsoneri/p/13814847.html
本文链接:https://www.cnblogs.com/jsoneri/p/13814847.html
最新更新
nodejs爬虫
Python正则表达式完全指南
爬取豆瓣Top250图书数据
shp 地图文件批量添加字段
爬虫小试牛刀(爬取学校通知公告)
【python基础】函数-初识函数
【python基础】函数-返回值
HTTP请求:requests模块基础使用必知必会
Python初学者友好丨详解参数传递类型
如何有效管理爬虫流量?
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
SQL Server -- 解决存储过程传入参数作为s
关于JS定时器的整理
JS中使用Promise.all控制所有的异步请求都完
js中字符串的方法
import-local执行流程与node模块路径解析流程
检测数据类型的四种方法
js中数组的方法,32种方法
前端操作方法
数据类型
window.localStorage.setItem 和 localStorage.setIte
如何完美解决前端数字计算精度丢失与数