首页
社区
课程
招聘
[原创] 渗透全加密App:三种实用方法之方案一
发表于: 2024-10-25 22:58 3783

[原创] 渗透全加密App:三种实用方法之方案一

2024-10-25 22:58
3783

渗透全加密App:三种实用方法解析

渗透全加密App:三种实用方法解析

1.今天我们对报文加密的app进行分析,请出我们的第一个app案例

image

2.我们先抓包看一下,抓到的包是什么样的,可以看到抓包出来,已经做了报文全加密,无法进行测试。

image

方案一:使用hook框架去获取明文报文。

1.我们怎么办呢?还是和之前一样我们先上算法助手,打印一下加解密相关的堆栈情况。

image

2.我们看到了里面有http相关的,去看一下反编译后的相关代码

image

3.这里我们对这里进行hook,不会安装frida的,去看入门教程:https://blog.csdn.net/qq_1290259791/article/details/100381831

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function main() {
  Java.perform(function () {
    let RequestUtil = Java.use("com.xxxxxx.xxxxx.http.RequestUtil");
    RequestUtil["paraMap"].overload('java.util.Map', 'java.lang.String', 'java.lang.String').implementation = function (addMap, append, sign) {
      console.log(`RequestUtil.paraMap is called: addMap=${addMap}, append=${append}, sign=${sign}`);
      let result = this["paraMap"](addMap, append, sign);
      console.log(`RequestUtil.paraMap result=${result}`);
      return result;
    };
 
    RequestUtil["decodeDesJson"].implementation = function (json, desKey, desIV) {
      console.log(`RequestUtil.decodeDesJson is called: json=${json}, desKey=${desKey}, desIV=${desIV}`);
      let result = this["decodeDesJson"](json, desKey, desIV);
      console.log(`RequestUtil.decodeDesJson result=${result}`);
      return result;
    };
 
  });
}
 
setTimeout(main, 500);

image

4.经过hook,发现我们hook到了明文,RequestUtil.paraMap里的result里是请求体内容,RequestUtil.decodeDesJson里的result里是响应体内容,就是我们需要的,接下来我们要写一个简单的hook脚本,把我们需要的内容发送到burp上,实现篡改明文请求及响应。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
Java.perform(function () {
 
  // 获取并拦截类 "com.xxxxxx.xxxxx.http.RequestUtil"
  let RequestUtil = Java.use("com.xxxxxx.xxxxx.http.RequestUtil");
 
  // Hook RequestUtil 类中的 "paraMap" 方法,该方法有三个参数:'java.util.Map''java.lang.String' 'java.lang.String'
  RequestUtil["paraMap"].overload('java.util.Map', 'java.lang.String', 'java.lang.String').implementation = function (addMap, append, sign) {
 
    // 打印 paraMap 方法调用时的输入参数
    console.log(`RequestUtil.paraMap is called: addMap=${addMap}, append=${append}, sign=${sign}`);
 
    // 调用原始的 paraMap 方法并保存返回结果
    let result = this["paraMap"](addMap, append, sign);
 
    // 打印原始方法返回的结果
    console.log(`RequestUtil.paraMap result=${result}`);
    console.log("data" + result);
 
    // 将结果转换为字符串形式
    let data = result.toString();
 
    // 将请求体数据发送给 Frida 客户端,以便进一步分析
    let sendData = {"TAG": "Request", "RequestBody": data}
    send(sendData);
 
    // 定义一个空对象,用于存储修改后的请求体
    let reqModify = {}
 
    // 接收来自 Frida 客户端的修改请求体并等待该操作完成
    recv(function (reqObj) {
      reqModify.reqModfyStr = reqObj.modify_requestBody; // 获取修改后的请求体
    }).wait();
 
    // 返回修改后的请求体
    return reqModify.reqModfyStr;
  };
 
  // Hook RequestUtil 类中的 "decodeDesJson" 方法,拦截该方法的输入和输出
  RequestUtil["decodeDesJson"].implementation = function (json, desKey, desIV) {
 
    // 打印 decodeDesJson 方法调用时的输入参数
    console.log(`RequestUtil.decodeDesJson is called: json=${json}, desKey=${desKey}, desIV=${desIV}`);
 
    // 调用原始的 decodeDesJson 方法并保存返回结果
    let result = this["decodeDesJson"](json, desKey, desIV);
 
    // 打印原始方法返回的结果
    console.log(`RequestUtil.decodeDesJson result=${result}`);
 
    // 将解密后的响应体数据发送给 Frida 客户端
    let data = result;
    let sendData = {"TAG": "Response", 'ResponseBody': data};
    send(sendData);
 
    // 定义一个空对象,用于存储修改后的响应体
    let respModify = {}
 
    // 接收来自 Frida 客户端的修改响应体并等待该操作完成
    recv(function (respObj) {
      respModify.respModfyStr = respObj.modify_responseBody; // 获取修改后的响应体
    }).wait();
 
    // 返回修改后的响应体
    return respModify.respModfyStr;
  };
 
});

