0xgame2024逆向week4复现
1438911687251843 发表于 江西 CTF 219浏览 · 2024-11-18 16:18

之前以为第四周的题目会很难,就没有去写了,今天第一次写才发现原来题目难度挺友好的,收获颇丰

PyPro

exe文件,但是题目提示了是使用python编写的,所以首先使用pyinstxtractor解包exe

在解包的文件夹中,可以找到PyPro.pyc文件,先使用DIE查查成分

python3.12版本,这个版本是不能使用uncompyle6反编译的,尝试使用pycdc反编译

警告反编译不完全,并且出现乱码,尝试使用pycdas得到python字节码

PyPro.pyc (Python 3.12)
[Code]
    File Name: PyPro.py
    Object Name: <module>
    Qualified Name: <module>
    Arg Count: 0
    Pos Only Arg Count: 0
    KW Only Arg Count: 0
    Stack Size: 2
    Flags: 0x00000000
    [Names]
        'base64'
        'Crypto.Cipher'
        'AES'
        'Crypto.Util.number'
        'long_to_bytes'
        'key'
        'PKCS5_pad'
        'main'
        '__name__'
    [Locals+Names]
    [Constants]
        0
        None
        (
            'AES'
        )
        (
            'long_to_bytes'
        )
        0x554B134A029DE539438BD18604BF114L
        [Code]
            File Name: PyPro.py
            Object Name: PKCS5_pad
            Qualified Name: PKCS5_pad
            Arg Count: 1
            Pos Only Arg Count: 0
            KW Only Arg Count: 0
            Stack Size: 5
            Flags: 0x00000003 (CO_OPTIMIZED | CO_NEWLOCALS)
            [Names]
                'len'
                'ljust'
                'to_bytes'
            [Locals+Names]
                'data'
                'length'
            [Constants]
                None
                48
            [Disassembly]
                0       RESUME                          0
                2       LOAD_GLOBAL                     1: NULL + len
                12      LOAD_FAST                       0: data
                14      CALL                            1
                22      LOAD_CONST                      1: 48
                24      COMPARE_OP                      2 (<)
                28      POP_JUMP_IF_FALSE               46 (to 122)
                30      LOAD_CONST                      1: 48
                32      LOAD_GLOBAL                     1: NULL + len
                42      LOAD_FAST                       0: data
                44      CALL                            1
                52      BINARY_OP                       10 (-)
                56      STORE_FAST                      1: length
                58      LOAD_FAST                       0: data
                60      LOAD_ATTR                       3: ljust
                80      LOAD_CONST                      1: 48
                82      LOAD_FAST                       1: length
                84      LOAD_ATTR                       5: to_bytes
                104     CALL                            0
                112     CALL                            2
                120     RETURN_VALUE
                122     RETURN_CONST                    0: None
        [Code]
            File Name: PyPro.py
            Object Name: main
            Qualified Name: main
            Arg Count: 0
            Pos Only Arg Count: 0
            KW Only Arg Count: 0
            Stack Size: 5
            Flags: 0x00000003 (CO_OPTIMIZED | CO_NEWLOCALS)
            [Names]
                'input'
                'encode'
                'len'
                'print'
                'range'
                'exit'
                'ord'
                'AES'
                'new'
                'long_to_bytes'
                'key'
                'MODE_ECB'
                'encrypt'
                'PKCS5_pad'
                'base64'
                'b64encode'
                'decode'
            [Locals+Names]
                'enc'
                'i'
                'chiper'
                'result'
                'data'
            [Constants]
                None
                '鍦ㄨ繖閲岃緭鍏ヤ綘鐨刦lag:\n'
                'utf-8'
                44
                'length error!'
                123
                6
                '{'
                -1
                '}'
                'format error'
                1
                '2e8Ugcv8lKVhL3gkv3grJGNE3UqkjlvKqCgJSGRNHHEk98Kd0wv6s60GpAUsU+8Q'
                'flag姝g‘'
                '閿欒'
            [Disassembly]
                0       RESUME                          0
                2       LOAD_GLOBAL                     1: NULL + input
                12      LOAD_CONST                      1: '鍦ㄨ繖閲岃緭鍏ヤ綘鐨刦lag:\n'
                14      CALL                            1
                22      LOAD_ATTR                       3: encode
                42      LOAD_CONST                      2: 'utf-8'
                44      CALL                            1
                52      STORE_FAST                      0: enc
                54      LOAD_GLOBAL                     5: NULL + len
                64      LOAD_FAST                       0: enc
                66      CALL                            1
                74      LOAD_CONST                      3: 44
                76      COMPARE_OP                      55 (!=)
                80      POP_JUMP_IF_FALSE               48 (to 178)
                82      LOAD_GLOBAL                     7: NULL + print
                92      LOAD_CONST                      4: 'length error!'
                94      CALL                            1
                102     POP_TOP
                104     LOAD_GLOBAL                     9: NULL + range
                114     LOAD_GLOBAL                     5: NULL + len
                124     LOAD_FAST                       0: enc
                126     CALL                            1
                134     CALL                            1
                142     GET_ITER
                144     FOR_ITER                        2 (to 150)
                148     STORE_FAST                      1: i
                150     JUMP_BACKWARD                   4 (to 144)
                152     END_FOR
                154     LOAD_GLOBAL                     11: NULL + exit
                164     LOAD_CONST                      5: 123
                166     CALL                            1
                174     POP_TOP
                176     JUMP_FORWARD                    57 (to 292)
                178     LOAD_FAST                       0: enc
                180     LOAD_CONST                      6: 6
                182     BINARY_SUBSCR
                186     LOAD_GLOBAL                     13: NULL + ord
                196     LOAD_CONST                      7: '{'
                198     CALL                            1
                206     COMPARE_OP                      55 (!=)
                210     POP_JUMP_IF_TRUE                17 (to 246)
                212     LOAD_FAST                       0: enc
                214     LOAD_CONST                      8: -1
                216     BINARY_SUBSCR
                220     LOAD_GLOBAL                     13: NULL + ord
                230     LOAD_CONST                      9: '}'
                232     CALL                            1
                240     COMPARE_OP                      55 (!=)
                244     POP_JUMP_IF_FALSE               23 (to 292)
                246     LOAD_GLOBAL                     7: NULL + print
                256     LOAD_CONST                      10: 'format error'
                258     CALL                            1
                266     POP_TOP
                268     LOAD_GLOBAL                     11: NULL + exit
                278     LOAD_CONST                      11: 1
                280     CALL                            1
                288     POP_TOP
                290     NOP
                292     LOAD_GLOBAL                     15: NULL + AES
                302     LOAD_ATTR                       16: new
                322     LOAD_GLOBAL                     19: NULL + long_to_bytes
                332     LOAD_GLOBAL                     20: key
                342     CALL                            1
                350     LOAD_GLOBAL                     14: AES
                360     LOAD_ATTR                       22: MODE_ECB
                380     CALL                            2
                388     STORE_FAST                      2: chiper
                390     LOAD_FAST                       2: chiper
                392     LOAD_ATTR                       25: encrypt
                412     LOAD_GLOBAL                     27: NULL + PKCS5_pad
                422     LOAD_FAST                       0: enc
                424     CALL                            1
                432     CALL                            1
                440     STORE_FAST                      0: enc
                442     LOAD_GLOBAL                     29: NULL + base64
                452     LOAD_ATTR                       30: b64encode
                472     LOAD_FAST                       0: enc
                474     CALL                            1
                482     STORE_FAST                      3: result
                484     LOAD_CONST                      12: '2e8Ugcv8lKVhL3gkv3grJGNE3UqkjlvKqCgJSGRNHHEk98Kd0wv6s60GpAUsU+8Q'
                486     STORE_FAST                      4: data
                488     LOAD_FAST                       3: result
                490     LOAD_ATTR                       33: decode
                510     CALL                            0
                518     LOAD_FAST                       4: data
                520     COMPARE_OP                      40 (==)
                524     POP_JUMP_IF_FALSE               12 (to 550)
                526     LOAD_GLOBAL                     7: NULL + print
                536     LOAD_CONST                      13: 'flag姝g‘'
                538     CALL                            1
                546     POP_TOP
                548     RETURN_CONST                    0: None
                550     LOAD_GLOBAL                     7: NULL + print
                560     LOAD_CONST                      14: '閿欒'
                562     CALL                            1
                570     POP_TOP
                572     RETURN_CONST                    0: None
        '__main__'
    [Disassembly]
        0       RESUME                          0
        2       LOAD_CONST                      0: 0
        4       LOAD_CONST                      1: None
        6       IMPORT_NAME                     0: base64
        8       STORE_NAME                      0: base64
        10      LOAD_CONST                      0: 0
        12      LOAD_CONST                      2: ('AES',)
        14      IMPORT_NAME                     1: Crypto.Cipher
        16      IMPORT_FROM                     2: AES
        18      STORE_NAME                      2: AES
        20      POP_TOP
        22      LOAD_CONST                      0: 0
        24      LOAD_CONST                      3: ('long_to_bytes',)
        26      IMPORT_NAME                     3: Crypto.Util.number
        28      IMPORT_FROM                     4: long_to_bytes
        30      STORE_NAME                      4: long_to_bytes
        32      POP_TOP
        34      LOAD_CONST                      4: 0x554B134A029DE539438BD18604BF114L
        36      STORE_NAME                      5: key
        38      LOAD_CONST                      5: <CODE> PKCS5_pad
        40      MAKE_FUNCTION                   0
        42      STORE_NAME                      6: PKCS5_pad
        44      LOAD_CONST                      6: <CODE> main
        46      MAKE_FUNCTION                   0
        48      STORE_NAME                      7: main
        50      LOAD_NAME                       8: __name__
        52      LOAD_CONST                      7: '__main__'
        54      COMPARE_OP                      40 (==)
        58      POP_JUMP_IF_FALSE               8 (to 76)
        60      PUSH_NULL
        62      LOAD_NAME                       7: main
        64      CALL                            0
        72      POP_TOP
        74      RETURN_CONST                    1: None
        76      RETURN_CONST                    1: None

