《逆向工程核心原理》学习笔记:反调试技术(代码片段)

思源湖的鱼 思源湖的鱼     2023-02-21     680

关键词:

目录

前言

继续学习《逆向工程核心原理》,本篇笔记是第七部分:反调试技术,包括一些静态反调试技术和动态反调试技术

值得注意的是,这本书距今有将近10年了,故这里这些都是比较老的东西了

一、反调试技术概况

反调试技术对调试器和OS有很强的的依赖性,分类如下所示:

二、静态反调试技术

静态反调试技术主要是通过一些API探测调试器,并使程序无法运行

1、PEB

PEB结构体信息可以判断进程是否处于调试状态

介绍具体可见:《逆向工程核心原理》学习笔记(六):高级逆向分析技术

几个用到的成员如下:

结构体成员调试信息破解之法
BeingDebugged调试时值为1用OD将其修改为0即可
Ldr未使用的堆内存区域全部填充0xFEEEFEEE,而Ldr指向的_ PEB _ LDR _ DATA结构体就在堆内存区域0xFEEEFEEE都改写为NULL即可
ProcessHeap指向Heap结构体,非调试状态时,Heap结构体的Flags0x2ForceFlags0x0;调试时这两个值都会变将这两个值改回0x20x0即可
NtGlobalFlag调试时值为0x70用OD将其修改为0即可

一个例子如下:

#include "stdio.h"
#include "windows.h"
#include "tchar.h"

void PEB()

    HMODULE hMod = NULL;
    FARPROC pProc = NULL;
    LPBYTE pTEB = NULL;
    LPBYTE pPEB = NULL;
    BOOL bIsDebugging = FALSE;
    
    // IsDebuggerPresent()
    bIsDebugging = IsDebuggerPresent();
    printf("IsDebuggerPresent() = %d\\n", bIsDebugging);
    if( bIsDebugging )  printf("  => Debugging!!!\\n\\n");
    else                printf("  => Not debugging...\\n\\n");

    // Ldr
    pProc = GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtCurrentTeb");
    pTEB = (LPBYTE)(*pProc)();               // address of TEB
    pPEB = (LPBYTE)*(LPDWORD)(pTEB+0x30);     // address of PEB

    printf("PEB.Ldr\\n");
    DWORD pLdrSig[4] =  0xEEFEEEFE, 0xEEFEEEFE, 0xEEFEEEFE, 0xEEFEEEFE ;
    LPBYTE pLdr = (LPBYTE)*(LPDWORD)(pPEB+0xC);
    __try 
    
        while( TRUE )
        
            if( !memcmp(pLdr, pLdrSig, sizeof(pLdrSig)) )
            
                printf("  => Debugging!!!\\n\\n");
                break;
            

            pLdr++;
        
    
    __except (EXCEPTION_EXECUTE_HANDLER)
    
        printf("  => Not debugging...\\n\\n");
    

    // Process Heap - Flags
    bIsDebugging = FALSE;
    LPBYTE pHeap = (LPBYTE)*(LPDWORD)(pPEB+0x18);
    DWORD dwFlags = *(LPDWORD)(pHeap+0xC);
    printf("PEB.ProcessHeap.Flags = 0x%X\\n", dwFlags);
    if( dwFlags != 0x2 )  printf("  => Debugging!!!\\n\\n");
    else                  printf("  => Not debugging...\\n\\n");

    // Process Heap - ForceFlags
    bIsDebugging = FALSE;
    DWORD dwForceFlags = *(LPDWORD)(pHeap+0x10);
    printf("PEB.ProcessHeap.ForceFlags = 0x%X\\n", dwForceFlags);
    if( dwForceFlags != 0x0 )  printf("  => Debugging!!!\\n\\n");
    else                       printf("  => Not debugging...\\n\\n");

    // NtGlobalFlag
    bIsDebugging = FALSE;
    DWORD dwNtGlobalFlag = *(LPDWORD)(pPEB+0x68);
    printf("PEB.NtGlobalFlag = 0x%X\\n", dwNtGlobalFlag);
    if( (dwNtGlobalFlag & 0x70) == 0x70 )  printf("  => Debugging!!!\\n\\n");
    else                                   printf("  => Not debugging...\\n\\n");


