攻防世界官网: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。