vs 2008
010 edit编辑器
目标
网络下载一个exe程序,并且在内存中展开,且运行。不需要写在硬盘上。
我先给全部代码,下面是解释部分
// RunExeThread.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
PIMAGE_DOS_HEADER dosHeader;
PIMAGE_NT_HEADERS ntHeader;
PIMAGE_FILE_HEADER fileHeader;
PIMAGE_EXPORT_DIRECTORY exportDirectory;
PIMAGE_SECTION_HEADER pSectionHeader;
PIMAGE_IMPORT_DESCRIPTOR importDescriptor;
PIMAGE_THUNK_DATA thunkData;
PIMAGE_IMPORT_BY_NAME ordAndName;
PIMAGE_BASE_RELOCATION baseRelocation;
char file[]="路径\\game.exe"; //这是读取文件的路径
LPBYTE lpBaseAddress;
int _tmain(int argc, _TCHAR* argv[])
{
//将磁盘文件映射到内存中
HANDLE hcf = CreateFileA(file,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
HANDLE hcfm = CreateFileMappingA(hcf,NULL,PAGE_READONLY,0,0,0);
lpBaseAddress=(LPBYTE)MapViewOfFile(hcfm,FILE_MAP_READ,0,0,0);
//获取一些基本变量
dosHeader = (PIMAGE_DOS_HEADER)lpBaseAddress;
int lfanew = dosHeader->e_lfanew;
ntHeader = (PIMAGE_NT_HEADERS)(lpBaseAddress+lfanew);
int sizeOfImage = ntHeader->OptionalHeader.SizeOfImage;
int sizeOfHeader = ntHeader->OptionalHeader.SizeOfHeaders;
pSectionHeader = (PIMAGE_SECTION_HEADER)(lpBaseAddress+lfanew+sizeof(IMAGE_NT_HEADERS));
//创建内存空间
LPBYTE loca = (LPBYTE)VirtualAlloc(NULL,sizeOfImage,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
//拷贝内存空间
LPBYTE virseek = (LPBYTE)loca;
memcpy(loca,lpBaseAddress,sizeOfHeader);
if(sizeOfHeader%0x1000!=0)
{
virseek+=0x1000;
}
virseek += (sizeOfHeader/0x1000)*0x1000;
LPBYTE sectionStartAddr = lpBaseAddress+sizeOfHeader;
for(int i=0;i<(ntHeader->FileHeader.NumberOfSections);i++,pSectionHeader++)
{
int sectionSize = pSectionHeader->Misc.VirtualSize/0x1000;
if(pSectionHeader->Misc.VirtualSize%0x1000!=0)
{
sectionSize++;
}
memcpy(virseek,sectionStartAddr,pSectionHeader->SizeOfRawData);
sectionStartAddr+=pSectionHeader->SizeOfRawData;
virseek += sectionSize*0x1000;
}
//修复IAT表
ntHeader = (PIMAGE_NT_HEADERS)(loca+lfanew);
int vAddr = ntHeader->OptionalHeader.DataDirectory[1].VirtualAddress;
importDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(loca + vAddr);
while(importDescriptor->Name)
{
HMODULE moduleHandle = LoadLibraryA((LPCSTR)(loca+importDescriptor->Name));
thunkData = (PIMAGE_THUNK_DATA)(importDescriptor->FirstThunk+loca);
DWORD * indexAddr = (DWORD *)(importDescriptor->FirstThunk+loca);
while(thunkData->u1.AddressOfData)
{
if(IMAGE_SNAP_BY_ORDINAL(thunkData->u1.AddressOfData))
{
LPCSTR addr = (LPCSTR)thunkData->u1.AddressOfData-0x80000000;
*indexAddr = (DWORD)GetProcAddress(moduleHandle,addr);
}else{
ordAndName = (PIMAGE_IMPORT_BY_NAME)(loca + thunkData->u1.AddressOfData);
*indexAddr = (DWORD)GetProcAddress(moduleHandle,(LPCSTR)(ordAndName->Name));
}
thunkData++;
indexAddr++;
}
importDescriptor++;
}
//修复重定位表
baseRelocation = (PIMAGE_BASE_RELOCATION)(loca + (ntHeader->OptionalHeader.DataDirectory[5].VirtualAddress));
int num;
WORD *data;
while(baseRelocation->VirtualAddress+baseRelocation->SizeOfBlock != 0)
{
data = (WORD *)((LPBYTE)baseRelocation+0x8);
num = (baseRelocation->SizeOfBlock-0x8)/sizeof(WORD);
for(int i = 0;i<num;i++)
{
if((DWORD)(data[i]&0x0000F000)==0x00003000)
{
DWORD* addr = (DWORD *)(loca+baseRelocation->VirtualAddress+(data[i]&0x00000FFF));
*addr +=(DWORD)(loca - ntHeader->OptionalHeader.ImageBase);
}
}
baseRelocation = (PIMAGE_BASE_RELOCATION)((LPBYTE)baseRelocation + baseRelocation->SizeOfBlock);
}
HANDLE h =CreateThread(0,0,(LPTHREAD_START_ROUTINE)(loca+ntHeader->OptionalHeader.AddressOfEntryPoint),0,0,0);
DWORD d = WaitForSingleObject(h,INFINITE);
VirtualFree(loca,0,MEM_RELEASE);
CloseHandle(hcfm);
CloseHandle(hcf);
return 0;
}以0x1000粒度拷贝到内存
拷贝过程
1.拷贝各个头部,即节区头以上的部分。(PE结构中在可选头中有SizeOfHeaders指明了大小)
2.各个节区块,如下图
修改导出表
有人会问为什么要修复导出表呢~
这就跟PE文件展开有关
导入表在磁盘中的存储值如下图
导出表中有两个成员,OriginalFirstThunk和FirstThunk。他们一开始指向的是不同的IMAGE_THUNK_DATA结构体数组。但是这两个数组指向的内容却是相同的。
在程序运行后
OriginalFirstThunk没有发生变化
但是FirstThunk却发生了改变
他在运行完成后指向的地方变成了函数的入口地址。
因为它的改变,我们就要去修改它。
修复重定向
这里又要了解下为啥修复重定向咯
我们程序有个基址重定向机制,有了这个机制,我们才能在一台电脑中跑多个程序。不然默认的exe基址都是0x400000,会有冲突。
总而言之,言而总之。就是基址变化,重定位表里面存放的是针对默认的基址准备的VA地址
现在我们基址改变了。我们就要改变他。
收藏的用户(0) X
正在加载信息~
推荐阅读
最新回复 (0)
站点信息
- 文章2313
- 用户1336
- 访客11759637
每日一句
Happiness depends on your mindset.
幸福取决于你的心态。
幸福取决于你的心态。
新会员


