吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3312|回复: 41
上一主题 下一主题
收起左侧

[系统底层] 手搓Nt*或Zw*函数,避免被hook 支持x86_x64

  [复制链接]
跳转到指定楼层
楼主
wtujoxk 发表于 2024-11-6 12:09 回帖奖励
本帖最后由 wtujoxk 于 2024-11-14 13:48 编辑

仅学习,如有错误请指出…………

在加壳软件中,ntdll.dll里的有些API会被加壳软件hook,导致我们在做补丁无法正常执行
如:有的程序会hook NtGetContextThread和NtSetContextThread,导致无法下硬件断点,也有的会hook NtProtectVirtualMemory,无法修改内存属性,就不能修改汇编代码等……
Nt或Zw开头的函数执行的代码是一样的,他们所指向的函数地址都是同一个,具体有什么不同,请自行搜索查看,我这里使用Nt函数进行编写。

代码:

代码是这篇文章代码的优化版:DLL巧妙的绕过被VMP壳HOOK的ZwProtectVirtualMemory

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

static void* lpNtdllBuffer = NULL;
ULONG_PTR CustomNtFunction(const char* functionName)
{
        ULONG_PTR functionAddress = 0;
        char dllPath[MAX_PATH];
        GetSystemDirectoryA(dllPath, MAX_PATH);
        strcat_s(dllPath, MAX_PATH, "\\ntdll.dll");//拼接系统目录ntdll.dll路径
        HMODULE dllHandle = LoadLibraryA(dllPath);
        ULONG_PTR apiAddress = (ULONG_PTR)GetProcAddress(dllHandle, functionName);

        //读取ntdll.dll到内存,程序运行时只读一次
        if (lpNtdllBuffer == NULL)
        {
                HANDLE hFile = CreateFileA(dllPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL);
                if (hFile != INVALID_HANDLE_VALUE)
                 {
                        DWORD dwBytesRead = 0;
                        DWORD dwSize = GetFileSize(hFile, NULL);
                        if (dwSize == INVALID_FILE_SIZE || dwSize == 0) return functionAddress;
                        lpNtdllBuffer = VirtualAlloc(NULL, dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
                        ReadFile(hFile, lpNtdllBuffer, dwSize, &dwBytesRead, NULL);
                        CloseHandle(hFile);
                }
        }

        //通过apiAddress地址获取函数的foa地址
        PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)lpNtdllBuffer;
        //取出PE头结构
        PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)(pDosHeader->e_lfanew + ((ULONG_PTR)pDosHeader));
        //取出节头结构
        PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)((ULONG_PTR)pNtHeaders + sizeof(IMAGE_NT_HEADERS));

        ULONG_PTR foaAddress = 0;
        //Nt函数地址 - ntdll基址 = rva
        ULONG_PTR rva = apiAddress - (ULONG_PTR)dllHandle;
        for (WORD i = 0; i < pNtHeaders->FileHeader.NumberOfSections; ++i)
        {
                if (rva >= pSectionHeader[i].VirtualAddress && rva <= pSectionHeader[i].VirtualAddress + pSectionHeader[i].SizeOfRawData)
                {
                        //找到foa地址
                        foaAddress = rva - pSectionHeader[i].VirtualAddress + pSectionHeader[i].PointerToRawData;
                        break;
                }
        }

#ifndef _WIN64  // x86位8、9位foa值与va值不同,要特殊处理
        memcpy((PVOID)((ULONG_PTR)lpNtdllBuffer + foaAddress + 6), (PVOID)(apiAddress + 6), 6);
#endif
        functionAddress = (ULONG_PTR)lpNtdllBuffer + foaAddress;
        printf("函数名称: %s, 地址:%Ix, 偏移:%Ix\n", functionName, functionAddress, foaAddress);

        //VirtualFree(lpNtdllBuffer, 0, MEM_RELEASE); lpNtdllBuffer = NULL;
        return functionAddress;
}

//NtGetContextThread
typedef BOOL(NTAPI* PNtGetContextThread)(HANDLE hThread, LPCONTEXT lpContext);
PNtGetContextThread pNtGetContextThread;

//NtSetContextThread
typedef BOOL(CALLBACK* PNtSetContextThread)(HANDLE hThread, LPCONTEXT lpContext);
PNtSetContextThread pNtSetContextThread;

//NtProtectVirtualMemory
typedef BOOL(NTAPI* PNtProtectVirtualMemory)(HANDLE hProcess, PVOID* lpAddress, PSIZE_T dwSize, ULONG flNewProtect, PULONG lpflOldProtect);
PNtProtectVirtualMemory pNtProtectVirtualMemory;

