首页
社区
课程
招聘
[原创]KCTF2021第7题WP
2021-12-3 10:14 14223

[原创]KCTF2021第7题WP

2021-12-3 10:14
14223

1.先尝试搜寻提示字符串未找到,然后祭出CE,搜自己输入的文本,下访问断点。
找到关键逻辑函数:0041D2D0
对逻辑逐一断点调试,分析出每个步骤的功能

-
-
-
2.使用IDA进行动态调试,分析传入序列号base64取返回字符串这个函数
看起来是个thiscall, ecx未知,参数1位传入的BASE64,参数2为接收的BUF

单步走一下

-
-
-
3.跟进取返回结果函数内部分析逻辑(程序BASE为730000)

继续跟进74D840(41D840)
这里发现将一个函数地址 | 上0x3300000000, 在下面再取低8位进行调用,算一个小干扰

继续跟进7456F0(4156F0),这里有点难看了,不过没关系,动态调试发现a3就是初始传入的函数地址7455AC(4155AC)

跟进7455AC(4155AC)

发现在资源段,IDA不能识别,需要手动将其设置为函数,对7455AC处右键-->undefine-->code-->create function

然后我们进入到关键函数了,分析发现底下一个判断就是返回文本"正确"or"错误"

继续分析上续判断条件,看起来是从地址0xFFFFFE4B,0xFFFFFE50,0xFFFFFE12取出一共48个字节数据

 

-
-
-
4.想在取48byte数据后设置一下断点看看数据,结果尝试了CE、OD、X32dbg、IDA调试器后,发现在这个算法内断点都会跳到win32u.dll里去。

查阅资料后发现可能是程序通过WOW64将关键算法转为64位形态去运行了

-
-
-
5.尝试了N遍断点后,换到IDA的windbg调试器发现可以断点!(之前都是选的local windows debug)

对算法下断点,查看ebp-30处48byte的数据如下,是一串BASE64字符串,每次输入不同此值都不变
GYldGg-iIoJlPX9hPXpjPqfdEY21B01TBTzeGqfKNR!!

-
-
-
6.注入DLL,调用程序函数穷举这串BASE64,利用BASE64的3字节转4字节特性对BASE64文本前4个字符进行穷举,发现这个f l a就觉得有戏了("fla"的BASE64为"GYld")

完善穷举代码,输出所有字节

 

当然通过找码表可以实现更快的解密算法,只是当时觉得穷举起来省事

 

程序代码如下,由于库版本可能不同,我的string传入程序会崩溃,临时构造了一个string结构体。函数返回的文本还存在内存泄漏问题。
FLAG:
flag{2021-10-04-yangyangbudeyi}

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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <map>
using namespace std;
#include <windows.h>
#include <stdio.h>
#include "Log/Log.h"
#include "MinHook/include/MinHook.h"
#if _DEBUG
#pragma comment(lib, "MinHook\\lib\\libMinHook-x86-v141-mdd.lib")
#else
#pragma comment(lib, "MinHook\\lib\\libMinHook-x86-v141-md.lib")
#endif
 
 
DWORD g_pModule;
 
 
struct MyString
{
    char* ptr = NULL;
    char buf[12] = { 0 };
    int size = 0;
    int serve = 0;
};
 
//base64  (%string, const char*)
int(__cdecl* g_myfunc_41E530)(int a1, int a2);
void Init()
{
    g_pModule = (DWORD)GetModuleHandleA(NULL);
    LOG_INFO("g_pModule[0x%x]", g_pModule);
    *(DWORD*)&g_myfunc_41E530 = g_pModule + 0x1E530;    //程序BASE函数地址
    LOG_INFO("g_myfunc_41E530[%p]", g_myfunc_41E530);
}
 
