在加壳软件中,ntdll.dll里的有些API会被加壳软件hook,导致我们在做补丁无法正常执行
如:有的程序会hook NtGetContextThread和NtSetContextThread,导致无法下硬件断点,也有的会hook NtProtectVirtualMemory,无法修改内存属性,就不能修改汇编代码等……
Nt或Zw开头的函数执行的代码是一样的,他们所指向的函数地址都是同一个,具体有什么不同,请自行搜索查看,我这里使用Nt函数进行编写。
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
;
}
}
memcpy((PVOID)((ULONG_PTR)lpNtdllBuffer
+
foaAddress
+
6
), (PVOID)(apiAddress
+
6
),
6
);
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
;
}
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
;
}
}
memcpy((PVOID)((ULONG_PTR)lpNtdllBuffer
+
foaAddress
+
6
), (PVOID)(apiAddress
+
6
),
6
);
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
;
}
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)
{
return
GetFunctionAddressByName(functionName);
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;
}
/
/
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
;
}
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编辑
,原因: