【CTF】Reverse Writeup 魔改tea,smc加密与验证 2022hws 逆向学习

CTF · 2022-08-10 · 1756 人浏览

re1

直接关键词捕捉Tea 那就是tea加密吧

image-20220729163312015

点进tea那个函数里面稍微美化下,可以发现其实是魔改过的xxtea,跑12轮,分了8组。那就直接开逆

image-20220729163344218

改一下现成的脚本

#include<stdio.h>
#include"defs.h"
#include <stdint.h>  

unsigned int enc_2[8] = {
   0x10BD3B47, 0x6155E0F9, 0x6AF7EBC5, 0x8D23435F, 0x1A091605, 0xD43D40EF, 0xB4B16A67, 0x6B3578A9
};
unsigned int data[8] = {
    0xD58F4C91, 0x9A751121, 0xD1F7D6AC, 0x63575833, 0x2A313023, 0xF9750867, 0xB2A9EDA5, 0xD6A7CD37
};
unsigned int data1[8] = {
    0x5DFAFC16, 0x3E3D5252, 0x03623808, 0x6B884FEA, 0xE99A75EB, 0xB741A335, 0x0C77D248, 0xE4908612
};

uint32_t DeryptoLoop(unsigned int num1, unsigned int num2, uint32_t sum, uint32_t index)
{
    unsigned int key[4] = { 0x1234,0x2345,0x4567,0x6789 };
    //unsigned int key[4] = { 4,3,2,2 };
    uint32_t tmp1 = ((num1 >> 3) ^ 16 * num2) + (4 * num1 ^ (num2 >> 5));
    uint32_t tmp2 = (key[(sum >> 2) & 3  ^ index] ^ num2) + (num1 ^ sum);
    return tmp1 ^ tmp2;

}

void decrypt2(unsigned dec_2[8])
{
    unsigned int state[8];
    unsigned int DELTA = 0x6a99b4ac;
    unsigned int key[4] = { 0x1234,0x2345,0x4567,0x6789 };
    int round = 0;
    for (int i = 0; i < 8; i++)
    {
        state[i] = enc_2[i];
    }
    int tmpd = DELTA;
    do {
        state[7] -= DeryptoLoop(state[0], state[6], tmpd, 3);
        state[6] -= DeryptoLoop(state[7], state[5], tmpd, 2);
        state[5] -= DeryptoLoop(state[6], state[4], tmpd, 1);
        state[4] -= DeryptoLoop(state[5], state[3], tmpd, 0);
        state[3] -= DeryptoLoop(state[4], state[2], tmpd, 3);
        state[2] -= DeryptoLoop(state[3], state[1], tmpd, 2);
        state[1] -= DeryptoLoop(state[2], state[0], tmpd, 1);
        state[0] -= DeryptoLoop(state[1], state[7], tmpd, 0);
        tmpd += 0x61C88647;
        round += 1;
    } while (round < 12);
    for (int i = 0; i < 8; i++)
    {
        dec_2[i] = state[i];
    }
}

int main(){
    unsigned int dec_2[8];
    decrypt2(dec_2);
    for (int i = 0; i < 8; i++)
    {
       for (int j = 0; j < 4; j++)
        {
            printf("%c", (dec_2[i] >> (j * 8)) & 0xFF);
        }  
    }
    //puts(dec_2);
    //0x33323130, 0x37363534, 0x31303938, 0x35343332, 0x39383736, 0x33323130, 0x37363534, 0x31303938
    return 0;
}

其中有几个要注意的地方,首先就是初始的delta需要动调一下,先动调跑到最后一轮拿到delta然后再拿来解密。然后就是key是异或0123位这样

最后得到flag:7f943921724d63dc0ac9c6febf99fa88

re2

ida打开可以发现有个TlsCallback_0,main里面有一些怪东西,动调可以发现把输入的东西读入到了byte_41B2EC

image-20220801192325157

然后看TlsCallback_0,经典smc异或,然后新线程执行。动调之后可以看代码,那么直接断在这里

image-20220801192612914

然后看401040的东西,上面一坨拿代码段的字节加起来然后取一个byte,然后用这个和输入进行异或(这个代码段还加了几个花指令,我直接被骗,patch之后发现后面跑不出来.....),下面一堆不用看,直接看最下面

image-20220801192840923

v6是上面一堆操作得到的,和输入没有关系,然后异或,最后进行验证

这个验证循环也比较有意思,他把密文直接放在代码段里面了,可以看到k+4199175,这个地址在代码段里面,过去把密文复制了就行

image-20220801193353098

我最终选择的方式是直接改内存,因为这一堆异或,都是可逆的。先直接把最上面的sleep上的dword改了,再改一下数组长度和输入,直接把输入的改成密文即可

image-20220801193739782

断在这里

image-20220801193814194

点进v7即可看到flag

image-20220801193841251

RE
  1. 鸟叔 2022-09-06

    虽然看不懂,还是支持一下~~
    鸟叔从十年之约而来,欢迎回访~~

Theme Jasmine by Kent Liao