int _tmain(int argc, TCHAR* argv[])

    PEB();

    printf("\\npress any key to quit...\\n");
    _gettch();

    return 0;

2、NtQueryInformationProcess()

NtQueryInformationProcess()定义如下:

NTSYSAPI NTSTATUS NTAPI NtQueryInformationProcess (
  IN 	HANDLE         	ProcessHandle,       // 进程句柄
  IN 	PROCESSINFOCLASS   	InformationClass,      // 信息类型
  OUT PVOID         	ProcessInformation,     // 缓冲指针
  IN 	ULONG          	ProcessInformationLength, // 以字节为单位的缓冲大小
  OUT PULONG         	ReturnLength OPTIONAL     // 写入缓冲的字节数
);

第二个参数PROCESSINFOCLASS是枚举类型,其中与反调试有关的成员有三个:

  • ProcessDebugPort(0x7)
  • ProcessDebugObjectHandle(0x1E)
  • ProcessDebugFlags(0x1F)

(1)ProcessDebugPort(0x7)

进程处于调试状态时,操作系统会为他分配1个调试端口(Debug Port)

PROCESSINFOCLASS设为ProcessDebugPort(0x07) 时,调用NtQueryInformationProcess()函数就可以获取调试端口

  • 若处于调试状态,dwDebugPort会被置为0xFFFFFFFF
  • 若处于非调试状态,dwDebugPort值会被设置为0

(2)ProcessDebugObjectHandle(0x1E)

调试进程时,会生成一个调试对象(Debug Obiect)

NtQueryInformationProcess() 函数的第二个参数值PROCESSINFOCLASSProcessDebugObjectHandle(0x1E)时,函数的第三个参数就能获取到调试对象句柄

  • 进程处于调试状态->调试句柄存在->返回值不为 NULL
  • 处于非调试状态 , 返回值为 NULL

(3)ProcessDebugFlags(0x1F)

调试标志(Debug Flags) 的值也可以判断进程是否处于被调试状态

NtQueryInformationProcess() 第二个参数PROCESSINFOCLASSProcessDebugFlags(0x1F)时,第三个参数:

  • 调试状态:0
  • 非调试状态:1

(4)例子

#include "stdio.h"
#include "windows.h"
#include "tchar.h"

enum PROCESSINFOCLASS

    ProcessBasicInformation = 0,
    ProcessQuotaLimits,
    ProcessIoCounters,
    ProcessVmCounters,
    ProcessTimes,
    ProcessBasePriority,
    ProcessRaisePriority,
    ProcessDebugPort = 7,
    ProcessExceptionPort,
    ProcessAccessToken,
    ProcessLdtInformation,
    ProcessLdtSize,
    ProcessDefaultHardErrorMode,
    ProcessIoPortHandlers,
    ProcessPooledUsageAndLimits,
    ProcessWorkingSetWatch,
    ProcessUserModeIOPL,
    ProcessEnableAlignmentFaultFixup,
    ProcessPriorityClass,
    ProcessWx86Information,
    ProcessHandleCount,
    ProcessAffinityMask,
    ProcessPriorityBoost,
    MaxProcessInfoClass,
    ProcessWow64Information = 26,
    ProcessImageFileName = 27,
    ProcessDebugObjectHandle = 30,
    ProcessDebugFlags = 31,
    SystemKernelDebuggerInformation = 35
;

