CTF-Reverse
首发于CTF-Reverse

第三届强网杯-RE(4/5)

强网先锋

base64

justre

  • windows逆向,打开main后,定位字符串到达sub_401BD0函数
  • 内部如下
  • 其中输入存在v1中,传入两个函数,一个是1610,一个是18a0,其中18a0里面什么也没有但是查看汇编可以看到大段明显的字节数据,怀疑这里存在smc(代码自修改)或者花指令,而下图中的CODE XREF更证明了我的猜测,也就是说sub_401610函数中存在对这段代码进行修改的过程
  • 逆向sub_401610函数发现前面是很熟悉的字符串转data,也就是类似于"1"->1的转换操作后面就是一堆很烦人的SSE指令集

但是可以看一下参数,这些东西和输入没有什么关系,这里先不管,那么输入其实是到了下一行的地方

这里的v20是循环下标i,v3和v11都是之前输入转换成的数据,这里用来运算,循环8轮,这里实际上就是8个算式,这里用z3解出来结果

from z3 import *

S = Solver()
x = BitVec("x",32)
y = BitVec("y",32)

S.add(y == y&0xff)


data = [ 659593944,
  663789525,
  51647302,
  207884977,
  4277163693,
  52128309,
  2387884190,
  22803995]

enc = [ 608471104,
  612666700,
  508,
  256901226,
  472138769,
  1005800,
  2369808896,
  38282372]

for i in range(16,24):
        S.add(enc[i-16] == (i + x) ^ (0x1010101 * y + data[i-16]))

print S.check()
print S.model()

这里拿到的是前十位的结果,之前的逆向可知,输入格式是hex。

伪代码中出现了rdtsc,是获取时间的操作,这里利用这个来实现反调试,当调试的时候,运行处在两个rdtsc汇编指令中间的代码就会花费更长的时间。通过这个时间差便可以检测是否处在调试中

后面直接是明文比较,所以其实可以直接将数据从401848中拿出来复制到18a0的函数头的位置,恢复后面的函数可以发现,很明显的des,而且调用了三次,这里直接将key dump下来,便可以获取后段flag

wasm

又是wasm逆向,这种题目说白了其实都是各种套路,当时手慢了只拿了一个三血

这种题目其实就是wasm2c,然后配合着wasm2c中存在的几个头文件,进行编译,注意不要链接,会报错,其实就是借助gcc优化一下wasm2c的c语言代码,有兴趣的可以看看那个c有多么难看。。

但是配合gcc的优化,就变得好了很多,可以很明显的看出来是个xtea了

一共4次xtea,key为0,后面连续xor验证,所以提取出来然后进行decode就行了

这种题目其实是需要各种工具,文件一起逆向,后面函数的功能则需要利用浏览器进行调试,最后整理出算法

固件逆向

给了一个镜像,/bin/hello文件是要求逆向的东西,这里将程序拿出来发现是一个mips架构的程序,ida简单逆向可以看出来,两个输入,一个username一个password,然后进行验证,先说逆向的算法部分,username的验证其实就是一个简单的类似于明文比较的东西

这里直接拿到username : 2cbca

然后进入400CC4验证password,可以看一下流程图

是一个类似于分发器的东西,里面存在一些关键运算比如mul,位移,取值等等

在数据区域发现了两个数组,一个是很明显的flagenc,另一个是类似于opcode的字节码,字节码决定flag的运算,最后逐位和flagenc进行比较,注意这里不是采用的单表加密

在jeb-mips中的伪代码也可以看出一堆if else,应该是switch的另外一种表示,但是结构体什么的都特别乱,反编译出的伪代码大概是下面的样子

