PE加载器:将PE文件在内存中加载,此加载方式,进程的模块列表中无法查看到模块名。Procmon中监视,堆栈,堆栈中显示<未知>,汇编跟踪时也没有模块名。
替换方法:找到模块所在的内存块,对内存块中的PE文件进行解析,定位到导入表处,再替换导入表。
方法详见代码
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,true,m_Pid);
char str[315392];
memset(str,0,315392);
DWORD lread;
BOOL bSuccess = ReadProcessMemory(hProcess,(LPCVOID)0x01ae0000,str,315392,&lread);
//判断PE文件
PIMAGE_DOS_HEADER PE_Head; //DOS头
PE_Head = (PIMAGE_DOS_HEADER)str;
if (PE_Head->e_magic != IMAGE_DOS_SIGNATURE)
{
AfxMessageBox("错误的MS_DOS头!");
return;
}
PIMAGE_NT_HEADERS PE_NtHead; //NT头
PE_NtHead = (PIMAGE_NT_HEADERS)(str+PE_Head->e_lfanew);
if (PE_NtHead->Signature != IMAGE_NT_SIGNATURE)
{
AfxMessageBox("错误的PE头!");
return;
}
//获取头的地址
PIMAGE_FILE_HEADER PE_FileHead; //文件头
PIMAGE_OPTIONAL_HEADER PE_OptionHead; //可选头
PE_FileHead = &PE_NtHead->FileHeader;
PE_OptionHead = &PE_NtHead->OptionalHeader;
//获取导入表的地址
PIMAGE_DATA_DIRECTORY PE_ImportDirectory;
//由于输入表为第二项,获取输入表的目录表的信息。
PE_ImportDirectory = &PE_OptionHead->DataDirectory[1];
//获取输入表前先获取输入表的偏移地址
DWORD PE_ImportOffset;
PE_ImportOffset = PE_ImportDirectory->VirtualAddress;
//输入表是以IMAGE_IMPORT_DESCRIPTOR为结构,以空为结尾
//先获得输入表的指针
PIMAGE_IMPORT_DESCRIPTOR pImportDesc;
pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)(str + PE_ImportOffset);
while (pImportDesc->FirstThunk)
{
char szName[1024];
memset(szName,0,1024);
strcpy(szName,str+pImportDesc->Name);
PIMAGE_THUNK_DATA PE_INT;
PE_INT = (PIMAGE_THUNK_DATA)(str+pImportDesc->OriginalFirstThunk);
PIMAGE_THUNK_DATA PE_IAT;
PE_IAT = (PIMAGE_THUNK_DATA)(str+pImportDesc->FirstThunk);
char *pszFunName = NULL;
while(PE_IAT->u1.Function)
{
if (PE_IAT->u1.Function == 0x7C801A28)
{
PE_IAT->u1.Function = 0x3449068;
}
// if (PE_IAT->u1.Function == 0x7C809BE7)
// {
// PE_IAT->u1.Function = 0x33C9068;
// }
//PDWORD lpAddr = str + PE_IAT->u1.Function
PE_IAT++;
}
pImportDesc++;
}
bSuccess = WriteProcessMemory(hProcess,(LPVOID)0x01ae0000,str,315392,&lread);
int x = 01;