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

查看 27|回复 4
作者:scllqk   
1.今天我们对报文加密的app进行分析,请出我们的第一个app案例
[img][/img]
2.我们先抓包看一下,抓到的包是什么样的,可以看到抓包出来,已经做了报文全加密,无法进行测试。
[img][/img]
方案一:使用hook框架去获取明文报文。
1.我们怎么办呢?还是和之前一样我们先上算法助手,打印一下加解密相关的堆栈情况。
[img][/img]
2.我们看到了里面有http相关的,去看一下反编译后的相关代码
[img][/img]
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);
[img][/img]
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.脚本写完之后,我们就可以准备运行脚本看看效果了
[img][/img]
[img][/img]
7.这样我们基本上实现了报文的hook解密

方法, 报文

xshadow   

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

有技术含量的
Ly1988   

感谢分享
w759003376   

可以的,又学习到了,感谢大佬多多分享
您需要登录后才可以回帖 登录 | 立即注册

返回顶部