[虎符CTF2021]GoEncrypt wp

拖入IDA64,F5反编译,找到主函数main_main(),很多代码没看懂;
先看到main_statictmp_0,跟进发现“input flag”,即程序运行初始显示的字符串;
接着调用fmt_Fprintln()和fmt_Fscanf()函数,按照函数名称理解应该是实现输出输入的功能,跟进去看了一下,还是什么也没看懂;
接着看到main_check()函数,跟进去看到一行代码:
在这里插入图片描述
跟进unk_5041E5,可以发现flag的正则表达式,flag{([0-9a-f]{8})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{12})},flag的长度为32位:
在这里插入图片描述
main_check之后有两行代码:
在这里插入图片描述
跟进main_statictmp_4,发现一串16字节的字符”0F0E0D0C0B0A09080706050403020100h”,即“102030405060708090A0B0C0D0E0F”:
在这里插入图片描述
跟进main_statictmp_5,又发现一串16字节的字符”0CB02275410D9F5EDF39AC745F011C30Eh”,即”EC311F045C79AF3EDF5D910542702CB”:
在这里插入图片描述
接下来有一个main_NewCipher()函数,不知道起的什么作用,另外有一些runtime函数,同样分析不出作用,略过;
接着来到main___myCipher__Encrypt()函数,这个是进行加密的关键函数,加密方法是XTEA,去了解了一下具体内容,XTEA加密的是2个32位无符号整数,密钥为4个32位无符号整数, 加密函数如下:

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=0x9E3779B9;
    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;
}

对照IDA的代码:
在这里插入图片描述
稍作整理:
在这里插入图片描述
猜测之前发现的两个字符串分别为密钥和加密后的数据;
随意输入符合正则表达式的flag{12345678-1234-1234-1234-123456789abc},在第55行代码下断点,动态调试,查看key的值:
在这里插入图片描述
得到key[4] = {0x10203, 0x4050607, 0x8090A0B, 0x0C0D0E0F};
调用main___myCipher__Encrypt()函数加密完成后返回main_main()主函数,接下来调用internal_bytealg_Equal()函数,猜测作用是验证flag的正确性,应该可以在这里找到正确的flag加密后得到的数据;
在internal_bytealg_Equal()处下断点,动态调试,发现有很多连续存储的字符串,跳转到随便一个字符串存储区域,往下拉可以看到与上面发现过的字符相同的一串字符,其首地址存储在RAX中:
在这里插入图片描述
无符号整数的大小为4个字节,flag的长度为32位,每8位组成一个十六进制4字节数据,共有4个数据,分两组进行XTEA加密,从字符串中截取16个字节恰好与上面发现的字符串相同,加密后的数据即为0xEC311F0, 0x45C79AF3, 0xEDF5D910, 0x542702CB;
分析if-else结构,跟进main_statictmp_2发现“error”,跟进main_statictmp_3发现”correct”,跟进main_statictmp_1发现”error”,据此可判断输入的flag正确与否跳转到的代码段;
从网上找到XTEA解密的脚本,略作修改,替换相应数据:

#include <stdio.h>
#include <stdint.h>
 
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=0x12345678, sum=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 data1[2]={0xEC311F0, 0x45C79AF3};
    uint32_t data2[2]={0xEDF5D910, 0x542702CB};
    uint32_t const key[4]={0x10203, 0x4050607, 0x8090A0B, 0x0C0D0E0F};
    unsigned int r=32;//num_rounds建议取值为32
    // v为要加密的数据是两个32位无符号整数
    // k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
    decipher(r, data1, key);
    decipher(r, data2, key);
    printf("解密后的数据1:%x %x\n",data1[0],data1[1]);
    printf("解密后的数据2:%x %x\n",data2[0],data2[1]);
    return 0;
}

编译运行:
在这里插入图片描述
将数据按照正则表达式整理,得到flag{3bbcf9ea-2918-4fee-8a2e-201b47dfcb4e}:
在这里插入图片描述

解题过程有参考:
https://bbs.pediy.com/thread-266935.htm
https://blog.csdn.net/jxnu_666/article/details/115448655
https://blog.csdn.net/qq_37439229/article/details/115424066?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-7.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-7.control
https://blog.csdn.net/gsls200808/article/details/48243019


版权声明:本文为weixin_51706019原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。