C++ 反反调试(PEB)

PEB 反调试参考这篇文章

没错,这也是我写的。(/手动滑稽)

把之前的程序用原版 OD 打开,根据控制台里的 PEB 地址,找到对应的内存地址:
在这里插入图片描述

根据 BeingDebugged 、 NtGlobalFlag_PEB 结构体中的位置,可以发现 01、70 这两个标志(注意这里 main函数还没开始运行,所以程序不会退出,只有当你第一次点击 “运行” 时才会执行到 main,检测代码才会有效。所以我们的任务就是在 main 执行之前,将调试标志擦除)
在这里插入图片描述
依次把 01 和 70 都改成 00,如图:
在这里插入图片描述
再点击 OD 的运行按钮,发现已经 bypass 成功了:
在这里插入图片描述
但是现在还没有完,要知道,一般情况下我们是不知道目标进程 PEB 地址的,所以我们还需要用代码获取 PEB 地址。(主要是获取指定 PID 的 PEB地址,而不是程序本身的 PEB 地址)
在这里插入图片描述

代码:参考样本


// Test_Console.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include <iostream>
#include <windows.h>
#include <subauth.h>

#pragma region 依赖 

#define NT_SUCCESS(x) ((x) >= 0)
#define ProcessBasicInformation 0

typedef
NTSTATUS(WINAPI *pfnNtWow64QueryInformationProcess64)
(HANDLE ProcessHandle, UINT32 ProcessInformationClass,
    PVOID ProcessInformation, UINT32 ProcessInformationLength,
    UINT32* ReturnLength);
 
typedef
NTSTATUS(WINAPI *pfnNtWow64ReadVirtualMemory64)
(HANDLE ProcessHandle, PVOID64 BaseAddress,
    PVOID BufferData, UINT64 BufferLength,
    PUINT64 ReturnLength);
 
typedef
NTSTATUS(WINAPI *pfnNtQueryInformationProcess)
(HANDLE ProcessHandle, ULONG ProcessInformationClass,
    PVOID ProcessInformation, UINT32 ProcessInformationLength,
    UINT32* ReturnLength);
 
template <typename T>
struct _UNICODE_STRING_T
{
    WORD Length;
    WORD MaximumLength;
    T Buffer;
};
 
template <typename T>
struct _LIST_ENTRY_T
{
    T Flink;
    T Blink;
};
 
template <typename T, typename NGF, int A>
struct _PEB_T
{
    typedef T type;
 
    union
    {
        struct
        {
            BYTE InheritedAddressSpace;
            BYTE ReadImageFileExecOptions;
            BYTE BeingDebugged;
            BYTE BitField;
        };
        T dummy01;
    };
    T Mutant;
    T ImageBaseAddress;
    T Ldr;
    T ProcessParameters;
    T SubSystemData;
    T ProcessHeap;
    T FastPebLock;
    T AtlThunkSListPtr;
    T IFEOKey;
    T CrossProcessFlags;
    T UserSharedInfoPtr;
    DWORD SystemReserved;
    DWORD AtlThunkSListPtr32;
    T ApiSetMap;
    T TlsExpansionCounter;
    T TlsBitmap;
    DWORD TlsBitmapBits[2];
    T ReadOnlySharedMemoryBase;
    T HotpatchInformation;
    T ReadOnlyStaticServerData;
    T AnsiCodePageData;
    T OemCodePageData;
    T UnicodeCaseTableData;
    DWORD NumberOfProcessors;
    union
    {
        DWORD NtGlobalFlag;
        NGF dummy02;
    };
    LARGE_INTEGER CriticalSectionTimeout;
    T HeapSegmentReserve;
    T HeapSegmentCommit;
    T HeapDeCommitTotalFreeThreshold;
    T HeapDeCommitFreeBlockThreshold;
    DWORD NumberOfHeaps;
    DWORD MaximumNumberOfHeaps;
    T ProcessHeaps;
    T GdiSharedHandleTable;
    T ProcessStarterHelper;
    T GdiDCAttributeList;
    T LoaderLock;
    DWORD OSMajorVersion;
    DWORD OSMinorVersion;
    WORD OSBuildNumber;
    WORD OSCSDVersion;
    DWORD OSPlatformId;
    DWORD ImageSubsystem;
    DWORD ImageSubsystemMajorVersion;
    T ImageSubsystemMinorVersion;
    T ActiveProcessAffinityMask;
    T GdiHandleBuffer[A];
    T PostProcessInitRoutine;
    T TlsExpansionBitmap;
    DWORD TlsExpansionBitmapBits[32];
    T SessionId;
    ULARGE_INTEGER AppCompatFlags;
    ULARGE_INTEGER AppCompatFlagsUser;
    T pShimData;
    T AppCompatInfo;
    _UNICODE_STRING_T<T> CSDVersion;
    T ActivationContextData;
    T ProcessAssemblyStorageMap;
    T SystemDefaultActivationContextData;
    T SystemAssemblyStorageMap;
    T MinimumStackCommit;
    T FlsCallback;
    _LIST_ENTRY_T<T> FlsListHead;
    T FlsBitmap;
    DWORD FlsBitmapBits[4];
    T FlsHighIndex;
    T WerRegistrationData;
    T WerShipAssertPtr;
    T pContextData;
    T pImageHeaderHash;
    T TracingFlags;
    T CsrServerReadOnlySharedMemoryBase;
};
 
