首页
社区
课程
招聘
[原创]手搓Nt*或Zw*函数,避免被hook 支持x86_x64
发表于: 2024-11-6 11:30 7572

[原创]手搓Nt*或Zw*函数,避免被hook 支持x86_x64

2024-11-6 11:30
7572

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

#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;
}
#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;
}
#include <iostream>
#include <windows.h>
  
static void* lpNtdllBuffer = NULL;
ULONG_PTR GetFunctionAddressByName(const char* functionName)
{
    ULONG_PTR functionAddress = 0;
     
    //读取ntdll.dll到内存,程序运行时只读一次
    if (lpNtdllBuffer == NULL)
    {
        char dllPath[MAX_PATH];
        GetSystemDirectoryA(dllPath, MAX_PATH);
        strcat_s(dllPath, MAX_PATH, "\\ntdll.dll");//拼接系统目录ntdll.dll路径
        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);
        }
    }
  
    //取出导出表
    //DLL内存数据转成DOS头结构
    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)lpNtdllBuffer;
    //取出PE头结构
    PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((ULONG_PTR)lpNtdllBuffer + pDosHeader->e_lfanew);
    //判断PE头导出表表是否为空
    if (pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress == 0) return functionAddress;
  
    //取出导出表偏移
    ULONG_PTR FileOffset = pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
  
    //取出节头结构
    PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)((ULONG_PTR)pNtHeaders + sizeof(IMAGE_NT_HEADERS));
    PIMAGE_SECTION_HEADER pOldSectionHeader = pSectionHeader;
    //遍历节结构进行地址运算
    for (WORD Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++)
    {
        if (pSectionHeader->VirtualAddress <= FileOffset && FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)
        {
            FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
            break;
        }
    }
  
    //导出表地址
    PIMAGE_EXPORT_DIRECTORY pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((ULONG_PTR)lpNtdllBuffer + FileOffset);
    //取出导出表函数地址
    FileOffset = pExportDirectory->AddressOfFunctions;
    //遍历节结构进行地址运算
    pSectionHeader = pOldSectionHeader;
    for (WORD Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++)
    {
        if (pSectionHeader->VirtualAddress <= FileOffset && FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)
        {
            FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
            break;
        }
    }
    PLONG AddressOfFunctions = (PLONG)((ULONG_PTR)lpNtdllBuffer + FileOffset);//这里注意一下foa和rva
  
    //取出导出表函数名字
    FileOffset = pExportDirectory->AddressOfNameOrdinals;
  
    //遍历节结构进行地址运算
    pSectionHeader = pOldSectionHeader;
    for (WORD Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++)
    {
        if (pSectionHeader->VirtualAddress <= FileOffset && FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)
        {
            FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
            break;
        }
    }
    PUSHORT AddressOfNameOrdinals = (PUSHORT)((ULONG_PTR)lpNtdllBuffer + FileOffset);//注意一下foa和rva
  
    //取出导出表函数序号
    FileOffset = pExportDirectory->AddressOfNames;
  
    //遍历节结构进行地址运算
    pSectionHeader = pOldSectionHeader;
    for (WORD Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++)
    {
        if (pSectionHeader->VirtualAddress <= FileOffset && FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)
        {
            FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
            break;
        }
    }
    PULONG AddressOfNames = (PULONG)((ULONG_PTR)lpNtdllBuffer + FileOffset);//注意一下foa和rva
  
    //分析导出表
    ULONG uNameOffset;
    ULONG uOffset;
    LPSTR FunName;
    ULONG uAddressOfNames;
    //获取所有导出函数名
    for (DWORD uIndex = 0; uIndex < pExportDirectory->NumberOfNames; uIndex++, AddressOfNames++, AddressOfNameOrdinals++)
    {
        uAddressOfNames = *AddressOfNames;
        pSectionHeader = pOldSectionHeader;
        for (WORD Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++)
        {
            if (pSectionHeader->VirtualAddress <= uAddressOfNames && uAddressOfNames <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)
            {
                uOffset = uAddressOfNames - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
                break;
            }
        }
        FunName = (LPSTR)((ULONG_PTR)lpNtdllBuffer + uOffset);
  
        //得到指定的函数地址
        if (!_stricmp(FunName, functionName))
        {
            pSectionHeader = pOldSectionHeader;
            uOffset = (ULONG)AddressOfFunctions[*AddressOfNameOrdinals];
            for (WORD Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++)
            {
                //计算函数偏移地址
                if (pSectionHeader->VirtualAddress <= uOffset && uOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)
                {
                    uNameOffset = uOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
                    break;
                }
            }
            functionAddress = (ULONG_PTR)lpNtdllBuffer + uNameOffset;
            printf("函数名称: %s, 地址:%Ix, 偏移:%Ix\n", functionName, functionAddress, uNameOffset);
  
            //VirtualFree(lpNtdllBuffer, 0, MEM_RELEASE); lpNtdllBuffer = NULL;
            return functionAddress;
        }
    }
    //VirtualFree(lpNtdllBuffer, 0, MEM_RELEASE); lpNtdllBuffer = NULL;
    return functionAddress;
}
static BYTE* lpJmpWow64TransitionBuffer = NULL;
ULONG_PTR CustomNtFunction2(const char* functionName)
{
#ifdef _WIN64
    return GetFunctionAddressByName(functionName);
#else
    if (lpJmpWow64TransitionBuffer == NULL)
    {
        // 只处理一次Wow64Transition的va地址
        char dllPath[MAX_PATH];
        GetSystemDirectoryA(dllPath, MAX_PATH);
        strcat_s(dllPath, MAX_PATH, "\\ntdll.dll");//拼接系统目录ntdll.dll路径
        //jmp ntdll.Wow64Transition 写到内存
        lpJmpWow64TransitionBuffer = (BYTE*)VirtualAlloc(NULL, sizeof(ULONG_PTR) + 2, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
        lpJmpWow64TransitionBuffer[0] = 0xFF// jmp ntdll.Wow64Transition地址
        lpJmpWow64TransitionBuffer[1] = 0x25;
        ULONG_PTR Wow64TransitionAddress = (ULONG_PTR)GetProcAddress(LoadLibraryA(dllPath), "Wow64Transition");
        memcpy(lpJmpWow64TransitionBuffer + 2, &Wow64TransitionAddress, sizeof(ULONG_PTR));
    }
    //写jmpWow64Transition地址的内存到functionNameAddress+6的位置
    ULONG_PTR functionNameAddress = GetFunctionAddressByName(functionName);
    memcpy((void*)(functionNameAddress + 6), &lpJmpWow64TransitionBuffer, sizeof(ULONG_PTR));
  
    //printf("函数名称: %s, 地址:%Ix,地址2:%Ix\n", functionName, functionNameAddress, lpJmpWow64TransitionBuffer);
    return functionNameAddress;
#endif
}
//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;
  
//extern "C" NTSTATUS NTAPI NtGetContextThread(HANDLE hThread, LPCONTEXT lpContext);
int main()
{
    CustomNtFunction2("ZwResumeThread");
    CustomNtFunction2("NtSuspendThread");
  
    HANDLE hThread = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
    CONTEXT context;
    memset(&context, 0, sizeof(CONTEXT));
    context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
    //NtGetContextThread
    pNtGetContextThread = (PNtGetContextThread)CustomNtFunction2("NtGetContextThread");
    pNtGetContextThread(hThread, &context);
  
    //NtSetContextThread
    pNtSetContextThread = (PNtSetContextThread)CustomNtFunction2("ZwSetContextThread");
    pNtSetContextThread(hThread, &context);
  
    NtProtectVirtualMemory
    SIZE_T size = 1;
    ULONG OldProtect = 0;
    PVOID addr = (PVOID)GetModuleHandle(nullptr);
    pNtProtectVirtualMemory = (PNtProtectVirtualMemory)CustomNtFunction2("NtProtectVirtualMemory");
    pNtProtectVirtualMemory((HANDLE)-1, &addr, &size, PAGE_EXECUTE_READWRITE, &OldProtect);
  
    system("pause");
    return 0;
}
#include <iostream>
#include <windows.h>
  
static void* lpNtdllBuffer = NULL;
ULONG_PTR GetFunctionAddressByName(const char* functionName)
{
    ULONG_PTR functionAddress = 0;
     
    //读取ntdll.dll到内存,程序运行时只读一次
    if (lpNtdllBuffer == NULL)
    {
        char dllPath[MAX_PATH];
        GetSystemDirectoryA(dllPath, MAX_PATH);
        strcat_s(dllPath, MAX_PATH, "\\ntdll.dll");//拼接系统目录ntdll.dll路径
        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);
        }
    }
  
    //取出导出表
    //DLL内存数据转成DOS头结构
    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)lpNtdllBuffer;
    //取出PE头结构
    PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((ULONG_PTR)lpNtdllBuffer + pDosHeader->e_lfanew);
    //判断PE头导出表表是否为空
    if (pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress == 0) return functionAddress;
  
    //取出导出表偏移
    ULONG_PTR FileOffset = pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
  
    //取出节头结构
    PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)((ULONG_PTR)pNtHeaders + sizeof(IMAGE_NT_HEADERS));
    PIMAGE_SECTION_HEADER pOldSectionHeader = pSectionHeader;
    //遍历节结构进行地址运算
    for (WORD Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++)
    {
        if (pSectionHeader->VirtualAddress <= FileOffset && FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)
        {
            FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
            break;
        }
    }
  
    //导出表地址
    PIMAGE_EXPORT_DIRECTORY pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((ULONG_PTR)lpNtdllBuffer + FileOffset);
    //取出导出表函数地址
    FileOffset = pExportDirectory->AddressOfFunctions;
    //遍历节结构进行地址运算

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2024-11-14 14:14 被wtujoxk编辑 ,原因:
上传的附件:
收藏
免费 77
支持
分享
最新回复 (69)
雪    币: 261
活跃值: (1427)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
太强大了 谢谢分享
2024-11-6 15:19
0
雪    币: 10384
活跃值: (4561)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
很强大,感谢分享
2024-11-6 15:33
0
雪    币: 11264
活跃值: (3226)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
很好狠强大,感谢分享
2024-11-6 16:25
0
雪    币: 882
活跃值: (1780)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
看看
2024-11-6 17:42
0
雪    币: 6348
活跃值: (4384)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
6
感谢分享  学习学习
2024-11-6 18:44
0
雪    币: 146
活跃值: (880)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
感谢分享
2024-11-6 19:25
0
雪    币: 10
活跃值: (746)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
很好狠强大,感谢分享
2024-11-6 19:30
0
雪    币: 4255
活跃值: (3496)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
9
回复来看看,先谢过楼主!
2024-11-6 20:16
0
雪    币: 466
活跃值: (2669)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
10
1
2024-11-6 20:31
0
雪    币: 2168
活跃值: (1997)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
支持楼主!
2024-11-6 20:58
0
雪    币: 128
活跃值: (1075)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
支持支持
2024-11-6 23:51
0
雪    币: 2947
活跃值: (3994)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
为你点赞!
2024-11-7 07:38
0
雪    币: 7487
活跃值: (4724)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
不错,勇气可嘉
2024-11-7 08:00
0
雪    币: 10723
活跃值: (2439)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
看看思路
2024-11-7 10:44
0
雪    币: 2148
活跃值: (3549)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
很不错的思路,学习
2024-11-7 17:42
0
雪    币: 68
活跃值: (175)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
我要看完整版
2024-11-7 18:12
0
雪    币: 8107
活跃值: (4889)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
太棒了 
2024-11-7 18:13
0
雪    币: 39
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
19
让我看看
2024-11-8 18:46
0
雪    币: 45
活跃值: (179)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
2024-11-8 19:10
0
雪    币: 753
活跃值: (1414)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
让我看看
2024-11-8 19:54
0
雪    币: 11
活跃值: (1976)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
Thanks for sharing
2024-11-8 20:17
0
雪    币: 200
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
23
感谢分享
2024-11-8 21:09
0
雪    币: 221
活跃值: (2381)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
24
很强大,感谢分享
2024-11-8 22:09
0
雪    币: 8
活跃值: (123)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
无敌
2024-11-9 01:08
0
游客
登录 | 注册 方可回帖
返回
//