scllqk 发表于 2024-10-25 22:54

渗透全加密App:三种实用方法之方法一

本帖最后由 scllqk 于 2024-10-25 23:48 编辑

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

!(https://imgsrc.baidu.com/forum/pic/item/94cad1c8a786c917042a9d1d8f3d70cf3bc757ed.jpg
)

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

!(https://imgsrc.baidu.com/forum/pic/item/7af40ad162d9f2d3b102ebcbefec8a136327cc80.jpg
)

### 方案一:使用hook框架去获取明文报文。
1.我们怎么办呢?还是和之前一样我们先上算法助手,打印一下加解密相关的堆栈情况。

!(https://imgsrc.baidu.com/forum/pic/item/d439b6003af33a87f466cf3e805c10385343b58f.jpg
)

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

!(https://imgsrc.baidu.com/forum/pic/item/024f78f0f736afc3c10bf041f519ebc4b745128b.jpg
)

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

```

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);

```

!(https://imgsrc.baidu.com/forum/pic/item/f636afc379310a55095911d0f14543a982261091.jpg
)

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

```

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脚本

```

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.脚本写完之后,我们就可以准备运行脚本看看效果了

!(https://imgsrc.baidu.com/forum/pic/item/8718367adab44aede13671c0f51c8701a18bfb9f.jpg
)

!(https://imgsrc.baidu.com/forum/pic/item/c75c10385343fbf2915a6907f67eca8065388fa4.jpg
)

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

yuth 发表于 2024-11-3 20:42

图片打不开了,不过呢,我百度一下标题,在隔壁某雪发现了同样的帖子,图片可以显示。发帖人ID一样,估计是帖主在某雪也发了一次。

xshadow 发表于 2024-10-28 11:42

厉害,把响应码code改成200或0是不是就能直接登录成功了?

Eapoul 发表于 2024-10-28 13:54

有技术含量的

Ly1988 发表于 2024-10-28 14:07

感谢分享

w759003376 发表于 2024-10-28 14:27

可以的,又学习到了,感谢大佬多多分享

HuskyHappy 发表于 2024-10-28 16:40

又学习到了,感谢大佬多多分享

Godjk 发表于 2024-10-28 18:08

学习了,感谢分享,学习思路
{:1_893:}

正己 发表于 2024-10-28 21:39

图片好像都炸了

xixicoco 发表于 2024-10-28 22:05

图片挂了的啊!!!!!

twl288 发表于 2024-10-29 00:08

向你学习,大佬
页: [1] 2 3
查看完整版本: 渗透全加密App:三种实用方法之方法一