夏时逆向分析

1. 关键字搜索 'crack' 定位函数位置

20240206011507_image.png

2. 分析函数 查找调用位置

20240206011653_image.png

20240206011752_image.png

经测试只要 result = 0 即可破解弹窗

3. 分析汇编代码 寻找突破口

20240206012930_image.png

// hook_swift.js
if (ObjC.available) {
    // 拦截 swift_dynamicCast 函数
    Interceptor.attach(Module.findExportByName(null, 'swift_dynamicCast'), {
        onEnter: function(args){
            console.log('onEnter');
            var instance = args[0];
            var targetType = args[1];
        
            // 使用 Memory.readPointer 读取指针参数的值
            var instanceValue = Memory.readPointer(instance);
            var targetValue = Memory.readPointer(targetType);
        
            console.log('instance 参数:', instanceValue);
            console.log('targetType 参数:', targetValue);
        },
        onLeave: function (retval) {
            console.log('onLeave', retval);
            // 将返回值修改为 0
            //retval.replace(ptr(0));
        }
    });
}

frida -U -f com.x1vpn.xiashijsq -l hook_swift.js
copy success
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//sub_reg.js
function get_func_addr(module, offset) {
    var base_addr = Module.findBaseAddress(module);
    var func_addr = base_addr.add(offset);
    if (Process.arch == 'arm')
        return func_addr.add(1);  //如果是32位地址+1
    else
        return func_addr;
}

if (ObjC.available) {
    var func_addr = get_func_addr('xiashiEasy', 0x000037320);
    Interceptor.attach(ptr(func_addr), {
        onEnter: function (args) {
            console.log("onEnter");
            console.log("arg0=", args[0]);
            console.log("arg1=", args[1]);
            console.log("v0=", this.context.x0);
            console.log("v1=", this.context.x1);
            console.log("v2=", this.context.x2);
            console.log("v3=", this.context.x3);
            console.log("v4=", this.context.x4);
            console.log("v5=", this.context.x5);
            console.log("v6=", this.context.x6);
            console.log("v7=", this.context.x7);
            console.log("v8=", this.context.x8);
            console.log("v9=", this.context.x9);
        },
        onLeave: function (retval) {
            console.log("onLeave", retval);
            retval.replace(0);  //返回值替换成3
        }
    });
}
copy success
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 // sub_patch.js
function get_func_addr(module, offset) {
    var base_addr = Module.findBaseAddress(module);
    console.log('模块基址: ' + base_addr);
    // 一般以 cf fa ed fe 开头 表示 Match-o 应用程序
    console.log(hexdump(ptr(base_addr), {
        length: 16,
        header: true,
        ansi: true
    }))

    var func_addr = base_addr.add(offset);
    if (Process.arch == 'arm')
        return func_addr.add(1);  //如果是32位地址+1
    else
        return func_addr;
}

if (ObjC.available) {
    // 可能需要去掉前面的 1 取决于 iDA 的 rebase 最好设为 0 即 0x00000000
    var func_addr = get_func_addr('xiashiEasy', 0x37320);
    console.log('函数地址: ' + func_addr,'函数内部偏移地址: ' + func_addr.add(0xFC));
    console.log(hexdump(ptr(func_addr.add(0xFC)), {
        length: 16,
        header: true,
        ansi: true
    }))

    // 修改成 汇编指令 MOV W0,#0
    Memory.patchCode(func_addr.add(0xFC), 4, code => {
        var bytes = [0x00, 0x00, 0x80, 0x52];
        code.writeByteArray(bytes);
    });

    console.log('修改后:');
    console.log(hexdump(ptr(func_addr.add(0xFC)), {
        length: 16,
        header: true,
        ansi: true
    }))
}
copy success
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41