猿人学2022安卓逆向对抗比赛第一题分析

整体的笔记为自己分析的流程,大佬勿喷

第一步 准备工具

  1. charles 抓包工具
  2. pixelxl 真机
  3. jadx
  4. 本机安装 python 和 frida

第二步 安装app 查壳 和 抓包

通过 GDA 可以 了解到 app 没有任何的壳
在这里插入图片描述
防止app 有可能不走代理,所以通过 charles + postern 进行 sock转发

通过 注册后 进入 第一题

** 计算1~100页所有数字之和**

在这里插入图片描述

Charles 中 可以看到 post 请求 有三个参数 ,请求的结果为 每页需要计算的数字

第一个是 page 页数 很明显

第二个是 sign 值 为加密流程

第三个 是 t 可以通过 上面的time 请求 了解到是时间戳

那么整体就是分析sign值 是如何产生的 ,是否和page页数和t时间戳相关
在这里插入图片描述
在这里插入图片描述

通过jdax 寻找 post 数据 发送点,找到sign 生成的地方

打开jadx 拖app包进入,发现内容是被混淆过的,
在这里插入图片描述
尝试通过post 发送的 参数的 关键词 进行定位,选择sign 关键词进行搜索。
在这里插入图片描述
发现匹配到的数据太多,更换思路,通过发包的url 中的 /app1 路径 进行搜索

在这里插入图片描述
发现 精准匹配到一处,直接双击进入,查看
在这里插入图片描述
发现匹配正确,然后通过右键查找用例去查找调用这个接口的地方
在这里插入图片描述
匹配到三个 发现前面两个是一样的,直接随便点击进入一个
在这里插入图片描述
可以简单名了的看到,页数 和 时间戳的定义的地方,并且在 return 的地方可以看到 sign 的函数 ,点击进入sign 瞅一眼
在这里插入图片描述
在这里插入图片描述
进入com.yuanrenxue.match2022.security.Sign 类中 可以看到整体就是加密库
那么可以直接 hook sign 方法 看看

frida 代码如下

function main(){
    console.log("Hooking.......")
    Java.perform(function(){
        var sign = Java.use("com.yuanrenxue.match2022.security.Sign");
        sign.sign.implementation = function(arg){
            console.log("sign_arg=>",(arg));
            var result = this.sign(arg);
            console.log("sign=>",result)
            return result;
        }
    });
}

setImmediate(main);

抓包的数据

在这里插入图片描述

hook的数据

在这里插入图片描述
可以看到sign 值是可以对应到的。但是获取到传入sign方法的数据的为啥是对象数据嘞。。。

看了一下sign方法,哦,原来传入的数据是 byte 数据 ,那就 搜索一下 js 字节集转字符串的代码

代码如下

function stringToByte(str) {
    var bytes = new Array();
    var len, c;
    len = str.length;
    for(var i = 0; i < len; i++) {
        c = str.charCodeAt(i);
        if(c >= 0x010000 && c <= 0x10FFFF) {
            bytes.push(((c >> 18) & 0x07) | 0xF0);
            bytes.push(((c >> 12) & 0x3F) | 0x80);
            bytes.push(((c >> 6) & 0x3F) | 0x80);
            bytes.push((c & 0x3F) | 0x80);
        } else if(c >= 0x000800 && c <= 0x00FFFF) {
            bytes.push(((c >> 12) & 0x0F) | 0xE0);
            bytes.push(((c >> 6) & 0x3F) | 0x80);
            bytes.push((c & 0x3F) | 0x80);
        } else if(c >= 0x000080 && c <= 0x0007FF) {
            bytes.push(((c >> 6) & 0x1F) | 0xC0);
            bytes.push((c & 0x3F) | 0x80);
        } else {
            bytes.push(c & 0xFF);
        }
    }
    return bytes;


}

//字节集转字符串
 function byteToString(arr) {
    if(typeof arr === 'string') {
        return arr;
    }
    var str = '',
        _arr = arr;
    for(var i = 0; i < _arr.length; i++) {
        var one = _arr[i].toString(2),
            v = one.match(/^1+?(?=0)/);
        if(v && one.length == 8) {
            var bytesLength = v[0].length;
            var store = _arr[i].toString(2).slice(7 - bytesLength);
            for(var st = 1; st < bytesLength; st++) {
                store += _arr[st + i].toString(2).slice(2);
            }
            str += String.fromCharCode(parseInt(store, 2));
            i += bytesLength - 1;
        } else {
            str += String.fromCharCode(_arr[i]);
        }
    }
    return str;
}

所以重新修改一下hook的代码,如下:

