反调原理
如果进程是正常运行起来的,那么其父进程应该是 explorer.exe,否则可能处于被调试状态
该检查方式只能进行有限检查,如果进程是通过附加的方式来进行调试的话,那么父进程的检查方式就会失效
如下通过 procexp64
可以查看进程的父进程是哪一个,procexp64
是微软出品的 SysinternalsSuite
工具包中的一款工具
实现代码
#include <iostream>
#include <thread>
#include <string>
#include <vector>
#include <windows.h>
#include <TlHelp32.h>
DWORD GetParentProcessId(DWORD nProcessId)
{
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == INVALID_HANDLE_VALUE)
{
return 0;
}
PROCESSENTRY32 pe32 = { 0 };
pe32.dwSize = sizeof(PROCESSENTRY32);
BOOL bRet = Process32First(hSnapshot, &pe32);
while (bRet)
{
if (pe32.th32ProcessID == nProcessId)
{
CloseHandle(hSnapshot);
return pe32.th32ParentProcessID;
}
bRet = Process32Next(hSnapshot, &pe32);
}
CloseHandle(hSnapshot);
return 0;
}
std::string GetProcessNameByProcessId(DWORD nProcessId)
{
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == INVALID_HANDLE_VALUE)
{
return std::string("");
}
PROCESSENTRY32 pe32 = { 0 };
pe32.dwSize = sizeof(PROCESSENTRY32);
BOOL bRet = Process32First(hSnapshot, &pe32);
while (bRet)
{
if (pe32.th32ProcessID == nProcessId)
{
std::string processName = pe32.szExeFile;
CloseHandle(hSnapshot);
return processName;
}
bRet = Process32Next(hSnapshot, &pe32);
}
CloseHandle(hSnapshot);
return std::string("");
}
bool CheckParentProcess(const char* szProcessName)
{
DWORD nProcessId = GetCurrentProcessId();
DWORD nParentProcessId = GetParentProcessId(nProcessId);
std::string processName = GetProcessNameByProcessId(nParentProcessId);
std::cout << "parent:" << processName << std::endl;
return (strstr(processName.c_str(), szProcessName) == NULL);
}
void ThreadProc()
{
while (true)
{
if (CheckParentProcess("explorer"))
{
std::cout << "Debugging..." << std::endl;
}
else
{
std::cout << "Running..." << std::endl;
}
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
}
int main()
{
std::thread thrd(ThreadProc);
thrd.join();
return 0;
}
逆向处理
基于该方式的逆向,只需要在程序运行起来后,再使用调试工具对其附加调试即可
评论区