上一篇是web端的ProtoBuf逆向,这篇就找了个app的ProtoBuf看看练练手
目标app:aHR0cHM6Ly93d3cud2FuZG91amlhLmNvbS9hcHBzLzc0NTAxNjM=
抓包分析
随便搜索一个线路点进去,看到请求头和响应都是加密的
用jadx分析下请求头的加密参数request
记住这里其他两个函数,有”/protoc.Request.Sequence”,还引用了proto的包
到这可以知道request的值是经过native函数加密后再由base64得到的。
用ida打开native so文件,定位encode2函数
!
可以看到是用了aes_cbc_128加密,那就是需要拿到密钥和iv
直接frida hook这两个函数
1 | function main(){ |
结果
1 | 入参: 0a270a182f70726f746f632e526571756573742e53657175656e6365120b080112053930e8b7af1801 |
明文,密文有了
iv和密钥就在这几个之间,两两组合试一试
1 | 2f d3 02 8e 14 a4 5d 1f 8b 6e b0 b2 ad b7 ca af |
所以这个aes是标准的算法,没经过魔改的,再把加密后的结果base64一下就是请求的参数了,过程算法知道了,那参数来源呢,是怎么得到的
使用proto
上面说了用了proto的包,看里面的函数过程,明文是经过了proto协议的才到aes加密
那就0a270a182f70726f746f632e526571756573742e53657175656e6365120b080112053930e8b7af1801转成二进制写进文件,再用proto解码器解码看看
1 | import binascii |
1 | protoc --decode_raw < req.bin |
解码后得到
1 | 1 { |
果不其然,那接下来如何模拟发请求呢
经过上一篇后,现在很快就能编写proto文件了
1 | syntax = "proto3"; |
编译成python版本
1 | protoc --python_out=. ./req.proto |
目录下生成了req_pb2.py 拖入项目中,需要使用时就调用即可
1 | import binascii |
运行后生成my_req.bin文件,跟原来的对比一下
发送请求
1 | import binascii |
运行后响应内容跟抓包的一样是加密的,用aes尝试解密
解完后很像protobuf格式,写进bin文件,再用proto解码看看
1 | decry_data = aes_decry(response.content) |
1 | D:\pythonProject\xxxx>protoc --decode_raw < resp.bin |
编写proto文件并编译
1 | syntax = "proto3"; // 定义proto的版本 |
完整代码
1 | import binascii |
使用blackboxprotobuf
还有一种更快的方式,使用blackboxprotobuf
读取请求的二进制文件,通过blackboxprotobuf转为json,直接把关键词修改掉再转回去
像响应内容的key只是一个符号,可以通过value大概知道它的含义就行了
1 | import blackboxprotobuf |