攻防世界 RE no-strings-attached

攻防世界官网:https://adworld.xctf.org.cn/

源程序下载: http://file.eonew.cn/ctf/re/no_strings_attached

一道简单的逆向题,虽然有一个坑,但是通过动态调试,很快就能得到flag。

观察

直接运行会出问题:

ex@Ex:~/Downloads$ gdb ./no_strings_attached 
pwndbg: loaded 175 commands. Type pwndbg [filter] for a list.
pwndbg: created $rebase, $ida gdb functions (can be used with print/break)
Reading symbols from ./no_strings_attached...(no debugging symbols found)...done.
pwndbg> r
Starting program: /home/ex/Downloads/no_strings_attached 
Welcome to cyber malware control software.
Currently tracking 1891687500 bots worldwide
no_strings_attached: malloc.c:2401: sysmalloc: Assertion `(old_top == initial_top (av) && old_size == 0) || ((unsigned long) (old_size) >= MINSIZE && prev_inuse (old_top) && ((unsigned long) old_end & (pagesize - 1)) == 0)' failed.

Program received signal SIGABRT, Aborted.
0xf7fd5059 in __kernel_vsyscall ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
────────────────────────────────────────────────────────────────────────────────────────[ REGISTERS ]─────────────────────────────────────────────────────────────────────────────────────────
 EAX  0x0
 EBX  0x2
 ECX  0xffff46ec ◂— 0x0
 EDX  0x0
 EDI  0x0
 ESI  0x8
 EBP  0xffff46ec ◂— 0x0
 ESP  0xffff46d0 —▸ 0xffff46ec ◂— 0x0
 EIP  0xf7fd5059 (__kernel_vsyscall+9) ◂— pop    ebp
──────────────────────────────────────────────────────────────────────────────────────────[ DISASM ]──────────────────────────────────────────────────────────────────────────────────────────
  0xf7fd5059 <__kernel_vsyscall+9>     pop    ebp
   0xf7fd505a <__kernel_vsyscall+10>    pop    edx
   0xf7fd505b <__kernel_vsyscall+11>    pop    ecx
   0xf7fd505c <__kernel_vsyscall+12>    ret    
    
   0xf7e03832                mov    edx, dword ptr [esp + 0x10c]
   0xf7e03839                xor    edx, dword ptr gs:[0x14]
   0xf7e03840                mov    eax, edi
   0xf7e03842                jne    raise+233 <0xf7e03859>
    
   0xf7e03859                call   __stack_chk_fail <0xf7edfb60>

   0xf7e0385e                           nop    
   0xf7e03860                   mov    eax, dword ptr [esp + 4]
──────────────────────────────────────────────────────────────────────────────────────────[ STACK ]───────────────────────────────────────────────────────────────────────────────────────────
00:0000│ esp      0xffff46d0 —▸ 0xffff46ec ◂— 0x0
01:0004│          0xffff46d4 ◂— 0x0
02:0008│          0xffff46d8 —▸ 0xffff46ec ◂— 0x0
03:000c│          0xffff46dc —▸ 0xf7e03832 (raise+194) ◂— mov    edx, dword ptr [esp + 0x10c]
04:0010│          0xffff46e0 ◂— 0x0
... 
────────────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]─────────────────────────────────────────────────────────────────────────────────────────
  f 0 f7fd5059 __kernel_vsyscall+9
   f 1 f7e03832 raise+194
   f 2 f7e03832 raise+194
   f 3 f7e04cc1 abort+289
   f 4 f7e4c66b __malloc_assert+91
   f 5 f7e4e7d0 sysmalloc+416
   f 6 f7e4f7c9 _int_malloc+2377
   f 7 f7e50cbe malloc+142
   f 8 f7e3b6e4 _IO_file_doallocate+148
   f 9 f7e3cbb9 _IO_wfile_doallocate+105
   f 10 f7e4a228 _IO_doallocbuf+120
Program received signal SIGABRT

分析

查看堆栈程序调用状态进行回溯。

pwndbg> bt
#0  0xf7fd5059 in __kernel_vsyscall ()
#1  0xf7e03832 in __libc_signal_restore_set (set=0xffff46ec) at ../sysdeps/unix/sysv/linux/nptl-signals.h:80
#2  __GI_raise (sig=6) at ../sysdeps/unix/sysv/linux/raise.c:48
#3  0xf7e04cc1 in __GI_abort () at abort.c:79
#4  0xf7e4c66b in __malloc_assert (assertion=assertion@entry=0xf7f589d8 "(old_top == initial_top (av) && old_size == 0) || ((unsigned long) (old_size) >= MINSIZE && prev_inuse (old_top) && ((unsigned long) old_end & (pagesize - 1)) == 0)", file=file@entry=0xf7f54f2d "malloc.c", line=line@entry=2401, function=0xf7f58fb0 <__PRETTY_FUNCTION__.11613> "sysmalloc") at malloc.c:298
#5  0xf7e4e7d0 in sysmalloc (nb=nb@entry=1040, av=0xf7fae7a0 ) at malloc.c:2398
#6  0xf7e4f7c9 in _int_malloc (av=av@entry=0xf7fae7a0 , bytes=bytes@entry=1024) at malloc.c:3559
#7  0xf7e50cbe in __GI___libc_malloc (bytes=1024) at malloc.c:3057
#8  0xf7e3b6e4 in __GI__IO_file_doallocate (fp=0xf7fae5c0 <_IO_2_1_stdin_>) at filedoalloc.c:101
#9  0xf7e3cbb9 in _IO_wfile_doallocate (fp=0xf7fae5c0 <_IO_2_1_stdin_>) at wfiledoalloc.c:70
#10 0xf7e4a228 in __GI__IO_doallocbuf (fp=0xf7fae5c0 <_IO_2_1_stdin_>) at genops.c:365
#11 0xf7e41bb3 in __GI__IO_wfile_underflow (fp=) at wfileops.c:179
#12 0xf7e4035b in __GI__IO_wdefault_uflow (fp=0xf7fae5c0 <_IO_2_1_stdin_>) at wgenops.c:204
#13 0xf7e3f320 in _IO_getwline_info (fp=0xf7fae5c0 <_IO_2_1_stdin_>, buf=0xffff4d1c L"", n=8191, delim=10, extract_delim=1, eof=0x0) at iogetwline.c:61
#14 0xf7e3f46a in _IO_getwline (fp=0xf7fae5c0 <_IO_2_1_stdin_>, buf=0xffff4d1c L"", n=8191, delim=10, extract_delim=1) at iogetwline.c:35
#15 0xf7e3eee5 in fgetws (buf=0xffff4d1c L"", n=8192, fp=0xf7fae5c0 <_IO_2_1_stdin_>) at iofgetws.c:53
#16 0x08048747 in authenticate ()
#17 0x080487d5 in main ()
#18 0xf7deee81 in __libc_start_main (main=0x80487a9 
, argc=1, argv=0xffffcde4, init=0x80487e0 <__libc_csu_init>, fini=0x8048850 <__libc_csu_fini>, rtld_fini=0xf7fe59b0 <_dl_fini>, stack_end=0xffffcddc) at ../csu/libc-start.c:310 #19 0x08048571 in _start ()

从上面可以看出是在0x08048747上一条指令调用fgetws才触发的异常。所以让我们来查看一下authenticate函数。

authenticate

.text:08048708                 public authenticate
.text:08048708 authenticate    proc near               ; CODE XREF: main+27↓p
.text:08048708
.text:08048708 var_800C        = dword ptr -800Ch
.text:08048708 var_C           = dword ptr -0Ch
.text:08048708
.text:08048708                 push    ebp
.text:08048709                 mov     ebp, esp
.text:0804870B                 sub     esp, 8028h
.text:08048711                 mov     dword ptr [esp+4], offset unk_8048A90
.text:08048719                 mov     dword ptr [esp], offset unk_8048AA8
.text:08048720                 call    decrypt
.text:08048725                 mov     [ebp+var_C], eax
.text:08048728                 mov     eax, ds:stdin@@GLIBC_2_0
.text:0804872D                 mov     [esp+8], eax
.text:08048731                 mov     dword ptr [esp+4], 2000h
.text:08048739                 lea     eax, [ebp+var_800C]
.text:0804873F                 mov     [esp], eax
.text:08048742                 call    _fgetws         ; error
.text:08048747                 test    eax, eax
.text:08048749                 jz      short loc_804879C
.text:0804874B                 lea     eax, [ebp+var_800C]
.text:08048751                 mov     [esp], eax
.text:08048754                 call    _wcslen
.text:08048759                 sub     eax, 1
.text:0804875C                 mov     [ebp+eax*4+var_800C], 0
.text:08048767                 mov     eax, [ebp+var_C]
.text:0804876A                 mov     [esp+4], eax
.text:0804876E                 lea     eax, [ebp+var_800C]
.text:08048774                 mov     [esp], eax
.text:08048777                 call    _wcscmp
.text:0804877C                 test    eax, eax
.text:0804877E                 jnz     short loc_804878F
.text:08048780                 mov     eax, offset unk_8048B44
.text:08048785                 mov     [esp], eax
.text:08048788                 call    _wprintf
.text:0804878D                 jmp     short loc_804879C
.text:0804878F ; ---------------------------------------------------------------------------
.text:0804878F
.text:0804878F loc_804878F:                            ; CODE XREF: authenticate+76↑j
.text:0804878F                 mov     eax, offset unk_8048BA4
.text:08048794                 mov     [esp], eax
.text:08048797                 call    _wprintf
.text:0804879C
.text:0804879C loc_804879C:                            ; CODE XREF: authenticate+41↑j
.text:0804879C                                         ; authenticate+85↑j
.text:0804879C                 mov     eax, [ebp+var_C]
.text:0804879F                 mov     [esp], eax
.text:080487A2                 call    _free
.text:080487A7                 leave
.text:080487A8                 retn
.text:080487A8 authenticate    endp

函数还是很简单的,最主要的地方还是0x8048777_wcscmp,他是用来判断我们的flag是否正确的。由于在0x8048742执行call _fgetws会出错,所以我们可以直接在这下断点,并跳过这里,然后直接到0x8048777_wcscmp查看flag。下面为调试结果。

调试

pwndbg> 
0x08048777 in authenticate ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
────────────────────────────────────────────────────────────────────────────────────────[ REGISTERS ]─────────────────────────────────────────────────────────────────────────────────────────
 EAX  0xffff4d1c ◂— 0x0
 EBX  0x0
 ECX  0x1480
 EDX  0xffff4d1c ◂— 0x0
 EDI  0x0
 ESI  0xf7fae000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1d7d6c
 EBP  0xffffcd28 —▸ 0xffffcd48 ◂— 0x0
 ESP  0xffff4d00 —▸ 0xffff4d1c ◂— 0x0
 EIP  0x8048777 (authenticate+111) —▸ 0xfffd54e8 ◂— 0x0
──────────────────────────────────────────────────────────────────────────────────────────[ DISASM ]──────────────────────────────────────────────────────────────────────────────────────────
   0x804875c <authenticate+84>     mov    dword ptr [ebp + eax*4 - 0x800c], 0
   0x8048767 <authenticate+95>     mov    eax, dword ptr [ebp - 0xc]
   0x804876a <authenticate+98>     mov    dword ptr [esp + 4], eax
   0x804876e <authenticate+102>    lea    eax, [ebp - 0x800c]
   0x8048774 <authenticate+108>    mov    dword ptr [esp], eax
  0x8048777 <authenticate+111>    call   wcscmp@plt <0x80484d0>
        s1: 0xffff4d1c ◂— 0x0
        s2: 0x804d940 ◂— 0x39 /* '9' */

   0x804877c <authenticate+116>    test   eax, eax
   0x804877e <authenticate+118>    jne    authenticate+135 <0x804878f>

   0x8048780 <authenticate+120>    mov    eax, 0x8048b44
   0x8048785 <authenticate+125>    mov    dword ptr [esp], eax
   0x8048788 <authenticate+128>    call   wprintf@plt <0x80484b0>
──────────────────────────────────────────────────────────────────────────────────────────[ STACK ]───────────────────────────────────────────────────────────────────────────────────────────
00:0000│ esp      0xffff4d00 —▸ 0xffff4d1c ◂— 0x0
01:0004│          0xffff4d04 —▸ 0x804d940 ◂— 0x39 /* '9' */
02:0008│          0xffff4d08 —▸ 0xf7fae5c0 (_IO_2_1_stdin_) ◂— 0xfbad2088
03:000c│          0xffff4d0c ◂— 0x0
... 
────────────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]─────────────────────────────────────────────────────────────────────────────────────────
  f 0  8048777 authenticate+111
   f 1  80487d5 main+44
   f 2 f7deee81 __libc_start_main+241
pwndbg> x/8wx 0x804d940
0x804d940:  0x00000039  0x00000034  0x00000034  0x00000037
0x804d950:  0x0000007b  0x00000079  0x0000006f  0x00000075
pwndbg> dump memory bin 0x804d940 0x804d940+0x100

从上面发现0x804d940里面储存的就是我们的flag,所以把他dump下来,并用strings分析一下,就可以得到我们的flag。

具体实例如下:

ex@Ex:~/Downloads$ strings -e L bin
9447{you_are_an_international_mystery}

总结

有些不必要的坑,如果不重要的话,就没必要去修复,即使直接跳过也不会影响我们拿flag。