2019DDCTF的一道简单逆向

作者: 丿feng | 来源:发表于2019-04-18 18:16 被阅读11次

    昨晚躺尸的时候看到群里大佬发了一张DDCTF战况的图就起床做了一下,也就有了这个题解,RE2跟RE1其实核心思想是差不多的,只是多了一些移位操作罢了,算是弥补上个月0CTF、“西湖论剑”逆向零的突破吧
    终究还是太菜了,另外一道CPP逆向也是看得头疼
    ——2019.4.13

    0x00 查壳

    一看是UPX壳,修复一下然后直接!

    0x01 分析

    1.载入IDA X86
    • main函数伪代码
    int __cdecl main(int argc, const char **argv, const char **envp)
    {
      int result; // eax@2
      char v4; // [sp+4h] [bp-804h]@1
      char v5; // [sp+5h] [bp-803h]@1
      char v6; // [sp+404h] [bp-404h]@1
      char Dst; // [sp+405h] [bp-403h]@1
    
      v6 = 0;
      memset(&Dst, 0, 0x3FFu);
      v4 = 0;
      memset(&v5, 0, 0x3FFu);
      printf("please input code:");
      scanf("%s", &v6);
      sub_401000(&v6);
      if ( !strcmp(&v4, "DDCTF{reverseME}") )
      {
        printf("You've got it!!%s\n", &v4);
        result = 0;
      }
      else
      {
        printf("Try again later.\n");
        result = 0;
      }
      return result;
    }
    
    • sub_401000函数伪代码
    unsigned int __cdecl sub_401000(const char *a1)
    {
      _BYTE *v1; // ecx@0
      unsigned int v2; // edi@1
      unsigned int result; // eax@1
      int v4; // ebx@2
    
      v2 = 0;
      result = strlen(a1);
      if ( result )
      {
        v4 = a1 - v1;
        do
        {
          *v1 = byte_402FF8[v1[v4]];
          ++v2;
          ++v1;
          result = strlen(a1);
        }
        while ( v2 < result );
      }
      return result;
    }
    

    程序大致就是将输入字符串在函数sub_401000中进行简单变换后与"DDCTF{reverseME}"比较

    2.载入OD

    直接在变换函数前断点



    然后动态调试
    伪代码中的变换就是401020~40103E的内容



    核心代码无非就三条
    ……
    movsx eax,byte ptr ds:[ebx+eax]//ds:[ebx+eax]寻址获得的数据即为将要处理的数据,并将其字扩展存入eax中
    mov dl,byte ptr ds:[eax+0x402FF8]//通过eax和0x402FF8相对寄存器存址获得的字节数据存入dl中
    ……
    mov byte ptr ds:[ecx],dl//dl数据写入数据段
    ……
    //循环执行
    

    所以该函数就是将输入的字符串逐个字符的hex作为偏移量在数据段中寻址获得的字符逐个拼接并写入数据段
    即伪代码是

    flag=""
    for i in input
        flag+=ds:[hex(i)+0x402FF8]
    

    查看地址为0x402FF8起的数据段内容

    .rdata:00402FF8 ; char byte_402FF8[]
    .rdata:00402FF8 byte_402FF8     db ?                    ; DATA XREF: sub_401000+24�r
    .rdata:00402FF9                 align 10h
    .rdata:00402FF9 _rdata          ends
    .rdata:00402FF9
    .data:00403000 ; Section 3. (virtual address 00003000)
    .data:00403000 ; Virtual size                  : 000003E4 (    996.)
    .data:00403000 ; Section size in file          : 00000200 (    512.)
    .data:00403000 ; Offset to raw data for section: 00001600
    .data:00403000 ; Flags C0000040: Data Readable Writable
    .data:00403000 ; Alignment     : default
    .data:00403000 ; ===========================================================================
    .data:00403000
    .data:00403000 ; Segment type: Pure data
    .data:00403000 ; Segment permissions: Read/Write
    .data:00403000 _data           segment para public 'DATA' use32
    .data:00403000                 assume cs:_data
    .data:00403000                 ;org 403000h
    .data:00403000 ___security_cookie dd 0BB40E64Eh        ; DATA XREF: _main+6�r
    .data:00403000                                         ; __security_check_cookie(x)�r ...
    .data:00403004 dword_403004    dd 44BF19B1h            ; DATA XREF: ___report_gsfailure+B0�r
    .data:00403004                                         ; ___security_init_cookie+2B�w ...
    .data:00403008                 db 0FFh
    .data:00403009                 db 0FFh
    .data:0040300A                 db 0FFh
    .data:0040300B                 db 0FFh
    .data:0040300C                 db 0FFh
    .data:0040300D                 db 0FFh
    .data:0040300E                 db 0FFh
    .data:0040300F                 db 0FFh
    .data:00403010 dword_403010    dd 0FFFFFFFEh           ; DATA XREF: .text:004013E2�r
    .data:00403014 dword_403014    dd 1                    ; DATA XREF: .text:004013C8�r
    .data:00403018 aZyxwvutsrqponm db '~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>'
    .data:00403018                 db '=<;:9876543210/.-,+*)(',27h,'&%$#"! ',0
    .data:00403078 ; int argc
    

    注意到0x403018起定义了这么一段字符

    ~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>'=<;:9876543210/.-,+*)(',27h,'&%$#"!
    

    到此就可以解题了,直接逆算法遍历目标字符串获得输入

    dst="DDCTF{reverseME}"
    str="~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>'=<;:9876543210/.-,+*)(',27h,'&%$#\"!"
    flag=""
    for i in dst:
        index=str.find(i)
        flag+=chr(index+(0x403018-0x402FF8))
    print("flag:"+flag)
    

    获得flag是ZZ[JX#,9(9,+9QY!


    最后包裹上DDCTF{}提交即可

    相关文章

      网友评论

        本文标题:2019DDCTF的一道简单逆向

        本文链接:https://www.haomeiwen.com/subject/coqrwqtx.html