首页
社区
课程
招聘
[原创]手搓Nt*或Zw*函数,避免被hook 支持x86_x64
发表于: 23小时前 1415

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

23小时前
1415

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

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) return functionAddress;
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) return functionAddress;
//把ntdll读入进内存
DWORD dwRead = 0;
DWORD dwSize = GetFileSize(hFile, &dwRead);
BYTE* pBuff = new BYTE[dwSize];
RtlZeroMemory(pBuff, sizeof(pBuff));
ReadFile(hFile, pBuff, dwSize, &dwRead, NULL);
//把ntdll读入进内存
DWORD dwRead = 0;
DWORD dwSize = GetFileSize(hFile, &dwRead);
BYTE* pBuff = new BYTE[dwSize];
RtlZeroMemory(pBuff, sizeof(pBuff));
ReadFile(hFile, pBuff, dwSize, &dwRead, NULL);
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pBuff;
#ifdef _WIN64
PIMAGE_NT_HEADERS64 pNtHeader = (PIMAGE_NT_HEADERS64)(pDosHeader->e_lfanew + ((ULONG_PTR)pDosHeader));
PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)(((ULONG_PTR)(pNtHeader)) + sizeof(IMAGE_NT_HEADERS64));
#else
PIMAGE_NT_HEADERS32 pNtHeader = (PIMAGE_NT_HEADERS32)(pDosHeader->e_lfanew + ((ULONG_PTR)pDosHeader));
PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)(((ULONG_PTR)(pNtHeader)) + sizeof(IMAGE_NT_HEADERS32));
#endif
ULONG_PTR foaAddress = 0;
//Nt函数地址 - ntdll基址 = rva
ULONG_PTR rva = apiAddress - (ULONG_PTR)dllHandle;
for (WORD i = 0; i < pNtHeader->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;
    }
}
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pBuff;
#ifdef _WIN64
PIMAGE_NT_HEADERS64 pNtHeader = (PIMAGE_NT_HEADERS64)(pDosHeader->e_lfanew + ((ULONG_PTR)pDosHeader));
PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)(((ULONG_PTR)(pNtHeader)) + sizeof(IMAGE_NT_HEADERS64));
#else
PIMAGE_NT_HEADERS32 pNtHeader = (PIMAGE_NT_HEADERS32)(pDosHeader->e_lfanew + ((ULONG_PTR)pDosHeader));
PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)(((ULONG_PTR)(pNtHeader)) + sizeof(IMAGE_NT_HEADERS32));
#endif
ULONG_PTR foaAddress = 0;
//Nt函数地址 - ntdll基址 = rva
ULONG_PTR rva = apiAddress - (ULONG_PTR)dllHandle;
for (WORD i = 0; i < pNtHeader->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;
    }
}
//opcode读取
int opcodeOffset = 0;
#ifdef _WIN64
while (true)
{
    //x64位opcode读取
    functionBytes.push_back(*(BYTE*)(pBuff + foaAddress + opcodeOffset));
    if (*(BYTE*)(pBuff + foaAddress + opcodeOffset) == 0xC3) //遇到ret指令结束
    {
        //C3       ret
        //CD 2E    int 2E
        //C3       ret
        //遇到C3后还要追加int 2E ret指令
        functionBytes.push_back(*(BYTE*)(pBuff + foaAddress + ++opcodeOffset)); //CD
        functionBytes.push_back(*(BYTE*)(pBuff + foaAddress + ++opcodeOffset)); //2E
        functionBytes.push_back(*(BYTE*)(pBuff + foaAddress + ++opcodeOffset)); //C3
        break;
    }
    ++opcodeOffset;
}
#else
while (true)
{
    //x86位opcode读取
    if (*(BYTE*)(pBuff + foaAddress + opcodeOffset) == 0xC2 && opcodeOffset > 10) //遇到ret指令结束
    {
        //C2 2000   ret 20
        //遇到C2后还要追加返回值opcode
        functionBytes.push_back(*(BYTE*)(pBuff + foaAddress + opcodeOffset));  //C2
        functionBytes.push_back(*(BYTE*)(pBuff + foaAddress + ++opcodeOffset)); //20
        functionBytes.push_back(*(BYTE*)(pBuff + foaAddress + ++opcodeOffset)); //00
        break;
    }
    //x86 opcode在89位时foa值与va值不同,需要特殊处理
    else if (opcodeOffset == 8 || opcodeOffset == 9)
    {
        functionBytes.push_back(*(BYTE*)(apiAddress + opcodeOffset));
    }
    else
    {
        functionBytes.push_back(*(BYTE*)(pBuff + foaAddress + opcodeOffset));
    }
    ++opcodeOffset;
}
#endif
//opcode读取
int opcodeOffset = 0;
#ifdef _WIN64
while (true)
{
    //x64位opcode读取
    functionBytes.push_back(*(BYTE*)(pBuff + foaAddress + opcodeOffset));
    if (*(BYTE*)(pBuff + foaAddress + opcodeOffset) == 0xC3) //遇到ret指令结束
    {
        //C3       ret
        //CD 2E    int 2E
        //C3       ret
        //遇到C3后还要追加int 2E ret指令
        functionBytes.push_back(*(BYTE*)(pBuff + foaAddress + ++opcodeOffset)); //CD
        functionBytes.push_back(*(BYTE*)(pBuff + foaAddress + ++opcodeOffset)); //2E
        functionBytes.push_back(*(BYTE*)(pBuff + foaAddress + ++opcodeOffset)); //C3
        break;
    }
    ++opcodeOffset;
}
#else
while (true)
{
    //x86位opcode读取
    if (*(BYTE*)(pBuff + foaAddress + opcodeOffset) == 0xC2 && opcodeOffset > 10) //遇到ret指令结束
    {
        //C2 2000   ret 20
        //遇到C2后还要追加返回值opcode
        functionBytes.push_back(*(BYTE*)(pBuff + foaAddress + opcodeOffset));  //C2
        functionBytes.push_back(*(BYTE*)(pBuff + foaAddress + ++opcodeOffset)); //20
        functionBytes.push_back(*(BYTE*)(pBuff + foaAddress + ++opcodeOffset)); //00
        break;
    }
    //x86 opcode在89位时foa值与va值不同,需要特殊处理
    else if (opcodeOffset == 8 || opcodeOffset == 9)
    {
        functionBytes.push_back(*(BYTE*)(apiAddress + opcodeOffset));
    }
    else
    {
        functionBytes.push_back(*(BYTE*)(pBuff + foaAddress + opcodeOffset));
    }
    ++opcodeOffset;
}
#endif
//申请堆空间执行汇编代码
int sizeCustomFunction = functionBytes.size();
functionAddress = (BYTE*)VirtualAlloc(0, sizeCustomFunction, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
for (int j = 0; j < sizeCustomFunction; j++)
{
    //写入opcode到新内存,执行汇编代码
    *(functionAddress + j) = functionBytes[j];
}
//申请堆空间执行汇编代码
int sizeCustomFunction = functionBytes.size();
functionAddress = (BYTE*)VirtualAlloc(0, sizeCustomFunction, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
for (int j = 0; j < sizeCustomFunction; j++)
{
    //写入opcode到新内存,执行汇编代码
    *(functionAddress + j) = functionBytes[j];
}
//NtGetContextThread
typedef BOOL(NTAPI* PNtGetContextThread)(HANDLE hThread, LPCONTEXT lpContext);
PNtGetContextThread pZwGetContextThread;
BOOL MyNtGetContextThread(HANDLE hThread, LPCONTEXT lpContext)
{
    pZwGetContextThread = (PNtGetContextThread)CustomNtFunction("NtGetContextThread");
    return pZwGetContextThread(hThread, lpContext);
}
//NtSetContextThread
typedef BOOL(CALLBACK* PNtSetContextThread)(HANDLE hThread, LPCONTEXT lpContext);
PNtSetContextThread pZwSetContextThread;
BOOL MyNtSetContextThread(HANDLE hThread, LPCONTEXT lpContext)
{
    pZwGetContextThread = (PNtSetContextThread)CustomNtFunction("NtSetContextThread");
    return pZwGetContextThread(hThread, lpContext);
}
//NtProtectVirtualMemory
typedef BOOL(NTAPI* PNtProtectVirtualMemory)(HANDLE hProcess, PVOID* lpAddress, PSIZE_T dwSize, ULONG flNewProtect, PULONG lpflOldProtect);
PNtProtectVirtualMemory pNtProtectVirtualMemory;
BOOL MyNtProtectVirtualMemory(HANDLE hProcess, PVOID* lpAddress, PSIZE_T dwSize, ULONG flNewProtect, PULONG lpflOldProtect)
{
    // 将函数名转换为地址并执行
    pNtProtectVirtualMemory = (PNtProtectVirtualMemory)CustomNtFunction("NtProtectVirtualMemory");
    return pNtProtectVirtualMemory(hProcess, lpAddress, dwSize, flNewProtect, lpflOldProtect);
}
//NtGetContextThread
typedef BOOL(NTAPI* PNtGetContextThread)(HANDLE hThread, LPCONTEXT lpContext);
PNtGetContextThread pZwGetContextThread;
BOOL MyNtGetContextThread(HANDLE hThread, LPCONTEXT lpContext)
{
    pZwGetContextThread = (PNtGetContextThread)CustomNtFunction("NtGetContextThread");
    return pZwGetContextThread(hThread, lpContext);
}
//NtSetContextThread
typedef BOOL(CALLBACK* PNtSetContextThread)(HANDLE hThread, LPCONTEXT lpContext);
PNtSetContextThread pZwSetContextThread;
BOOL MyNtSetContextThread(HANDLE hThread, LPCONTEXT lpContext)
{
    pZwGetContextThread = (PNtSetContextThread)CustomNtFunction("NtSetContextThread");
    return pZwGetContextThread(hThread, lpContext);
}
//NtProtectVirtualMemory
typedef BOOL(NTAPI* PNtProtectVirtualMemory)(HANDLE hProcess, PVOID* lpAddress, PSIZE_T dwSize, ULONG flNewProtect, PULONG lpflOldProtect);
PNtProtectVirtualMemory pNtProtectVirtualMemory;
BOOL MyNtProtectVirtualMemory(HANDLE hProcess, PVOID* lpAddress, PSIZE_T dwSize, ULONG flNewProtect, PULONG lpflOldProtect)
{
    // 将函数名转换为地址并执行
    pNtProtectVirtualMemory = (PNtProtectVirtualMemory)CustomNtFunction("NtProtectVirtualMemory");
    return pNtProtectVirtualMemory(hProcess, lpAddress, dwSize, flNewProtect, lpflOldProtect);
}
BYTE* CustomNtFunction(const char* functionName)
{
    std::vector<BYTE> functionBytes;
    BYTE* functionAddress = 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) return functionAddress;
    HMODULE dllHandle = LoadLibraryA(dllPath);
    ULONG_PTR apiAddress = (ULONG_PTR)GetProcAddress(dllHandle, functionName);
 
    //把ntdll读入进内存
    DWORD dwRead = 0;
    DWORD dwSize = GetFileSize(hFile, &dwRead);
    BYTE* pBuff = new BYTE[dwSize];
    RtlZeroMemory(pBuff, sizeof(pBuff));
    ReadFile(hFile, pBuff, dwSize, &dwRead, NULL);
 
    //通过apiAddress地址获取函数的foa地址
    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pBuff;
#ifdef _WIN64
    PIMAGE_NT_HEADERS64 pNtHeader = (PIMAGE_NT_HEADERS64)(pDosHeader->e_lfanew + ((ULONG_PTR)pDosHeader));
    PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)(((ULONG_PTR)(pNtHeader)) + sizeof(IMAGE_NT_HEADERS64));
#else
    PIMAGE_NT_HEADERS32 pNtHeader = (PIMAGE_NT_HEADERS32)(pDosHeader->e_lfanew + ((ULONG_PTR)pDosHeader));
    PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)(((ULONG_PTR)(pNtHeader)) + sizeof(IMAGE_NT_HEADERS32));
