吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1986|回复: 11
收起左侧

[CTF] 春秋杯Re2024

  [复制链接]
rea1 发表于 2024-7-7 19:43
本帖最后由 rea1 于 2024-7-9 10:22 编辑

Snake
是一个pygame框架的python逆向。
简单的把代码扔给在线解密网站就可以看出来是个RC4,只是最后异或加了一个和循环次数异或。
略过不提了。
但是有一点是,我本来是想试试用CE把分数改成9999来出的,但是,这游戏没法暂停的话我没时间去修改。。一死亡就会结束。对于这一点想的是用IDA调试把它的进程挂起,但终归还是有点拼手速而且好像新建的进程也不属于它了,不会在IDA UI的右下角显示。
总之,最后还是选择去常规逆向了。
HardSignin
做完后总的来说的话,感觉是把一些常规的反调试和加密算法汇总起来出了一道中规中矩的题叭,感觉适合招新做的说。
屏幕截图 2024-07-07 193141.png
他把所有的UPX字样改成了VMP。改回来即可用工具脱掉壳。UPX4.24吧我记得。
手脱的话ESP断点没断住,于是就没有再深挖,做完后来看的话,可能是被反调结束了吗?不知道有没有师傅解答一下。
脱掉后放进IDA会发现一个很明显的TLS_3,于是转过去,查看调用,发现其他的tls。
屏幕截图 2024-07-07 193234.png
然后都加了常规的花指令,去后F5,第一个对main函数代码段进行了异或操作,其他三个均主要是反调试和赋值。
但是这个main异或似乎有点问题,就是没有实现它正常来说的作用,我调试的话每次都会挂掉,main函数被修正后并不能很好地运行。
所以我把这里的异或改成了0.
屏幕截图 2024-07-07 193504.png
同时写了IDC脚本来将代码还原,同时保存。地址根据自己的修改即可。大小一共是170.
[C] 纯文本查看 复制代码
#include <idc.idc>
static main() 
{
    auto x,Fbin,ProcRange;
    for (x=0x401890;x<0x40193A;x=x+1)
    {   Fbin=Byte(x);
           PatchByte (x,Fbin^0x66);//nop掉

    }
}

主要加密函数
image.png
base64+rc4+tea
TLS函数生成了他们的码表和密钥。相应动调获取即可。
然后就是常规解密。
我的解密脚本没放一起,base64和rc4都是常规,这里只放一个容易出错的tea吧。
[C] 纯文本查看 复制代码
#include <stdio.h>  
#include <stdint.h>  

/* take 64 bits of data in v[0] and v[1] and 128 bits of key[0] - key[3] */

void encipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
    unsigned int i;
    uint32_t v0 = v[0], v1 = v[1], sum = 0, delta = 0x61C88647;
    for (i = 0; i < num_rounds; i++) {
        v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
        sum += delta;
        v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
    }
    v[0] = v0; v[1] = v1;
}

void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
    unsigned int i;
    uint32_t v0 = v[0], v1 = v[1], delta = 1640531527, sum = 0 - delta * num_rounds;
    for (i = 0; i < num_rounds; i++) {
        v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
        sum += delta;
        v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
    }
    v[0] = v0; v[1] = v1;
}

