0x01:前言

主要还是加密算法识别,花指令识别,dll反调试(非必要)

0x02:分析

比赛版当中的分析

题目提供了一个exe以及一个dll,exe无壳,ida启动:
图片暂时没看到flag的密文,考虑硬玩ing
第一个是猜1到100的随机数,第二个游戏是贪吃蛇图片怎么操作
噢在dll里面
这里接收输入图片贪吃蛇游戏界面,图片wasd操作我先玩玩图片还有一个,先在ida里面翻一下图片好像是这个函数,有花:图片去一下图片flag密文应该是这一串, 就是那个while(里面的byte_1800A890)

unsigned char ida_chars[] =
{
0x3D, 0x01, 0x1C, 0x19, 0x0B, 0xA0, 0x90, 0x81, 0x5F, 0x67,
0x27, 0x31, 0xA8, 0x9A, 0xA4, 0x74, 0x97, 0x36, 0x21, 0x67,
0xAB, 0x2E, 0xB4, 0xA0, 0x94, 0x18, 0xD3, 0x7D, 0x93, 0xE6,
0x46, 0xE7
};

看起来明文长度应该是16, 看不懂加密算法


赛后复现版:

直到去除花指令这一步之后都是正确的, 当时只是欠缺了加密算法识别这个环节图片实际上当时就是在这里卡住了,我们先尝试用Findcrypt看一下这个dll里面可能包含什么加密算法
图片图片结果是AES,跟进一下看看是不是我们卡住的地方:图片果然就是, 再往上看:图片这一串就是key,交叉引用找了一下发现有初始化:图片但没有设定随机数种子的语句,有可能有花,看一下:图片果然有花,去一下:图片不难注意到这里虽然有v1-v32一共32个变量,但是被用作aes中的变量只有16个,所以我们只看srand(114514)之后的就可以了, 继续往下看:图片这里的if()里面貌似有反调试的指令,正常来说我们走的是反调试的那边,可以看看else里面装了什么:图片貌似就是把刚才随机数种子为114514的那串东西进行异或0x17的操作。知道了全部的魔改,现在该恢复这段东西了, 注意这里用到了随机数种子, 要在windows环境下运行

#include<iostream>
using namespace std;

int main()
{
unsigned int key[16] = { 0 };
srand(114514);
for (int i = 0;i < 16;i++)
{
int v = rand();
key[i] = 0x17 ^ ((v+v/255)&0xff);//转换为字节类型再异或
if (key[i] < 16)
cout << "0";
cout << hex << key[i];
}
cout << endl;
return 0;
}
//09e5fdeb683175b6b13b840891eb78d2

最后则是把比赛当时得到的密文拿去进行AES-ECB解密,具体位置在:图片

3D011C190BA090815F672731A89AA47497362167AB2EB4A09418D37D93E646E7

不太会用cyberchef的AES, 这里让ai给我搓了一段python代码来解:

from Crypto.Cipher import AES
import binascii

# 密钥和密文
key = binascii.unhexlify('09e5fdeb683175b6b13b840891eb78d2')
ciphertext = binascii.unhexlify('3D011C190BA090815F672731A89AA47497362167AB2EB4A09418D37D93E646E7')

# 创建AES解密器
cipher = AES.new(key, AES.MODE_ECB)

# 解密
decrypted = cipher.decrypt(ciphertext)

# 输出结果
print(decrypted.decode('utf-8'))

0x03:get flag

得到flag:

VNCTF{W0w_u_g0t_Fuk0's_st4rf1sh}