本帖最后由 watchdoge 于 2017-5-15 20:58 编辑
最近在看FrIDA,又看坛子里PJ头狼的帖子http://www.52pojie.cn/thread-559205-1-1.html,于是顺手用frida来试试,对于这题frida有个很大的优势,就是不会触发反调试,这样就节省了很多功夫。
先简单介绍下frida,frida是一款代码插桩工具,它可以向windows,macOS,Linux,iOS,Android等平台的原生应用中注射自定义的JavaScript代码片段,它的主要作用有:
- Access process memory
- Overwrite functions while the application is running
- Call functions from imported classes
- Find object instances on the heap and use them
- Hook, trace and intercept functions etc.
0x01 简单地绕过验证
如果只是想绕过验证的话,那么非常简单,通常思路是反编译成smali文件然后编辑这里的代码,然后重新打包签名,不过这里我们用frida也很容易实现,用下面的代码在java层hook住这个securityCheck函数,直接重新编写其逻辑:
[JavaScript] 纯文本查看 复制代码 send("Running Script");
Java.perform(function(){
MainActivity = Java.use("com.yaotong.crackme.MainActivity");
MainActivity.securityCheck.implementation = function(v){
send("securityCheck hooked");
return true;
}
});
0x02 获取密码
我们的主要目的当然还是获取到正确的密码,这个程序的具体情况不细说了,感兴趣的可以自己分析或者看头狼的那篇帖子,其验证逻辑如下:
最核心的就是将我们的输入与off_628c所指向的值做比较,而我们在这里用frida来获取程序运行时该处的值,frida提供了劫持native函数以及操作内存的一系列方法,首先我们需要通过导出函数表获取securityCheck这个函数的地址
[JavaScript] 纯文本查看 复制代码 var securityCheck = undefined;
exports = Module.enumerateExportsSync("libcrackme.so");
for(i=0; i<exports.length; i++){
if(exports[i].name == "Java_com_yaotong_crackme_MainActivity_securityCheck"){
securityCheck = exports[i].address;
send("securityCheck is at " + securityCheck);
break;
}
}
然后就是读取off_628C的值了,在ida的exports里可以看到该函数的偏移为0x11A8,因此可以通过函数当前地址减0x11A8再加0x628C,然后用Memory.readPointer获取该处所指向的地址,最后用Memory.readUtf8String读取最终的结果,所有的代码如下:
[Python] 纯文本查看 复制代码 #!/usr/bin/env python
# coding=utf-8
from __future__ import print_function
import frida,sys
native_hook_code = """
Java.perform(function(){
send("Running Script");
var securityCheck = undefined;
exports = Module.enumerateExportsSync("libcrackme.so");
for(i=0; i<exports.length; i++){
if(exports[i].name == "Java_com_yaotong_crackme_MainActivity_securityCheck"){
securityCheck = exports[i].address;
send("securityCheck is at " + securityCheck);
break;
}
}
Interceptor.attach(securityCheck,{
onEnter: function(args){
send("key is: " + Memory.readUtf8String(Memory.readPointer(securityCheck.sub(0x11a8).add(0x628c))));
}
});
});
"""
check_hook_code = """
send("Running Script");
Java.perform(function(){
MainActivity = Java.use("com.yaotong.crackme.MainActivity");
MainActivity.securityCheck.implementation = function(v){
send("securityCheck hooked");
return true;
}
});
"""
def on_message(message, data):
if message['type'] == 'send':
print(" {0}".format(message['payload']))
else:
print(message)
process = frida.get_device_manager().enumerate_devices()[-1].attach("com.yaotong.crackme")
script = process.create_script(native_hook_code)
script.on('message', on_message)
script.load()
sys.stdin.read()
结果如图:
|