5.上面的代码主要是js相关的代码,若想正常使用,还要写一个用于frida rpc的python脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import argparse
import urllib
from urllib.parse import quote, unquote
from threading import Thread
from http.server import HTTPServer, BaseHTTPRequestHandler
import sys
import requests
import frida
import re
 
# 定义一个继承自BaseHTTPRequestHandler的请求处理类
class RequestHandler(BaseHTTPRequestHandler):
 
    # 处理请求方法
    def do_REQUEST(self):
        content_length = int(self.headers.get('content-length', 0))  # 获取请求体长度
        self.send_response(200# 设置响应状态码为200
        self.send_header('Content_Length', str(content_length))  # 添加响应头
        self.send_header('X-Mirror-Server', 'True')
        self.send_header('TMF_apiName', self.headers.get('TMF_apiName'))  # 获取并设置请求中的TMF_apiName头
        self.end_headers()  # 结束头部设置
        self.wfile.write(self.rfile.read(content_length))  # 将请求体数据作为响应体返回
 
    # 处理响应方法
    def do_RESPONSE(self):
        content_length = int(self.headers.get('content-length', 0))  # 获取响应体长度
        self.send_response(200# 设置响应状态码为200
        self.send_header('Content_Length', str(content_length))  # 添加响应头
        self.send_header('X-Mirror-Server', 'True')
        self.end_headers()  # 结束头部设置
        self.wfile.write(self.rfile.read(content_length))  # 将响应体数据返回给客户端
 
# 启动回显服务器
def echo_server_thread():
    print('start echo server at port {}'.format(28080))
    server = HTTPServer(('', 28080), RequestHandler)
    server.serve_forever()  # 永久运行服务器
 
# 使用线程启动镜像服务器
t = Thread(target=echo_server_thread)
t.daemon = True  # 设置为守护线程
t.start()
 
proxies = {'http': 'http://127.0.0.1:8080'# 设置代理
 
# 处理 Frida 中发送的数据
def on_message(message, data):
    if message['type'] == 'send'# 处理从 JS 发送来的数据
        payload = message['payload']
        TAG = payload['TAG']
 
        # 处理请求数据
        if TAG == 'Request':
            RequestBody = unquote(payload["RequestBody"])  # 解码请求体
            requestHeaders = {'X-Turbo_Intruder': 's'# 设置请求头
            requestURL = "http://127.0.0.1:28080/Request/"  # 发送到镜像服务器的URL
            request = requests.request("REQUEST", requestURL, proxies=proxies, headers=requestHeaders, data=RequestBody.encode("utf-8"))  # 发送请求
            request.encoding = 'utf-8'  # 设置编码
            script.post({"modify_requestBody": request.text})  # 将修改后的请求体发送给JS
 
        # 处理响应数据
        elif TAG == 'Response':
            ResponseBody = payload["ResponseBody"# 获取响应体
            responseURL = "http://127.0.0.1:28080/Response"  # 发送到镜像服务器的URL
            response = requests.request("RESPONSE", responseURL, proxies=proxies, data=ResponseBody.encode('utf-8'))  # 发送响应
            script.post({"modify_responseBody": response.text})  # 将修改后的响应体发送给JS
    else:
        print("error", message)  # 错误处理
 
# 连接到远程设备并附加到进程
process = frida.get_device_manager().add_remote_device('127.0.0.1:26666').attach('中文包名')
 
# 读取并加载JS脚本
with open("dodonew.js", "r", encoding='utf-8') as f:
    js_code = f.read()
script = process.create_script(js_code)
 
# 监听来自JS的消息
script.on('message', on_message)
script.load()  # 加载脚本
sys.stdin.read()  # 保持主线程运行

6.脚本写完之后,我们就可以准备运行脚本看看效果了

image

image

7.这样我们基本上实现了报文的hook解密


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2024-10-25 23:45 被scllqk编辑 ,原因:
收藏
免费 1
支持
分享
最新回复 (2)
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
算法助手应该是可以直接hook到加密算法的
2024-10-27 15:04
0
雪    币: 8175
活跃值: (6399)
能力值: ( LV12,RANK:207 )
在线值:
发帖
回帖
粉丝
3
2024-11-8 14:51
0
游客
登录 | 注册 方可回帖
返回
//