随便看了下,应该是先aes(ecb)加密,然后base64加密

Register

进入主函数,找到lpfnWndProc,双击这个函数

注册机用户名就写在第20行这里

显然那个buf1是待输入的序列号,进入28行的函数

这个23行的buf2就是待比较的序列号,上面22行为解密序列号的函数

调试调到这里自动解密出了buf2也就是序列号的值

验证成功

MineSweeper

第一次做unity的题目,拿到题目不知道干什么

稍微学了一下,在Minesweeper_Data/Managed下找到了Assembly-CSharp.dll文件,是c#编译的,要用dnSpy反编译

看了半天,才在NewGames函数这里找到生成雷的逻辑

感觉反编译的代码很好看,反编译器也可以直接修改伪代码(比ida还好用),把GenerateMines()里面mines改成0就行了,记住要点保存模块

然后启动游戏,点一下就出flag了,因为没有雷了

Tea2.0

这题初看下来只有一个普通的xtea加密,但是发现解密解不通,这是就要怀疑数据被改了

看一下函数表,有几个明显的tls回调函数

这里虽然有4个,但实际有意义的只有两个

果然修改了数据部分

在数据这里可以发现,事实上存在两个key

上面那个是用在tls中的,下面那个是用在主函数的xtea中的

分析这两个tls函数,发现第一个tls修改了第一个key,第二个tls将主函数中的数据进行了一次普通tea加密,使用的是上面那个key

