当前位置: 首页 > news >正文

软件反调试(2)- 基于窗口列表的检测

反调原理

通过枚举屏幕上所有的窗口,来检测当前是否打开了调试器

EnumWindows 枚举的时候,会进行窗口回调处理,直到所有窗口回调都结束后函数才返回

VS 提供了 Spy++ 可以查看窗口的信息,通过工具下的菜单可以打开 Spy++ 程序

20250702181531

打开 Spy++ 程序,并打开其搜索窗口,左键按下窗口上的圆饼,并将光标拖动到应用的窗口上

这时候,搜索窗口上就会显示要查看窗口的信息,如这里显示窗口标题为 x64dbg [管理员]

20250702182006

在打开 x64dbg 的情况下,通过 CheckDebugWindowByEnum 函数,编译并运行 anti02.exe 程序,终端显示输出如下的信息

20250702185742

除了通过 EnumWindows 的方式进行枚举,也可以通过 GetWindow 的方式进行遍历查找窗口

每个进程的主窗口通常都是顶级窗口,一个进程通常会有一个到多个顶级窗口,可以通过遍历顶级窗口搜索目标进程

通过 CheckDebugWindowByFind 函数,编译并运行 anti02.exe 程序,终端显示输出如下的信息

20250702185659

实现代码

完成的实现代码如下,包含前面说的两种方式 CheckDebugWindowByEnum 和 CheckDebugWindowByFind


#include <iostream>
#include <thread>
#include <string>
#include <vector>
#include <windows.h>
#include <TlHelp32.h>BOOL isDebugging = FALSE;
std::string g_szWindowsTile = "";BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{char windows_title[256] = { 0 };char class_name[256] = { 0 };GetWindowText(hwnd, windows_title, 256);if (strlen(windows_title) > 0 && strstr(windows_title, g_szWindowsTile.c_str()) != 0){std::cout << "handle:" << hwnd << " find debug windows:" << windows_title << std::endl;isDebugging = TRUE;}return TRUE;
}bool CheckDebugWindowByEnum(const char* szWindowTitle)
{isDebugging = false;g_szWindowsTile = szWindowTitle;EnumWindows(EnumWindowsProc, NULL);return isDebugging;
}bool CheckDebugWindowByFind(const char* szWindowName)
{std::vector<HWND> vec;HWND hWnd = GetTopWindow(0);while (hWnd){if (GetParent(hWnd) == 0){vec.push_back(hWnd);}hWnd = GetWindow(hWnd, GW_HWNDNEXT);}char szTempName[MAX_PATH] = { 0 };for (auto& v : vec){GetWindowTextA(v, szTempName, MAX_PATH);if (strstr(szTempName, szWindowName) != 0){std::cout << "find debug windows:" << szTempName << std::endl;return true;}memset(szTempName, 0, sizeof(szTempName));}return false;
}void ThreadProc()
{while (true){if (CheckDebugWindowByFind("x64dbg")) //CheckDebugWindowByEnum("x64dbg"){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;
}

逆向处理

和前面的[基于进程列表的检测]一样,修改内存中的 x64dbg 字符串,然后保存到补丁文件

重新运行补丁过的文件,已经去掉了基于窗口列表的反调试检测

http://www.lqws.cn/news/605215.html

相关文章:

  • javaWeb02-Tomcat
  • 一些ubuntu命令记录(持续补充)
  • Harbor镜像仓库修改端口号密码
  • HarmonyOS 页面路由Router切换组件导航Navigation
  • 操作系统考试大题-处理机调度算法-详解-2
  • 【GHS】Green Hills软件MULTI-IDE的安装教程
  • 文心快码答用户问|Comate AI IDE专场
  • UniApp(vue3+vite)如何原生引入TailwindCSS(4)
  • 如何备份和恢复 Ubuntu 系统 ?
  • Electron 快速上手
  • AWS RDS Aurora全局数据库转区域数据库实战指南:无缝迁移零停机
  • 数学建模_插值
  • 银行回单ocr api集成解析-图像文字识别-文字识别技术
  • Linux--线程池
  • Node.js 使用 WebSockets 和 Socket.IO 实现实时聊天应用程序
  • 移动conda虚拟环境的安装目录
  • MAC 多应用切换技巧,单应用切换技巧
  • Adobe高阶技巧与设计师创意思维的进阶指南
  • 「日拱一码」015 机器学习常用库——scikit-learn
  • Appium与Appium Inspector配置教程
  • 埃隆・马斯克公司Neuralink 2025发布:脑机接口的跨越式突破
  • 【GNSS定位原理及算法杂记2】GNSS观测量:伪距、载波相位、多普勒频移
  • Day 24
  • 使用 Ansys Discovery 为初学者准备几何结构
  • IDS检测原理和架构
  • 分布式定时任务:xxl-job
  • CDC是什么?一文讲清CDC如何打通数据孤岛
  • linux升级降级内核实验
  • 使用 Pytorch Lightning 时追踪指标和可视化指标
  • JavaEE-博客系统项目