#include <windows.h>
#include <ShellAPI.h>
#include <tchar.h>
#include <Tlhelp32.h>
#include <Shlwapi.h>
BOOL ImportDll(LPTSTR PeFileName, char* dllName, char* funName)
{
// 先备份一个
size_t len = _tcslen(PeFileName);
LPTSTR bakfile = (LPTSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (len+4)*sizeof(TCHAR));
_tcscpy(bakfile, PeFileName);
int i;
for (i=4; ; i--)
{
if ( *(bakfile+len-i) == TEXT('.') || i == 0)
{
_tcscpy(bakfile+len-i, (".bak"));
break;
}
}
CopyFile(PeFileName, bakfile, TRUE);
HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, bakfile);
// 读取pe所有数据
HANDLE handle = CreateFile(PeFileName,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (handle == INVALID_HANDLE_VALUE)
{
return FALSE;
}
DWORD dwBytes = 0;
DWORD dwsize = GetFileSize(handle, NULL);
PBYTE buf = (PBYTE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwsize*sizeof(BYTE));
ReadFile(handle, buf, dwsize, &dwBytes, NULL);
// 解析
PIMAGE_DOS_HEADER Header = (PIMAGE_DOS_HEADER)buf;
PIMAGE_NT_HEADERS peheader =
(PIMAGE_NT_HEADERS)((LPBYTE)Header + Header->e_lfanew);
// 加一个区段
IMAGE_SECTION_HEADER new_section = {0};
strcpy((char*)new_section.Name, ".Patch");
PIMAGE_SECTION_HEADER SectionHeader = (PIMAGE_SECTION_HEADER)( (DWORD)peheader +
sizeof(peheader->FileHeader) +
sizeof(peheader->Signature) +
peheader->FileHeader.SizeOfOptionalHeader ); // 节表项的开始
// IAT地址
DWORD VirtualAddress = peheader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
new_section.SizeOfRawData = peheader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size + strlen(dllName) + strlen(funName) + 14;
new_section.SizeOfRawData += sizeof(IMAGE_IMPORT_DESCRIPTOR); // 文件大小
new_section.Misc.VirtualSize = (new_section.SizeOfRawData/peheader->OptionalHeader.SectionAlignment + 1 )*peheader->OptionalHeader.SectionAlignment; // 内存大小
new_section.Characteristics = IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE|IMAGE_SCN_CNT_INITIALIZED_DATA;
// 枚举现有区段地址
for (i=0; i<peheader->FileHeader.NumberOfSections; i++)
{
DWORD ulsize = SectionHeader[i].Misc.VirtualSize;
if ( ulsize > SectionHeader[i].SizeOfRawData )
{
ulsize = SectionHeader[i].SizeOfRawData;
}
// 找到导入表文件偏移
if (VirtualAddress >= SectionHeader[i].VirtualAddress &&
VirtualAddress <= SectionHeader[i].VirtualAddress+SectionHeader[i].Misc.VirtualSize)
{
VirtualAddress = VirtualAddress- SectionHeader[i].VirtualAddress + SectionHeader[i].PointerToRawData;
}
// 加在最后一个区段后面
if (new_section.VirtualAddress <= SectionHeader[i].VirtualAddress)
{
DWORD temp = ulsize%peheader->OptionalHeader.SectionAlignment? (ulsize/peheader->OptionalHeader.SectionAlignment+1)*peheader->OptionalHeader.SectionAlignment: ulsize;
new_section.VirtualAddress = SectionHeader[i].VirtualAddress + temp;
}
if (new_section.PointerToRawData <= SectionHeader[i].PointerToRawData )
{
DWORD temp = SectionHeader[i].SizeOfRawData%peheader->OptionalHeader.FileAlignment?
(SectionHeader[i].SizeOfRawData/peheader->OptionalHeader.FileAlignment+1)*peheader->OptionalHeader.FileAlignment:
SectionHeader[i].SizeOfRawData;
new_section.PointerToRawData = SectionHeader[i].PointerToRawData + temp;
}
}
new_section.SizeOfRawData = peheader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size+sizeof(IMAGE_IMPORT_DESCRIPTOR)+strlen(dllName)+3+strlen(funName)+1+8;
memcpy(&SectionHeader[peheader->FileHeader.NumberOfSections], &new_section, sizeof(new_section));
SetFilePointer(handle, 0, NULL, FILE_BEGIN); // 设置文件尾部
WriteFile(handle, buf, dwsize, &dwBytes, NULL);
SetFilePointer(handle, new_section.PointerToRawData, NULL, FILE_BEGIN);
WriteFile(handle, dllName, strlen(dllName)+1, &dwBytes, NULL);
WriteFile(handle, "\0\0\0", 2, &dwBytes, NULL);
WriteFile(handle, funName, strlen(funName)+1, &dwBytes, NULL);
DWORD FileStart = new_section.VirtualAddress+strlen(dllName)+1;
WriteFile(handle, &FileStart, 4, &dwBytes, NULL);
WriteFile(handle, "\0\0\0\0", 4, &dwBytes, NULL);
WriteFile(handle, buf+VirtualAddress, peheader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size-sizeof(IMAGE_IMPORT_DESCRIPTOR), &dwBytes, NULL);
FileStart = new_section.VirtualAddress+strlen(dllName)+3+strlen(funName)+1;
WriteFile(handle, &FileStart, 4, &dwBytes, NULL);
WriteFile(handle, "\0\0\0\0\0\0\0\0", 8, &dwBytes, NULL);
WriteFile(handle, &new_section.VirtualAddress, 4, &dwBytes, NULL);
WriteFile(handle, &FileStart, 4, &dwBytes, NULL);
WriteFile(handle, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 0x14, &dwBytes, NULL);
// 修改Image大小
DWORD dwIDEI = peheader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
if (dwIDEI%peheader->OptionalHeader.SectionAlignment)
{
dwIDEI = dwIDEI/peheader->OptionalHeader.SectionAlignment + 1;
}
else
{
dwIDEI = dwIDEI/peheader->OptionalHeader.SectionAlignment;
}
peheader->OptionalHeader.SizeOfImage += peheader->OptionalHeader.SectionAlignment * dwIDEI; // Image 大小变大
// 输入表地址修改
peheader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = new_section.VirtualAddress+strlen(dllName)+3+strlen(funName)+1+8;
peheader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size += sizeof(IMAGE_IMPORT_DESCRIPTOR);
// 区段加1
peheader->FileHeader.NumberOfSections++;
SetFilePointer(handle, 0, NULL, FILE_BEGIN);
WriteFile(handle, buf, peheader->OptionalHeader.FileAlignment, &dwBytes, NULL);
HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, buf);
CloseHandle(handle);
return TRUE;
}
int main(int argc, char* argv[])
{
ImportDll("C:\\YGDP_Assembly.exe", "nilldll.dll", "?nNilldll@@3HA");
return 0;
}
//from lgj