猿人学11题so逆向

文章讲述了如何使用Unidbg工具对Android应用进行逆向工程,定位到sign生成位置,观察到sign方法在native层,并利用JNIOnload动态注册。接着介绍了如何通过Unidbg调用SO文件中的函数,以及通过Python接口实现与服务器交互的过程。
摘要由CSDN通过智能技术生成

猿人学第11题

将App下载后进行观察

在这里插入图片描述

界面还算简单,拖到jadx中进行反编译

在这里插入图片描述

全局搜索sign关键字进行定位很快就会找到sign生成的位置,仔细观察最后会发现sig方法在native层

在这里插入图片描述

到这里就可以直接将so文件拉出来看了

通过ida查看发现 sign方法是动态注册,所以直接搜JniOnload

在这里插入图片描述

点击方法进入

在这里插入图片描述

直接很清楚的就会发现getSign关键字,点击Tab键进入伪c代码界面

在这里插入图片描述

大致看了下,还是直接进行Unidbg调用so比较方便,这个是需要补JNi环境的

package com.dta.yuanrenxue8;

import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.Module;
import com.github.unidbg.linux.android.AndroidEmulatorBuilder;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.linux.android.dvm.*;
import com.github.unidbg.linux.android.dvm.wrapper.DvmLong;
import com.github.unidbg.memory.Memory;

import java.io.File;
import java.io.IOException;

import java.util.Random;

public class MainActivity2 {

    private final AndroidEmulator emulator;
    private final VM vm;
    private final Module module;
    private final DvmClass TTEncryptUtils;
    private final boolean logging;

    MainActivity2(boolean logging) {
        this.logging = logging;

        emulator = AndroidEmulatorBuilder.for32Bit().setProcessName("com.yuanrenxue.onlinejudge2020").build(); // 创建模拟器实例,要模拟32位或者64位,在这里区分
        final Memory memory = emulator.getMemory(); // 模拟器的内存操作接口
        memory.setLibraryResolver(new AndroidResolver(23)); // 设置系统类库解析

        vm = emulator.createDalvikVM(new File("unidbg-android/src/test/java/com/dta/yuanrenxue8/YuanRenXueOJ_1.2-release.apk")); // 创建Android虚拟机
        vm.setVerbose(logging); // 设置是否打印Jni调用细节

        vm.setJni(new AbstractJni() {
            @Override
            public DvmObject<?> callStaticObjectMethodV(BaseVM vm, DvmClass dvmClass, DvmMethod dvmMethod, VaList vaList) {
                if ("android/os/Looper->myLooper()Landroid/os/Looper;".equals(dvmMethod.toString())){
                    return vm.resolveClass("android/os/Looper").newObject(null);
                }
                return null;
            }
            @Override
            public DvmObject<?> newObjectV(BaseVM vm, DvmClass dvmClass, DvmMethod dvmMethod, VaList vaList) {
                if ("java/util/Random-><init>()V".equals(dvmMethod.toString())){
                    return vm.resolveClass("java/util/Random").newObject(new Random());
                }else if("java/util/Random-><init>(J)V".equals(dvmMethod.toString())){
                    return vm.resolveClass("java/util/Random").newObject(new Random(vaList.getLongArg(0)));
                }
                return null;
            }
            @Override
            public int callIntMethodV(BaseVM vm, DvmObject<?> dvmObject, DvmMethod dvmMethod, VaList vaList) {
                if ("java/util/Random->nextInt(I)I".equals(dvmMethod.toString())){
                    Random a = (Random)dvmObject.getValue();
                    return a.nextInt(vaList.getIntArg(0));
                }
                return 0;
            }
            @Override
            public DvmObject<?> callObjectMethodV(BaseVM vm, DvmObject<?> dvmObject, DvmMethod dvmMethod, VaList vaList) {
                if("android/content/ContextWrapper->getFilesDir()Ljava/io/File;".equals(dvmMethod.toString())){
                    return vm.resolveClass("java/io/File").newObject(new File("/"));
                }else if("java/io/File->getAbsolutePath()Ljava/lang/String;".equals(dvmMethod.toString())){
                    return new StringObject(vm, "/");
                    // 这里会在你的电脑C:\Users\用户名称\AppData\Local\Temp\rootfs\default目录下创建一个.did.bin的文件
                }
                return null;
            }
            @Override
            public boolean acceptMethod(DvmClass dvmClass, String signature, boolean isStatic) {
                return true;
            }
        });

        DalvikModule dm = vm.loadLibrary(new File("unidbg-android/src/test/resources/example_binaries/armeabi-v7a/libyuanrenxue_native.so"), false); // 加载libttEncrypt.so到unicorn虚拟内存,加载成功以后会默认调用init_array等函数

        DvmClass cContextWrapper = vm.resolveClass("android/content/ContextWrapper");
        TTEncryptUtils = vm.resolveClass("com/yuanrenxue/onlinejudge2020/OnlineJudgeApp", cContextWrapper);

        dm.callJNI_OnLoad(emulator); // 手动执行JNI_OnLoad函数
        module = dm.getModule(); // 加载好的libttEncrypt.so对应为一个模块

    }

    void destroy() throws IOException {
        emulator.close();
        if (logging) {
            System.out.println("destroy");
        }
    }

    public static void main(String[] args) throws Exception {
        MainActivity2 test = new MainActivity2(false);
       // test.ttEncrypt(args[0]);
        test.ttEncrypt("1");
        test.destroy();
    }

    void ttEncrypt(String number){
        StringObject signobj = TTEncryptUtils.newObject(null).callJniMethodObject(emulator, "getSign(J)Ljava/lang/String;", DvmLong.valueOf(vm, Long.parseLong(number))); // 执行Jni方法
        String sign = signobj.getValue();
        System.out.println(sign);
    }
}

以下是Unidbg返回的结果

在这里插入图片描述

我这里是直接使用springboot+Unidbg通过接口将返回值传送给python进行调用,也可以使用jar包的形式传递给python进行调用,手机进行抓包查看该题的请求参数以及url

在这里插入图片描述

总体上也就这几个参数需要注意,到这里就可以使用python进请求了

import requests


def get_res(page):
    global s
    url = 'http://localhost:8080/getSign/' + str(page)

    sign = requests.get(url=url).text

    new_url = 'https://match.yuanrenxue.com/api/match/11/query'
    params = {
        'id': str(page),
        'sign': sign
    }
    res = requests.get(url=new_url, params=params).json()
    s += res['data']
    print(res)


if __name__ == '__main__':
    s = 0
    for i in range(0, 100):
        get_res(i)
    print(s)

python返回结果如下:

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值