zoukankan      html  css  js  c++  java
  • BUUCTF Re部分wp(MIPS特别篇)

    mips指令集不同,而且ida F5不支持,分析时把自动注释打开挺好用的

    在本文中主要使用了retdec

    ida插件:https://github.com/avast-tl/retdec-idaplugin

    retdec:  https://github.com/avast-tl/retdec/releases

    (这插件没装明白,一直报错,所以我没用。。。)

    使用方法

    $ retdec-decompiler.sh test.exe

     

    [QCTF2018]Xman-babymips

    int32_t function_4009a8(void) {
        // 0x4009a8
        setbuf(g6, NULL);
        setbuf(g7, NULL);
        printf("Give me your flag:");
        int32_t str = 0; // bp-44
        scanf("%32s", &str);
        int32_t v1 = 0; // bp-48
        int32_t v2 = 0; // 0x400a58
        char * v3 = (char *)(v2 + (int32_t)&v1 + 4); // 0x400a28
        *v3 = (char)((int32_t)*v3 ^ 32 - v2);
        int32_t v4 = v1 + 1; // 0x400a70
        v1 = v4;
        // branch -> 0x400a1c
        while (v4 < 32) {
            // 0x400a1c
            v2 = v4;
            v3 = (char *)(v2 + (int32_t)&v1 + 4);
            *v3 = (char)((int32_t)*v3 ^ 32 - v2);
            v4 = v1 + 1;
            v1 = v4;
            // continue -> 0x400a1c
        }
        int32_t str2 = *(int32_t *)&g8; // 0x400a90
        int32_t puts_rc;
        if (strncmp((char *)&str, (char *)str2, 5) == 0) {
            // 0x400ab4
            puts_rc = function_4007f0((char *)&str);
            // branch -> 0x400adc
        } else {
            // 0x400acc
            puts_rc = puts("Wrong");
            // branch -> 0x400adc
        }
        // 0x400adc
        return puts_rc;
    }
    View Code
    int32_t function_4007f0(char * a1) {
        int32_t v1 = (int32_t)a1; // 0x400800
        char * str = (char *)v1; // 0x400800
        int32_t puts_rc;
        int32_t str2; // 0x400944
        if (strlen(str) <= 5) {
            // 0x400934
            str2 = *(int32_t *)&g9;
            if (strncmp((char *)(v1 + 5), (char *)str2, 27) == 0) {
                // 0x400964
                puts_rc = puts("Right!");
                // branch -> 0x40098c
            } else {
                // 0x40097c
                puts_rc = puts("Wrong!");
                // branch -> 0x40098c
            }
            // 0x40098c
            return puts_rc;
        }
        int32_t v2 = 5;
        while (true) {
            char * v3 = (char *)(v2 + v1); // 0x4008a8
            int32_t v4 = (int32_t)*v3; // 0x4008a8
            char v5;
            if (v2 % 2 == 0) {
                char v6 = *v3; // 0x4008cc
                v5 = (int32_t)v6 / 64 | 0x4000000 * v4 / 0x1000000;
                // branch -> 0x400900
            } else {
                // 0x400828
                v5 = 64 * (int32_t)*v3 | v4 / 4;
                // branch -> 0x400900
            }
            // 0x400900
            *v3 = v5;
            int32_t v7 = v2 + 1; // 0x400908
            if (v7 >= strlen(str)) {
                // break -> 0x400934
                break;
            }
            v2 = v7;
            // continue -> 0x400814
        }
        // 0x400934
        str2 = *(int32_t *)&g9;
        if (strncmp((char *)(v1 + 5), (char *)str2, 27) == 0) {
            // 0x400964
            puts_rc = puts("Right!");
            // branch -> 0x40098c
        } else {
            // 0x40097c
            puts_rc = puts("Wrong!");
            // branch -> 0x40098c
        }
        // 0x40098c
        return puts_rc;
    }
    View Code

    反编译效果一般,不过比指令好多了。。。

    可以分析得到逻辑,用到的数据可结合ida获得

    [UTCTF2020]babymips

    int main(int argc, char ** argv) {
        // 0x400de8
        int32_t v1; // bp-152
        _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC1Ev((int32_t)&v1);
        int32_t v2; // bp-104
        int32_t v3; // bp-128
        function_401164((int32_t)&v2, (int32_t)&v3, 84);
        int32_t v4 = *(int32_t *)g4; // 0x400f40
        return *(int32_t *)g4 == v4 ? 0 : g1;
    }
    
    // Address range: 0x401164 - 0x401334
    int32_t function_401164(int32_t a1, int32_t a2, int32_t a3) {
        // 0x401164
        if (_ZNKSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE4sizeEv(a2) == 78) {
            // 0x4011fc
            if (*(int32_t *)0x4120a0 != 0) {
                int32_t v1 = 0;
                // branch -> 0x40122c
                while (true) {
                    char v2 = *(char *)(v1 + a1); // 0x401274
                    if (((int32_t)*g3 ^ v1 + 23) != (int32_t)v2) {
                        // 0x401288
                        // branch -> 0x40131c
                        // 0x40131c
                        return g2;
                    }
                    int32_t v3 = v1 + 1; // 0x4012d0
                    if (v3 >= *(int32_t *)0x4120a0) {
                        // break -> 0x4012e0
                        break;
                    }
                    v1 = v3;
                    // continue -> 0x40122c
                }
                // 0x4012e0
                // branch -> 0x40131c
                // 0x40131c
                return g2;
            }
    View Code

    可以看到是个简单的异或,并且用这段数据比对

    a="62 6C 7F 76 7A 7B 66 73 76 50 52 7D 40 54 55 79 40 49 47 4D 74 19 7B 6A 42 0A 4F 52 7D 69 4F 53 0C 64 10 0F  1E 4A 67 03 7C 67 02 6A 31 67 61 37 7A 62 2C 2C  0F 6E 17 00 16 0F 16 0A 6D 62 73 25 39 76 2E 1C  63 78 2B 74 32 16 20 22 44 19"
    a=a.split()
    for i in range(len(a)):
        print(chr(eval("0x"+a[i])^(i+23)),end="")
    #utflag{mips_cpp_gang_5VDm:~`N]ze;)5%vZ=C'C(r#$q=*efD"ZNY_GX>6&sn.wF8$v*mvA@'}

    这个flag是我目前见过最丑的了,我一度怀疑自己有什么地方做错了。。。 

    [CISCN2018]2ex

    这题文件比前几个大,符号表也没有,看着挺困难,先拖进ida

    .text:0040020C loc_40020C:                              # CODE XREF: start+4↑j
    .text:0040020C                 li      $gp, 0x429EA0    # Load Immediate
    .text:00400214                 move    $ra, $zero
    .text:00400218                 la      $a0, sub_400788  # Load Address
    .text:0040021C                 lw      $a1, arg_0($sp)  # Load Word
    .text:00400220                 addiu   $a2, $sp, arg_4  # Add Immediate Unsigned
    .text:00400224                 li      $at, 0xFFFFFFF8  # Load Immediate
    .text:00400228                 and     $sp, $at         # AND
    .text:0040022C                 addiu   $sp, -0x20       # Add Immediate Unsigned
    .text:00400230                 la      $a3, sub_400128  # Load Address
    .text:00400234                 la      $t0, sub_4101B0  # Load Address
    .text:00400238                 sw      $t0, 0x20+var_10($sp)  # Store Word
    .text:0040023C                 sw      $v0, 0x20+var_C($sp)  # Store Word
    .text:00400240                 sw      $sp, 0x20+var_8($sp)  # Store Word
    .text:00400244                 la      $t9, sub_4013D8  # Load Address
    .text:00400248                 bal     sub_4013D8       # Branch Always and Link

    入口函数用了sub_4013D8,,参数有sub_400788,sub_400128,sub_4101B0

    用retdec反编译一下,发现主要应分析sub_400788

    int32_t function_400788(void) {
        // 0x400788
        int32_t v1; // bp-80
        g5 = &v1;
        g80 = g27;
        int32_t v2 = 0; // bp-56
        function_400840((char *)&v2);
        int32_t v3; // bp-36
        int32_t v4 = &v3; // 0x4007c0
        g80 = g28;
        function_4010f0(v4, 25);
        function_400430((int32_t)&v2, 17, v4);
        g80 = g29;
        function_4009c0(v4);
        return 0;
    }

    这里调用了四个函数,运行程序发现,程序获取一个输入后输出密文,所以假设,

    function_4009c0(v4)为输出函数,v4为密文

    function_400840((char *)&v2)为输入函数,v2为输入

    function_400430((int32_t)&v2, 17, v4)为加密函数,v2加密后存在v4里

    接下来分析function_400430((int32_t)&v2, 17, v4)

    int32_t function_400430(int32_t a1, int32_t a2, int32_t a3) {
        g2 = a2;
        uint32_t v1 = g2; // 0x400440
        int32_t v2 = 0;
        int32_t v3 = -1;
        if (v1 != 0) {
            int32_t v4 = 0; // 0x40061019
            int64_t v5 = 0;
            int32_t v6 = 0;
            // branch -> 0x40045c
            int32_t v7;
            while (true) {
                uint64_t v8 = 0xaaaaaaab * (v5 & 0xffffffff) / 0x200000000; // 0x40047010
                int32_t v9 = v4 - (int32_t)v8 - (int32_t)(2 * v8); // 0x400480
                int32_t v10; // 0x400608
                if (v9 == 1) {
                    int32_t v11 = 16 * (int32_t)*(char *)(v4 - 1 + a1) & 48; // 0x400524
                    int32_t v12 = (int32_t)(*(char *)(a1 + v4) / 16) | v11; // 0x400544
                    char v13 = *(char *)(v12 + (int32_t)"@,.1fgvw#`/2ehux$~"3dity%_;4cjsz^+{5bkrA&=}6alqB*-[70mpC()]89noD/dev/null"); // 0x400554
                    *(char *)(v6 + a3) = v13;
                    v7 = v6 + 1;
                    // branch -> 0x400604
                  lab_0x400604_2:
                    // 0x400604
                    v10 = v4 + 1;
                    if (v10 >= v1) {
                        // break -> 0x400610
                        break;
                    }
                    v4 = v10;
                    v5 = v10;
                    v6 = v7;
                    // continue -> 0x40045c
                    continue;
                } else {
                    // 0x400498
                    v7 = v6;
                    switch (v9) {
                        case 2: {
                            int32_t v14 = 4 * (int32_t)*(char *)(v4 - 1 + a1) & 60; // 0x400590
                            g2 = a1;
                            int32_t v15 = (int32_t)(*(char *)(a1 + v4) / 64) | v14; // 0x4005b0
                            char v16 = *(char *)(v15 + (int32_t)"@,.1fgvw#`/2ehux$~"3dity%_;4cjsz^+{5bkrA&=}6alqB*-[70mpC()]89noD/dev/null"); // 0x4005c0
                            *(char *)(v6 + a3) = v16;
                            int32_t v17 = (int32_t)(*(char *)(a1 + v4) % 64); // 0x4005ec
                            char v18 = *(char *)(v17 + (int32_t)"@,.1fgvw#`/2ehux$~"3dity%_;4cjsz^+{5bkrA&=}6alqB*-[70mpC()]89noD/dev/null"); // 0x4005fc
                            *(char *)(a3 + 1 + v6) = v18;
                            v7 = v6 + 2;
                            // branch -> 0x400604
                            goto lab_0x400604_2;
                        }
                        case 0: {
                            int32_t v19 = (int32_t)(*(char *)(a1 + v4) / 4); // 0x4004d0
                            char v20 = *(char *)(v19 + (int32_t)"@,.1fgvw#`/2ehux$~"3dity%_;4cjsz^+{5bkrA&=}6alqB*-[70mpC()]89noD/dev/null"); // 0x4004e8
                            *(char *)(v6 + a3) = v20;
                            v7 = v6 + 1;
                            // branch -> 0x400604
                            goto lab_0x400604_2;
                        }
                    }
                    // 0x400604
                    v10 = v4 + 1;
                    if (v10 >= v1) {
                        // break (via goto) -> 0x400610
                        goto lab_0x400610;
                    }
                    v4 = v10;
                    v5 = v10;
                    v6 = v7;
                    // continue -> 0x40045c
                    continue;
                }
            }
          lab_0x400610:
            // 0x400610
            v2 = v7;
            v3 = v1 - 1;
            // branch -> 0x400624
        }
        uint64_t v21 = 0xaaaaaaab * (int64_t)v3 / 0x200000000; // 0x4006442
        int32_t v22 = v3 - ((int32_t)(2 * v21) + (int32_t)v21); // 0x400654
        if (v22 == 0) {
            int32_t v23 = 16 * (int32_t)*(char *)(a1 + v3) & 48; // 0x400688
            char v24 = *(char *)(v23 + (int32_t)"@,.1fgvw#`/2ehux$~"3dity%_;4cjsz^+{5bkrA&=}6alqB*-[70mpC()]89noD/dev/null"); // 0x400698
            *(char *)(v2 + a3) = v24;
            *(char *)(a3 + 1 + v2) = 61;
            g82 = 61;
            *(char *)(a3 + 2 + v2) = 61;
            // branch -> 0x400770
        } else {
            // 0x4006e0
            g82 = v22;
            if (v22 == 1) {
                int32_t v25 = 4 * (int32_t)*(char *)(a1 + v3) & 60; // 0x40073c
                char v26 = *(char *)(v25 + (int32_t)"@,.1fgvw#`/2ehux$~"3dity%_;4cjsz^+{5bkrA&=}6alqB*-[70mpC()]89noD/dev/null"); // 0x40074c
                *(char *)(v2 + a3) = v26;
                g82 = 61;
                *(char *)(a3 + 1 + v2) = 61;
                // branch -> 0x400770
            }
        }
        // 0x400770
        return 0;
    }

    可以看出来就是个换表base64

    import base64
    
    c="│_r-+_Cl5;vgq_pdme7#7eC0="
    flag=""
    
    table="@,.1fgvw#`/2ehux$~"3dity%_;4cjsz^+{5bkrA&=}6alqB*-[70mpC()]89noD"
    table2="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
    for i in c:
        for j in range(len(table)):
            if i==table[j]:
                flag+=table2[j]
    
    flag=base64.b64decode(flag)
    print(flag)
  • 相关阅读:
    React 高阶组件(HOC)
    使用 httpclient 连接 https 请求
    JAVA递归生成树形菜单
    Java8 stream 操作 GroupBy 设置键允许为null
    Java中简单对象(数组)拷贝
    idea中的Java项目引入外部jar包以及打包
    Java代码测试Kafka集群收发消息
    docker环境下,查看服务的线程数
    前端 vue3 随手记
    当GPU型号选定后,用什么样GPU的服务器?
  • 原文地址:https://www.cnblogs.com/harmonica11/p/13395639.html
Copyright © 2011-2022 走看看