int main()
{
        CustomNtFunction("ZwResumeThread");
        CustomNtFunction("NtSuspendThread");

        HANDLE hThread = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
        CONTEXT context;
        memset(&context, 0, sizeof(CONTEXT));
        context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
        //NtGetContextThread
        pNtGetContextThread = (PNtGetContextThread)CustomNtFunction("NtGetContextThread");
        pNtGetContextThread(hThread, &context);

        //NtSetContextThread
        pNtSetContextThread = (PNtSetContextThread)CustomNtFunction("ZwSetContextThread");
        pNtSetContextThread(hThread, &context);

        //NtProtectVirtualMemory
        SIZE_T size = 1;
        ULONG OldProtect = 0;
        PVOID addr = (PVOID)GetModuleHandle(nullptr);
        pNtProtectVirtualMemory = (PNtProtectVirtualMemory)CustomNtFunction("NtProtectVirtualMemory");
        pNtProtectVirtualMemory((HANDLE)-1, &addr, &size, PAGE_EXECUTE_READWRITE, &OldProtect);

        system("pause");
        return 0;
}

最后,实战一个VMP加壳的程序,此程序正常情况下无法修改内存属性

程序下载地址:https://nns.lanzouu.com/iiMLu2ee6sxi
ntdll.h.zip (45.8 KB, 下载次数: 6, 售价: 15 CB吾爱币)

效果演示



免费评分

参与人数 14吾爱币 +16 热心值 +14 收起 理由
Kaibottcher + 1 我很赞同!
allspark + 1 + 1 用心讨论,共获提升!
Tonyha7 + 2 + 1 用心讨论,共获提升!
sam喵喵 + 1 + 1 谢谢@Thanks!
ioyr5995 + 1 + 1 我很赞同!
DearDavies + 1 + 1 用心讨论,共获提升!
kj1004 + 1 + 1 谢谢@Thanks!
xukefei + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
156608225 + 2 + 1 用心讨论,共获提升!
Issacclark1 + 1 谢谢@Thanks!
hunfeifei + 1 + 1 我很赞同!
朱朱你堕落了 + 3 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
SnowRen + 1 + 1 我很赞同!
海水很咸 + 1 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
hunfeifei 发表于 2024-11-7 08:12
goodluckwxl 发表于 2024-11-6 22:02
愿闻其详,我没有明白

正常的 VirtualProtect(a,b,c,d)里面是调用的 VirtualProtectEx 句柄 传递的-1,类似VirtualProtectEx(-1,a,b,c,d),然后调用NtProtectVirtualMemory      
而VMP 会在 NtProtectVirtualMemory
挂上HOOK 做一些检测 ,猜测估计就是判断句柄是否为 -1 ,如果是 -1 则检测 内存是否为 被保护的exe或者dll 的内存地址。如果 是则返回失败。
但是如果 我们openprocess一下 自己的进程  。    HANDLE hProc =  OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());获取 进程句柄,不传-1。 然后手动调用 VirtualProtectEx(hProcess, lpAddress, dwSize, flNewProtect, lpflOldProtect);
就可以过掉这个检测。封装一下就是这样。

static BOOL        WINAPI        _VirtualProtect(
        LPVOID lpAddress,
        DWORD dwSize,
        DWORD flNewProtect,
        PDWORD lpflOldProtect)
{
        static HANDLE hProcess = NULL;
        if (hProcess==NULL) {
                hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
        }
        return VirtualProtectEx(hProcess, lpAddress, dwSize, flNewProtect, lpflOldProtect);
}
推荐
hunfeifei 发表于 2024-11-6 15:51
感谢分享。之前也被VMP的保护坑过。做过这个。后来发现只要 openprocess 一下 ,句柄不用 -1 就可以了
沙发
lc2006 发表于 2024-11-6 12:59
3#
yaoguen 发表于 2024-11-6 13:07
多谢分享,下载试试看
4#
wshq 发表于 2024-11-6 13:51
感谢分享
5#
hbfp 发表于 2024-11-6 14:07
收藏学习,谢谢
7#
影风 发表于 2024-11-6 15:54
shadow api??
8#
wuai52001 发表于 2024-11-6 16:53

感谢分享。
9#
sherlock0209 发表于 2024-11-6 17:24
牛啊,牛啊
10#
910jqkAAAA 发表于 2024-11-6 17:37
还得是你啊
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-21 14:02

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表