代码:
//
// Copy from Matt Pietrek
// Given an RVA, look up the section header that encloses it and return a
// pointer to its IMAGE_SECTION_HEADER
//
PIMAGE_SECTION_HEADER
GetEnclosingSectionHeader(
DWORD rva,
PIMAGE_NT_HEADERS pNTHeader
)
{
PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION32(pNTHeader);
unsigned i;
for ( i=0; i < pNTHeader->FileHeader.NumberOfSections; i++, section++ )
{
// Is the RVA within this section?
if ( (rva >= section->VirtualAddress) &&
(rva < (section->VirtualAddress + section->Misc.VirtualSize)))
return section;
}
return 0;
}
int
AddImportDll(
HANDLE hFile,
DWORD dwBase,
PIMAGE_NT_HEADERS pNTHeader
)
{
//
// 通过OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress
回答人的补充 2009-06-12 01:13
// 获得导入表的RVA, 利用此RVA找到ImportTable所在的Section,之后计算Offset,公式:
// Offset = (INT)(pSection->VirtualAddress - pSection->PointerToRawData)
// 之后利用Offset来定位文件中ImportTable的位置.
//
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = 0;
PIMAGE_SECTION_HEADER pSection = 0;
PIMAGE_THUNK_DATA pThunk, pThunkIAT = 0;
int Offset = -1;
pSection = GetEnclosingSectionHeader(
pNTHeader->OptionalHeader.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress,
pNTHeader);
if(!pSection)
{
fprintf(stderr, "No Import Table../n");
return -1;
}
Offset = (int) (pSection->VirtualAddress - pSection->PointerToRawData);
//
// 计算ImportTable在文件中的位置
//
pImportDesc =
(PIMAGE_IMPORT_DESCRIPTOR)(pNTHeader->OptionalHeader.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress - Offset + dwBase);
//
回答人的补充 2009-06-12 01:14
// 取出导入的DLL的个数
//
int nImportDllCount = 0;
while(1)
{
if ((pImportDesc->TimeDateStamp==0 ) && (pImportDesc->Name==0))
break;
pThunk = (PIMAGE_THUNK_DATA)(pImportDesc->Characteristics);
pThunkIAT = (PIMAGE_THUNK_DATA)(pImportDesc->FirstThunk);
if(pThunk == 0 && pThunkIAT == 0)
return -1;
nImportDllCount++;
pImportDesc++;
}
//
// 恢复pImportDesc的值,方便下面的复制当前导入表的操作.
//
pImportDesc -= nImportDllCount;
//
// 取得ImportTable所在Section的RawData在文件中的末尾地址,计算公式:
// dwOrigEndOfRawDataAddr = pSection->PointerToRawData + pSection->Misc.VirtualSize
//
DWORD dwEndOfRawDataAddr = pSection->PointerToRawData + pSection->Misc.VirtualSize;
PIMAGE_IMPORT_DESCRIPTOR pImportDescVector =
(PIMAGE_IMPORT_DESCRIPTOR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 20 * (nImportDllCount+1));
if(pImportDescVector == NULL)
{
fprintf(stderr, "HeapAlloc() failed. --err: %d/n", GetLastError());
return -1;
}
回答人的补充 2009-06-12 01:15
CopyMemory(pImportDescVector+1, pImportDesc, 20*nImportDllCount);
//
// 构造添加数据的结构,方法笨拙了点.
//
struct _Add_Data
{
char szDllName[256]; // 导入DLL的名字
int nDllNameLen; // 实际填充的名字的长度
WORD Hint; // 导入函数的Hint
char szFuncName[256]; // 导入函数的名字
int nFuncNameLen; // 导入函数名字的实际长度
int nTotal; // 填充的总长度
} Add_Data;
const char szDll[256] = "test.dll";
const char szFunc[256] = "Startup";
strcpy(Add_Data.szDllName, szDll);
strcpy(Add_Data.szFuncName, szFunc);