首页
社区
课程
招聘
[求助]如何申请 0x400000 地址
发表于: 2009-7-9 19:31 5544

[求助]如何申请 0x400000 地址

2009-7-9 19:31
5544
我有一个第三方的工具程序 苦于没有源码 想直接用到我的EXE里面 然后将此EXE作为DLL加载,然后调用OEP 不过为了避免重定位需要将此EXE加载到0x400000上面 我已经将主EXE的基地址设为其他地址了 第三方的基地址是0x400000 但因为主EXE需要加载其他DLL 这个DLL的基地址也设成其他地址了 但只要先加载这个DLL第三方EXE就不能正确的加载到0x400000上 这是什么原因呢 如果不加载这个DLL首先就加载这个第三方EXE就可以加载到0x400000 但主EXE可能需要链接到一些其他DLL 该怎么把0x400000分配出来供我使用呢

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (3)
雪    币: 211
活跃值: (18)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
0x00400000一般是PE的几个头和表结构,你可以修改。其实问题主要在于节区的安置。
现在有点忙,给你写个例子,你先研究研究。

你还得在你的代码里避免使用依赖ImageBase的API,否则你的代码会崩溃的。
上传的附件:
2009-7-10 13:19
0
雪    币: 86
活跃值: (34)
能力值: ( 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系统中无法运行。
代码写的比较粗糙。。。。纯粹是一个实验品。
2009-7-11 17:54
0
雪    币: 86
活跃值: (34)
能力值: ( LV2,RANK:150 )
在线值:
发帖
回帖
粉丝
4
刚看了白家拳的代码,思路很新颖,学习了。。。收藏
2009-7-11 22:19
0
游客
登录 | 注册 方可回帖
返回
//