某日,逆向一EXE(这里命名它为HH),发现内部使用了Rijndael-256,以及某个不知名的算法。
从网上找到N个相关AES算法的实现,结果密码表是一样了,但运行结果却怎么都不一样。
由于实在对AES头晕,再加上还有某个不知名的算法(内部流程复杂),所以考虑需要利用这个EXE的加解密实现。
可是EXE不是DLL,没有重定位表。不能像DLL一样Load一下,直接CALL就能用。
怎么办?把EXE当DLL使?修正重定位信息?网上找了找,基本是这个说法,但说法的后面,也明确指出:依然不足,修正重定位信息是件苦力活,还容易出错。
而且,N个地方需要重定位,这一路做下来,不吐血也脑溢血了。
考虑考虑怎么取巧吧。
思路:
  首先,自己写的利用程序(这里命名它为CC)是可以设置有重定位信息的,所以可以让出EXE的默认加载位置。
  把HH放在400000位置,嘿嘿,重定位不就省了?
。。。
说得容易,实现一下看看?指定CC加载到别处,设置重定位,MapViewOfFileEx把HH加载到0x400000。
报错?不行?不行!
什么错?目标位置已被使用,无法加载?!
OD看看,果然,让出来的茅坑让系统给用了。
再想:
  由于茅坑让出来了,系统就认为是无主的,爱怎么用,用多少,咱管不到。
  就算这个茅坑系统没有使用,万一HH屁股比较大,需要连坐N个坑,那就保不齐系统把后面坑占走,害HH屁股装不下了。。。
  如何通知系统留着坑哩?
试着手工打造一个占坑PE。试来试去,不尽人意。
又想:
  最好的办法是让HH自己占。
  可是HH自己占坑就得运行,我们只想使用数据与代码,不想它运行起来。
  于是需要改造HH入口。
  由于HH入口承接着主线程,不能让它结束。正好,把主线程转移给CC。
  用LoadLibrary加载CC。
  LoadLibrary加载PE文件,找到PE入口,并把入口视作DLLMain,以DLL_PROCESS_ATTACH为参数调用之。
  所以不管你是EXE还是DLL,入口总能得到运行。
  如此,主线程将被交付CC。
试试呗。
实现CC,内部使用HH的绝对地址。当然,这样CC程序是不能独立运行的。
修改HH入口,指定加载CC。
不成功?CC无法加载。
其实是小问题,用LordPE把CC的Characteristics加上DLL标志。
再来,成功了!!!成功利用了HH内部数据与代码!!!

好,再分析一下细节:注意到可能CC与HH的子系统不同,所以需要统一子系统。
另外,如果HH加过壳,这个方法就不能直接使用了。虽然俺不大会脱,但总有牛人会脱,脱了壳再应用,一样一样的。

给出实现DEMO:

代码:
// Replacer.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include <windows.h>
#include <iostream>
using namespace std;
#include "netline.h"

void usage()
  {
  cout<<endl;
  cout<<"Usage: Replacer Host Client [Client_argv]\n"<<endl;
  cout<<"Options:"<<endl;
  cout<<"    Host\t将占用原有的原始空间"<<endl;
  cout<<"    Client\t将作为DLL被加载,需要有重定位信息"<<endl;
  cout<<"\t\t主线程将被交付到入口"<<endl;
  cout<<"\t\t注意导入库可能无法正确识别(环境设置)"<<endl;
  cout<<"    Client_argv\t将被用于Client启动参数\n"<<endl;
  }


unsigned long GetRAbyRVA(HANDLE hMapView,unsigned long RVA)
  {
  IMAGE_DOS_HEADER* doshead = (IMAGE_DOS_HEADER*)hMapView;
  IMAGE_NT_HEADERS* PEhead = (IMAGE_NT_HEADERS*)((unsigned long)doshead + (unsigned long)doshead->e_lfanew);
  IMAGE_SECTION_HEADER* ISH = (IMAGE_SECTION_HEADER*)((unsigned long)PEhead + sizeof(IMAGE_NT_HEADERS));
  IMAGE_EXPORT_DIRECTORY*  lpExpF = 0;
  for(int i=0;i<PEhead->FileHeader.NumberOfSections;++i)
    {
    if(RVA>=ISH->VirtualAddress && RVA<=(ISH->VirtualAddress+ISH->Misc.VirtualSize))
      {
      return( (unsigned long)hMapView + ISH->PointerToRawData + RVA - ISH->VirtualAddress );
      }
    ++ISH;
    }
  return 0;
  }

const TCHAR* hostEXE = TEXT("host.exe");
const TCHAR* clientEXE = TEXT("client.exe");

