簡單實現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;
}windows
dEARMoONapp
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,大意.內存
rongingit
2012-05-12, 15:22:24io
印象中看雪中最多的帖子有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
不是吧,加載不成功