本文主要是介绍Android破签:密钥native方法里了?不会C也看不懂IDA?用这个工具吧~,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
吉祥知识星球http://mp.weixin.qq.com/s?__biz=MzkwNjY1Mzc0Nw==&mid=2247485367&idx=1&sn=837891059c360ad60db7e9ac980a3321&chksm=c0e47eebf793f7fdb8fcd7eed8ce29160cf79ba303b59858ba3a6660c6dac536774afb2a6330&scene=21#wechat_redirect
《网安面试指南》http://mp.weixin.qq.com/s?__biz=MzkwNjY1Mzc0Nw==&mid=2247484339&idx=1&sn=356300f169de74e7a778b04bfbbbd0ab&chksm=c0e47aeff793f3f9a5f7abcfa57695e8944e52bca2de2c7a3eb1aecb3c1e6b9cb6abe509d51f&scene=21#wechat_redirect
最近在挖某APP时,想要尝试修改请求参数,但是发现这个APP对所有的请求都做了签名校验。那没办法,只能反编译APK看一下签名是怎么实现的了。
反编译不细说,无非就是dex2jar / jadx这些工具
反编译之后,在源码中根据签名请求头名称“Sign
”搜索来找到对应的代码,发现签名的方式比较常规,就是通过“appId + 参数 + 时间戳 + 随机数 + 请求体(如果有)”生成一个字符串,然后使用一个密钥对这个字符串进行HMACMD5,生成一个签名后,将它放在“Sign
”请求头里面一起传给服务端进行验证。
但是问题来了,其它的参数都好获取,但是它的密钥是通过一个Java的native方法获取的,像这样:
public native String a();
这就难搞了,这意味着密钥是通过调用C来生成的,而C动态库的反编译可比Java难搞多了,而我对C也实在说不上很熟悉。
不管怎么样,先试一下吧,先通代码找到对应的动态库名称,然后使用IDA反编译看了下,20分钟之后,我决定放弃了。我只想拿个密钥,并不想分析它的汇编代码(也没有这个能力),何况我也不是一个Android逆向工程师。
0x02
既然静态的分析不可行,那就只能换一种方式了,使用动态的分析来解决。作为一个Java应用程序是肯定可以Hook的,因为它原生就提供了这个功能。
而Frida则是一个Android的Hook工具,它可以通过简单的几行代码,来Hook应用中的某些方法,那我只需要Hook这个本地方法的上层方法,打印一下密钥就行了,这不比苦哈哈的去分析汇编简单多了?
安装
本机命令行工具安装使用pip只需要一行命令:
$ pip install frida-tools
Android Server则在Github下载对应版本的Server,使用adb推到手机/模拟器上再启动就行了:
$ adb root
$ adb push frida-server /data/local/tmp/
$ adb shell "chmod 755 /data/local/tmp/frida-server"
$ adb shell "/data/local/tmp/frida-server &"
这里就不细说了,看官方文档就行了,很详细:
https://frida.re/docs/android/
脚本
安装好了之后,就要写个Hook脚本了,它支持多种语言来实现,简单起见,使用JS吧,大概就是这样:
def on_message(message, data):
if message['type']=='send':
print("[*] {0}".format(message['payload']))
else:
print(message)jscode ="""Java.perform(() => {// hook 脚本// 找到我们需要hook的类const secret = Java.use('com.xxxx.xxxx.Secret');//对secret类的a方法提供一个新的实现secret.a.implementation = function () {//执行原来的方法 a()const result = this.a();//打印密钥console.log('key is: ', result);//返回return result;};
});
"""# 找到对应android应用的进程,可以使用 frida-ps -U 查看
process = frida.get_usb_device().attach(1001)
# 创建JS脚本
script = process.create_script(jscode)
script.on('message', on_message)
print('[*] Running')
# 加载脚本
script.load()
sys.stdin.read()
执行
执行上面的脚本,如果没有报错的话,那就是成功了,我们再回到应用中,触发一次HTTP请求,看到密钥已经被打印出来了:
知道密钥和签名方式之后,那就简单了,使用mimtproxy写个代理来自动对请求进行重新签名就行了,现在就可以愉快的随便修改参数啦~
这篇关于Android破签:密钥native方法里了?不会C也看不懂IDA?用这个工具吧~的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!