祥云杯2021复盘

re_Dizzy

  1. 反汇编出main函数,导出汇编文件(.asm)
  2. 利用正则表达式将所有加密功能的汇编代表转换为python语法表示
  3. 使用脚本计算flag
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    with open('./Dizzy.exe.asm') as f:
    lines = f.readlines()

    lines.reverse()

    flag = [0x27 ,0x3C ,0x0E3,0x0FC,0x2E ,0x41 ,7,0x5E ,0x62 ,0x0CF,0x0E8,0x0F2,0x92,0x80,0x0E2,0x36 ,0x0B4,0x0B2,0x67 ,0x77 ,0x0F,0x0F6,0x0D,0x0B6,0x0ED,0x1C,0x65 ,0x8A,7,0x53 ,0x0A6,0x66]

    for line in lines:
    if '-' in line:
    tmp = line.replace('-', '+')
    exec(tmp)
    continue
    elif '+' in line:
    tmp = line.replace('+', '-')
    exec(tmp)
    else:
    exec(line)

    for f in flag:
    print(chr(f & 0xff), end='')

re_勒索解密

  1. 编译、运行以下C++程序
  2. 在生成的bmp文件中寻找0x424d开头的文件
  3. 打开图片
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include <Windows.h>
#include <wincrypt.h>
#include <stdio.h>
#include <string>
#pragma comment(lib, "advapi32.lib")

#define AES_KEY_SIZE 16
#define CHUNK_SIZE (0xD6850) // an output buffer must be a multiple of the key size
const size_t sizeChunk = CHUNK_SIZE;
BYTE bsChunk[sizeChunk] = { 0 };

int main(int argc, const char* argv[])
{
int x = 0;

while (x < 65536)
{
DWORD dwStatus = 0;
BOOL bResult = FALSE;
char info[] = "Microsoft Enhanced RSA and AES Cryptographic Provider";
HCRYPTPROV hProv;
char key_str[] = "\xB2\x2F\xC6\x0E\x4F\xD4\x54\x4B\x6c\x81\x1a\x61\x21\xE7\xB1\x8E";
key_str[8] = *((BYTE*)&x);
key_str[9] = *(((BYTE*)&x) + 1);
if (!CryptAcquireContextA(&hProv, NULL, info, 0x18u, 0xF0000000))
{
dwStatus = GetLastError();
printf("CryptAcquireContext failed: %x\n", dwStatus);
CryptReleaseContext(hProv, 0);
return dwStatus;
}

HCRYPTHASH hHash;
if (!CryptCreateHash(hProv, 0x800Cu, 0, 0, &hHash)) {
dwStatus = GetLastError();
printf("CryptCreateHash failed: %x\n", dwStatus);
CryptReleaseContext(hProv, 0);
return dwStatus;
}

if (!CryptHashData(hHash, (BYTE*)key_str, 16, 0)) {
DWORD err = GetLastError();
printf("CryptHashData Failed : %#x\n", err);
system("pause");
return (-1);
}

HCRYPTKEY hKey;
if (!CryptDeriveKey(hProv, 0x660Eu, hHash, 0, &hKey)) {
dwStatus = GetLastError();
printf("CryptDeriveKey failed: %x\n", dwStatus);
CryptReleaseContext(hProv, 0);
return dwStatus;
}

BOOL bIsFinal = FALSE;
LPCWSTR lpwszInputFile = L"D:\\CTF\\祥云杯2021\\勒索解密_a6b0af561d5ad1ff25888265806a1be3\\flag.bmp.ctf_crypter";
wchar_t lpwszOut[MAX_PATH];

swprintf_s(lpwszOut, MAX_PATH, L"D:\\CTF\\祥云杯2021\\勒索解密_a6b0af561d5ad1ff25888265806a1be3\\flag-%d.bmp");
LPCWSTR lpwszOutputFile = lpwszOut;
HANDLE hInputFile = CreateFileW(lpwszInputFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
HANDLE hOutputFile = CreateFileW(lpwszOutputFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

if (hInputFile == NULL || hOutputFile == NULL)
{
dwStatus = GetLastError();
printf("CreateFileW failed: %x\n", dwStatus);
CryptReleaseContext(hProv, 0);
return dwStatus;
}

DWORD dwInputFileSize = GetFileSize(hInputFile, NULL);
DWORD dwTotalReadFileSize = 0;
DWORD dwReadFileLen = 0;
BYTE* pbOutBytes = (BYTE*)malloc(sizeof(BYTE) * dwInputFileSize);
int i = 0;

BYTE dwData[4];

*((DWORD*)dwData) = 1;

CryptSetKeyParam(hKey, KP_PADDING, (BYTE*)&dwData, 0);
CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwData, 0);

while (bResult = ReadFile(hInputFile, bsChunk, sizeChunk, &dwReadFileLen, NULL))
{
if (dwReadFileLen == 0) break;

if (dwReadFileLen < sizeChunk)
{
bIsFinal = TRUE;
}

printf("i=%d, read=%d, total_read=%d, is_final=%d\n", i, dwReadFileLen, dwTotalReadFileSize, bIsFinal);

if (!CryptDecrypt(hKey, NULL, bIsFinal, 0, bsChunk, &dwReadFileLen))
{
printf("[-] CryptDecrypt failed %x\n", GetLastError());
break;
}

DWORD written = 0;
if (!WriteFile(hOutputFile, bsChunk, dwReadFileLen, &written, NULL)) {
printf("writing failed!\n");
break;
}

memset(bsChunk, 0, sizeChunk);
i++;
}
x++;
}
}