Loading... > `某游戏使用了PE节保护技术,重新映射PE内存,致使PE节不可修改` 参考资料: 1.[[原创]分享下wow PE section保护技术](https://bbs.pediy.com/thread-268057.htm) 2.[Self-Remapping-Code](https://github.com/changeofpace/Self-Remapping-Code) 参考资料1中,是使用lua来实现的内层空间重新映射,自己对这块关注蛮久了,遂使用c/c++进行了实现。 说明:本代码运行于R3层,无需进行驱动开发。 ## 一.结构体定义 ```c/c++ typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } UNICODE_STRING, * PUNICODE_STRING; typedef struct _OBJECT_ATTRIBUTES { ULONG Length; HANDLE RootDirectory; PUNICODE_STRING ObjectName; ULONG Attributes; PVOID SecurityDescriptor; PVOID SecurityQualityOfService; } OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES; typedef enum _SECTION_INHERIT { ViewShare = 1, ViewUnmap = 2 } SECTION_INHERIT, * PSECTION_INHERIT; ``` ## 二.ntdll未导出函数声明及地址获取 ### 1.函数声明 ```c/c++ typedef DWORD(WINAPI* NtSuspendProcess)(HANDLE ProcessHandle); //进程暂停 typedef DWORD(WINAPI* NtResumeProcess)(HANDLE hProcess); //进程恢复 typedef NTSTATUS(NTAPI* NtCreateSection)( _Out_ PHANDLE SectionHandle, _In_ ACCESS_MASK DesiredAccess, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_opt_ PLARGE_INTEGER MaximumSize, _In_ ULONG SectionPageProtection, _In_ ULONG AllocationAttributes, _In_opt_ HANDLE FileHandle ); typedef NTSTATUS (NTAPI* NtMapViewOfSection)( _In_ HANDLE SectionHandle, _In_ HANDLE ProcessHandle, _Inout_ PVOID* BaseAddress, _In_ ULONG_PTR ZeroBits, _In_ SIZE_T CommitSize, _Inout_opt_ PLARGE_INTEGER SectionOffset, _Inout_ PSIZE_T ViewSize, _In_ SECTION_INHERIT InheritDisposition, _In_ ULONG AllocationType, _In_ ULONG Win32Protect ); typedef NTSTATUS(NTAPI* NtUnmapViewOfSection)( _In_ HANDLE ProcessHandle, _In_opt_ PVOID BaseAddress ); typedef NTSTATUS(NTAPI* NtClose)( _In_ HANDLE Handle ); ``` ### 2.函数地址获取 ```c/c++ NtSuspendProcess m_NtSuspendProcess; NtResumeProcess m_NtResumeProcess; NtCreateSection m_NtCreateSection; NtMapViewOfSection m_NtMapViewOfSection; NtUnmapViewOfSection m_NtUnmapViewOfSection; NtClose m_NtClose; HMODULE h_module = LoadLibrary("ntdll.dll"); if (h_module == 0) { printf("loadlibrary error.\n"); return 0; } m_NtResumeProcess = (NtResumeProcess)GetProcAddress(h_module, "NtResumeProcess"); m_NtSuspendProcess = (NtResumeProcess)GetProcAddress(h_module, "NtSuspendProcess"); m_NtCreateSection = (NtCreateSection)GetProcAddress(h_module, "NtCreateSection"); m_NtMapViewOfSection=(NtMapViewOfSection)GetProcAddress(h_module, "NtMapViewOfSection"); m_NtUnmapViewOfSection=(NtUnmapViewOfSection)GetProcAddress(h_module, "NtUnmapViewOfSection"); m_NtClose=(NtClose)GetProcAddress(h_module, "NtClose"); ``` ### 3.核心功能函数实现 ```c/c++ bool RemapViewOfSection(HANDLE handle, DWORD64 baseAddress, DWORD64 regionSize, DWORD NewProtection) { // 申请内存空间以存放目标节内容 auto address = VirtualAlloc(NULL, regionSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (address == 0) { printf("virtualalloc error.\n"); return false; } SIZE_T numberOfBytesRead = 0; //读取目标内存 if (!ReadProcessMemory(handle, (LPCVOID)baseAddress, address, regionSize, &numberOfBytesRead)) { printf("ReadProcessMemory error.\n"); return false; } HANDLE hSection; LARGE_INTEGER cbSectionSize = {}; cbSectionSize.QuadPart = regionSize; //重新申请节 auto ntStatus = m_NtCreateSection(&hSection,SECTION_ALL_ACCESS,NULL,&cbSectionSize,PAGE_EXECUTE_READWRITE,SEC_COMMIT,NULL); if (ntStatus != STATUS_SUCCESS) { printf("NtCreateSection error.\n"); return false; } //释放目标节 if (m_NtUnmapViewOfSection(handle, (LPVOID)baseAddress) != STATUS_SUCCESS) { printf("NtUnmapViewOfSection error.\n"); return false; } SIZE_T cbViewSize = 0; cbSectionSize.QuadPart = 0; //重新映射,注意这里需要将cbSectionSize.QuadPart 置0。 ntStatus = m_NtMapViewOfSection(hSection, handle, (PVOID*)&baseAddress, 0, regionSize, &cbSectionSize, &cbViewSize, ViewUnmap, 0, NewProtection); if (ntStatus != STATUS_SUCCESS) { printf("NtMapViewOfSection error.\n"); return false; } //目标内存数据恢复 if (!WriteProcessMemory(handle, (LPVOID)baseAddress, address, regionSize, &numberOfBytesRead)) { printf("WriteProcessMemory error.\n"); return false; } VirtualFree(address, regionSize, MEM_RELEASE); return true; } ``` 最后修改:2021 年 09 月 22 日 11 : 37 AM © 禁止转载