-
-
[原创]KCTF2021第7题WP
-
发表于: 2021-12-3 10:14 15358
-
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")#endifDWORD 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")#endifDWORD 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")
[培训]科锐软件逆向54期预科班、正式班开始火爆招生报名啦!!!