autoDecoder
-
Burp插件,根据自定义来达到对数据包的处理(适用于加解密、爆破等),类似mitmproxy,不同点在于经过了burp中转,在自动加解密的基础上,不影响APP、网站加解密正常逻辑等。
官方地址:https://github.com/f0ng/autoDecoder
个人理解:在安卓app请求整体被加密了以后用这个很方便下面例子说明
对测试app进行分析
- 使用jadx进行反编看看这个apk
- 使用查看工具看看
- 安装app到手机并且进行抓包 找个可用的手机号验证码注册然后设置密码用账号密码登陆这个app。我已经注册并且设置把密码设置好了。你们自行设置。由于这个app处于运行状态涉及到敏感的地方直接打码如果后续你们遇到的话可以尝试一下。这次测试在于掌握autodecoder插件的使用其他东西我直接略过将讲解一下。想要了解详细的步骤过程后续会在飞机内部群里面讲解如果有人对博客发布文章想要详细步骤什么的。废话不多说开始抓包了。
从上面看不出这个app是什么加固一看是MyApplication 肯定是加固过的
通过抓包可以看到数据加密传输。一开始想用frida自吐算法搞一波说干就干。启动frida server。
Traceback (most recent call last):
File "D:\python3\lib\threading.py", line 932, in _bootstrap_inner
self.run()
File "D:\python3\lib\threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
File "D:\python3\lib\site-packages\frida_tools\application.py", line 796, in _run
work()
File "D:\python3\lib\site-packages\frida_tools\application.py", line 394, in _try_start
self._start()
File "D:\python3\lib\site-packages\frida_tools\repl.py", line 139, in _start
self._set_autoperform(self._autoperform_option)
File "D:\python3\lib\site-packages\frida_tools\repl.py", line 472, in _set_autoperform
if self._is_java_available():
File "D:\python3\lib\site-packages\frida_tools\repl.py", line 479, in _is_java_available
script = self._session.create_script(name="java_check", source="rpc.exports.javaAvailable = () => Java.available;", runtime=self._runtime)
File "D:\python3\lib\site-packages\frida\core.py", line 26, in wrapper
return f(*args, **kwargs)
File "D:\python3\lib\site-packages\frida\core.py", line 262, in create_script
return Script(self._impl.create_script(*args, **kwargs))
frida.TransportError: the connection is closed
我们看sapwn的方式 使用命令frida-ps -Ua 查看包名画红线框的这个就是
接下来使用包名启动firda 直接等一会进程就退出了。猜测此肯定检测了frida。并且可能在so层检测。所以我们就要干掉frida检测使用葫芦娃大佬修改版的frida。减少了frida特征但是还是会被检测。思考检测肯定在某个so文件里面的某些个函数进行检测。所以我们通过这个思路可以bypass 对frida的检测干掉检测函数即可。猜测检测可能是网易易盾对frida的检测。本身app代码检测的概率很少。
编写frida bypass脚本对抗frida检测
- 由于网络某些地方都没有公开放出来检测代码这里仅仅演示bypass效果
使用自吐算法脚本定位算法细节
-
随便输入一个不存在的手机号显示账号不存在我们配合包就行查找
放出堆栈信息java.lang.Throwable at javax.crypto.Cipher.doFinal(Native Method) at com.xxxxx.utils.SecurityUtil.aesEncrypt(SecurityUtil.java:3) at com.xxxxx.l.d.getBody(KnowAsynHttpRequestDefEncrypt.java:1) at com.android.volley.toolbox.HurlStack.addBodyIfExists(HurlStack.java:1) at com.android.volley.toolbox.HurlStack.setConnectionParametersForRequest(HurlStack.java:12) at com.android.volley.toolbox.HurlStack.executeRequest(HurlStack.java:12) at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:4) at com.android.volley.NetworkDispatcher.processRequest(NetworkDispatcher.java:11) at com.android.volley.NetworkDispatcher.processRequest(NetworkDispatcher.java:2) at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:2)
直接定位算法aes 算法 AES/ECB/PKCS5Padding 秘钥和key都吐出来了解密一波看看我们
因为app是有加固的所以我们还是使用脱壳工具进行脱壳这里使用frida-dexdump 测试了一下blackdex貌似脱不全。总之两个工具交替使用吧
发现者str2是个字符串那么我们查调用这个加密的
看看n0.b可能就是秘钥点一下
接下来这个引用所有的用frida hook一遍看登陆调用了哪些函数。确定以后一级一级的判断。这里我就不用这个hook通杀算法定位了来一个新的既然是 请求和响应都是base64那么他肯定要把字符串转换成字节所以。我们可以hook转换成字节的方法
字节定位分析app请求框架
- 定位效果不错
-
java.lang.Throwable at java.lang.String.Bytes(Native Method) at com.networkbench.agent.impl.util.j.a(SourceFile:33) at com.networkbench.agent.impl.instrumentation.NBSTransactionStateUtil.setCrossProcessHeader(SourceFile:7) at com.networkbench.agent.impl.instrumentation.NBSHttpsURLConnectionExtension.<init>(SourceFile:8) at com.networkbench.agent.impl.instrumentation.NBSInstrumentation.openConnection(SourceFile:4) at com.android.volley.toolbox.HurlStack.createConnection(HurlStack.java:1) at com.android.volley.toolbox.HurlStack.openConnection(HurlStack.java:1) at com.android.volley.toolbox.HurlStack.executeRequest(HurlStack.java:9) at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:4) at com.android.volley.NetworkDispatcher.processRequest(NetworkDispatcher.java:11) at com.android.volley.NetworkDispatcher.processRequest(NetworkDispatcher.java:2) at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:2) java.lang.Throwable at java.lang.String.Bytes(Native Method) at xxxxx.utils.SecurityUtil.aesEncrypt(SecurityUtil.java:2) at xxxxx.l.d.getBody(KnowAsynHttpRequestDefEncrypt.java:1) at com.android.volley.toolbox.HurlStack.addBodyIfExists(HurlStack.java:1) at com.android.volley.toolbox.HurlStack.setConnectionParametersForRequest(HurlStack.java:12) at com.android.volley.toolbox.HurlStack.executeRequest(HurlStack.java:12) at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:4) at com.android.volley.NetworkDispatcher.processRequest(NetworkDispatcher.java:11) at com.android.volley.NetworkDispatcher.processRequest(NetworkDispatcher.java:2) at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:2) java.lang.Throwable at java.lang.String.Bytes(Native Method) at xxxxx.utils.SecurityUtil.aesEncrypt(SecurityUtil.java:3) at xxxxx.l.d.getBody(KnowAsynHttpRequestDefEncrypt.java:1) at com.android.volley.toolbox.HurlStack.addBodyIfExists(HurlStack.java:1) at com.android.volley.toolbox.HurlStack.setConnectionParametersForRequest(HurlStack.java:12) at com.android.volley.toolbox.HurlStack.executeRequest(HurlStack.java:12) at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:4) at com.android.volley.NetworkDispatcher.processRequest(NetworkDispatcher.java:11) at com.android.volley.NetworkDispatcher.processRequest(NetworkDispatcher.java:2) at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:2) java.lang.Throwable at java.lang.String.Bytes(Native Method) at xxxxx.utils.SecurityUtil.aesDecrypt(SecurityUtil.java:2) at xxxxx.utils.SecurityUtil.aesDecrypt(Native Method) at xxxxx.l.d.parseNetworkResponse(KnowAsynHttpRequestDefEncrypt.java:1) at com.android.volley.NetworkDispatcher.processRequest(NetworkDispatcher.java:17) at com.android.volley.NetworkDispatcher.processRequest(NetworkDispatcher.java:2) at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:2)
我们发现了一堆com.android.volley.toolbox 名字猜测有可能是发包用的 百度搜索一下
随便搜索一个看看内置框架没办法看源码于是看看包有什么特点发现这里Port=PhoneLogin&CheckCode=0000000000;6.08.2.0;android;0;0 不变搜索一波
随便点一个函数。看到super 一看继承StringRequest点一下看看发现点不动。看看这包名。import com.android.volley.toolbox.StringRequest;
百度一下import com.android.volley.toolbox.StringRequest; 如何发包不就行了https://blog.csdn.net/nuli888/article/details/52169679
* @param path 请求路径
* @param map 请求参数
* @param entity 需要解析的类
* @return
*/
public void StringRequest_POST(final Handler handler, String path, final Map<String, String> map, final Object entity) {
* get请求
*
* @param path 请求路径
* @param entity 需要解析的类
* @return
*/
public void StringRequest_GET(final Handler handler, String path, final Object entity)
调用
StringRequest request_post = new StringRequest(Request.Method.POST,
path, succes, error) {
可以看出第二个参数是请求url ,如果是post第三个是参数的key 和value
编写frida hook脚本
- frida编写脚本提示信息
Error: StringRequest(): has more than one overload, use .overload(<signature>) to choose from:
.overload('java.lang.String', 'com.android.volley.Response$Listener', 'com.android.volley.Response$ErrorListener')
.overload('int', 'java.lang.String', 'com.android.volley.Response$Listener', 'com.android.volley.Response$ErrorListener')
at X (frida/node_modules/frida-java-bridge/lib/class-factory.js:563)
at K (frida/node_modules/frida-java-bridge/lib/class-factory.js:558)
at set (frida/node_modules/frida-java-bridge/lib/class-factory.js:926)
at <anonymous> (/stringRequest.js:5)
at <anonymous> (frida/node_modules/frida-java-bridge/lib/vm.js:12)
at _performPendingVmOps (frida/node_modules/frida-java-bridge/index.js:238)
at <anonymous> (frida/node_modules/frida-java-bridge/index.js:213)
at <anonymous> (frida/node_modules/frida-java-bridge/lib/vm.js:12)
at _performPendingVmOpsWhenReady (frida/node_modules/frida-java-bridge/index.js:232)
at perform (frida/node_modules/frida-java-bridge/index.js:192)
at <eval> (/stringRequest.js:14)
看这个比较像 ‘int’, ‘java.lang.String hook一下 这样我们可以获取到任意url,至于请求数据的话直接获取密钥解密就完事了。
搜索一下解密的内容直接定位
这会儿请求的url有了返回的直接hook aes解密算法就行了。
使用脚本分析登陆以后的操作
-
下图显示登陆成功了返回的数据。
- 看个登陆以后返回什么在看个人信息那里明文请求是什么 登陆画红框的memberid就是登陆者的id好 portpassword 是动态aes的秘钥
在看个人信息那分析包以后用hook方式发现用的是AES/ECB/PKCS5Padding 采用的动态秘钥方式 登陆成功以后给你一个动态key。所有请求用这个key进行加密响应也是用这个进行解密。
配置bp插件autodecoder测试
Charles 转发请求到bp,直接修改id就可以获取到铭感信息
手机号信息,至此此app只要绑定手机号只要知道对方id号就可以获取手机号码
总结
此app采用的动态秘钥方式 登陆成功以后给你一个动态key。AES/ECB/PKCS5Padding 所有请求用这个key进行加密响应也是用这个进行解密。关注频道后续还会带来精彩的实战内容。和小姐姐聊天不给手机号怎么办搞他(前提是有漏洞哈哈哈)