调试&检测
文章平均质量分 54
反调试、反反调试、检测、过检测
(-: LYSM :-)
这个作者很懒,什么都没留下…
展开
-
[检测&过检测] 重写 ReadProcessMemory 、WriteProcessMemory
一、本文大纲系统调用的两种方式:中断门和快速调用_KUSER_SHARED_DATA 结构使用 cpuid 指令判断当前CPU是否支持快速调用3环进0环需要更改的4个寄存器以 ReadProcessMemory 为例说明系统调用全过程重写 ReadProcessMemory 和 WriteProcessMemoryint 0x2e 和 sysenter 都做了什么工作?二、中断门和快速调用以我的理解,系统调用,即从调用操作系统提供的3环API开始,到进0环,再到返回结果到3环的全过程转载 2021-07-12 19:42:11 · 2433 阅读 · 0 评论 -
[反调试&进程保护] 使用 hook 的方式保护自身进程
以下 HOOK 需要 全局:函数名作用Hook 后NtOpenThread创建内核线程防止调试器在内部创建线程NtOpenProcess打开进程防止OD等调试工具在调试列表中看到kiAttachProcess附加调试进程防止被附加NtReadVirtualMemory读取虚拟内存防止自己进程被读内存(ReadProcessMemory)NtWriteVirtualMemory写内存防止内存被写KdReceivePacketKDCOM原创 2021-04-16 17:46:51 · 1058 阅读 · 0 评论 -
[反调试 r0] KdDisableDebugger
原理这是微软提供的一个 api , KdDisableDebugger 例程禁用内核调试器。NTSTATUS KdDisableDebugger();应用直接调用这个 api 可以让 windbg 与被调试机器脱离,对抗的方法就是 hook 这个 api ,在开头返回 STATUS_SUCCESS 。...原创 2021-04-16 17:37:45 · 605 阅读 · 0 评论 -
[反反调试] 时间
参考关于时间反调试方法参考这里windows 获取系统时间的函数:void GetLocalTime( LPSYSTEMTIME lpSystemTime);void GetSystemTime( LPSYSTEMTIME lpSystemTime);BOOL QueryPerformanceCounter( LARGE_INTEGER *lpPerformanceCount);BOOL QueryPerformanceFrequency( LARGE_INTEGE原创 2020-11-09 16:01:41 · 346 阅读 · 0 评论 -
[反调试 r0] —— KdDebuggerEnabled
理论基础无论是在 32 位系统内存分布,还是在 64 位系统内存分布中,我们知道高地址空间分配给系统内核使用,低地址空间分配给用户进程使用。事实上,用户空间和内核空间其实有一块共享区域(KUSER_SHARED_DATA),大小为 4 KB。它们的内存地址虽然不一样,但是它们都是有同一块物理内存映射出来的,KdDebuggerEnabled 就在存放这一块内存里。对于 32 位系统和 64 位系统来说,这块共享区域对应的内核地址范围以及对应用户空间的地址范围如下表所示:????内核起始地原创 2020-07-03 09:16:14 · 1983 阅读 · 5 评论 -
C++ 反反调试(DbgUiRemoteBreakin)
碰到一个有反调试的软件,正常附加这个进程时是会失败的(进程崩溃)这是因为程序挂钩了 DbgUiRemoteBreakin 这个 API 的原因,打开 PCHunter,查看进程钩子,找到 DbgUiRemoteBreakin 恢复:(恢复后不要忘记刷新下看钩子是否还会自动生成)再次用调试器附加,发现程序已成功断下:神兽致敬 = =...原创 2019-11-19 10:30:37 · 2733 阅读 · 0 评论 -
C++ 反反调试(基于 SEH 的 SetUnhandledExceptionFilter)
C++ 反调试(基于 SEH 的 SetUnhandledExceptionFilter),参考这篇文章上面的反调试说到了在 原版OD 打开我们的测试程序,点击运行后直接终止,如下(没有弹出MessageBoxW)为了验证程序是否真的没有走到第一个 MessageBoxW(参考开头文章中的代码),我们 ctrl+f2 重新运行程序,使用 bp MessageBoxW 下断点,再次点击运行程序...原创 2019-09-20 10:41:46 · 881 阅读 · 0 评论 -
C++ 反反调试(NtQueryInformationProcess)
关于 NtQueryInformationProcess 的反调试参考这篇文章没错! 这也是我写的(可能这就是所谓的自己打自己把 /手动滑稽 |ू・ω・` ))首先我们看下之前写的代码(部分):status = NtQueryInformationProcess( GetCurrentProcess(), // 进程句柄 ...原创 2019-09-17 10:52:53 · 2165 阅读 · 0 评论 -
C++ 反反调试(PEB)
PEB 反调试参考这篇文章没错,这也是我写的。(/手动滑稽)把之前的程序用原版 OD 打开,根据控制台里的 PEB 地址,找到对应的内存地址:根据 BeingDebugged 、 NtGlobalFlag 在 _PEB 结构体中的位置,可以发现 01、70 这两个标志(注意这里 main函数还没开始运行,所以程序不会退出,只有当你第一次点击 “运行” 时才会执行到 main,检测代码才会有...原创 2019-09-10 18:43:15 · 929 阅读 · 0 评论 -
C++ 反反调试(TLS回调函数)
关于 TSL 反调试的内容,参考这篇文章说完反调试,如果不说反反调试就 毫无意义 !下面讲下针对 TLS 回调函数的反反调试方法。引用了 TLS 功能的程序会在 PE 文件里生成一个 TLS 表:进入这个表中查看,发现它的大小为 24 个字节:关于 TLS 的结构体,有 32 位和 64 位两个版本:其中 _IMAGE_TLS_DIRECTORY64 大小为:84+42=40,...原创 2019-09-05 15:18:39 · 1335 阅读 · 0 评论 -
[反调试 r0] DebugPort 端口清零
原理debugport 是在 EPROCESS 结构中的.调试时间会通过 DebugPor t端口将调试事件发送给 ring3 进行调试的.如果设置为0.则 ring3 就无法进行调试了。这是我随便找的一个系统下的 _eprocess 结构kd> !strct eprocess!strct eprocessstruct _EPROCESS (sizeof=648)+000 struct _KPROCESS Pcb+000 struct _DISPATCHER_HEADER Header原创 2021-04-16 17:18:09 · 904 阅读 · 0 评论 -
[反调试] STATUSINFO
背景STARTUPINFO 反调试:程序启动时默认会通过 explorer 资源管理器,调用 CreateProcess() 函数创建的时候会把 STARTUPINFO 结构体中的值设置为0,但如果通过调试器启动程序时该值并不会发生变化,我们可以通过判断结构体中的 dwFlags 参数来实现反调试.代码#include <Windows.h>#include <stdio.h>int IsDebug(){ STARTUPINFO si = {0}; GetStar转载 2020-11-27 19:42:18 · 499 阅读 · 0 评论 -
[检测] CRC 校验内存补丁
背景通常程序中至少包括了代码段,数据段,而数据段中所存储的数据是经常会发生变动的,例如我们的全局变量,静态变量等都会默认存储在数据段,而代码段则不会发生变化,我们在检验时只需要注重.text内存段中的数据完整性即可,针对内存的校验同样可以抵御调试器的CC断点,该断点原理就是在下端处写入int3指令,同样可以检测得到。校验思路如下1.首先从内存得到PE的代码节的RVA和节大小2.根据得到的RVA和节大小计算出crc32或是RC4值3.读取自身保存的原始CRC32值,与校验结果进行比较代码:转载 2020-11-27 17:06:25 · 1023 阅读 · 0 评论 -
[反静态分析] 字符串动态赋值
代码:#include <iostream>#include <Windows.h>using namespace std;int main(){ string s1 = "qwedsazxc"; string s2; s2 += 'q'; s2 += 'a'; s2 += 'z'; s2 += 'x'; s2 += 's'; s2 += 'w'; s2 += 'e'; s2 += 'd'; s2 += 'c'; cout << "原创 2020-11-06 21:04:48 · 223 阅读 · 0 评论 -
反调试 —— 时间
#include <windows.h>#include <iostream>#include <time.h>using namespace std;VOID isDebuger() { time_t Tbefore = time(0); time_t Tafter = time(0); while (1) { Tafter = time(0); if (Tafter - Tbefore &.原创 2020-08-06 18:40:25 · 573 阅读 · 0 评论 -
反调试 - r3 使用 NtQuerySystemInformation 获取 KdKdDebuggerEnable 和 KdDebuggerNotPresent
原理NtQuerySystemInformation 被 ntdll.dll 导出,当第一个参数传入 0x23 (SystemInterruptInformation) 时,会返回一个 SYSTEM_KERNEL_DEBUGGER_INFORMATION 结构,里面的成员KdKdDebuggerEnable 和 KdDebuggerNotPresent 标志系统是否启用内核调试。代码示例// Test_Console_1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。//原创 2020-07-14 18:32:41 · 1297 阅读 · 0 评论 -
反调试 - 调试对象
原理当一个程序被调试时,有两种情况:“打开” 和 “附加” ,分别调用 CreateProcess 和 DebugActiveProcess 创建一个调试对象,而通过检测系统中有无调试对象,可以判断出是否有进程正在被调试。这种方法适用于全局反调试,也就是说即使被调试的程序不是自身,也仍然会被检测到。代码示例// Test_Console_1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。//#include <iostream>#include <W原创 2020-07-14 10:52:05 · 576 阅读 · 0 评论 -
反调试 - OpenProcess 权限
原理在没有调试器的情况下,程序默认没有 “调试权限” 的,在默认权限下使用 OpenProcess 已 PROCESS_QUERY_LIMITED_INFORMATION 作为第一个参数是无法打开类似与 Csrss.exe 这种系统进程的。但如果程序处于被调试状态,就会被赋予一个 “调试权限”,这时 OpenProcess 就会成功。代码示例// Test_Console_1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。//#include <iostream&原创 2020-07-13 17:47:04 · 878 阅读 · 0 评论 -
反调试 - 父进程是否为 explorer.exe
原理正常情况下,我们自己的进程的父进程是 explorer.exe ,当然也有很多进程的父进程不是 explorer.exe(比如服务进程)但这不是我们考虑的范畴。如果程序在调试则父进程是就是调试器进程。代码示例// Test_Console_1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。//#include <iostream>#include <Windows.h>#include <intrin.h>using na原创 2020-07-13 15:21:58 · 847 阅读 · 0 评论 -
反调试 - TrapFlag
原理TrapFlag(陷阱标志位)。这种反调试手段属于异常的范畴,通过设置 eflags 寄存器的值来触发某个异常,当存在调试器时这个异常由调试器接管(不走我们 的异常处理回调函数),但调试器也可以选择不接管这个异常,所以这属于一种低级的反调试手段 ????。代码(以单步异常为例)// Test_Console_1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。//#include <iostream>#include <Windows.h>原创 2020-07-13 11:22:57 · 985 阅读 · 1 评论 -
反调试 - int 2dh , int 3h
原理第 0x2d(45) 号中断处理函数是 KiDebugService,执行Int 2dh指令时,进程如果没有处于被调试状态,将会抛出异常,如果在被调试状态则能够正常执行。我们可以利用这一点检测调试器的存在。如果有调试器,调试器就会接管这个 int 2dh 产生的异常从而不走我们设置的异常回调处理函数,当然如果调试器选择不接管这个异常我们是无法检测出调试器的,所以这是一种比较低级的反调试手段。代码int2d_x64.asm:首先创建一个.cpp 文件,改下后缀为 .asm找到这个asm 文件原创 2020-07-12 23:22:44 · 1111 阅读 · 0 评论 -
反调试 - 硬件断点
原理如果程序设置了硬件断点,则 dr0 - dr7 寄存器的值就会改变,其中 dr0 - dr3存放硬件断点的地址,dr4 - dr5 保留,dr6 存放调试事件的详细信息,dr7 存放断点触发的条件。可以使用 GetThreadContext 获取线程上下文环境,然后读取当前的 dr0 - dr3 有没有值,有的话就说明调试器设置了硬件断点,说明有调试器。但是缺点就是如果调试器没有设置硬件断点的话就无法检测调试器,所以这种方法一般都和其他反调试计数配合使用。????函数介绍/* 检索线程上原创 2020-07-12 15:45:04 · 1257 阅读 · 2 评论 -
反调试 - SetUnhandledExceptionFilter
原理SetUnhandledExceptionFilter 可以注册一个异常处理函数,当一个异常产生且我们的 try - catch(或 try - expect)没有处理处理这个异常时,异常会转交给 SetUnhandledExceptionFilter ,这是我们的应用程序处理异常的最后机会。我们可以自己触发一个异常,然后不在 try-catch 中处理它,如果存在调试器则调试器就会接管这个异常,那么这个异常就不会走到我们的 SetUnhandledExceptionFilter 注册的异常处理原创 2020-07-12 14:48:45 · 5385 阅读 · 0 评论 -
反调试 - CloseHanlde,NtClose
原理就是调用 CloseHandle 释放一个无效句柄,如果没有被调试,那么函数返回FALSE,GetLastError = ERROR_INVALID_HANDLE;但如果被调试,那么系统将抛出异常 C0000008H。代码:// Test_Console_1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。//#include <iostream>#include <Windows.h>using namespace std;typed原创 2020-07-05 19:16:17 · 1168 阅读 · 0 评论 -
反调试 - WUDFPlatform.dll 导出函数
在 C:\Windows\System32 目录下有一个 WUDFPlatform.dll , 这个 dll 中有三个导出函数 —— WudfIsAnyDebuggerPresent,WudfIsKernelDebuggerPresent,WudfIsUserDebuggerPresent:代码示例:// Test_Console_1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。//#include <iostream>#include <Windo原创 2020-07-05 17:42:45 · 684 阅读 · 0 评论 -
反调试 - HeapFlags,HeapForceFlags
peb 中有一个成员 ProcessHeap,这个成员是一个 指针:进程 peb 地址可以用以下代码拿到:(拿 ProcessHeap 就再加上 ProcessHeap 在 _PEB 中的偏移)// x64ULONG64 ul_peb64 = __readgsqword(0x60);// x86ULONG64 ul_peb86 = __readgsqword(0x30);对于 x64 系统,vista 以上版本的 HeapFlags 位于 *ProcessHeap+ 0x70,剩余低原创 2020-07-04 18:50:29 · 848 阅读 · 0 评论 -
反调试 - CheckRemoteDebuggerPresent
和 IsDebuggerPresent 差不多简单的反调试技术 ????BOOL bIsDbgPresent = FALSE;if(CheckRemoteDebuggerPresent(GetCurrentProcess(), &bIsDbgPresent) != 0){ if(bIsDbgPresent == TRUE){ cout << "发现调试器" << endl; } else{ cout << "没有调试器" << end原创 2020-07-04 17:47:00 · 617 阅读 · 0 评论 -
反调试 - IsDebuggerPresent
目前这个是我知道的最简单的反调试方法了 ????if(IsDebuggerPresent() == 0){ cout << "没有调试器" << endl;}else{ cout << "发现调试器" << endl;}原创 2020-07-04 17:29:13 · 419 阅读 · 0 评论 -
[反调试 r0] ValidAccessMask 清零
介绍ValidAccessMask 是调试权限标志,正常的情况下 ValidAccessMask 的值是 0x1FF000F , 如果 ValidAccessMask 被修改为 0,则系统内的所有调试器都会失效。手动找 ValidAccessMask打开 WinDbg , 输入 u NtCreateDebugObject , 这个函数中调用了 DbgkDebugObjectType :输入 dp fffff8060ffeb100` 拿到地址中的值:这是一个 _OBJECT_TYPE 结构体原创 2020-06-11 21:57:55 · 1240 阅读 · 0 评论 -
C++ 反调试(NtSetInformationThread)
先上代码:// Test_Console.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <afx.h> #include <tchar.h>#include <afxwin.h>#include <Windows.h>#include <vector>#inclu...原创 2019-11-20 15:08:42 · 3447 阅读 · 0 评论 -
C++ 反调试(基于 SEH 的 SetUnhandledExceptionFilter)
终于! 终于把静态反调试串了一遍,虽然没有包含全部但是也对反调试的轮廓有了初步的认识。但是这一切才刚刚开始,翻过一座山(坑),还有另一座山(坑)在等着你 ????刚发现 csdn 还有个发表情的功能,这就是传说中的彩蛋吗(以后有机会一定要发一个怎么发表情的教程)参考代码:// Test_Console.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"...原创 2019-09-19 18:08:04 · 1421 阅读 · 0 评论 -
C++ 反调试(ZwSetInformationThread)
这个 API 的功能是:如果程序正在被调试,则强制将自己从调试器里分离出来。代码:#include "stdafx.h"#include <iostream>#include <tchar.h>#include <Windows.h>#include <stdio.h>#pragma region 全局变量 /* ZwSet...原创 2019-09-18 18:25:17 · 2763 阅读 · 0 评论 -
反调试 - NtQueryInformationProcess(ProcessDebugPort,ProcessDebugFlags,ProcessDebugObjectHandle)
NtQueryInformationProcess 是微软 未公开 的一个 API,嗯,这个反调试的方法有一个特点就是 能过吾爱破解版OD! ,其他版本的OD没有尝试,但相信这种反调试手法可以检测大部分的第三方OD。首先需要知道的几点:// NtQueryInformationProcess 函数原型__kernel_entry NTSTATUS NtQueryInformationPro...原创 2019-09-16 15:56:03 · 4162 阅读 · 4 评论 -
反调试 - PEB(BeingDebugged ,NtGlobalFlag)
姜姜姜姜 ··················· ~!如题,PEB 里其实本来有很多可以用来检测调试器的成员(虽然有的本意不一定是,但确实在被调试时会有固定变化),但是在 Win7 之后,能用的只剩下了两个:(所以这到底是好事还是坏事)/*002*/ UCHAR BeingDebugged;/*068*/ LARGE_INTEGER NtGlobalFlag;以上两个都来自于 _PEB...原创 2019-09-10 16:59:23 · 1748 阅读 · 2 评论 -
C++ 反调试 - TLS
这个反调试的手法有一定的局限性,因为 TLS (线程局部存储)只是优先于 main 函数运行而已,并不是专门的反调试,所以 —— 这种反调试只能放置 OD ~ 打开,而不能防止 OD ~ 附加。上代码:// 指定一个 "/INCLUDE:__tls_used" 连接选项#pragma comment(linker, "/INCLUDE:__tls_used")VOID NTAPI TLS...原创 2019-09-05 12:01:32 · 682 阅读 · 0 评论