void MyNtQueryInformationProcess()

    typedef NTSTATUS (WINAPI *NTQUERYINFORMATIONPROCESS)(
        HANDLE ProcessHandle,
        PROCESSINFOCLASS ProcessInformationClass,
        PVOID ProcessInformation,
        ULONG ProcessInformationLength,
        PULONG ReturnLength
    );

    NTQUERYINFORMATIONPROCESS pNtQueryInformationProcess = NULL;

    pNtQueryInformationProcess = (NTQUERYINFORMATIONPROCESS)
                                 GetProcAddress(GetModuleHandle(L"ntdll.dll"), 
                                                "NtQueryInformationProcess");

    // ProcessDebugPort (0x7)
    DWORD dwDebugPort = 0;
    pNtQueryInformationProcess(GetCurrentProcess(),
                               ProcessDebugPort,
                               &dwDebugPort,
                               sizeof(dwDebugPort),
                               NULL);
    printf("NtQueryInformationProcess(ProcessDebugPort) = 0x%X\\n", dwDebugPort);
    if( dwDebugPort != 0x0  )  printf("  => Debugging!!!\\n\\n");
    else                       printf("  => Not debugging...\\n\\n");

    // ProcessDebugObjectHandle (0x1E)
    HANDLE hDebugObject = NULL;
    pNtQueryInformationProcess(GetCurrentProcess(),
                               ProcessDebugObjectHandle,
                               &hDebugObject,
                               sizeof(hDebugObject),
                               NULL);
    printf("NtQueryInformationProcess(ProcessDebugObjectHandle) = 0x%X\\n", hDebugObject);
    if( hDebugObject != 0x0  )  printf("  => Debugging!!!\\n\\n");
    else                        printf("  => Not debugging...\\n\\n");

    // ProcessDebugFlags (0x1F)
    BOOL bDebugFlag = TRUE;
    pNtQueryInformationProcess(GetCurrentProcess(),
                               ProcessDebugFlags,
                               &bDebugFlag,
                               sizeof(bDebugFlag),
                               NULL);
    printf("NtQueryInformationProcess(ProcessDebugFlags) = 0x%X\\n", bDebugFlag);
    if( bDebugFlag == 0x0  )  printf("  => Debugging!!!\\n\\n");
    else                      printf("  => Not debugging...\\n\\n");


int _tmain(int argc, TCHAR* argv[])

    MyNtQueryInformationProcess();

    printf("\\npress any key to quit...\\n");
    _gettch();

    return 0;

(5)破解之法

PROCESSINFOCLASS的值进行操作

  • 直接 HOOK API
  • 修改返回值
  • 利用 OD 插件 strong OD 中 KernelMode 可以绕过

3、NtQuerySystemInformation()

ntdll!NtQuerySystemInformation() API是系统函数,用来获取当前运行的多种OS信息

NTSTATUS WINAPI NtQuerySystemInformation(
    _In_      SYSTEM_INFORMATION_CLASS SystemInformationClass, //指定需要的系统信息类型
    _Inout_   PVOID                    SystemInformation, //结构体地址
    _In_      ULONG                    SystemInformationLength,
    _Out_opt_ PULONG                   ReturnLength
);

SYSTEM_INFORMATION_CLASS 是枚举类型,如下:

调试状态下 SYSTEM_KERNEL_DEBUGGER_INFORMATION.DebuggerEnabled值为1

破解之法:

  • Win XP 编辑boot.ini,删除/debugport=com1 /baudrate=115200 /Debug
  • Win 7 执行bcdedit /debug off

可以参考下:NtQuerySystemInformation用法详解

一个例子如下:

#include "stdio.h"
#include "windows.h"
#include "tchar.h"

