反调试专题丨反调试之最朴实的招式最致命

反调试之最朴实的招式最致命

反调试手段检测花样层出不穷,今天来介绍俩种相对简单的手段,但是却能达到出其不意的效果。

在系统编程中我们遍历进程,模块,线程,堆的时候都需要用到一个函数:CreateToolhelp32Snapshot,其函数原型及其解释如下:

HANDLE CreateToolhelp32Snapshot(
  [in] DWORD dwFlags,
  [in] DWORD th32ProcessID
);
//获取指定进程的快照,以及这些进程使用的堆、模块和线程。

TH32CS_INHERIT:0x80000000

指示快照句柄是可继承的。

TH32CS_SNAPALL

包括系统中的所有进程和线程,以及 th32ProcessID 中指定的进程的堆和模块。 等效于使用 OR 操作 。

TH32CS_SNAPHEAPLIST:0x00000001

包括快照中 th32ProcessID 中指定的进程的所有堆。 若要枚举堆,请参阅 Heap32ListFirst。

TH32CS_SNAPMODULE:0x00000008

包括快照中 th32ProcessID 中指定的进程的所有模块。 若要枚举模块,请参阅 Module32First。 如果函数失败 且ERROR_BAD_LENGTH,请重试该函数,直到函数成功。

TH32CS_SNAPMODULE32:0x00000010

64 位 Windows: 在 32 位进程中使用此标志包括 第 32 个ProcessID 中指定的进程的 32 位模块,而在 64 位进程中使用它包括 64 位模块。若要从 64 位进程包含 在 th32ProcessID 中指定的进程的 32 位模块,请使用 TH32CS_SNAPMODULE32 标志。从 64 位进程调用时,在快照中包含 在 th32ProcessID 中指定的进程的所有 32 位模块。此标志可以与 TH32CS_SNAPMODULE 或 TH32CS_SNAPALL结合使用。 如果函数失败 且ERROR_BAD_LENGTH,请重试该函数,直到函数成功。

TH32CS_SNAPPROCESS:0x00000002

在快照中包含系统中的所有进程。 若要枚举进程,请参阅 Process32First。

TH32CS_SNAPTHREAD:0x00000004

在快照中包含系统中的所有线程。 若要枚举线程,请参阅 Thread32First。

接下来通过此函数完成进程遍历:

#include
#include
#include


int main()
{
PROCESSENTRY32 pe32 = { 0 };
pe32.dwSize = sizeof(PROCESSENTRY32);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
BOOL bRet = Process32First(hSnap, &pe32);
do
{
printf("Process Name:%S\n", pe32.szExeFile);
printf("Process ID:%d\n", pe32.th32ProcessID);
} while (Process32Next(hSnap, &pe32));
CloseHandle(hSnap);
system("pause");
return 0;
}

运行效果如下:

 

那么遍历出进程名,就可以开始对各种调试器进行名称查找,如果找到,说明开启了调试器,这里以x32dbg为例:

#include
#include
#include


int main()
{
PROCESSENTRY32 pe32 = { 0 };
pe32.dwSize = sizeof(PROCESSENTRY32);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
BOOL bRet = Process32First(hSnap, &pe32);
do
{
/*printf("Process Name:%S\n", pe32.szExeFile);
printf("Process ID:%d\n", pe32.th32ProcessID);*/
if (wcsstr(pe32.szExeFile,L"x32dbg.exe") != 0)
{
printf("被调试");
system("pause");
return 0;
}
} while (Process32Next(hSnap, &pe32));
CloseHandle(hSnap);
printf("一切正常");
system("pause");
return 0;
}

效果如下:

 

 

同样的道理,除了可以通过遍历进程名检检查是否有调试器开启,还可以遍历窗口名称,就像这一块:

 

 

这里用到函数FindWindow,函数介绍如下:

//检索顶级窗口的句柄,该窗口的类名称和窗口名称与指定的字符串匹配。此函数不搜索子窗口。此函数不执行区分大小写.
//的搜索。若要搜索子窗口,请从指定的子窗口开始,请使用 FindWindowEx 函数。
HWND FindWindowA(
  [in, optional] LPCSTR lpClassName,
  [in, optional] LPCSTR lpWindowName
);
[in, optional] lpClassName
类型: LPCTSTR
类名或上一次对 RegisterClass 或 RegisterClassEx 函数的调用创建的类名或类原子。原子必须位于 lpClassName 的低序单词中;高阶单词必须为零。
如果 lpClassName 指向字符串,则指定窗口类名。类名可以是向 RegisterClass 或 RegisterClassEx 注册的任何名称,也可以是预定义控件类名称中的任何名称。
如果 lpClassName 为 NULL,它将查找其标题与 lpWindowName 参数匹配的任何窗口。
[in, optional] lpWindowName
类型: LPCTSTR
窗口名称 (窗口的标题) 。如果此参数为 NULL,则所有窗口名称都匹配。

#include
#include
#include


int main()
{
HWND hWnd = NULL;
hWnd = FindWindow(NULL, L"x32dbg");
if (hWnd != NULL)
{
printf("被调试");
}
else {
printf("一切正常");
}
system("pause");
return 0;
}

 

 

注:这里单纯演示手法,在主函数中进行检测

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

极安御信安全研究院

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值