|
发表于 2018-4-16 15:50:58
|
显示全部楼层
本楼为最佳答案
我什么也不想说
main.c#pragma warning(disable:4996)
#include "PE_Functions.h"
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#define FREE_SPACE 0x2000
// *************************************************************************************
IMAGE_IMPORT_DESCRIPTOR *g_dest_iid = NULL;
IMAGE_THUNK_DATA *g_dest_itd = NULL;
IMAGE_IMPORT_BY_NAME *g_dest_iibn = NULL;
char *g_dest_string = NULL;
// 使用全局变量 g_dest_string
// 返回复制后的字符串的 RVA
static DWORD MoveString(char *base, char *src)
{
DWORD ret = OffsetToRva(base, ((char *)g_dest_string - base));
strcpy(g_dest_string, src);
g_dest_string += strlen(g_dest_string) + 1; // g_dest_string 指向下一个
return ret;
}
// 使用全局变量 g_dest_iibn
static DWORD MoveImportByName(char *base, IMAGE_IMPORT_BY_NAME *src)
{
DWORD ret = OffsetToRva(base, ((char *)g_dest_iibn - base));
g_dest_iibn->Hint = src->Hint;
strcpy(g_dest_iibn->Name, src->Name);
// 要确保 g_dest_iibn 指向下一个,由于结构体对齐,其他环境可能会出问题
g_dest_iibn = (IMAGE_IMPORT_BY_NAME *)((char *)g_dest_iibn + sizeof(IMAGE_IMPORT_BY_NAME) + strlen(g_dest_iibn->Name) - 1);
return ret;
}
// 使用全局变量 g_dest_itd
// 返回复制后的 IMAGE_THUNK_DATA 结构的RVA
static DWORD MoveThunkData(char *base, IMAGE_THUNK_DATA *src)
{
DWORD ret = OffsetToRva(base, ((char *)g_dest_itd - base));
for(int i = 0; src[i].u1.AddressOfData != 0; ++i)
{
g_dest_itd->u1.AddressOfData = MoveImportByName(base, (IMAGE_IMPORT_BY_NAME *)(RvaToOffset(base, src[i].u1.AddressOfData) + base));
++g_dest_itd;
}
memset(g_dest_itd, 0, sizeof(IMAGE_THUNK_DATA)); // 最后一个全为0的结构
++g_dest_itd; // 指向下一个
return ret;
}
// 使用全局变量 g_dest_iid
static void MoveImportDescriptor(char *base, IMAGE_IMPORT_DESCRIPTOR *src)
{
for(int i = 0; src[i].Characteristics != 0; ++i)
{
g_dest_iid->OriginalFirstThunk = MoveThunkData(base, (IMAGE_THUNK_DATA *)(RvaToOffset(base, src[i].OriginalFirstThunk) + base));
g_dest_iid->TimeDateStamp = src[i].TimeDateStamp; // 原样复制
g_dest_iid->ForwarderChain = src[i].ForwarderChain; // 原样复制
g_dest_iid->Name = MoveString(base, RvaToOffset(base, src[i].Name) + base);
g_dest_iid->FirstThunk = src[i].FirstThunk; // FirstThunk 不做改变
++g_dest_iid;
}
memset(g_dest_iid, 0, sizeof(IMAGE_IMPORT_DESCRIPTOR)); // 最后一个全为0的结构
++g_dest_iid; // 指向下一个
}
// ----------------------------------------------------------------
void DebugPrintImportByName(char *base, IMAGE_IMPORT_BY_NAME *iibn)
{
printf("\t\tiibn->Hint: %x\n", iibn->Hint);
printf("\t\tiibn->Name: %s\n", iibn->Name);
}
void DebugPrintThunkData(char *base, IMAGE_THUNK_DATA *itd)
{
for(int i = 0; itd[i].u1.AddressOfData != 0; ++i)
{
printf("\t{\n");
printf("\t\titd[i].u1.AddressOfData: %x\n", itd[i].u1.AddressOfData);
DebugPrintImportByName(base, (IMAGE_IMPORT_BY_NAME *)(RvaToOffset(base, itd[i].u1.AddressOfData) + base));
printf("\t}\n");
}
}
void Debug(char *base)
{
IMAGE_DOS_HEADER *idh = (IMAGE_DOS_HEADER *)base;
IMAGE_NT_HEADERS32 *inh = (IMAGE_NT_HEADERS32 *)(base + idh->e_lfanew);
DWORD import_rva = inh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
IMAGE_IMPORT_DESCRIPTOR *iid = (IMAGE_IMPORT_DESCRIPTOR *)(base + RvaToOffset(base, import_rva));
for(int i = 0; iid[i].Characteristics != 0; ++i)
{
printf("{\n");
printf("\tiid[i].OriginalFirstThunk: %x\n", iid[i].OriginalFirstThunk);
DebugPrintThunkData(base, (IMAGE_THUNK_DATA *)(RvaToOffset(base, iid[i].OriginalFirstThunk) + base));
printf("}\n");
printf("iid[i].TimeDateStamp: %x\n", iid[i].TimeDateStamp);
printf("iid[i].ForwarderChain: %x\n", iid[i].ForwarderChain);
printf("iid[i].Name: %x\t\t\t%s\n", iid[i].Name, RvaToOffset(base, iid[i].Name) + base);
printf("{\n");
printf("\tiid[i].FirstThunk: %x\n", iid[i].FirstThunk);
DebugPrintThunkData(base, (IMAGE_THUNK_DATA *)(RvaToOffset(base, iid[i].FirstThunk) + base));
printf("}\n");
printf("------------------------------------------------\n");
}
}
// ----------------------------------------------------------------
// 将导入表移动到 ish 指向的区块
void MoveImportTable(char *base, IMAGE_SECTION_HEADER *ish)
{
// 0x00 - 0x1FF 存放 IMAGE_IMPORT_DESCRIPTOR
// 0x200 - 0x3FF 存放 IMAGE_THUNK_DATA
// 0x400 - 0x9FF 存放 IMAGE_IMPORT_BY_NAME
// 0xa00 - 0xaFF 存放 dll字符串(ASCII 字符串)
// 初始化全局变量
char *data = (char *)(base + ish->PointerToRawData);
g_dest_iid = (IMAGE_IMPORT_DESCRIPTOR *)(data + 0x00);
g_dest_itd = (IMAGE_THUNK_DATA *)(data + 0x200);
g_dest_iibn = (IMAGE_IMPORT_BY_NAME *)(data + 0x400);
g_dest_string = (char *)(data + 0xa00);
IMAGE_DOS_HEADER *idh = (IMAGE_DOS_HEADER *)base;
IMAGE_NT_HEADERS32 *inh = (IMAGE_NT_HEADERS32 *)(base + idh->e_lfanew);
DWORD import_rva = inh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
IMAGE_IMPORT_DESCRIPTOR *iid = (IMAGE_IMPORT_DESCRIPTOR *)(base + RvaToOffset(base, import_rva));
MoveImportDescriptor(base, iid);
// 修正数据目录表
inh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = OffsetToRva(base, ish->PointerToRawData);
}
// *************************************************************************************
int main(void)
{
//char *filename = "NewHello.exe";
//CopyFile("Hello.exe", "NewHello.exe", FALSE);
char *filename = "NewMessageBox.exe";
CopyFile("MessageBox.exe", "NewMessageBox.exe", FALSE);
HANDLE hFile = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
printf("Could not open: %s", filename);
exit(1);
}
DWORD orig_file_size = GetFileSize(hFile, NULL);
HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, orig_file_size + FREE_SPACE, NULL);
LPVOID pMem = MapViewOfFile(hMap, FILE_MAP_WRITE | FILE_MAP_READ | FILE_MAP_COPY, 0, 0, 0);
MoveImportTable(pMem, (IMAGE_SECTION_HEADER *)(AddSection(pMem, "hello", 0xb00) + (char *)pMem));
UnmapViewOfFile(pMem);
CloseHandle(hMap);
CloseHandle(hFile);
return 0;
}
PE_Functions.c#pragma warning(disable:4996)
#include "PE_Functions.h"
#include <windows.h>
#include <time.h>
DWORD PE_Align(DWORD tar_num, DWORD align_to)
{
DWORD n = tar_num / align_to;
if(n * align_to < tar_num)
++n;
return n * align_to;
}
DWORD RvaToOffset(LPVOID base, DWORD rva)
{
IMAGE_DOS_HEADER *idh = (IMAGE_DOS_HEADER *)base;
IMAGE_NT_HEADERS32 *inh = (IMAGE_NT_HEADERS32 *)((char *)base + idh->e_lfanew);
IMAGE_SECTION_HEADER *ish = (IMAGE_SECTION_HEADER *)(inh + 1);
for(int i = 0; i < inh->FileHeader.NumberOfSections; ++i)
{
if((ish[i].VirtualAddress <= rva) && (rva < ish[i].VirtualAddress + ish[i].SizeOfRawData))
{
return rva - ish[i].VirtualAddress + ish[i].PointerToRawData;
}
}
return -1;
}
DWORD OffsetToRva(LPVOID base, DWORD offset)
{
IMAGE_DOS_HEADER *idh = (IMAGE_DOS_HEADER *)base;
IMAGE_NT_HEADERS32 *inh = (IMAGE_NT_HEADERS32 *)((char *)base + idh->e_lfanew);
IMAGE_SECTION_HEADER *ish = (IMAGE_SECTION_HEADER *)(inh + 1);
for(int i = 0; i < inh->FileHeader.NumberOfSections; ++i)
{
if((ish[i].PointerToRawData <= offset) && (offset < ish[i].PointerToRawData + ish[i].SizeOfRawData))
{
return offset - ish[i].PointerToRawData + ish[i].VirtualAddress;
}
}
return -1;
}
// **************************************************************************************
static DWORD GetVirtualAddress(IMAGE_NT_HEADERS32 *inh, IMAGE_SECTION_HEADER *ish)
{
DWORD address = ish[inh->FileHeader.NumberOfSections - 1].VirtualAddress;
DWORD size = ish[inh->FileHeader.NumberOfSections - 1].Misc.VirtualSize;
return address + size;
}
static DWORD GetPointerToRawData(IMAGE_NT_HEADERS32 *inh, IMAGE_SECTION_HEADER *ish)
{
DWORD address = ish[inh->FileHeader.NumberOfSections - 1].PointerToRawData;
DWORD size = ish[inh->FileHeader.NumberOfSections - 1].SizeOfRawData;
return address + size;
}
// 返回值为 新增区块表的偏移
DWORD AddSection(LPVOID base, const char *section_name, DWORD section_size)
{
IMAGE_DOS_HEADER *idh = (IMAGE_DOS_HEADER *)base;
IMAGE_NT_HEADERS32 *inh = (IMAGE_NT_HEADERS32 *)((char *)base + idh->e_lfanew);
IMAGE_SECTION_HEADER *ish = (IMAGE_SECTION_HEADER *)(inh + 1);
DWORD ret = (DWORD)((char *)&ish[inh->FileHeader.NumberOfSections] - (char *)base);
strncpy(ish[inh->FileHeader.NumberOfSections].Name, section_name, 8);
ish[inh->FileHeader.NumberOfSections].Misc.VirtualSize = section_size;
ish[inh->FileHeader.NumberOfSections].VirtualAddress = PE_Align(GetVirtualAddress(inh, ish), inh->OptionalHeader.SectionAlignment);
ish[inh->FileHeader.NumberOfSections].SizeOfRawData = PE_Align(section_size, inh->OptionalHeader.FileAlignment);
ish[inh->FileHeader.NumberOfSections].PointerToRawData = PE_Align(GetPointerToRawData(inh, ish), inh->OptionalHeader.FileAlignment);
ish[inh->FileHeader.NumberOfSections].PointerToRelocations = 0;
ish[inh->FileHeader.NumberOfSections].PointerToLinenumbers = 0;
ish[inh->FileHeader.NumberOfSections].NumberOfRelocations = 0;
ish[inh->FileHeader.NumberOfSections].NumberOfLinenumbers = 0;
ish[inh->FileHeader.NumberOfSections].Characteristics = 0xE00000E0; // 可读可写可执行
// 对数据区填0
RtlZeroMemory((char *)base + ish[inh->FileHeader.NumberOfSections].PointerToRawData, ish[inh->FileHeader.NumberOfSections].SizeOfRawData);
inh->FileHeader.TimeDateStamp = (DWORD)time(NULL); // 修改时间戳
inh->OptionalHeader.SizeOfImage =
PE_Align(ish[inh->FileHeader.NumberOfSections].VirtualAddress + ish[inh->FileHeader.NumberOfSections].Misc.VirtualSize,
inh->OptionalHeader.SectionAlignment); // 调整 SizeOfImage
inh->FileHeader.NumberOfSections += 1; // 区块个数加1
return ret;
}
// **************************************************************************************
PE_Functions.h#ifndef _PE_FUNCTIONS_H_
#define _PE_FUNCTIONS_H_
#include <windows.h>
DWORD PE_Align(DWORD tar_num, DWORD align_to);
DWORD RvaToOffset(LPVOID base, DWORD rva);
DWORD OffsetToRva(LPVOID base, DWORD offset);
// 返回值为 新增区块表的偏移
DWORD AddSection(LPVOID base, const char *section_name, DWORD section_size);
#endif
|
|