void MyNtQuerySystemInformation()

    typedef NTSTATUS (WINAPI *NTQUERYSYSTEMINFORMATION)(
        ULONG SystemInformationClass,
        PVOID SystemInformation,
        ULONG SystemInformationLength,
        PULONG ReturnLength
    );

    typedef struct _SYSTEM_KERNEL_DEBUGGER_INFORMATION 
    
        BOOLEAN DebuggerEnabled;
        BOOLEAN DebuggerNotPresent;
     SYSTEM_KERNEL_DEBUGGER_INFORMATION, *PSYSTEM_KERNEL_DEBUGGER_INFORMATION;

    NTQUERYSYSTEMINFORMATION NtQuerySystemInformation;
  
    NtQuerySystemInformation = (NTQUERYSYSTEMINFORMATION)  
                                GetProcAddress(GetModuleHandle(L"ntdll"), 
                                               "NtQuerySystemInformation");

    ULONG SystemKernelDebuggerInformation = 0x23;
    ULONG ulReturnedLength = 0;
    SYSTEM_KERNEL_DEBUGGER_INFORMATION DebuggerInfo = 0,;

    NtQuerySystemInformation(SystemKernelDebuggerInformation, 
                             (PVOID) &DebuggerInfo, 
                             sizeof(DebuggerInfo),      // 2 bytes
                             &ulReturnedLength);

    printf("NtQuerySystemInformation(SystemKernelDebuggerInformation) = 0x%X 0x%X\\n", 
           DebuggerInfo.DebuggerEnabled, DebuggerInfo.DebuggerNotPresent);
    if( DebuggerInfo.DebuggerEnabled )  printf("  => Debugging!!!\\n\\n");
    else                                printf("  => Not debugging...\\n\\n");


int _tmain(int argc, TCHAR* argv[])

    MyNtQuerySystemInformation();

    printf("\\npress any key to quit...\\n");
    _gettch();

    return 0;

4、NtQueryObject()

ntdll!NtQueryObject()API用来获取各种内核对象的信息

NTSTATUS NtQueryObject(
	_In_opt_  	HANDLE  					Handle,
	_In_        OBJECT_INFORMATION_CLASS 	objectInformationClass,
	_Out_opt_ 	PVOID   					ObjectInformation,
	_In_ 		ULONG 						ObjectInformationLength,
	_Out_opt_ 	PULONG 						ReturnLength
);

类似的,是第二个参数是枚举类型,相关信息的结构体指针返回到第三个参数


使用ObjectAllTypesInformation获取系统所有对象信息,从中检测是否存在调试对象

破解之法:在调用 ntdll.ZwQueryObject() API的CALL ESI指令下断点,然后将栈中ObjectAllTypesInformation的值改为0

一个例子:

#include "stdio.h"
#include "windows.h"
#include "tchar.h"

typedef enum _OBJECT_INFORMATION_CLASS 
    ObjectBasicInformation,
    ObjectNameInformation,
    ObjectTypeInformation,
    ObjectAllTypesInformation,
    ObjectHandleInformation
 OBJECT_INFORMATION_CLASS, *POBJECT_INFORMATION_CLASS;

