1.注入概念:
2.导入表注入流程:
第一步:
根据目录项(第二个就是导入表)得到导入表信息:
typedef struct _IMAGE_DATA_DIRECTORY {
DWORD VirtualAddress;
DWORD Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
VirtualAddress :指向导入表结构
Size:导入表的总大小
这两个值都需要
第二步:
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
union {
DWORD Characteristics;
DWORD OriginalFirstThunk;
};
DWORD TimeDateStamp;
DWORD ForwarderChain;
DWORD Name;
DWORD FirstThunk;
} IMAGE_IMPORT_DESCRIPTOR;
typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR;
判断哪一个节的空白区 > Size(原导入表的大小) + 20 + A + B + C + D
如果空间不够:可以将C/D 存储在其他的空白区
也就是,只要空白区 > Size + 0x20就可以了
如果仍然不够,就需要扩大最后一个节,或者新增节来解决.
第三步:
将原导入表全部Copy到空白区
第四步:
在新的导入表后面,追加一个导入表.
第五步:
追加8个字节的INT表 8个字节的IAT表
第六步:
追加一个IMAGE_IMPORT_BY_NAME 结构,前2个字节是0 后面是函数名称字符串
第七步:
将IMAGE_IMPORT_BY_NAME结构的RVA赋值给INT和IAT表中的第一项
第八步:
分配空间存储DLL名称字符串 并将该字符串的RVA赋值给Name属性
第九步:
修正IMAGE_DATA_DIRECTORY结构的VirtualAddress和Size
4.代码实现:
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#define size_surplus_sizeofheader 0x50
#define test 1
BOOL MemoryToFile(PVOID pMemBuffer, DWORD size, LPSTR lpszFile);
DWORD ToLoaderPE(LPSTR file_path, PVOID* pFileBuffer);
DWORD CopyFileBufferToImageBuffer(PVOID pFileBuffer, PVOID* pImageBuffer);
DWORD CopyImageBufferToNewFileBuffer(PVOID pImageBuffer, PVOID* pNewFileBuffer);
DWORD FoaToImageOffset(PVOID pBuffer, DWORD dwFoa);
DWORD RvaToFileOffset(PVOID pBuffer, DWORD dwRva);
DWORD GetSctionEmptySpace(PVOID pFileBuffer, DWORD SectionOrdinal);
DWORD Alignment(DWORD alignment_value, DWORD addend, DWORD address);
DWORD DLLInject(PVOID pFileBuffer, PVOID* pNewFileBuffer, char* dllname, char* dllfunction);
VOID LogPEHeaderInfo(PVOID pFileBuffer);
VOID LogImportTable(PVOID pFileBuffer);
char file_path[] = "d:\\ipmsg2007\\ipmsg2007.exe";
char dllname[] = "InjectDll.dll";
char dllfunction[] = "ExportFunction";
char write_dllinject_file_path[] = "D:\\Lib\\cp_XX.exe";
//返回PE文件大小
DWORD ToLoaderPE(LPSTR file_path, PVOID* pFileBuffer)
{
FILE *pFile = NULL;
DWORD FileSize = 0;
PVOID pFileBufferTemp = NULL;
pFile = fopen(file_path, "rb");
if (!pFile)
{
printf("(ToLoaderPE)Can't open file!\n");
return 0;
}
fseek(pFile, 0, SEEK_END);
FileSize = ftell(pFile);
printf("FileBuffer: %#x\n", FileSize);
fseek(pFile, 0, SEEK_SET);
pFileBufferTemp = malloc(FileSize);
if (!pFileBufferTemp)
{
printf("(ToLoaderPE)Allocate dynamic memory failed!\n");
fclose(pFile);
return 0;
}
DWORD n = fread(pFileBufferTemp, FileSize, 1, pFile);
if (!n)
{
printf("(ToLoaderPE)Read file failed!\n");
free(pFileBufferTemp);
fclose(pFile);
return 0;
}
*pFileBuffer = pFileBufferTemp;
pFileBufferTemp = NULL;
fclose(pFile);
return FileSize;
}
BOOL MemoryToFile(PVOID pMemBuffer, DWORD size, LPSTR lpszFile)
{
FILE *fp;
fp = fopen(lpszFile, "wb");
if (fp != NULL)
{
fwrite(pMemBuffer, size, 1, fp);
}
fclose(fp);
printf("Store file success!\n");
return 1;
}
DWORD RvaToFileOffset(PVOID pBuffer, DWORD dwRva)
{
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS pNTHeader = NULL;
PIMAGE_FILE_HEADER pPEHeader = NULL;
PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
if (!pBuffer)
{
printf("(RvaToFileOffset)Can't open file!\n");
return 0;
}
if (*((PWORD)pBuffer) != IMAGE_DOS_SIGNATURE)
{
printf("(RvaToFileOffset)No MZ flag, not exe file!\n");
return 0;
}
pDosHeader = (PIMAGE_DOS_HEADER)pBuffer;
if (*((PDWORD)((DWORD)pBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
{
printf("(RvaToFileOffset)No