int main()
{
    //uint32_t v[2] = { 1,2 };
    //uint32_t const k[4] = { 2,2,3,4 };
    //unsigned int r = 32;//num_rounds建议取值为32  
    //// v为要加密的数据是两个32位无符号整数  
    //// k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位  
    //printf("加密前原始数据:%u %u\n", v[0], v[1]);
    //encipher(r, v, k);
    //printf("加密后的数据:%u %u\n", v[0], v[1]);
    //decipher(r, v, k);
    //printf("解密后的数据:%u %u\n", v[0], v[1]);
    //return 0;
    int i, len, j;
    //密文或明文
    unsigned char eninput[] = { 0x59, 0x1B, 0xFD, 0xB4, 0x6B, 0xB8, 0xBE, 0xD9, 0xB3, 0xD3, 0x77, 0xD6, 0xF0, 0x65, 0x5F, 0x18,
     0xA0, 0x9D, 0x3A, 0x53, 0x6D, 0x4A, 0x7B, 0x26, 0x74, 0x3A, 0x9C, 0x4E, 0x20, 0x43, 0x19, 0xD8,
     0x72, 0xED, 0x95, 0xB5, 0x9C, 0x05, 0x22, 0x56, 0xCB, 0x7A, 0x11, 0x91, 0x9F, 0x7A, 0xBC, 0x0C,
     0x4A, 0x69, 0x6D, 0xCE, 0x3D, 0xB4, 0xAB, 0x29, 0x61, 0xFA, 0x62, 0x32, 0xB4, 0xEC, 0x4C, 0xB6,0x00 };
    len = strlen(eninput);
    eninput[len] = 0;
    int r = 100;//加解密轮数
    //4yZRiNP8LoK/GSA5ElWkUjXtJCz7bMYcuFfpm6+hV0rxeHIdwv32QOTnqg1BDsa9
    //0x49338976, 0xC7C31319, 0x68E4D8AD, 0xBC0448FC
    //0x0CAA5BDD, 0xD6846924, 0x51041EB8, 0x8B2AAB06
    for (i = 0; i < len / 8; i++)
    {
        int* v = (int*)eninput + i * 2, k[] = { 0x0CAA5BDD, 0xD6846924, 0x51041EB8, 0x8B2AAB06 };

        // v为要加密的数据是两个32位无符号整数  
        // k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位  
     /*   encrypt(v, k);
        printf("加密后的数据:%u %u\n", v[0], v[1]);*/
        decipher(r, v, k);
    }
    //printf("%s", eninput);
    for (int g = 0; g < 64; g++)
        printf("0x%x,", eninput[g]);
    return 0;
}


最后的flag
image.png

Bedtea
nim语言,是吧?
image.png
获取时间,下面有一个再次获取时间并比较,小小的反调试。把下面的if改为恒跳转即可。


image.png
反调试,在调试就是1,不是就是3.
这个值会用来生成tea的密钥,生成规律应该是斐波那契数列。


这里两个函数实现了先序遍历创建二叉树,和后序遍历二叉树。最后结果就是把输入进行了倒序。

image.png
三个异或,就是对每个字符进行0x33的异或。
然后就是最后的比较了。
只是这个语言的原因有点难看。。。
image.png
解密脚本
[C] 纯文本查看 复制代码
#include <stdio.h>  
#include <stdint.h>  
#include<string.h>
//加密函数  
void encrypt(uint32_t* v, uint32_t* k) {
    uint32_t v0 = v[0], v1 = v[1], sum =0, i;           /* set up */
    unsigned int delta = 0x61CBB648;                     /* a key schedule constant */
    uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
    i = 0;/* cache key */
    printf("0x%x,0x%x\n", v0, v1);
    do {                       /* basic cycle start */
        sum -= delta;
        v0 += ((v1 >> 4) + k1) ^ (v1 + sum) ^ ((v1*32) + k0);
        v1 += ((v0 >> 4) + k3) ^ (v0 + sum) ^ ((v0*32) + k2);
    } while (sum != 0x987E55D0);

   
    v[0] = v0; v[1] = v1;
}
//解密函数  
void decrypt(uint32_t* v, uint32_t* k) {
    uint32_t v0 = v[0], v1 = v[1], i;  /* set up */
    uint32_t delta = 0x61CBB648;                     /* a key schedule constant */
    unsigned int sum =0x987E55D0;
    uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
    i = 0;/* cache key */
    do {                         /* basic cycle start */
        
        v1 -= ((v0 >> 4) + k3) ^ (v0 + sum) ^ ((v0*32) + k2);

        v0 -= ((v1 >> 4) + k1) ^ (v1 + sum) ^ ((v1*32) + k0);
        sum += delta;
    } while (sum != 0);      
   
    v[0] = v0; v[1] = v1;
}