void MyNtQueryObject()

    typedef struct _LSA_UNICODE_STRING 
        USHORT Length;
        USHORT MaximumLength;
        PWSTR Buffer;
     LSA_UNICODE_STRING, *PLSA_UNICODE_STRING, UNICODE_STRING, *PUNICODE_STRING;

    typedef NTSTATUS (WINAPI *NTQUERYOBJECT)(
        HANDLE Handle,
        OBJECT_INFORMATION_CLASS ObjectInformationClass,
        PVOID ObjectInformation,
        ULONG ObjectInformationLength,
        PULONG ReturnLength
    );
    
    #pragma pack(1)
    typedef struct _OBJECT_TYPE_INFORMATION 
        UNICODE_STRING TypeName;
        ULONG TotalNumberOfHandles;
        ULONG TotalNumberOfObjects;
    OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;

    typedef struct _OBJECT_ALL_INFORMATION 
        ULONG                   NumberOfObjectsTypes;
        OBJECT_TYPE_INFORMATION ObjectTypeInformation[1];
     OBJECT_ALL_INFORMATION, *POBJECT_ALL_INFORMATION;
    #pragma pack()
       
    POBJECT_ALL_INFORMATION pObjectAllInfo = NULL;
    void *pBuf = NULL;
    ULONG lSize = 0;
    BOOL bDebugging = FALSE;

    NTQUERYOBJECT pNtQueryObject = (NTQUERYOBJECT)
                                    GetProcAddress(GetModuleHandle(L"ntdll.dll"), 
                                                   "NtQueryObject");

    // Get the size of the list
    pNtQueryObject(NULL, ObjectAllTypesInformation, &lSize, sizeof(lSize), &lSize);

    // Allocate list buffer
    pBuf = VirtualAlloc(NULL, lSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);

    // Get the actual list
    pNtQueryObject((HANDLE)0xFFFFFFFF, ObjectAllTypesInformation, pBuf, lSize, NULL);

    pObjectAllInfo = (POBJECT_ALL_INFORMATION)pBuf;

    UCHAR *pObjInfoLocation = (UCHAR *)pObjectAllInfo->ObjectTypeInformation;
    POBJECT_TYPE_INFORMATION pObjectTypeInfo = NULL;
    for( UINT i = 0; i < pObjectAllInfo->NumberOfObjectsTypes; i++ )
    
        pObjectTypeInfo = (POBJECT_TYPE_INFORMATION)pObjInfoLocation;
        if( wcscmp(L"DebugObject", pObjectTypeInfo->TypeName.Buffer) == 0 )
        
            bDebugging = (pObjectTypeInfo->TotalNumberOfObjects > 0) ? TRUE : FALSE;
            break;
        
        
        // calculate next struct
        pObjInfoLocation = (UCHAR*)pObjectTypeInfo->TypeName.Buffer;
        pObjInfoLocation += pObjectTypeInfo->TypeName.Length;
        pObjInfoLocation = (UCHAR*)(((ULONG)pObjInfoLocation & 0xFFFFFFFC) + sizeof(ULONG));
    

    if( pBuf )
    VirtualFree(pBuf, 0, MEM_RELEASE);

    printf("NtQueryObject(ObjectAllTypesInformation)\\n");
    if( bDebugging )  printf("  => Debugging!!!\\n\\n");
    else              printf("  => Not debugging...\\n\\n");


int _tmain(int argc, TCHAR* argv[])

    MyNtQueryObject();

    printf("\\npress any key to quit...\\n");
    _gettch();

    return 0;

5、ZwSerInformationThread()

ZwSerInformationThread() 等同于 NtSetInformationThread,通过将ThreadInformationClass设置 ThreadHideFromDebugger(0x11),可以禁止线程产生调试事件。函数原型如下:

typedef enum _THREAD_INFORMATION_CLASS 
        ThreadBasicInformation,
        ThreadTimes,
        ThreadPriority,
        ThreadBasePriority,
        ThreadAffinityMask,
        ThreadImpersonationToken,
        ThreadDescriptorTableEntry,
        ThreadEnableAlignmentFaultFixup,
        ThreadEventPair,
        ThreadQuerySetWin32StartAddress,
        ThreadZeroTlsCell,
        ThreadPerformanceCount,
        ThreadAmILastThread,
        ThreadIdealProcessor,
        ThreadPriorityBoost,
        ThreadSetTlsArrayAddress,
        ThreadIsIoPending,
        ThreadHideFromDebugger           // 17 (0x11)
 THREAD_INFORMATION_CLASS, *PTHREAD_INFORMATION_CLASS;

typedef NTSTATUS (WINAPI* ZWSETINFORMATIONTHREAD)(
        HANDLE ThreadHandle, //接收当前线程的句柄
        THREAD_INFORMATION_CLASS ThreadInformationClass, //表示线程信息类型
        PVOID ThreadInformation,
        ULONG ThreadInformationLength
);

破解方法:调试执行到该函数时,若发现第ThreadInformationClass参数值为 0x11,跳过或者将修改为0

一个例子:

#include "stdio.h"
#include "windows.h"
#include "tchar.h"