这样思路就清晰了,要先把数据经过tea加密,然后再xtea解密,一共两轮,且key不一样

写攻击脚本

#include <stdio.h>
#include <stdint.h>


void en_tea(uint32_t* v, uint32_t* k) {
    uint32_t v0 = v[0], v1 = v[1], sum = 0;
    uint32_t delta = 0x9e3779b9;
    uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
    for (int i = 0; i < 32; i++) {
        sum += delta;
        v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
        v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
    }
    v[0] = v0; v[1] = v1;
}


void de_xtea(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
    uint32_t v0 = v[0], v1 = v[1], delta = 0x9E3779B9, sum = delta * num_rounds;
    for (int i = 0; i < num_rounds; i++) {
        v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
        sum -= delta;
        v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
    }
    v[0] = v0; v[1] = v1;
}

int main()
{
    unsigned int cipher[12] = {
        0x018DC360, 0xD5835457, 0x8BEE2DCB, 0x92BB2DEE, 0xFDF4AD54, 0x043F8C2D, 0x61A232A9, 0x0F15F4D1,
        0x16EA4979, 0x7C2BF6DA, 0xDCD5FA32, 0x76450819
    };

    unsigned int r = 64;
    unsigned int key_tea[4] = {
        0x00001245, 0x00003298, 0x00004756, 0x00001463
    };
    unsigned int key_xtea[4] = {
        0x00004512, 0x00009832, 0x00005647, 0x00006314
    };

    for (int i = 0; i < 4; i++) {
        key_tea[i] ^= 0xABCD;
    }


    for (int i = 0; i < 12; i += 2)
    {
        en_tea(&cipher[i], key_tea);
    }
    for (int i = 0; i < 12; i += 2)
    {
        de_xtea(64, &cipher[i], key_xtea);
    }

    printf("%s", (char*)cipher);
    return 0;
}

EzAndroid

使用jeb反编译,直接可以看到主函数和加密函数

定义了一个base62加密函数,逻辑看起来不难

只需要注意加密得到的密文在R方法里面找

encoded = "J6IwkwOvgGFthiofcwab0ka7KrOMpVbfROQ9Jh5C5YMqfyLLdMrNoj4YGVh"
B62table = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
Base = 62

num = 0
for char in encoded:
    num = num * Base + B62table.index(char)

byte_array = []
while num > 0:
    byte_array.insert(0, num & 0xFF)
    num >>= 8

decoded_bytes = bytes(byte_array)
print(decoded_bytes)
0 条评论
某人
表情
可输入 255
目录