2023腾讯游戏安全PC决赛复现
题目
(一)解题过程
第一问让我们杀死进程,可以尝试根据windowsAPI提供的TerminateProcess函数去停止进程,写份代码测试下
复制代码 隐藏代码
bool KillProcessByName(const char* processName) {
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 pe;
pe.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(hSnapshot, &pe)) {
do {
if (strcmp(pe.szExeFile, processName) == 0) {
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe.th32ProcessID);
if (hProcess) {
TerminateProcess(hProcess, 0);
CloseHandle(hProcess);
Num++;
printf("Kill suc:[%d]\n", Num);
}
}
} while (Process32Next(hSnapshot, &pe));
}
CloseHandle(hSnapshot);
return true;
}
int main()
{
while(1)
{
KillProcessByName("WorkingService.exe");
}
return 0;
}
以管理员身份启动测试
启动前:
https://attach.52pojie.cn/forum/202408/13/200155gg5qjqur5jqqjl9q.png
启动后
https://attach.52pojie.cn/forum/202408/13/200157z44jqqst4vt62she.png
https://attach.52pojie.cn/forum/202408/13/200159vdqd07o93qzdqtp7.png
(二)解题过程
先DIE查壳发现有VMP,只能动调入手,先观察程序功能。程序启动后会有两个进程启动,并且其中之一占用CPU性能较高;程序目录会创建十六个文件,并会做重复的删除和重新创建的操作;观察任务管理器发现进程会自动重启,手动杀死进程后就会重生一个新的进程。
拖进xdbg里观察符号,发现引入了ShellExcuteA这个函数,正好是启动进程函数,对这个函数下断点,发现确实断了下来,观察传参窗口。
https://attach.52pojie.cn/forum/202408/13/200201el3khztqtcvk37l3.png
第六个参数不同,对应的是lpParameters(传入进程的参数),一个是working
,一个是daemon restart
根据这个在控制台上运行加上参数working,发现只有一个工作进程,CPU占用100%,同理加上daemon restart,只有一个守护进程CPU占用不到1%。
调试参数为working的进程,观察线程发现有16个线程运行同一个函数,刚好对应16个txt日志文件的输出!!!
https://attach.52pojie.cn/forum/202408/13/200059iwby5ytvhjvzhhyb.png
于是进入线程入口开始分析,对所有可能的写入文件的windowsAPI下断,发现都没有断下来,于是向CreateFile等API下断,
所有线程在CreateFileA上成功断下,观察传参确定这是对日志文件的操作函数
https://attach.52pojie.cn/forum/202408/13/200101l7sayj2nuv6skyo4.png
有了这个依据,能确认的就是16个线程会循环通过CreateFileA打开文件,这可能是占用CPU的一个主要因素。但是跟之前运行的结果不同,调试发现,写入文件的API一直没有被调用,而正常运行的结果是,十六个文件会循环的做一个过程,文件被创建->文件被写入->文件被删除->新文件创建…。我通过加working参数运行,只会有一个循环过程,即不会有新文件诞生,文件内容也不会被修改。所以,十六个线程循环CreateFileA打开文件过程是无用功,只会徒增CPU负担!那么我们是不是可以HOOK CreateFileA这个函数,然后每个线程调用它的第二次的时候我们进行线程终止,是不是可以减少CPU的压力了呢?写份代码跑一下看看
复制代码 隐藏代码
#include "pch.h"
#include <windows.h>
#include <shellapi.h>
#include <detours.h>
#include <tlhelp32.h>
#pragma comment(lib,"detours.lib")
#define _DEBUG
#define DBGMGEBOX(fmt, ...) \
do { \
/* 假设最大长度为1024,根据需要调整大小 */ \
wsprintfA(out, fmt, __VA_ARGS__); \
MessageBoxA(NULL, out, "提示", MB_OK); \
} while(0)
char out[100];
DWORD tlsIndex;//tls索引
typedef BOOL(WINAPI* ShellExecuteExA_t)(SHELLEXECUTEINFOA*);
typedef HANDLE (WINAPI* CreateFileA_t)(
LPCSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile
);
ShellExecuteExA_t TrueShellExecuteExA = NULL;
CreateFileA_t TrueCreateFileA = NULL;
BOOL WINAPI HookedShellExecuteExA(SHELLEXECUTEINFOA* pExecInfo) {
#if 1
//执行第一个ShellExecuteExA守护进程
static int Num = 0;
DBGMGEBOX("ShellExecuteExA 被调用:Num = %d\nhProcess = %p", Num, pExecInfo->hProcess);
if (Num == 0)
{
Num++;
return TrueShellExecuteExA(pExecInfo);
}
else
{
return TrueShellExecuteExA(pExecInfo);
}
#else
//执行第二个ShellExecuteExA病毒进程
static int Num = 0;
DBGMGEBOX("ShellExecuteExA 被调用:Num = %d \n调用者窗口句柄 = 0x%p\n", Num, pExecInfo->hwnd);
if (Num == 0)
{
Num++;
DBGMGEBOX("[2]:当前线程ID:%d", GetCurrentThreadId());
pExecInfo->lpFile = "C:\\Users\\Administrator\\Desktop\\自动F8直到call.txt";//修改参数导致重启失败;
return TrueShellExecuteExA(pExecInfo);
}
else
{
DBGMGEBOX("[1]:当前线程ID:%d", GetCurrentThreadId());
return TrueShellExecuteExA(pExecInfo);
}
#endif
}
HANDLE WINAPI HookCreateFileA(
LPCSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile
)
{
//判断线程是否是第一次运行CreateFileA,是的话就放行,不是第一次运行就终止线程
// 获取当前线程的TLS值
LPVOID tlsValue = TlsGetValue(tlsIndex);
if (tlsValue == NULL)
{
// 第一次运行,设置TLS值
#ifdef _DEBUG
DBGMGEBOX("放行\nlpFileName:%s\n", lpFileName);
#endif
TlsSetValue(tlsIndex, (LPVOID)1);
}
else
{
// 不是第一次运行,终止线程
#ifdef _DEBUG
DBGMGEBOX("终止\nlpFileName:%s\n", lpFileName);
#endif
ExitThread(0);
}
return CreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
/*TrueShellExecuteExA = (ShellExecuteExA_t)DetourFindFunction("shell32.dll", "ShellExecuteExA");
DetourAttach(&(PVOID&)TrueShellExecuteExA, HookedShellExecuteExA);*/
tlsIndex = TlsAlloc();//初始化TLS
TrueCreateFileA = (CreateFileA_t)DetourFindFunction("kernelbase.dll", "CreateFileA");
DetourAttach(&(PVOID&)TrueCreateFileA, HookCreateFileA);
DetourTransactionCommit();
break;
case DLL_PROCESS_DETACH:
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)TrueShellExecuteExA, HookedShellExecuteExA);
DetourDetach(&(PVOID&)TrueCreateFileA, HookCreateFileA);
TlsFree(tlsIndex);//清理TLS
DetourTransactionCommit();
break;
}
return TRUE;
}
注入进去查看CPU,与不注入的CPU情况对比如图,进程CPU占比显著下降
一旦您浏览本站,即表示您已接受以下条约:
1.使用辅助可能会违反游戏协议,甚至违法,用户有权决定使用,并自行承担风险;
2.本站辅助严禁用于任何形式的商业用途,若被恶意贩卖,利益与本站无关;
3.本站为非营利性网站,但为了分担服务器等运营费用,收费均为赞助,没有任何利益收益。
死神科技 » 2023腾讯游戏安全PC决赛复现