#endif
    ULONG_PTR foaAddress = 0;
    //Nt函数地址 - ntdll基址 = rva
    ULONG_PTR rva = apiAddress - (ULONG_PTR)dllHandle;
    for (WORD i = 0; i < pNtHeader->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;
        }
    }
 
    //opcode读取
    int opcodeOffset = 0;
#ifdef _WIN64
    while (true)
    {
        //x64位opcode读取
        functionBytes.push_back(*(BYTE*)(pBuff + foaAddress + opcodeOffset));
        if (*(BYTE*)(pBuff + foaAddress + opcodeOffset) == 0xC3) //遇到ret指令结束
        {
            //C3       ret
            //CD 2E    int 2E
            //C3       ret
            //遇到C3后还要追加int 2E ret指令
            functionBytes.push_back(*(BYTE*)(pBuff + foaAddress + ++opcodeOffset)); //CD
            functionBytes.push_back(*(BYTE*)(pBuff + foaAddress + ++opcodeOffset)); //2E
            functionBytes.push_back(*(BYTE*)(pBuff + foaAddress + ++opcodeOffset)); //C3
            break;
        }
        ++opcodeOffset;
    }
#else
    while (true)
    {
        //x86位opcode读取
        if (*(BYTE*)(pBuff + foaAddress + opcodeOffset) == 0xC2 && opcodeOffset > 10) //遇到ret指令结束
        {
            //C2 2000   ret 20
            //遇到C2后还要追加返回值opcode
            functionBytes.push_back(*(BYTE*)(pBuff + foaAddress + opcodeOffset));  //C2
            functionBytes.push_back(*(BYTE*)(pBuff + foaAddress + ++opcodeOffset)); //20
            functionBytes.push_back(*(BYTE*)(pBuff + foaAddress + ++opcodeOffset)); //00
            break;
        }
        //x86 opcode在89位时foa值与va值不同,需要特殊处理
        else if (opcodeOffset == 8 || opcodeOffset == 9)
        {
            functionBytes.push_back(*(BYTE*)(apiAddress + opcodeOffset));
        }
        else
        {
            functionBytes.push_back(*(BYTE*)(pBuff + foaAddress + opcodeOffset));
        }
        ++opcodeOffset;
    }
