简单实现LoadLibrary然后实现GetProcAddress再然后用LoadLibrary的结果填充输入表,达到隐形调用API的目的.32位测试,正规PE文件测试,优化过的不认.
出处:本文来自看雪学院.
作者:Worker
编译平台:VS2005
#include "stdafx.h"
#include "LoadLibrary.h"
DWORD AlignUp(DWORD n, DWORD A)
{
return ((n / A) + ((n % A) ? 1 : 0)) * A;
}
HMODULE LoadStandardDLL(LPCWSTR pszDLLName)
{
wchar_t pwzFullPath[MAX_PATH*2];
//获得DLL的全部路径
memset(pwzFullPath,0,MAX_PATH*2);
GetSystemDirectory(pwzFullPath,MAX_PATH*2);
wcscat_s(pwzFullPath,pszDLLName);
//映射文件到内存
HANDLE hFile=CreateFile(pwzFullPath,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(INVALID_HANDLE_VALUE==hFile)
{
return NULL;
}
HANDLE hMapFile=CreateFileMapping(hFile,NULL,PAGE_READONLY,0,GetFileSize(hFile,NULL),NULL);
if(NULL==hMapFile)
{
return NULL;
}
PBYTE lpMapAddress=(PBYTE)MapViewOfFile(hMapFile,FILE_MAP_READ,0,0,0);
if(NULL==lpMapAddress)
{
return NULL;
}
//解析PE文件格式
PIMAGE_DOS_HEADER pDosHeader=(PIMAGE_DOS_HEADER)lpMapAddress;
PIMAGE_NT_HEADERS pNtHeader=(PIMAGE_NT_HEADERS)((DWORD)pDosHeader+pDosHeader->e_lfanew);
IMAGE_OPTIONAL_HEADER32 pOptionalHead=pNtHeader->OptionalHeader;
PIMAGE_SECTION_HEADER pSecHeader=(PIMAGE_SECTION_HEADER)((DWORD)pNtHeader+sizeof(IMAGE_OPTIONAL_HEADER)+sizeof(IMAGE_FILE_HEADER)+sizeof(DWORD));
DWORD dwSecAlign=pOptionalHead.SectionAlignment;
//分配新内存PE的空间
PBYTE pMemPE=(PBYTE)VirtualAlloc(NULL,pOptionalHead.SizeOfImage,MEM_COMMIT,PAGE_READWRITE);
if(NULL==pMemPE)
{
return NULL;
}
//保留.用于返回值
PBYTE pbBase=(PBYTE)pMemPE;
//复制PE头到虚拟内存
memcpy(pMemPE,lpMapAddress,pOptionalHead.SizeOfHeaders);
pMemPE+=4096;
//复制区段信息.根据内存中的物理地址,复制到区段中的虚拟地址.虚拟地址的大小增长以虚拟大小计算.
for(int Index=0;Index<pNtHeader->FileHeader.NumberOfSections;Index++) //注意PE虚拟内存大小对齐.
{
DWORD RawSize=pSecHeader[Index].SizeOfRawData;
DWORD VirtualSize=pSecHeader[Index].Misc.VirtualSize;
DWORD Align=AlignUp(VirtualSize,dwSecAlign);
PBYTE pbPhysicalPE=(PBYTE)(pSecHeader[Index].PointerToRawData+lpMapAddress);
memcpy(pMemPE,pbPhysicalPE,RawSize);
pMemPE+=Align;
}
//填充输出表
PIMAGE_EXPORT_DIRECTORY pExportTable=(PIMAGE_EXPORT_DIRECTORY)
(pOptionalHead.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress+pbBase);
DWORD dwExportSize=pOptionalHead.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
if(false!=dwExportSize&&NULL!=pExportTable)
{
PBYTE *pbAddressArray=(PBYTE*)(pExportTable->AddressOfFunctions+pbBase);
PBYTE *pbSerialIndex=(PBYTE*)(pExportTable->AddressOfNameOrdinals+pbBase);
for(WORD Index=reinterpret_cast<WORD>(pbSerialIndex[0*2]);Index<pExportTable->NumberOfFunctions;Index++)
{
pbAddressArray[Index*1]=(pbAddressArray[Index*1]+(DWORD)pbBase);
}
}
//填充输入表
PIMAGE_IMPORT_DESCRIPTOR pImportTable=(PIMAGE_IMPORT_DESCRIPTOR)
(pOptionalHead.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress+pbBase);
DWORD dwImportSize=pOptionalHead.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
if(false!=dwImportSize&&NULL!=pImportTable)
{
for(DWORD DllIndex=0;DllIndex<dwImportSize/sizeof(IMAGE_IMPORT_DESCRIPTOR);DllIndex++)
{
PBYTE *pbAddressArray=(PBYTE*)pImportTable->FirstThunk;
if(NULL==pbAddressArray)
{
break;
}
pbAddressArray=(PBYTE*)(reinterpret_cast<DWORD>(pbAddressArray)+pbBase);
LPCSTR pbNameArray=(LPCSTR)pImportTable->Name;
if(NULL==pbNameArray)
{
break;
}
pbNameArray=(LPCSTR)((DWORD)pbNameArray+pbBase);
PIMAGE_THUNK_DATA32 pThunkData=(PIMAGE_THUNK_DATA32)pImportTable->OriginalFirstThunk;
if(NULL==pThunkData)
{
break;
}
pThunkData=(PIMAGE_THUNK_DATA32)((DWORD)pThunkData+pbBase);
HMODULE hModule=LoadLibraryA(pbNameArray);
PWORD pdwOrdinal=(PWORD)pThunkData->u1.Ordinal;
for(DWORD NameIndex=0;false!=pdwOrdinal;NameIndex++)
{
PSZ pszProcName=(PSZ)(pThunkData->u1.Function+pbBase+2);
pbAddressArray[NameIndex*1]=(PBYTE)GetProcAddress(hModule,pszProcName);
pThunkData++;
pdwOrdinal=(PWORD)pThunkData->u1.Ordinal;
}
pImportTable++;
}
}
//结束处理
if(lpMapAddress)
{
UnmapViewOfFile(lpMapAddress);
}
if(hMapFile)
{
CloseHandle(hMapFile);
}
if(hFile)
{
CloseHandle(hFile);
}
return (HMODULE)pbBase;
}
FARPROC GetStandardProc(HMODULE hModule,PSZ pszProcName)
{
PBYTE pbBase=(PBYTE)hModule;
PIMAGE_DOS_HEADER pDosHeader=(PIMAGE_DOS_HEADER)pbBase;
PIMAGE_NT_HEADERS pNtHeader=(PIMAGE_NT_HEADERS)((DWORD)pDosHeader+pDosHeader->e_lfanew);
IMAGE_OPTIONAL_HEADER32 pOptionalHead=pNtHeader->OptionalHeader;
PIMAGE_EXPORT_DIRECTORY pExportTable=(PIMAGE_EXPORT_DIRECTORY)
(pOptionalHead.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress+pbBase);
if(NULL==pExportTable)
{
return NULL;
}
//获得搜索需要的辅助信息
PBYTE *pbNameArray=(PBYTE*)(pExportTable->AddressOfNames+pbBase);
PBYTE *pbAddressArray=(PBYTE*)(pExportTable->AddressOfFunctions+pbBase);
PBYTE *pbSerialIndex=(PBYTE*)(pExportTable->AddressOfNameOrdinals+pbBase);
//搜索到处表中的API地址.
for(WORD Index=reinterpret_cast<WORD>(pbSerialIndex[0*2]);Index<pExportTable->NumberOfFunctions;Index++)
{
PSZ pszNameBase=(PSZ)pbNameArray[Index*1];
pszNameBase=(reinterpret_cast<DWORD>(pbBase)+pszNameBase);
if(false==stricmp(pszNameBase,pszProcName))
{
return (FARPROC)pbAddressArray[Index*1];
}
}
return NULL;
}
ULONG FullImportTable()
{
DWORD OldProtect;
DWORD NewProtect;
wchar_t pwzRelativeName[MAX_PATH];
memset(pwzRelativeName,0,MAX_PATH);
PBYTE pbBase=(PBYTE)GetModuleHandle(NULL);
PIMAGE_DOS_HEADER pDosHeader=(PIMAGE_DOS_HEADER)pbBase;
PIMAGE_NT_HEADERS pNtHeader=(PIMAGE_NT_HEADERS)((DWORD)pDosHeader+pDosHeader->e_lfanew);
IMAGE_OPTIONAL_HEADER32 pOptionalHead=pNtHeader->OptionalHeader;
PIMAGE_IMPORT_DESCRIPTOR pImportTable=(PIMAGE_IMPORT_DESCRIPTOR)
(pOptionalHead.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress+pbBase);
DWORD dwImportSize=pOptionalHead.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
DWORD SizeImage=pOptionalHead.SizeOfImage;
VirtualProtect(pbBase,SizeImage,PAGE_EXECUTE_READWRITE,&OldProtect);
if(NULL==pImportTable)
{
return GetLastError();
}
//获得导入表的每个DLL导入的函数.并且填充为内存中的地址.
for(DWORD DllIndex=0;DllIndex<dwImportSize/sizeof(IMAGE_IMPORT_DESCRIPTOR);DllIndex++)
{
PBYTE *pbAddressArray=(PBYTE*)pImportTable->FirstThunk;
if(NULL==pbAddressArray)
{
break;
}
pbAddressArray=(PBYTE*)(reinterpret_cast<DWORD>(pbAddressArray)+pbBase);
LPCSTR pbNameArray=(LPCSTR)pImportTable->Name;
if(NULL==pbNameArray)
{
break;
}
pbNameArray=(LPCSTR)((DWORD)pbNameArray+pbBase);
PIMAGE_THUNK_DATA32 pThunkData=(PIMAGE_THUNK_DATA32)pImportTable->OriginalFirstThunk;
if(NULL==pThunkData)
{
break;
}
pThunkData=(PIMAGE_THUNK_DATA32)((DWORD)pThunkData+pbBase);
pwzRelativeName[0]=L'\\';
for(BYTE LengthIndex=0,Index=1;LengthIndex<strlen(pbNameArray);LengthIndex++,Index++)
{
pwzRelativeName[Index*1]=pbNameArray[LengthIndex*1];
}
HMODULE hModule=LoadStandardDLL(pwzRelativeName);
if(NULL!=hModule)
{
PWORD pdwOrdinal=(PWORD)pThunkData->u1.Ordinal;
for(DWORD NameIndex=0;false!=pdwOrdinal;NameIndex++)
{
PSZ pszProcName=(PSZ)(pThunkData->u1.Function+pbBase+2);
pbAddressArray[NameIndex*1]=(PBYTE)GetStandardProc(hModule,pszProcName);
pThunkData++;
pdwOrdinal=(PWORD)pThunkData->u1.Ordinal;
}
}
memset(pwzRelativeName,0,MAX_PATH);
pImportTable++;
}
VirtualProtect(pbBase,SizeImage,OldProtect,&NewProtect);
return false;
}
int APIENTRY _tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow)
{
void (WINAPI *MyExitProcess)(DWORD ExitCode);
FullImportTable();
HMODULE hMod=LoadStandardDLL(L"\\Kernel32.dll");
*(DWORD*)&MyExitProcess=(DWORD)GetStandardProc(hMod,"ExitProcess");
MessageBox(NULL,L"请尝试Dump",L"提示",MB_OK);
MyExitProcess(0);
return false;
}
dEARMoON
2012-05-12, 13:08:46
HANDLE hFile=CreateFile(pwzFullPath,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(INVALID_HANDLE_VALUE==hFile)
{
return NULL;
}
HANDLE hMapFile=CreateFileMapping(hFile,NULL,PAGE_READONLY,0,GetFileSize(hFile,NULL),NULL);
if(NULL==hMapFile)
{
return NULL;
}
诸如此类,CreateFileMapping返回失败,hFile句柄也应该要关掉.
心如止境
2012-05-12, 14:38:07
诸如此类,CreateFileMapping返回失败,hFile句柄也应该要关掉.
3Q,大意.
ronging
2012-05-12, 15:22:24
印象中看雪中最多的帖子有2种,一是破解了什么什么,另一个就是这内存加载了。:D:
1.
memcpy(pMemPE,lpMapAddress,pOptionalHead.SizeOfHeaders);
pMemPE+=4096;
SizeOfHeader一定是4096嘛?
记得SectionHeader中有个VirtualAddress属性。
2.
pbSerialIndex[0*2]
pbAddressArray[Index*1]=(pbAddressArray[Index*1]+(DWORD)pbBase)
这的0*2和Index*1有什么特别的意思没?
3. 重定位信息的处理
4. 输入节的处理
DLL的加载是件很复杂的事,这个代码里没有看到如何处理 “绑定输入”?还有“ForwarderChain ”?的情况。
5. 输出的情况和上面类似,也有forwarder的情况。
心如止境
2012-05-12, 15:34:01
印象中看雪中最多的帖子有2种,一是破解了什么什么,另一个就是这内存加载了。:D:
1.
memcpy(pMemPE,lpMapAddress,pOptionalHead.SizeOfHeaders);
pMemPE+=4096;
SizeOfHeader一定是4096嘛?
记得Secti...
认真看清楚我想干什么再来吧
shahuo
2012-05-13, 02:54:49
#include "LoadLibrary.h"也发出来啊,,,是用VC什么版本编译的?
心如止境
2012-05-13, 05:56:41
#include "LoadLibrary.h"也发出来啊,,,是用VC什么版本编译的?
LoadLibrary.H里面啥都没.只有windows.h.VS2005
fiorentina
2012-05-15, 22:31:45
看看再说吧!
boywhp
2012-05-16, 19:13:56
我是来模版楼主头像的
ruoko
2012-09-07, 03:31:49
vs2005.....
myheartred
2012-09-08, 16:12:03
话说也正想写一个LoadLibrary呢,先马克,完成发出来
fanpei
2012-10-23, 10:30:40
怎么回事?这段代码win7运行不了,没有错误,但是运行不了。
kmsmxpro
2012-10-23, 15:14:58
占位学习楼主大作
毁灭
2012-12-08, 16:28:52
以前自己也写过这样的一个函数 当时是为了做免杀
小调调
2012-12-10, 09:25:49
LoadLibrary 在遇到 导入表有msvcr80.dll 的时候一直失败
qiluword
2012-12-31, 18:06:00
不是吧,加载不成功