能力值:
( LV2,RANK:10 )
|
-
-
2 楼
0x00400000一般是PE的几个头和表结构,你可以修改。其实问题主要在于节区的安置。
现在有点忙,给你写个例子,你先研究研究。
你还得在你的代码里避免使用依赖ImageBase的API,否则你的代码会崩溃的。
|
能力值:
( LV2,RANK:150 )
|
-
-
3 楼
我们课堂上讲过LOADEXE的,下边是C的代码,你看下,是不是你需要的。
用VC实现这个功能的最大麻烦是,如何让程序运行起来的0X401000—0X0404000这段内存空出,用来放被加载程序的各个区段。。
首先在编译器LINK选项中设置BASEADDR的地址。我先把这个地址设置的高点。默认应该是0X400000。我把这个地址设为0X500000,然后用VirautlAlloc函数申请0X401000开头的0X3000大小的内存。。。现在的问题是:无论我怎么设置BASEADDR,0X401000这段内存都会被系统资源占用。。。。,VirautlAlloc失败。。郁闷。
只好定义了一个大的数组,作为全局变量。然后慢慢调整BASEADDR,使得程序执行的时候,
这个数组可以包含0X401000这段内存。。下面给出程序实现。
BYTE g_bImageBsae[0xe000];
void CLoadExeDlg::OnButton1()
{
// TODO: Add your control notification handler code here
UpdateData();
void *pFileAddr;//文件隐射基地址
IMAGE_DOS_HEADER *pDosHead;
IMAGE_OPTIONAL_HEADER *pOPHead;
IMAGE_FILE_HEADER *pFileHead;
DWORD dwSecNum;
IMAGE_SECTION_HEADER *pSecInfo;
IMAGE_IMPORT_DESCRIPTOR *pIID;
LPTHREAD_START_ROUTINE OEP;
void *pImageBase = (void*)0x400000;
HANDLE hFile = ::CreateFile(m_strFileName,GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if (hFile==INVALID_HANDLE_VALUE)
{
AfxMessageBox("Can't open file");
return;
}
HANDLE hMaping = CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL);
pFileAddr = MapViewOfFile(hMaping,FILE_MAP_READ,0,0,0);
pDosHead = (IMAGE_DOS_HEADER*)pFileAddr;
pFileHead = (IMAGE_FILE_HEADER*)(pDosHead->e_lfanew+4 +(DWORD)pFileAddr);
pOPHead = (IMAGE_OPTIONAL_HEADER*)((DWORD)pFileHead +
sizeof(_IMAGE_FILE_HEADER));
OEP = (LPTHREAD_START_ROUTINE)(pOPHead->AddressOfEntryPoint + (DWORD)pImageBase);
dwSecNum = pFileHead->NumberOfSections;
pSecInfo = new IMAGE_SECTION_HEADER[dwSecNum];
//描述表首地址
DWORD SecInfoStart;
SecInfoStart = (DWORD)pOPHead + pFileHead->SizeOfOptionalHeader ;
//获取区信息表
memcpy((void*)pSecInfo, (void*)SecInfoStart,
sizeof(IMAGE_SECTION_HEADER)*dwSecNum);
//把区搬到0X400000为基地址的地方。
for (DWORD i = 0; i < dwSecNum; i++)
{
DWORD dwSecImageAddr = pSecInfo[i].VirtualAddress+(DWORD)pImageBase;
DWORD dwSecFileAddr = pSecInfo[i].PointerToRawData + (DWORD)pFileAddr;
memcpy((void*)dwSecImageAddr,(void*)dwSecFileAddr,pSecInfo[i].Misc.VirtualSize);
}
pIID = (IMAGE_IMPORT_DESCRIPTOR*)((pOPHead->DataDirectory[1].VirtualAddress) + (DWORD)pImageBase);
//解析INT表并填入IAT。
while (pIID->Name != 0)
{
char *pDllName;
char *pFacName;
HMODULE hDll;
IMAGE_THUNK_DATA32 *pIDT,*pIAT;
PIMAGE_IMPORT_BY_NAME *pImByName;
pDllName = (char*)((DWORD)(pIID->Name) + (DWORD)pImageBase);
hDll = LoadLibrary((LPCSTR)pDllName);
pIDT = (IMAGE_THUNK_DATA32*)(pIID->OriginalFirstThunk + (DWORD)pImageBase);
pIAT = (IMAGE_THUNK_DATA32*)(pIID->FirstThunk + (DWORD)pImageBase);
while (*(DWORD*)pIDT != 0)
{
pImByName = (PIMAGE_IMPORT_BY_NAME*)((DWORD)(pIDT->u1.AddressOfData)+ (DWORD)pImageBase);
pFacName =(char*)pImByName+2;
pIAT->u1.Function = (PDWORD)GetProcAddress(hDll,pFacName);
pIDT++ ;
}
pIID++;
}
DWORD dwThreadID;
HANDLE hThread = ::CreateThread(NULL,NULL,OEP,NULL,NULL,&dwThreadID);
::WaitForSingleObject(hThread,INFINITE);
delete []pSecInfo;
}
上边代码在VC6.0下编译通过。编译器警告:在95系统中无法运行。
代码写的比较粗糙。。。。纯粹是一个实验品。
|
能力值:
( LV2,RANK:150 )
|
-
-
4 楼
刚看了白家拳的代码,思路很新颖,学习了。。。收藏
|