#endif
 
    //申请堆空间执行汇编代码
    int sizeCustomFunction = functionBytes.size();
    functionAddress = (BYTE*)VirtualAlloc(0, sizeCustomFunction, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    for (int j = 0; j < sizeCustomFunction; j++)
    {
        //写入opcode到新内存,执行汇编代码
        *(functionAddress + j) = functionBytes[j];
    }
 
    delete[] pBuff; pBuff = NULL;
    CloseHandle(hFile);
    return functionAddress;
}
 
//NtProtectVirtualMemory
typedef BOOL(NTAPI* PNtProtectVirtualMemory)(HANDLE hProcess, PVOID* lpAddress, PSIZE_T dwSize, ULONG flNewProtect, PULONG lpflOldProtect);
PNtProtectVirtualMemory pNtProtectVirtualMemory;
BOOL MyNtProtectVirtualMemory(HANDLE hProcess, PVOID* lpAddress, PSIZE_T dwSize, ULONG flNewProtect, PULONG lpflOldProtect)
{
    // 将函数名转换为地址并执行
    pNtProtectVirtualMemory = (PNtProtectVirtualMemory)CustomNtFunction("NtProtectVirtualMemory");
    return pNtProtectVirtualMemory(hProcess, lpAddress, dwSize, flNewProtect, lpflOldProtect);
}

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

