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

[原创]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")

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

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