-
-
[原创]KCTF2021第7题WP
-
发表于: 2021-12-3 10:14 14929
-
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}
#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()
{
}
#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"
)
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!