typedef _PEB_T<DWORD, DWORD64, 34> _PEB32;
typedef _PEB_T<DWORD64, DWORD, 30> _PEB64;
 
typedef struct _STRING_32
{
    WORD Length;
    WORD MaximumLength;
    UINT32 Buffer;
} STRING32, *PSTRING32;
 
typedef struct _STRING_64
{
    WORD Length;
    WORD MaximumLength;
    UINT64 Buffer;
} STRING64, *PSTRING64;
 
typedef struct _RTL_DRIVE_LETTER_CURDIR_32
{
    WORD Flags;
    WORD Length;
    ULONG TimeStamp;
    STRING32 DosPath;
} RTL_DRIVE_LETTER_CURDIR32, *PRTL_DRIVE_LETTER_CURDIR32;
 
typedef struct _RTL_DRIVE_LETTER_CURDIR_64
{
    WORD Flags;
    WORD Length;
    ULONG TimeStamp;
    STRING64 DosPath;
} RTL_DRIVE_LETTER_CURDIR64, *PRTL_DRIVE_LETTER_CURDIR64;
 
typedef struct _UNICODE_STRING_32
{
    WORD Length;
    WORD MaximumLength;
    UINT32 Buffer;
} UNICODE_STRING32, *PUNICODE_STRING32;
 
typedef struct _UNICODE_STRING_64
{
    WORD Length;
    WORD MaximumLength;
    UINT64 Buffer;
} UNICODE_STRING64, *PUNICODE_STRING64;
 
 
typedef struct _CURDIR_32
{
    UNICODE_STRING32 DosPath;
    UINT32 Handle;
} CURDIR32, *PCURDIR32;
 
typedef struct _RTL_USER_PROCESS_PARAMETERS_32
{
    ULONG MaximumLength;
    ULONG Length;
    ULONG Flags;
    ULONG DebugFlags;
    UINT32 ConsoleHandle;
    ULONG ConsoleFlags;
    UINT32 StandardInput;
    UINT32 StandardOutput;
    UINT32 StandardError;
    CURDIR32 CurrentDirectory;
    UNICODE_STRING32 DllPath;
    UNICODE_STRING32 ImagePathName;
    UNICODE_STRING32 CommandLine;
    UINT32 Environment;
    ULONG StartingX;
    ULONG StartingY;
    ULONG CountX;
    ULONG CountY;
    ULONG CountCharsX;
    ULONG CountCharsY;
    ULONG FillAttribute;
    ULONG WindowFlags;
    ULONG ShowWindowFlags;
    UNICODE_STRING32 WindowTitle;
    UNICODE_STRING32 DesktopInfo;
    UNICODE_STRING32 ShellInfo;
    UNICODE_STRING32 RuntimeData;
    RTL_DRIVE_LETTER_CURDIR32 CurrentDirectores[32];
    ULONG EnvironmentSize;
} RTL_USER_PROCESS_PARAMETERS32, *PRTL_USER_PROCESS_PARAMETERS32;
 
 
typedef struct _CURDIR_64
{
    UNICODE_STRING64 DosPath;
    UINT64 Handle;
} CURDIR64, *PCURDIR64;
 
typedef struct _RTL_USER_PROCESS_PARAMETERS_64
{
    ULONG MaximumLength;
    ULONG Length;
    ULONG Flags;
    ULONG DebugFlags;
    UINT64 ConsoleHandle;
    ULONG ConsoleFlags;
    UINT64 StandardInput;
    UINT64 StandardOutput;
    UINT64 StandardError;
    CURDIR64 CurrentDirectory;
    UNICODE_STRING64 DllPath;
    UNICODE_STRING64 ImagePathName;
    UNICODE_STRING64 CommandLine;
    UINT64 Environment;
    ULONG StartingX;
    ULONG StartingY;
    ULONG CountX;
    ULONG CountY;
    ULONG CountCharsX;
    ULONG CountCharsY;
    ULONG FillAttribute;
    ULONG WindowFlags;
    ULONG ShowWindowFlags;
    UNICODE_STRING64 WindowTitle;
    UNICODE_STRING64 DesktopInfo;
    UNICODE_STRING64 ShellInfo;
    UNICODE_STRING64 RuntimeData;
    RTL_DRIVE_LETTER_CURDIR64 CurrentDirectores[32];
    ULONG EnvironmentSize;
} RTL_USER_PROCESS_PARAMETERS64, *PRTL_USER_PROCESS_PARAMETERS64;
 
 
 
