由于另一个问题基于相同的二进制文件,并且接受的答案没有详细说明如何找到负责的函数,这里有一篇文章。平常的东西$ r2 wysiNwyg; aaa
看看功能列表(afl)
[0x080484a0]> afl
0x080483bc 3 35 fcn.080483bc
0x080483f0 1 6 sym.imp.strcmp
0x08048400 1 6 sym.imp.printf
0x08048410 1 6 sym.imp.fgets
0x08048420 1 6 sym.imp.puts
0x08048430 1 6 loc.imp.__gmon_start
0x08048440 1 6 sym.imp.exit
0x08048450 1 6 sym.imp.strlen
0x08048460 1 6 sym.imp.__libc_start_main
0x08048470 1 6 sym.imp.memset
0x08048480 1 6 sym.imp.putchar
0x08048490 1 6 sym.imp.ptrace
0x080484a0 1 33 entry0
0x080484d0 1 4 fcn.080484d0
0x080484e0 4 43 fcn.080484e0
0x08048550 3 30 entry3.fini
0x08048570 8 43 -> 93 entry1.init
0x0804859b 3 55 entry2.init
0x080485d2 12 446 entry4.fini
0x08048790 8 250 main
除此之外main,entry4.fini功能相当大。查看二进制文件(iS)中的.fini和.fini_array部分。.fini_array当程序即将终止时(在 main 之后)调用函数 from 。
[0x080484a0]> iS~fini
14 0x00000904 20 0x08048904 20 -r-x .fini
19 0x00000c08 8 0x08049c08 8 -rw- .fini_array
寻找那个地址。转储.fini_array(pxw)。
[0x080484a0]> s 0x08049c08
[0x08049c08]> pxw 0x10
0x08049c08 0x08048550 0x080485d2 0x00000000 0x00000001 P...............
entry4.fini中已被引用.fini_array。转到主要和反汇编。检查输入的存储位置
│ 0x080487d5 a1409d0408 mov eax, dword [obj.stdin] ; [0x8049d40:4]=0
│ 0x080487da 83ec04 sub esp, 4
│ 0x080487dd 50 push eax ; FILE *stream
│ 0x080487de 6a23 push 0x23 ; '#' ; 35 ; int size
│ 0x080487e0 68609d0408 push 0x8049d60 ; char *s
│ 0x080487e5 e826fcffff call sym.imp.fgets ; char *fgets(char *s, int size, FILE *stream)
来自 fgets 的输入将到达 0x8049d60。你也可以给它命名f input 35 @ 0x8049d60。检查其上的外部参照
[0x08048790]> axt 0x8049d60
entry4.fini 0x80486ec [DATA] push 0x8049d60
main 0x80487c8 [DATA] push 0x8049d60
main 0x80487e0 [DATA] push 0x8049d60
main 0x80487f8 [DATA] push 0x8049d60
main 0x8048808 [DATA] movzx eax, byte [eax + 0x8049d60]
main 0x8048816 [DATA] push 0x8049d60
main 0x8048826 [DATA] mov byte [eax + 0x8049d60], 0
main 0x8048835 [DATA] push 0x8049d60
main 0x804885b [DATA] push 0x8049d60
entry4.fini还引用了输入。拆开它。
│ 0x080486ec 68609d0408 push 0x8049d60 ; const char *s
│ 0x080486f1 e85afdffff call sym.imp.strlen ; size_t strlen(const char *s)
│ 0x080486f6 83c410 add esp, 0x10
│ 0x080486f9 83f822 cmp eax, 0x22 ; '"' ; 34
首先检查您的输入是否为 34 字节长。
│ 0x080486f9 83f822 cmp eax, 0x22 ; '"' ; 34
│ ┌─< 0x080486fc 7405 je 0x8048703
│ ┌──< 0x080486fe e988000000 jmp 0x804878b
│ ││ ; CODE XREF from entry4.fini (0x80486fc)
│ │└─> 0x08048703 c745f4000000. mov dword [local_ch], 0
│ │┌─< 0x0804870a eb2c jmp 0x8048738
│ ││ ; CODE XREF from entry4.fini (0x804873c)
│ ┌───> 0x0804870c 8d55d1 lea edx, [local_2fh]
│ ⁝││ 0x0804870f 8b45f4 mov eax, dword [local_ch]
│ ⁝││ 0x08048712 01d0 add eax, edx
│ ⁝││ 0x08048714 0fb600 movzx eax, byte [eax]
│ ⁝││ 0x08048717 0fbed0 movsx edx, al
│ ⁝││ 0x0804871a 8b45f4 mov eax, dword [local_ch]
│ ⁝││ 0x0804871d 05609d0408 add eax, 0x8049d60
│ ⁝││ 0x08048722 0fb600 movzx eax, byte [eax]
│ ⁝││ 0x08048725 83f033 xor eax, 0x33
│ ⁝││ 0x08048728 0fbec0 movsx eax, al
│ ⁝││ 0x0804872b 0fb6c0 movzx eax, al
│ ⁝││ 0x0804872e 39c2 cmp edx, eax
│ ┌────< 0x08048730 7402 je 0x8048734
│ ┌─────< 0x08048732 eb57 jmp 0x804878b
│ ││⁝││ ; CODE XREF from entry4.fini (0x8048730)
│ │└────> 0x08048734 8345f401 add dword [local_ch], 1
│ │ ⁝││ ; CODE XREF from entry4.fini (0x804870a)
│ │ ⁝│└─> 0x08048738 837df421 cmp dword [local_ch], 0x21 ; [0x21:4]=-1 ; '!' ; 33
│ │ └───< 0x0804873c 7ece jle 0x804870c
│ │ │ 0x0804873e c745f4000000. mov dword [local_ch], 0
│ │ │┌─< 0x08048745 eb21 jmp 0x8048768
第二次检查涉及对每个字节local_2fh与 0x33进行异或,并逐字节与输入进行比较。启动 VM 转储内存(来自 local_2fh 的 0x22 字节)并执行异或操作。
[0x080484a0]> s entry4.fini
[0x080485d2]> aei
[0x080485d2]> aeim
[0x080485d2]> aeip
局部变量被分配到指令 0x08048665 以进行检查。模拟和转储值。
[0x080485d2]> aesu 0x08048665
[0x08048659]> pcp 0x22 @ebp-0x2f
import struct
buf = struct.pack ("34B", *[
0x02,0x5d,0x02,0x67,0x6c,0x07,0x5d,0x77,0x6c,0x75,0x02,
0x5d,0x02,0x6c,0x07,0x41,0x61,0x07,0x6a,0x40,0x6c,0x07,
0x41,0x00,0x6c,0x60,0x03,0x6c,0x00,0x07,0x40,0x6a,0x12,
0x12])
[0x00000041]> !python
Python 2.7.15rc1 (default, Apr 15 2018, 21:51:34)
[GCC 7.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import struct
>>> buf = struct.pack ("34B", *[
... 0x02,0x5d,0x02,0x67,0x6c,0x07,0x5d,0x77,0x6c,0x75,0x02,
... 0x5d,0x02,0x6c,0x07,0x41,0x61,0x07,0x6a,0x40,0x6c,0x07,
... 0x41,0x00,0x6c,0x60,0x03,0x6c,0x00,0x07,0x40,0x6a,0x12,
... 0x12])
>>> print ''.join(map(lambda x:chr(ord(x)^0x33),buf))
1n1T_4nD_F1n1_4rR4Ys_4r3_S0_34sY!!
这有效
./wysiNwyg
#########################################################
### Welcome to the "wysiNwyg" challenge!
### Your task is to find out the password to be able
### to decrypt the password-protected zip and read
### the secret flag. Good Luck!!
#########################################################
Password: 1n1T_4nD_F1n1_4rR4Ys_4r3_S0_34sY!!
Congratulations! You just won :p