void DetachDebugger()

    typedef enum _THREAD_INFORMATION_CLASS 
        ThreadBasicInformation,
        ThreadTimes,
        ThreadPriority,
        ThreadBasePriority,
        ThreadAffinityMask,
        ThreadImpersonationToken,
        ThreadDescriptorTableEntry,
        ThreadEnableAlignmentFaultFixup,
        ThreadEventPair,
        ThreadQuerySetWin32StartAddress,
        ThreadZeroTlsCell,
        ThreadPerformanceCount,
        ThreadAmILastThread,
        ThreadIdealProcessor,
        ThreadPriorityBoost,
        ThreadSetTlsArrayAddress,
        ThreadIsIoPending,
        ThreadHideFromDebugger           // 17 (0x11)
     THREAD_INFORMATION_CLASS, *PTHREAD_INFORMATION_CLASS;

    typedef NTSTATUS (WINAPI* ZWSETINFORMATIONTHREAD)(
        HANDLE ThreadHandle,
        THREAD_INFORMATION_CLASS ThreadInformationClass,
        PVOID ThreadInformation,
        ULONG ThreadInformationLength
    );

    ZWSETINFORMATIONTHREAD pZwSetInformationThread = NULL;《逆向工程核心原理》学习笔记:反调试技术(代码片段)

...4、StolenBytes5、API重定向6、DebugBlocker结语前言继续学习《逆向工程核心原理》,本篇笔记是第七部分:反调试技术,包括一些静态反调试技术和动态反调试技术值得注意的是, 查看详情

《逆向工程核心原理》学习笔记:高级逆向分析技术(代码片段)

