吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 877|回复: 17
上一主题 下一主题
收起左侧

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

  [复制链接]
跳转到指定楼层
楼主
scllqk 发表于 2024-10-25 22:54 回帖奖励
本帖最后由 scllqk 于 2024-10-25 23:48 编辑

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

image

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

image

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

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

image

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

image

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

image

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

image

image

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

免费评分

参与人数 8吾爱币 +7 热心值 +8 收起 理由
wolfstudio + 1 + 1 谢谢@Thanks!
allspark + 1 + 1 用心讨论,共获提升!
Issacclark1 + 1 谢谢@Thanks!
freesoft + 1 + 1 谢谢@Thanks!
空城^ + 1 + 1 dudu牛,果然安卓逆向教程还是少不了我
youngdh + 1 + 1 用心讨论,共获提升!
index0079 + 1 + 1 谢谢@Thanks!
yikepinguo + 1 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

沙发
xshadow 发表于 2024-10-28 11:42
厉害,把响应码code改成200或0是不是就能直接登录成功了?
3#
Eapoul 发表于 2024-10-28 13:54
4#
Ly1988 发表于 2024-10-28 14:07
5#
w759003376 发表于 2024-10-28 14:27
可以的,又学习到了,感谢大佬多多分享
6#
HuskyHappy 发表于 2024-10-28 16:40
又学习到了,感谢大佬多多分享
7#
Godjk 发表于 2024-10-28 18:08
学习了,感谢分享,学习思路
8#
正己 发表于 2024-10-28 21:39
图片好像都炸了
9#
xixicoco 发表于 2024-10-28 22:05
图片挂了的啊!!!!!
10#
twl288 发表于 2024-10-29 00:08
向你学习,大佬
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-10-30 04:04

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表