typedef struct _PROCESS_BASIC_INFORMATION64 {
    NTSTATUS ExitStatus;
    UINT32 Reserved0;
    UINT64 PebBaseAddress;
    UINT64 AffinityMask;
    UINT32 BasePriority;
    UINT32 Reserved1;
    UINT64 UniqueProcessId;
    UINT64 InheritedFromUniqueProcessId;
} PROCESS_BASIC_INFORMATION64;
 
typedef struct _PROCESS_BASIC_INFORMATION32 {
    NTSTATUS ExitStatus;
    UINT32 PebBaseAddress;
    UINT32 AffinityMask;
    UINT32 BasePriority;
    UINT32 UniqueProcessId;
    UINT32 InheritedFromUniqueProcessId;
} PROCESS_BASIC_INFORMATION32;

#pragma endregion

int _tmain(int argc, _TCHAR* argv[])
{
	HANDLE m_ProcessHandle = 
		OpenProcess(
			PROCESS_ALL_ACCESS,		// 所有权限
			FALSE,					// 不继承句柄
			8016					// 进程ID,此处为了方便直接写死
		);
 
    BOOL bSource = FALSE;			// 判断自身进程是否为 64位
    BOOL bTarget = FALSE;			// 判断目标进程是否为 64位
    IsWow64Process(
		GetCurrentProcess(),		// 进程句柄
		&bSource					// 用来接收返回值的变量,64位 FLASE | 32位 TRUE
		);
    IsWow64Process(
		m_ProcessHandle,			// 进程句柄
		&bTarget					// 用来接收返回值的变量,64位 FLASE | 32位 TRUE
		);

	// 目标 64位,自身 32位
    if(bTarget == FALSE && bSource == TRUE)
    {
		// 获取 ntdll.dll 模块句柄
        HMODULE NtdllModule = GetModuleHandle("ntdll.dll");

		pfnNtWow64QueryInformationProcess64 NtWow64QueryInformationProcess64 = (pfnNtWow64QueryInformationProcess64)GetProcAddress(NtdllModule,"NtWow64QueryInformationProcess64");
		pfnNtWow64ReadVirtualMemory64 NtWow64ReadVirtualMemory64 = (pfnNtWow64ReadVirtualMemory64)GetProcAddress(NtdllModule,"NtWow64ReadVirtualMemory64");
        PROCESS_BASIC_INFORMATION64 pbi = {0};
        UINT64 ReturnLength = 0;
        NTSTATUS Status = NtWow64QueryInformationProcess64(m_ProcessHandle,ProcessBasicInformation,&pbi,(UINT32)sizeof(pbi),(UINT32*)&ReturnLength);
 
        if (NT_SUCCESS(Status)){
            _PEB64* Peb = (_PEB64*)malloc(sizeof(_PEB64));
            RTL_USER_PROCESS_PARAMETERS64* ProcessParameters = (RTL_USER_PROCESS_PARAMETERS64*)malloc(sizeof(RTL_USER_PROCESS_PARAMETERS64));
            Status = NtWow64ReadVirtualMemory64(m_ProcessHandle,(PVOID64)pbi.PebBaseAddress,(_PEB64*)Peb,sizeof(_PEB64),&ReturnLength);
			
            std::cout << "PEB地址:" << std::hex << pbi.PebBaseAddress << std::endl;
            //cout << "Ldr:" << hex << Peb->Ldr << endl;
            //cout << "ImageBaseAddress:" << hex << Peb->ImageBaseAddress << endl;
        }
    }
 
    // 目标 32位,自身 32位
    else if (bTarget == TRUE && bSource == TRUE)
    {
        HMODULE NtdllModule = GetModuleHandle("ntdll.dll");
        pfnNtQueryInformationProcess NtQueryInformationProcess = (pfnNtQueryInformationProcess)GetProcAddress(NtdllModule,"NtQueryInformationProcess");
        PROCESS_BASIC_INFORMATION32 pbi = {0};
        UINT32  ReturnLength = 0;
        NTSTATUS Status = NtQueryInformationProcess(m_ProcessHandle,ProcessBasicInformation,&pbi,(UINT32)sizeof(pbi),(UINT32*)&ReturnLength);
        
		if (NT_SUCCESS(Status)){
            _PEB32* Peb = (_PEB32*)malloc(sizeof(_PEB32));
            ReadProcessMemory(m_ProcessHandle, (PVOID)pbi.PebBaseAddress,(_PEB32*)Peb,sizeof(_PEB32),NULL);
           
			std::cout << "PEB地址:" << std::hex << pbi.PebBaseAddress << std::endl;
            //printf("LdrAddress:%x\r\n", ((_PEB32*)Peb)->Ldr);
            //printf("ImageBaseAddress:%x\r\n", ((_PEB32*)Peb)->ImageBaseAddress);
        }
    }

	getchar();
	return 0;
}

效果图:
在这里插入图片描述

注意:

以上所有的操作都是基于本身程序是32位的前提下,如果本身代码被编译成64位则不会有效果!

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值