function main(){
    console.log("Hooking.......")
    Java.perform(function(){
        var sign = Java.use("com.yuanrenxue.match2022.security.Sign");
        sign.sign.implementation = function(arg){
            console.log("sign_arg=>",byteToString(arg));
            var result = this.sign(arg);
            console.log("sign=>",result)
            return result;
        }
    });
}

setImmediate(main);

hook到的传入数据就可以正常显示了

在这里插入图片描述
在这里插入图片描述

对应到抓包的数据可以看出,sign 的值的数据 是通过 page的标识和值+t的值 然后通过sign()方法进行计算的出来的

进行主动调用

知道sign值的传入值 ,我们可以手动赋值,那么就可以进行hook 主动调用

代码如下

function invokeSign(){
    Java.choose("com.yuanrenxue.match2022.security.Sign",{
        onMatch:function(ins){
            console.log("ins=>",ins);
            ins.sign(stringToByte("page=51657210487"));
            
        },onComplete(){}
    });
}


hook获取的效果如下,和上面的 获取的sign值一样
在这里插入图片描述

如何进行1~100页的调用?

如何 一次性自动化的 获取到 1~100页的 sign值 ,并且进行100次的请求,然后获取到 response 中 返回的数据 进行sum 计算?

抽了一根烟,想了一下,既然都用主动调用了,那么就直接frida rpc 通过python 请求一下就行

在这里插入图片描述
搞了半天,最终成了!!!
在这里插入图片描述

附上代码

import time
import frida
import requests
from requests.packages import urllib3
urllib3.disable_warnings()

def my_message_handler(message, payload):
    print("message=>",message)
    print("payloa=>d",payload)


# connect wifiadb
device = frida.get_device_manager().add_remote_device("192.168.0.102:8888")
print('设备=>',device)
session = device.attach("com.yuanrenxue.match2022")
print('session=>',session)
#load script
with open("app1.js") as f:
    script = session.create_script(f.read())
script.on("message", my_message_handler)
script.load()

# script.exports.invokesign('page=121657216931')
def get_url():
    num = 0
    for i in range(1,101):
        url = 'https://appmatch.yuanrenxue.com/app1'
        headers = {
            'accept-language': 'zh-CN,zh;q=0.8',
            'user-agent': 'Mozilla/5.0 (Linux; U; Android 8.1.0; zh-cn; Pixel XL Build/OPM1.171019.011) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30',
            'content-type': 'application/x-www-form-urlencoded',
            'accept-encoding': 'gzip',
            'cache-control': 'no-cache'
        }
        data = {
            'page':str(i),
            't': str(int(time.time()))
        }
        data['sign'] = script.exports.invokesign('page='+data['page']+data['t'])
        print(data)
        response = requests.post(url,headers=headers,data=data,verify=False)
        print(response.json())
        value_data = response.json()
        for value in value_data['data']:
            num += int(value['value'])
        print(num)

        time.sleep(1)
    # print(num)
if __name__ == '__main__':
    get_url()

    

总结

在这里 学习了使用frida rpc 进行主动调用 然后进行 获取sign 值 在通过python 进行 post请求
还有需要注意的是 ,需要进行一次 sign 的实例化才可以进行调用,不然会报错!
自己其实是一个初学者,对frida其实并不了解多少,rpc是第一次使用,发现这个功能很nice,省去扣加密算法流程
针对一些app的算法,如果混淆厉害的话,后续可以直接使用这个,不需要硬刚算法了。很棒!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于您提到的错误TypeError: list indices must be integers or slices, not str,这是因为您在访问列表中的元素时使用了字符串作为索引,而列表的索引必须是整数或切片类型。解决这个错误的方法是使用整数或切片来访问列表中的元素。 关于您提到的猿人js逆向的问,我需要更多的信息才能为您提供具体的答案。对于爬虫编写,您可以使用Python的各种库(如Requests、BeautifulSoup、Scrapy等)来获取网页的内容,并进一步解析和处理。您可以使用这些库发送HTTP请求获取网页内容,然后使用解析库来提取您需要的数据。 爬虫编写的一般步骤如下: 1. 导入所需的库 2. 发送HTTP请求获取网页内容 3. 使用解析库解析网页内容 4. 提取所需的数据 5. 进行数据的进一步处理和存储 您可以根据具体的需求和网站的结构进行相应的编写和调试。如果您需要更具体的帮助,请提供更多的信息。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Python:TypeError: list indices must be integers or slices, not str报错解决及原理](https://blog.csdn.net/hhd1988/article/details/128031602)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [Python BeautifulSoup [解决方法] TypeError: list indices must be integers or slices, not str](https://download.csdn.net/download/weixin_38590567/14871394)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值