int main()
{
    int i, len, j;
    //密文或明文
    unsigned char ddd[] = { 0x0076, 0x0071, 0x009D, 0x00E7, 0x0070, 0x0077, 0x003F, 0x00A3,
   0x0002, 0x00F1, 0x008D, 0x00C9, 0x0002, 0x00C6, 0x00A2, 0x004B,
   0x00BA, 0x0019, 0x0056, 0x0005, 0x00F2, 0x0089, 0x005E, 0x00E0,0x00 };
    unsigned char eninput[25];
    for (int i = 0; i < 24; i++)
    {
        ddd[i] ^= 0x33;
    }
    for (int i = 0; i < 24; i++)
    {
        eninput[i] = ddd[23 - i];
        printf("0x%x,", eninput[i]);
    }
    printf("\n\n");
    unsigned char input[] = "123456789012345678901234";
   // unsigned char eninput[] = { 0xd3,0x6d,0xba,0xc1,0x36,0x65,0x2a,0x89,0x78,0x91,0xf5,0x31,0xfa,0xbe,0xc2,0x31,0x90,0xc,0x44,0x43,0xd4,0xae,0x42,0x45,0x00 };
    len = 24;
    eninput[len] = 0;
  
        for (i = 0; i < len / 8; i++)
        {
           unsigned int* v = (int*)eninput + i * 2, k[] = { 0x3, 0x5, 0x8, 0xD };
           unsigned int  k1[] = {0x15,0x22,0x37,0x59};
          unsigned  int k2[] = { 0x00000090, 0x000000E9, 0x00000179, 0x00000262 };
            // v为要加密的数据是两个32位无符号整数  
            // k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位  
         /*   encrypt(v, k);
            printf("加密后的数据:%u %u\n", v[0], v[1]);*/
           if(i==0)
           decrypt(v, k);
           if(i==1)
               decrypt(v, k1);
           if (i==2)
               decrypt(v, k2);
            //encrypt(v, k);
        }

    printf("%s",eninput);
    return 0;

}
//k={8,0xD,0x15,0x22}
//k={0x37,0x59,0x90,0xE9}


flag{y0u_reallyl1ke_te@}
吐槽
第一题没啥好说的,签到叭,第二题的话,常规题叭,就像我上面说的,感觉作为一道招新题还挺合适的,第三题的话,坑不少。。,二叉树那里本来挺难蚌的,感觉现在喜欢往逆向里塞点算法。。而我算法又不好,但是发现只是个倒序倒是松了口气。
然后就是一点吐槽了,前两天本来是有事没咋打这个比赛的,今天想找找wp看下题,结果。。只找到了web的wp没找到逆向的,故自己又做了一下。
到此,希望能给找春秋杯逆向wp的一点帮助。


附件

链接:https://pan.baidu.com/s/10aE6oLsvGYDNviaDbKaDhg?pwd=52pj
提取码:52pj
里面的压缩包是原题文件,其他的是我patch后的exe和ida分析的i64文件。
image.png

点评

建议将原始题目做附件上传或上传到网盘哦  发表于 2024-7-9 02:39

免费评分

参与人数 9威望 +1 吾爱币 +25 热心值 +8 收起 理由
Hmily + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
mikumikujun + 1 用心讨论,共获提升!
zsjdjh + 1 我很赞同!
机制呆萌的我 + 1 + 1 用心讨论,共获提升!
不负韶华 + 1 用心讨论,共获提升!
JerryGod + 1 + 1 用心讨论,共获提升!
discom + 1 我很赞同!
为之奈何? + 1 + 1 我很赞同!
Bob5230 + 1 + 1 热心回复!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| rea1 发表于 2024-7-7 19:47
二叉树那张图片到最下面了。
ghx230011 发表于 2024-7-8 00:17
n1kOvO 发表于 2024-7-8 09:10
WUMEIHAI 发表于 2024-7-8 09:46
感谢分享!
yinxzh 发表于 2024-7-8 09:57
感谢楼主分享!
woshicaodj 发表于 2024-7-8 11:36
加油,支持,感谢
Triple.J 发表于 2024-7-8 12:37
大佬。不过有点看不懂,有大佬能再简化一下吗?
红动中国 发表于 2024-7-8 14:42
大神一如既往的多,谢谢分享
Bag5 发表于 2024-7-8 18:43
感谢大佬的分享,打的时候去花那里卡了一下
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-9-8 09:26

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表