int _tmain(int argc, _TCHAR* argv[])
{
  HANDLE hMapView = 0;
try
  {
  if(argc<3)    throw runtime_error("");
  cout<<"配置Client中...";
  if(!CopyFile(argv[2],clientEXE,false))    throw runtime_error("复制Client文件失败!");
  HANDLE hFile = CreateFile(clientEXE,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
  if(hFile == INVALID_HANDLE_VALUE)        throw runtime_error("打开Client文件失败!");
  HANDLE hFileMapping = CreateFileMapping(hFile,0,PAGE_READWRITE,0,0,0);
  CloseHandle(hFile);
  if(!hFileMapping)        throw runtime_error("CreateFileMapping失败!");
  hMapView = MapViewOfFile(hFileMapping,FILE_MAP_READ|FILE_MAP_WRITE,0,0,0);
  CloseHandle(hFileMapping);
  if(!hMapView)        throw runtime_error("MapViewOfFile失败!");
  IMAGE_DOS_HEADER* doshead = (IMAGE_DOS_HEADER*)hMapView;
  if(doshead->e_magic != 'ZM')        throw runtime_error("检测MZ标志失败!");
  IMAGE_NT_HEADERS* PEhead = (IMAGE_NT_HEADERS*)((unsigned long)doshead + (unsigned long)doshead->e_lfanew);
  if(PEhead->Signature != 'EP')        throw runtime_error("检测PE标志失败!");
  WORD subsystem = PEhead->OptionalHeader.Subsystem;    //得到子系统
  IMAGE_DATA_DIRECTORY* IDD = PEhead->OptionalHeader.DataDirectory;
  IDD+=5;    //指向重定位表
  if(IDD->Size==0)    throw runtime_error("Client没有重定位表,无法继续!");
  if((IMAGE_FILE_DLL & PEhead->FileHeader.Characteristics)!=IMAGE_FILE_DLL)
    {
    cout<<"Client没有DLL标志,加载修改成DLL...";
    PEhead->FileHeader.Characteristics = PEhead->FileHeader.Characteristics | IMAGE_FILE_DLL;
    }
  UnmapViewOfFile(hMapView);
  hMapView = 0;
  cout<<"完成!"<<endl;
  cout<<"配置Host中...";
  if(!CopyFile(argv[1],hostEXE,false))    throw runtime_error("复制Host文件失败!");
  hFile = CreateFile(hostEXE,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
  if(hFile == INVALID_HANDLE_VALUE)        throw runtime_error("打开Host文件失败!");
  hFileMapping = CreateFileMapping(hFile,0,PAGE_READWRITE,0,0,0);
  CloseHandle(hFile);
  if(!hFileMapping)        throw runtime_error("CreateFileMapping失败!");
  hMapView = MapViewOfFile(hFileMapping,FILE_MAP_READ|FILE_MAP_WRITE,0,0,0);
  CloseHandle(hFileMapping);
  if(!hMapView)        throw runtime_error("MapViewOfFile失败!");
  doshead = (IMAGE_DOS_HEADER*)hMapView;
  if(doshead->e_magic != 'ZM')        throw runtime_error("检测MZ标志失败!");
  PEhead = (IMAGE_NT_HEADERS*)((unsigned long)doshead + (unsigned long)doshead->e_lfanew);
  if(PEhead->Signature != 'EP')        throw runtime_error("检测PE标志失败!");
  if(subsystem!=PEhead->OptionalHeader.Subsystem)
    {
    cout<<"Host与Client的子系统不同,修改匹配之...";
    PEhead->OptionalHeader.Subsystem = subsystem;
    }
  cout<<"\n重做Host入口...";
  unsigned long Entry = PEhead->OptionalHeader.AddressOfEntryPoint;
  Entry = GetRAbyRVA(hMapView,Entry);
  int ClientName_len = _tcslen(clientEXE)+sizeof(TCHAR);
  ClientName_len*=2;
  HMODULE hMod = GetModuleHandle(TEXT("Kernel32.dll"));
  unsigned long LodLib = (unsigned long)GetProcAddress(hMod,"LoadLibraryW");
  netline nline;
  nline.net(false);
  nline<<(unsigned char)0xB8<<LodLib;  //mov eax, LoadLibrary
  nline<<(unsigned char)0xE8;    //call ...
  nline<<ClientName_len;
  nline.setstr((unsigned char*)clientEXE,ClientName_len);
  nline.setstr((unsigned char*)"\xFF\xD0\xC2\x10\x00",5);  //call   eax        retn 10
  nline.getstr((unsigned char*)Entry,(int)nline);
  cout<<"搞定!"<<endl;
  UnmapViewOfFile(hMapView);
  hMapView = 0;
  }
catch (runtime_error &err)
  {
  DeleteFile(clientEXE);
  DeleteFile(hostEXE);
  if(hMapView)UnmapViewOfFile(hMapView);
  cout<<err.what()<<endl;
  usage();
  }
catch (...)
  {
  cout<<"未知异常!"<<endl;
  usage();
  }
  return 0;
}