void MyBase64(string str, string& str_base64, bool isPrint = true)
{
    str_base64.clear();
    MyString a1;
    MyString a2;
 
    if (str.length() < 18)
    {
        string tmp;
        for (size_t i = 0; i < 18 - str.length(); i++)
        {
            tmp += "1";
        }
        str += tmp;
    }
 
    a2.ptr = (char*)calloc(1, str.length() + 1);
    if (!a2.ptr)return;
    strcpy(a2.ptr, str.c_str());
    a2.size = str.length();
    a2.serve = str.length() + 1;
 
 
    //LOG_INFO("a2[%s]", a2.ptr);
    g_myfunc_41E530((int)&a1, (int)&a2);
    if (a1.ptr)
    {
        if (isPrint)
        {
            LOG_INFO("[%s][%s]", str.c_str(), a1.ptr);
        }
        str_base64 = a1.ptr;
    }
    free(a2.ptr);
}
 
 
std::map<int, string> tmpMap;
void* threadfunc(void* arg)
{
    Sleep(1000);
 
    string str1;
 
    for (size_t i = 0; i < 10; i++)
    {
        tmpMap[i] = "XXX";
    }
    char buf[4] = { 0 };
    char szKey[] = "01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/{}-=";
    int i0 = 0;
    int i1 = 0;
    int i2 = 0;
    for (i0 = 0; i0 < sizeof(szKey); i0++)
    {
        //LOG_INFO("i0==%d", i0);
        buf[0] = szKey[i0];
        for (i1 = 0; i1 < sizeof(szKey); i1++)
        {
            buf[1] = szKey[i1];
            for (i2 = 0; i2 < sizeof(szKey); i2++)
            {
                buf[2] = szKey[i2];
                MyBase64(buf, str1, false);
                if (str1.substr(0, 4) == "GYld")
                {
                    if (tmpMap[0] != "XXX")continue;
                    tmpMap[0] = buf;
                    LOG_INFO("1 OK!!!   %c %c %c", szKey[i0], szKey[i1], szKey[i2]);
                }
                if (str1.substr(0, 4) == "Gg-i")
                {
                    if (tmpMap[1] != "XXX")continue;
                    tmpMap[1] = buf;
                    LOG_INFO("2 OK!!!   %c %c %c", szKey[i0], szKey[i1], szKey[i2]);
                }
                if (str1.substr(0, 4) == "IoJl")
                {
                    if (tmpMap[2] != "XXX")continue;
                    tmpMap[2] = buf;
                    LOG_INFO("3 OK!!!   %c %c %c", szKey[i0], szKey[i1], szKey[i2]);
                }
                if (str1.substr(0, 4) == "PX9h")
                {
                    if (tmpMap[3] != "XXX")continue;
                    tmpMap[3] = buf;
                    LOG_INFO("4 OK!!!   %c %c %c", szKey[i0], szKey[i1], szKey[i2]);
                }
                if (str1.substr(0, 4) == "PXpj")
                {
                    if (tmpMap[4] != "XXX")continue;
                    tmpMap[4] = buf;
                    LOG_INFO("5 OK!!!   %c %c %c", szKey[i0], szKey[i1], szKey[i2]);
                }
                if (str1.substr(0, 4) == "Pqfd")
                {
                    if (tmpMap[5] != "XXX")continue;
                    tmpMap[5] = buf;
                    LOG_INFO("6 OK!!!   %c %c %c", szKey[i0], szKey[i1], szKey[i2]);
                }
                if (str1.substr(0, 4) == "EY21")
                {
                    if (tmpMap[6] != "XXX")continue;
                    tmpMap[6] = buf;
                    LOG_INFO("7 OK!!!   %c %c %c", szKey[i0], szKey[i1], szKey[i2]);
                }
                if (str1.substr(0, 4) == "B01T")
                {
                    if (tmpMap[7] != "XXX")continue;
                    tmpMap[7] = buf;
                    LOG_INFO("8 OK!!!   %c %c %c", szKey[i0], szKey[i1], szKey[i2]);
                }
                if (str1.substr(0, 4) == "BTze")
                {
                    if (tmpMap[8] != "XXX")continue;
                    tmpMap[8] = buf;
                    LOG_INFO("9 OK!!!   %c %c %c", szKey[i0], szKey[i1], szKey[i2]);
                }
                if (str1.substr(0, 4) == "GqfK")
                {
                    if (tmpMap[9] != "XXX")continue;
                    tmpMap[9] = buf;
                    LOG_INFO("10 OK!!!   %c %c %c", szKey[i0], szKey[i1], szKey[i2]);
                }
            }
        }
    }
 
    string szFlag;
    for (size_t i = 0; i < 10; i++)
    {
        szFlag += tmpMap[i];
    }
    LOG_INFO("szFlag1:   %s", szFlag.c_str());
    //30位 有2个!号,所以剩下1
    szFlag += "0";
    for (i0 = 0; i0 < sizeof(szKey); i0++)
    {
        szFlag[30] = szKey[i0];
        MyBase64(szFlag, str1, false);
        if (str1 == "GYldGg-iIoJlPX9hPXpjPqfdEY21B01TBTzeGqfKNR!!")
        {
            LOG_INFO("FLAG:   %s", szFlag.c_str());
        }
    }
    while (true)
    {
        Sleep(100);
    }
    return NULL;
}
 
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        Init();
        CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadfunc, NULL, 0, NULL);
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
 
extern "C" void _declspec(dllexport) aaa()
{
 
}

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

最后于 2021-12-3 10:19 被wx_孤城编辑 ,原因:
收藏
点赞4
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回