...异常处理方法2、SEH说明五、IA-32指令结语前言继续学习《逆向工程核心原理》,本篇笔记是第六部分:高级逆向分析技术,包括TLS、TEB、PEB、SEH和IA-32指令等内容一、TLS回调函数TLS(ThreadLocalStorage,线性局部存... 查看详情

《逆向工程核心原理》学习笔记:高级逆向分析技术(代码片段)

...异常处理方法2、SEH说明五、IA-32指令结语前言继续学习《逆向工程核心原理》,本篇笔记是第六部分:高级逆向分析技术,包括TLS、TEB、PEB、SEH和IA-32指令等内容一、TLS回调函数TLS(ThreadLocalStorage,线性局部存... 查看详情

《逆向工程核心原理》学习笔记:高级逆向分析技术(代码片段)

目录前言一、TLS回调函数1、TLS简介(1)IMAGE_DATA_DIRECTORY(2)IMAGE_TLS_DIRECTORY2、TLS回调函数简介3、示例1:HelloTls.exe4、示例2:TlsTest.exe二、TEB1、TEB简介2、TEB访问方法三、PEB1、PEB简介(1ÿ 查看详情

《逆向工程核心原理》学习笔记:api钩取(代码片段)

目录前言一、API钩取简介1、基础概念2、技术图表二、调试钩取技术1、调试器2、调试流程3、示例:记事本WriteFile()API钩取(1)hookdbg.exe(2)试验三、DLL注入实现IAT钩取技术1、选定目标API2、IAT钩取工作原理3、... 查看详情

《逆向工程核心原理》学习笔记:api钩取(代码片段)

目录前言一、API钩取简介1、基础概念2、技术图表二、调试钩取技术1、调试器2、调试流程3、示例:记事本WriteFile()API钩取(1)hookdbg.exe(2)试验三、DLL注入实现IAT钩取技术1、选定目标API2、IAT钩取工作原理3、... 查看详情

《逆向工程核心原理》学习笔记:api钩取(代码片段)

...xff09;HideProc2.exe(2)stealth2.dll结语前言继续学习《逆向工程核心原理》,本篇笔记是第四部分:API钩取,主要介绍了调试钩取、DLL注入实现IAT钩取、API代码修改钩取和全局API钩取等内容一、API钩取简介1、基础... 查看详情

《逆向工程核心原理》学习笔记:dll注入(代码片段)

目录前言一、windows消息钩取1、钩子2、SetWindowsHookEx()3、键盘消息钩取4、调试练习(1)调试HookMain.exe(2)调试KeyHook.dll二、DLL注入1、CreateRemoteThread()2、AppInit_DLLs三、DLL卸载四、通过修改PE加载DLL1、TextView.exe2、myhac 查看详情

ios逆向笔记之反调试以及反反调试和反反反调试ptrace篇

参考技术A1.ptrace(processtrace进程跟踪)为了方便软件的开发和调试,UNIX早期版本就提供了一种对运行进程进行跟踪和控制的手段,那就是系统调用ptrace.通过ptrace可以实现对另一个进程实现调试和跟踪.同时,ptrace提供了一个非常有用的... 查看详情

《逆向工程核心原理》读书笔记——第10章函数调用约定(代码片段)

第10章10.1函数调用约定10.1.1cdecl10.1.2stdcall10.1.3fastcall其他几种类型:本章学习函数调用约定(CallingConvention)的相关知识。10.1函数调用约定  CallingConvention译成中文是“函数调用约定”,它是对函数调用时如何传递参数的一种约... 查看详情

反调试手法之createprocess反调试(代码片段)

...          反调试手法之CreateProcess反调试在学习Win32创建进程的时候.我们发现了有一个进程信息结构体.STARTUPINFO.这个结构体可以实现反调试.具体CreateProcess可以参考上一篇博客.:  https://www.cnblogs.com/iBinary/p/95715... 查看详情

一种基于tls的高级反调试技术(代码片段)

...越引起人们的重视。在反盗版技术中,起最大作用的当属反调试技术。然而传统的反调试技术都存在一个弱点:他们都在程序真正开始执行之后才采取反调试手段。实际上在反调试代码被执行前,调试器有大量的时间来影响程序... 查看详情

《逆向工程核心原理》学习笔记:64位&windows内核6(代码片段)

...RY3、WinDbg二、内核61、会话2、DLL注入结语前言继续学习《逆向工程核心原理》,本篇笔记是第五部分:64位&Windows内核6一、x641、x64处理器中的变化含有VA的指令大小增加了4个字节虚拟内存从4GB变成16GB通用寄存器的数量... 查看详情

《逆向工程核心原理》学习笔记:64位&windows内核6(代码片段)

...RY3、WinDbg二、内核61、会话2、DLL注入结语前言继续学习《逆向工程核心原理》,本篇笔记是第五部分:64位&Windows内核6一、x641、x64处理器中的变化含有VA的指令大小增加了4个字节虚拟内存从4GB变成16GB通用寄存器的数量... 查看详情

*(长期更新)软考网络工程师学习笔记——section20路由技术原理(代码片段)

目录一、路由器的概念二、路由器的功能三、路由器的端口(一)RJ-45端口(二)Console端口、AUX端口(四)WAN/LAN端口(五)E1/T1端口(六)光纤端口(七)异步/同步端口(八࿰... 查看详情

*(长期更新)软考网络工程师学习笔记——section20路由技术原理(代码片段)

目录一、路由器的概念二、路由器的功能三、路由器的端口(一)RJ-45端口(二)Console端口、AUX端口(四)WAN/LAN端口(五)E1/T1端口(六)光纤端口(七)异步/同步端口(八࿰... 查看详情

学习:反调试之检测类名与标题名(代码片段)

反调试之检测类名与标题名:通过FindWindow函数来进行反调试HWNDFindWindowA(LPCSTRlpClassName,LPCSTRlpWindowName);返回值类型:类型:HWND如果函数成功,则返回值是具有指定类名和窗口名的窗口的句柄。如果函数失败,则返回值为NULL。要获... 查看详情

《逆向工程核心原理》读书笔记——第7章栈帧(代码片段)

第7章栈帧7.1栈帧7.2调试示例:stackframe.exe7.2.1StackFrame.cpp7.2.2开始执行main()函数&生成栈帧7.2.3设置局部变量7.2.4add()函数参数传递与调用7.2.5开始执行add()函数&生成栈帧7.2.6设置add()函数的局部变量(x,y)7.2.7ADD运算7.2.8删除函数add()... 查看详情