了解 hook_finder
Understanding hook_finder
我正在尝试了解 PE 格式和此处“hook_finder”的源代码
"https://github.com/Mr-Un1k0d3r/EDRs/blob/main/hook_finder64.c"
在这个片段中,我现在正在尝试计算 Export_Table 偏移量:
VOID DumpListOfExport(VOID *lib, BOOL bNt) {
DWORD dwIter = 0;
CHAR* base = (CHAR*)lib;
CHAR* PE = base + (unsigned char)*(base + 0x3c);
DWORD ExportDirectoryOffset = *((DWORD*)PE + (0x8a / 4));
CHAR* ExportDirectory = base + ExportDirectoryOffset;
DWORD dwFunctionsCount = *((DWORD*)ExportDirectory + (0x14 / 4));
DWORD OffsetNamesTableOffset = *((DWORD*)ExportDirectory + (0x20 / 4));
CHAR* OffsetNamesTable = base + OffsetNamesTableOffset;
printf("------------------------------------------\nBASE\t\t\t0x%p\t%s\nPE\t\t\t0x%p\t%s\nExportTableOffset\t0x%p\nOffsetNameTable\t\t0x%p\nFunctions Count\t\t0x%x (%d)\n------------------------------------------\n",
base, base, PE, PE, ExportDirectory, OffsetNamesTable, dwFunctionsCount, dwFunctionsCount);
for(dwIter; dwIter < dwFunctionsCount - 1; dwIter++) {
DWORD64 offset = *((DWORD*)OffsetNamesTable + dwIter);
CHAR* current = base + offset;
GetBytesByName((HANDLE)lib, current, bNt);
}
}
ox3c 是 e_lfnew 偏移量。但是,无法理解其他十六进制值是什么以及为什么除以 4 字节?
此外,
VOID GetBytesByName(HANDLE hDll, CHAR *name, BOOL bNt) {
FARPROC ptr = GetProcAddress((HMODULE)hDll, name);
DWORD* opcode = (DWORD*)*ptr;
if(bNt) {
if(name[0] != 'N' && name[1] != 't') {
return;
}
}
if((*opcode << 24) >> 24 == 0xe9) {
if(!IsFalsePositive(name)) {
printf("%s is hooked\n", name);
}
}
}
什么是左右移动,为什么是 24?
根据我对EDR的理解,它在函数的最开头添加了一条JMP指令,这就是为什么条件试图检查它是否是(0xe9),但是它如何遵循并确定函数流程?
这是否仅适用于 ntdll.dll?
抱歉,我开始研究 PE 行为并试图让事情变得非常清楚。
提前致谢
函数DumpListOfExport
假设NtHeaders
从基址的偏移量0x3c开始,但是,根据大小的不同,情况并非总是如此DOS存根。可能,这段代码对 ntdll.dll
.
做了这样的假设
并且在函数 GetBytesByName
中,如果过程的第一个字节以 JMP
开头(在这种情况下,它是 near,相对 jmp,其操作码以 开头” E9") 指令且过程名称不在误报列表中,则该函数决定该函数被挂钩。
设为opcode
0xca0e4be9指向的4个字节的值,左移24将得到0xe9000000,然后右移 24,结果将是 0x000000e9,这是 ptr
.
处第一个字节的值
该程序可以简化如下。
VOID GetBytesByName(HANDLE hDll, CHAR *name, BOOL bNt) {
FARPROC ptr = GetProcAddress((HMODULE)hDll, name);
BYTE* opcode = (BYTE*)ptr;
if(bNt) {
if(name[0] != 'N' && name[1] != 't') {
return;
}
}
if(!IsFalsePositive(name) && *opcode == 0xe9) {
printf("%s is hooked\n", name);
}
}
注 : 我可以说代码写得不好,也没有遵循任何好的编码风格。
我正在尝试了解 PE 格式和此处“hook_finder”的源代码 "https://github.com/Mr-Un1k0d3r/EDRs/blob/main/hook_finder64.c"
在这个片段中,我现在正在尝试计算 Export_Table 偏移量:
VOID DumpListOfExport(VOID *lib, BOOL bNt) {
DWORD dwIter = 0;
CHAR* base = (CHAR*)lib;
CHAR* PE = base + (unsigned char)*(base + 0x3c);
DWORD ExportDirectoryOffset = *((DWORD*)PE + (0x8a / 4));
CHAR* ExportDirectory = base + ExportDirectoryOffset;
DWORD dwFunctionsCount = *((DWORD*)ExportDirectory + (0x14 / 4));
DWORD OffsetNamesTableOffset = *((DWORD*)ExportDirectory + (0x20 / 4));
CHAR* OffsetNamesTable = base + OffsetNamesTableOffset;
printf("------------------------------------------\nBASE\t\t\t0x%p\t%s\nPE\t\t\t0x%p\t%s\nExportTableOffset\t0x%p\nOffsetNameTable\t\t0x%p\nFunctions Count\t\t0x%x (%d)\n------------------------------------------\n",
base, base, PE, PE, ExportDirectory, OffsetNamesTable, dwFunctionsCount, dwFunctionsCount);
for(dwIter; dwIter < dwFunctionsCount - 1; dwIter++) {
DWORD64 offset = *((DWORD*)OffsetNamesTable + dwIter);
CHAR* current = base + offset;
GetBytesByName((HANDLE)lib, current, bNt);
}
}
ox3c 是 e_lfnew 偏移量。但是,无法理解其他十六进制值是什么以及为什么除以 4 字节?
此外,
VOID GetBytesByName(HANDLE hDll, CHAR *name, BOOL bNt) {
FARPROC ptr = GetProcAddress((HMODULE)hDll, name);
DWORD* opcode = (DWORD*)*ptr;
if(bNt) {
if(name[0] != 'N' && name[1] != 't') {
return;
}
}
if((*opcode << 24) >> 24 == 0xe9) {
if(!IsFalsePositive(name)) {
printf("%s is hooked\n", name);
}
}
}
什么是左右移动,为什么是 24? 根据我对EDR的理解,它在函数的最开头添加了一条JMP指令,这就是为什么条件试图检查它是否是(0xe9),但是它如何遵循并确定函数流程?
这是否仅适用于 ntdll.dll?
抱歉,我开始研究 PE 行为并试图让事情变得非常清楚。
提前致谢
函数DumpListOfExport
假设NtHeaders
从基址的偏移量0x3c开始,但是,根据大小的不同,情况并非总是如此DOS存根。可能,这段代码对 ntdll.dll
.
并且在函数 GetBytesByName
中,如果过程的第一个字节以 JMP
开头(在这种情况下,它是 near,相对 jmp,其操作码以 开头” E9") 指令且过程名称不在误报列表中,则该函数决定该函数被挂钩。
设为opcode
0xca0e4be9指向的4个字节的值,左移24将得到0xe9000000,然后右移 24,结果将是 0x000000e9,这是 ptr
.
该程序可以简化如下。
VOID GetBytesByName(HANDLE hDll, CHAR *name, BOOL bNt) {
FARPROC ptr = GetProcAddress((HMODULE)hDll, name);
BYTE* opcode = (BYTE*)ptr;
if(bNt) {
if(name[0] != 'N' && name[1] != 't') {
return;
}
}
if(!IsFalsePositive(name) && *opcode == 0xe9) {
printf("%s is hooked\n", name);
}
}
注 : 我可以说代码写得不好,也没有遵循任何好的编码风格。