最后于 21小时前 被wtujoxk编辑 ,原因:
上传的附件:
收藏
免费 30
支持
分享
最新回复 (14)
雪    币: 261
活跃值: (1242)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
太强大了 谢谢分享
19小时前
0
雪    币: 10191
活跃值: (4311)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
很强大,感谢分享
19小时前
0
雪    币: 11077
活跃值: (3040)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
很好狠强大,感谢分享
18小时前
0
雪    币: 756
活跃值: (1665)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
看看
17小时前
0
雪    币: 6151
活跃值: (4161)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
6
感谢分享  学习学习
16小时前
0
雪    币: 146
活跃值: (825)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
感谢分享
15小时前
0
雪    币: 0
活跃值: (601)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
很好狠强大,感谢分享
15小时前
0
雪    币: 3934
活跃值: (3306)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
9
回复来看看,先谢过楼主!
14小时前
0
雪    币: 466
活跃值: (2519)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
10
1
14小时前
0
雪    币: 2096
活跃值: (1872)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
支持楼主!
13小时前
0
雪    币: 128
活跃值: (907)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
支持支持
11小时前
0
雪    币: 2825
活跃值: (3834)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
为你点赞!
3小时前
0
雪    币: 7258
活跃值: (4472)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
不错,勇气可嘉
2小时前
0
雪    币: 10555
活跃值: (2234)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
看看思路
13分钟前
0
游客
登录 | 注册 方可回帖
返回
//