void* sub_4000CC4(void* param0){
    unsigned int v0;
    void* ptr0 = param0;
    void* ptr1 = malloc(256);
    unsigned int v1 = (unsigned int)&enc;
    *ptr = 0;
    param0 = ptr0 + 40;
    unsigned int v2 = ptr1 + 96;
    unsigned int v3 = ptr1 + 96;
    
    do{
        v0 = * v1;
        v1 += 4;
        *v2 = (short)(*param0);
        ++param0;
        *v3 = v0;
        v2 += 2;
        v3 += 4;
    }
    while(v1 != 4264128);
    
    *(ptrl + 8) = code;
    *(ptr1 + 12) = what;
    param0 = ptr1;
    unsigned int v4 = *(ptr1 + 8);
    v1 = 0;
loc_400850:
    
    do{
        ptr1 = v1*2;
        
        while(1){
            ptr1 = ((unsigned int)(((int)ptr1) + v1))*2 + v4;
            v0 = (unsigned int)(*(ptr1 + 1));
            ++v1;
            v3 = (unsigned int)(*ptr1);
            v2 = (int)(*(ptr1+2));
            ptr1 = (int)(*(ptr1 + 4));
            *param0 = v1;
            
            if(v0 == 0 || *(para + 4) == v0){
                v0 = v3 < 10 ? 1:0;
                
                if(v3 == 9){
                    printf("qwe");
                    return 0;
                }
                else if(v0 == 0){
                    v0 = v3<14?1:0;
                    
                    if(v3 == 13){
                        v1 = *(para0 + 12);
                        v2 = v2 * 4 + v1;
                        *v2 = (unsigned int)(((int)(*(((unsigned int)(((int)ptr1)*4))+v1)))*((int)(*v2)));
                        v1 = *param0;
                        ptr1 = v1*2;
                        continue;
                    }
                    else if(v0 != 0){
                        unsigned char v5 = v3 == 11;
                        v3 = v3 < 12 ? 1 : 0;
                        v1 = *(param0 + 12);
                        
                        if(!v5 && v3 == 0){
                            v2 = v2*4 + v1;
                            *v2 = *(((unsigned int)(((int)ptr1)*4))+v1)^*v2;
                        }
                        else if(!v5){
                            ptr1 = (void*)((*(((unsigned int)(((int)ptr1)*4))+v1)+8)*2 + ((int)param0));
                            *(v2*4 + v1) = (int)(*ptr1);
                        }
                        else{
                            *(v2*4 + v1) = *((unsigned int*)((*(((unsigned int)(((int)ptr1)*4))+v1)+24)*4 + ((int)param0)));
                        }
                        
                        v1 = *param0;
                        ptr1 = v1*2;
                        continue;
                    }
                    else{
                        v0 = v3 < 15 ? 1 : 0;
                        
                        if(v3 == 15){
                            v1 = *(para0 + 12);
                            v2 =v2*4+ v1;
                            *v2 = *v2 < ((unsigned int)(unsigned char)(*((unsigned int)(((int)ptr1) * 4)) + v1))));
                            ptr1 = v1 * 2;
                            continue;
                        }
                        else if(v0 != 0) {
                            v1 = *(param0 + 12);
                            v2=v2*4+v1;
                            v1 = *(((unsigned int)(int)ptr1) * 4)) + v1);
                            unsigned int v6 = (unsigned int)(((int)(*v2)) / ((int)v1));
                            
                            if(v1 == 0){
                                _asm(" BREAK 7");
                            }
                            *v2 = v6;
                            v1 = *parame;
                            ptr1=v1*2;
                            continue;
                        }
                        else{
                            ptr1 = (void*)(((int)ptr1) * 4);
                            
                            if(v3 == 16){
                                v1 = *(parame + 12);
                                v2 =v2*4+ v1;
                                *v2 = *v2 >> ((unsigned int)(unsigned char)(*((unsigned int*)(((int)ptr1) + v1)))));
                                v1 = *param0 ;
                                ptr1 =v1 * 2;
                                continue;
                            }
                            else if(v3 != 255){
                                goto loc_ 400850;
                            }
                            else {
                                return 1;
                            }
                        }
                    }
                }
                else{
                    v0=v3<5?1:0;
                    
                    if(v3 == 4){
                        v1 += v2;
                        *param0 = v1;
                        goto loc_ 400850;
                    }
                    else if(v0 != 0){
                        v0=v3<3?1:0;
                        
                        if(v3!=2&&v0==0){
                            v3 = *(param0 + 12);
                            *(param0 + 4) = *(((unsigned int)(((int)ptr1) * 4)) + v3) != *(v2*4+ v3) ? 2: 1;
                            goto loc_ 400850;
                        }
                        else if(v3 != 2){
                            ptr1 = (void*)(((int)ptr1) * 4);
                            if(v3 != 1){
                                goto loc_ 400850;
                            }
                            else{
                                v1 = *(param0 + 12);
                                v2=v2*4 + v1;
                                *v2 = *((unsigned int*)(((int)ptr1) + v1)) + *v2;
                                v1 = *param0;
                                ptr1=v1*2;
                                continue;
                            }
                        }
                        else{
                            v1 = *(param0 + 12);
                            v2=v2* 4 + v1;
                            *v2 = *v2 - *(((unsigned int)(((int)ptr1) * 4)) + v1);
                            v1 =*param0;
                            ptr1=v1*2;
                            continue;
                        }
                    }
                    else{
                        v0=v3<б?1:0;
                        
                        if(v3 == 6){
                            *(v2 * 4 + *(param0 + 12)) = (int)(((unsigned short)v1));
                            v1 = *param0;
                            ptr1=v1*2;
                            continue;
                        }
                        else if(v0 != 0){
                            v1 = *(param0 + 12);
                            *(v2 * 4 + v1) = *(((unsigned int)((int)ptr1) * 4)) + v1);
                            v1 = *param0;
                            ptr1 = v1 * 2;
                            continue;
                        }
                        else if(v3 != 7){
                            v2 *= 4;
                            
                            if(v3 != 8){
                                goto loc_400850;
                            }
                            else{
                                *(*(param0 + 12) + v2) = ptr1;
                                v1 = *param0;
                                ptr1 = v1*2;
                                continue;
                            }
                        }
                    }
                }
                v1 = *(v2*4 + *(param0 + 12));
                *param0 = *(v2 * 4 + *(param0 + 12));
            }
            
            goto loc_400850;
        }
    }
    while(1);
    return 1;

    
}

最后了解了一下大概逻辑,配合着调试和汇编,整理算法,发现在乘法的代码块中,几个寄存器会出现输入,最后整理出算法为input[i] = (input[i] * out) >> 6,其中out的初值为0x1024,out += i,爆破flag

s = "5B0C0000DD0C00001F0D0000C0180000C6180000260C0000720E0000F70D0000B1190000410D0000080D00001C190000D90C0000B10E0000EE0C0000781A00008B0D0000990D0000640D0000ED0C0000F8190000610E00007F1A0000E71A0000260F0000341B0000D01A00007C0D0000C90F00007E0E00000E1C0000AE1B0000".decode("hex")

from pwn import *

flagenc = []

for i in range(0,len(s),4):
        flagenc.append(u32(s[i:i+4]))

flag = ""

out = 0x1024

for i in range(len(flagenc)):
        for j in range(33,127):
                if(((j * out) >> 6) == flagenc[i]):
                        flag += chr(j)
                        print flag
        out += (i + 1)

print flag

安卓

这个题还没有调试环境,过几天再补上吧

  • 静态逆了一下,拿到aes,怀疑ollvm了aes,然后还能拿到32字节怀疑是key,memcmp拿到80字节的待比较数据,题目中存在5次aes的过程


有不对的还要请师傅们多多指正。。。

发布于 2019-05-28

文章被以下专栏收录