生成证书
keytool -genkey -keystore my-release-key.keystore -alias my_alias -keyalg RSA -keysize 4096 -validity 10000
签名
jarsigner -sigalg MD5withRSA -digestalg SHA1 -keystore my-release-key.keystore -signedjar com.yaotong_sign.apk com.yaotong.apk my_alias
frida
安装
在github
下载,github.com/frida/frida/releases
Frida api接口
frida.re/docs/javascript-api
然后
Frida使用
add push (解压后得到的文件,单文件,重命名为frida-server)frida-server /data/local/tmp
add shell
cd /data/local/tmp
chmod 777 frida-server
开启服务./frida-server
frida-ps -U
验证是否成功
adb forward tcp:27043 tcp:27043
adb forward tcp:27042 tcp:27042
python + Javascript
Python
代码是控制,写法固定,负责跟frida-server
通信,把JS
代码传递给fridaserver
Javascript
代码进行Hook
操作
5307端口占用解决
问题:adb server is out of date. killing...
1. netstat -ano | findstr "5037"
2. tasklist | findstr "10760"
3. taskkill /f /pid 10760
开发接口
import frida, sys
def on_message(message, data):
if message['type'] == 'send':
print("[*]{0}".format(message['payload']))
else:
print(message)
jscode = """
"""
process = frida.get_usb_device().attach('com.example.seccon2015.rock_paper_scissors')
script = process.create_script(jscode)
script.on('message', on_message)
print('[*] Running CTF')
script.load()
sys.stdin.read()
安卓运行原理
hook so库
Module
模块
Module.findExportByName(moduleName|null, exportName)
moduleName:lib名字
exportName:函数名字
返回exportName的地址
Module.findBaseAddress(moduleName)
moduleName:lib名字
返回lib的基地址
Process
模块
Process.findModuleByAddress(address)
address:lib的指针地址
返回一个Module对象
Momery
模块
Memory.readCString(pointer)
pointer:指针地址
把pointer还原成字符串
Memory.readUtf8String(pointer);
Memory.readAnsiString(pointer)
Interceptor
模块:监听
.attach(target, callbacks)
target:指针地址
callbacks:回调函数
onEnter
onLeave
常Hook
的系统so
库
libc.so
常调用的函数:
void * dlopen(const char *filename, int flag)加载动态链接库
如何Hook App
启动阶段的方法:
jscode= """
Java.perform(
function(){
var TestSig = Java.use('com.yaotong.crackme.MainActivity');
TestSig.onCreate.overload('android.os.Bundle').implementation = function(){
send('i am here')
return true;
}
}
)
"""
device = frida.get_usb_device()
# 先hook住
pid = device.spawn(['com.yaotong.crackme'])
process = device.attach(pid)
script = process.create_script(jscode)
script.on('message', on_message)
print('[*] Running CTF')
script.load()
# 然后重启
device.resume(pid)
sys.stdin.read()
Hook
打印堆栈信息
Hook
常见加密类
如何Hook
重载的方法
Hook SSL
Hook 常用安卓
//打印基地址
var base_address = Module.findBaseAddress('libc.so')
send('base_address:'+base_address)
//打印dlopen地址
var mod_address = Module.findExportByName('libc.so', 'dlopen');
send('mod_address:'+ mod_address);
//打印module地址
var lib_module = Process.findModuleByAddress(base_address);
send('lib_module_name:' + lib_module.name)
//监听
Interceptor.attach(mod_address, {
onEnter: function(args){
send("open(" + Memory.readUtf8String(args[0]) + "," + args[1] + ")")
},
onLeave:function(retval){
send("retval:" + retval)
}
})
function printstack(){
send(Java.use('android.util.Log').getStackTraceString(Java.use('java.lang.Exception').$new()))
}
function array2string(array){
//因为这里面的array是`byte`数组
var buffer = Java.array('byte', array)
var result = ""
for(var i=0;i<buffer.length;i++){
result += (String.fromCharCode(buffer[i]))
}
return result
}
Java.perform(
function(){
var MessageDigest = Java.use('java.security.MessageDigest');
//重载
MessageDigest.update.overload('[B').implementation = function(bytesarray){
send('i am here 0')
send('orig:' + array2string(bytesarray))
printstack()
this.update(bytesarray)
},
MessageDigest.update.overload('byte').implementation = function(bytesarray){
send('i am here 1')
send('orig:' + array2string(bytesarray))
printstack()
this.update(bytesarray)
},
MessageDigest.update.overload('java.nio.ByteBuffer').implementation = function(bytesarray){
send('i am here 2')
send('orig:' + array2string(bytesarray))
printstack()
this.update(bytesarray)
},
MessageDigest.update.overload('[B', 'int', 'int').implementation = function(bytesarray){
send('i am here 3')
send('orig:' + array2string(bytesarray))
printstack()
this.update(bytesarray)
},
MessageDigest.getInstance.overloads[0].implementation = function(algorithm){
send('i am here 4');
send('call ->getInstance for:' + algorithm)
return this.getInstance.overloads[0].apply(this, arguments)
}
}
)
this.update(bytesarray)
是调用程序中本来的update
方法,让程序继续执行。
Frida hook JAVA api
访问成员变量
this.成员变量名.value
hook匿名类写法:
Java.use('类$类') smali文件里找
从匿名类/内部类访问外部类的属性写法:
this.this$0.value.外部类的属性名.value
先解包,
从smali包里找这个路径
下面的是外部类,上面带的是匿名内部类,可以用文本编辑器打开,然后发现只有带的才有匿名内部类的方法
var mainClass = Java.use('com.example.seccon2015.rock_paper_scissors.MainActivity$1')
mainClass.run.implementation = function(){
}
hook静态方法
类.方法()
var ee = Java.use("com.pp.asss")
console.log(ee.a(5))
hook成员方法
必须new
var se = Java.use("java.security.SecureRandom").$new()
var sb = Java.use("java.lang.StringBuffer").$new()
新建一个对象 new
这块markdown显示有问题,是有个英文的dollar符号new
类.方法名.$new(参数)
重载写法
类.方法名.overload(arg1,arg2.......).implementation
hook 构造方法
类.$init().implementation
类型转换
var Map = Java.use(‘java.util.Map’)
var NewP = Java.cast(P, Map)
把P 转成 Map类型
方法一:
1.先确认object是什么类型(比如要打印p) 先console.log(p.$className) 查看p是什么
数据类型
2.Java.cast 把p强转为对应类型
3.调用该类对应的输出方法。通常有一个toString()方法
方法二:
使用js里的JSON类
尝试 console.log(JSON.stringify(p))
可能打印不出来字符串,一般能打印出p的字节数组。(可以用着你的数据和真实数
据的对比)
bytes array 是object
String 和 bytes array可以相互转化
String.getBytes() 字符串转bytes array
new String(bytes) bytes转成字符串。PS:本身如果是不可打印字符串,打印是乱码
1 条评论
smart contract auditor · 2023-04-22 17:16
I was astonished Ƅү their knowledge off the subject.
评论已关闭。