没什么新技术,就是把目标进程的内存读过来分析而已。
代码在x86下测试通过,由于手头没有x64系统,希望热心的朋友测试一下x64的兼容性,可能不兼容的地方已经在代码中标出。
PVOID GetProcAddressEx(HANDLE hProc, HMODULE hModule, LPCSTR lpProcName)
{
PVOID pAddress = NULL;
SIZE_T OptSize;
IMAGE_DOS_HEADER DosHeader;
SIZE_T ProcNameLength = lstrlenA(lpProcName) + sizeof(CHAR);//'\0'
//读DOS头
if (ReadProcessMemory(hProc, hModule, &DosHeader, sizeof(DosHeader), &OptSize))
{
IMAGE_NT_HEADERS NtHeader;
//读NT头
if (ReadProcessMemory(hProc, (PVOID)((SIZE_T)hModule + DosHeader.e_lfanew), &NtHeader, sizeof(NtHeader), &OptSize))
{
IMAGE_EXPORT_DIRECTORY ExpDir;
SIZE_T ExportVirtualAddress = NtHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
//读输出表
if (ExportVirtualAddress && ReadProcessMemory(hProc, (PVOID)((SIZE_T)hModule + ExportVirtualAddress), &ExpDir, sizeof(ExpDir), &OptSize))
{
if (ExpDir.NumberOfFunctions)
{
//x64待定:地址数组存放RVA的数据类型是4字节还是8字节???
SIZE_T *pProcAddressTable = (SIZE_T *)GlobalAlloc(GPTR, ExpDir.NumberOfFunctions * sizeof(SIZE_T));
//读函数地址表
if (ReadProcessMemory(hProc, (PVOID)((SIZE_T)hModule + ExpDir.AddressOfFunctions), pProcAddressTable, ExpDir.NumberOfFunctions * sizeof(PVOID), &OptSize))
{
//x64待定:名称数组存放RVA的数据类型是4字节还是8字节???
SIZE_T *pProcNamesTable = (SIZE_T *)GlobalAlloc(GPTR, ExpDir.NumberOfNames * sizeof(SIZE_T));
//读函数名称表
if (ReadProcessMemory(hProc, (PVOID)((SIZE_T)hModule + ExpDir.AddressOfNames), pProcNamesTable, ExpDir.NumberOfNames * sizeof(PVOID), &OptSize))
{
CHAR *pProcName = (CHAR *)GlobalAlloc(GPTR, ProcNameLength);
//遍历函数名称
for (DWORD i = 0; i < ExpDir.NumberOfNames; i++)
{
if (ReadProcessMemory(hProc, (PVOID)((SIZE_T)hModule + pProcNamesTable[i]), pProcName, ProcNameLength, &OptSize))
{
if (RtlEqualMemory(lpProcName, pProcName, ProcNameLength))
{
//x64待定:函数在地址数组索引的数据类型是2字节还是???
WORD NameOrdinal;
//获取函数在地址表的索引
if (ReadProcessMemory(hProc, (PVOID)((SIZE_T)hModule + ExpDir.AddressOfNameOrdinals + sizeof(NameOrdinal) * i), &NameOrdinal, sizeof(NameOrdinal), &OptSize))
{
pAddress = (PVOID)((SIZE_T)hModule + pProcAddressTable[NameOrdinal]);
}
break;//for
}
}
}
GlobalFree(pProcName);
}
GlobalFree(pProcNamesTable);
}
GlobalFree(pProcAddressTable);
}
}
}
}
return pAddress;
}