Coder Jozu

I believe --- 这里坚持原创,拒绝转贴

  VC知识库BLOG :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 登录 ::
  13 随笔 :: 4 文章 :: 87 评论 :: 1 Trackbacks
<2008年9月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

留言簿(4)

随笔分类

随笔档案

文章分类

文章档案

东接西链

搜索

最新评论

阅读排行榜

评论排行榜

hiahia,被这个题目吓住了吧,一个CreateProcess不就可以吗,嘿嘿,可是你会看到两个进程存在,这里要干的是让进程管理器只能看到一个进程。好了,如果你有了Win32进程的基础理论,了解PE格式,再加上熟悉管理进程(当然你要是不知道这些,代码运行以后的效果你都不会看到。。。那我不是白忙了:P)开始:

先来看看代码:

// ExeLoader.cpp : Defines the entry point for the console application.
//
// Coder Jozu

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <tchar.h>

#define MakePtr( cast, ptr, addValue ) (cast)( (DWORD)(ptr) + (DWORD)(addValue))

//////////////////////////////////////////////////////////////////////////

void CopyRight()
{
 _tprintf("ExeLoader --- Load a exe FILE and execute it IN CURRENT CONTEXT.\n");
 _tprintf("                                                     Coder Jozu.\n");
 _tprintf("----------------------------------------------------------------\n");
}

//////////////////////////////////////////////////////////////////////////

void Usage()
{
 _tprintf("Exeloader program\n");
 _tprintf("ExeLoader program\n");
 _tprintf("    Program is what you want to executed.\n");
}

//////////////////////////////////////////////////////////////////////////

HINSTANCE hInst;

typedef HMODULE (WINAPI* LPFNGETMODULEHANDLEA)(LPCSTR lpModuleFilename);
typedef HMODULE (WINAPI* LPFNGETMODULEHANDLEW)(LPCWSTR lpModuleFilename);
LPFNGETMODULEHANDLEA lpfnGetModulehandleA = NULL;
LPFNGETMODULEHANDLEW lpfnGetModulehandleW = NULL;

static
HMODULE
WINAPI
HandlerGetModuleHandleA(LPCSTR lpModuleFileName)
{
 if(!lpModuleFileName)
  return hInst;
 return lpfnGetModulehandleA(lpModuleFileName);
}

static
HMODULE
WINAPI
HandlerGetModuleHandleW(LPCWSTR lpModuleFileName)
{
 if(!lpModuleFileName)
  return hInst;
 
 return lpfnGetModulehandleW(lpModuleFileName);
}

//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////

DWORD
WINAPI
GetFunctionAddrWithIndex(HMODULE hInst, PIMAGE_IMPORT_BY_NAME piibn)
{
 //
 // I am tired of do this bitch, so just do it directly
 // Don't say it is a bug. en....
 //
 if( !stricmp((LPCSTR)piibn->Name, "GetModuleHandleA") )
  return (DWORD)HandlerGetModuleHandleA;
 if( !stricmp((LPCSTR)piibn->Name, "GetModuleHandleW") )
  return (DWORD)HandlerGetModuleHandleW;

 return (DWORD)GetProcAddress(hInst, (LPCSTR)piibn->Hint);
}

//////////////////////////////////////////////////////////////////////////

DWORD
WINAPI
GetFunctionAddrWithName(HMODULE hInst, PIMAGE_IMPORT_BY_NAME piibn)
{
 if( !stricmp((LPCSTR)piibn->Name, "GetModuleHandleA") )
  return (DWORD)HandlerGetModuleHandleA;
 if( !stricmp((LPCSTR)piibn->Name, "GetModuleHandleW") )
  return (DWORD)HandlerGetModuleHandleW;
 
 return (DWORD)GetProcAddress(hInst, (LPCSTR)piibn->Name);
}

//////////////////////////////////////////////////////////////////////////

BOOL
WINAPI
WalkWithImportTable(PVOID hInst)
{
#define THUNK_INDEXMASK 0x80000000

 PIMAGE_DOS_HEADER  pidh;
 PIMAGE_NT_HEADERS  pinhs;
 PIMAGE_SECTION_HEADER pish;
 PIMAGE_IMPORT_DESCRIPTOR piid;
 BOOL bDone = FALSE;
 HMODULE  hModule;
 LPCSTR  lpDllName;
 PIMAGE_THUNK_DATA pitd;
 PIMAGE_THUNK_DATA pFirstThunk;
 PIMAGE_IMPORT_BY_NAME piibn;
 DWORD  dwFuncAddr;
 SYSTEM_INFO si;
 MEMORY_BASIC_INFORMATION mbi;

 pidh = (PIMAGE_DOS_HEADER)hInst;
 pinhs = MakePtr(PIMAGE_NT_HEADERS, pidh, pidh->e_lfanew);
 pish = MakePtr(PIMAGE_SECTION_HEADER, pinhs, sizeof(*pinhs));

 piid = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, pidh,
  pinhs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);

 if(piid->TimeDateStamp == 0)
 {
  _tprintf("sorry about it.... You try to execute a exe with no bind import table. I will process later\n");
  return FALSE;
 }

 if((DWORD)piid == (DWORD)pidh)
 {
  _tprintf("ft.... You try to execute a exe with no import table?");
  return FALSE;
 }

 while(piid->Name != (DWORD)0)
 {
  lpDllName = MakePtr(LPCSTR, pidh, piid->Name);
  
  _tprintf("Processes dll: %s.\n", lpDllName);
  //
  // Check this dll is loaded, if not, just load it!
  //
  if((hModule = GetModuleHandle(lpDllName)) == NULL)
   hModule = LoadLibrary(lpDllName);

  //
  // Walk with the functions, if the functions not been bind,
  // we can use FirstThunk or OriginalFirstThunk, else
  // we use OriginalFirstThunk
  //
  pitd = MakePtr(PIMAGE_THUNK_DATA, pidh, piid->OriginalFirstThunk);
  pFirstThunk = MakePtr(PIMAGE_THUNK_DATA, pidh, piid->FirstThunk);
  //
  // Make virtual memory could be write
  //
  GetSystemInfo(&si);
  VirtualQuery(pFirstThunk, &mbi, sizeof(mbi));
  if( (mbi.Protect & PAGE_READWRITE) != PAGE_READWRITE)
  {
   if(!VirtualProtect(mbi.BaseAddress, si.dwPageSize, PAGE_READWRITE, &mbi.Protect))
    return FALSE;
  }
  while(*(DWORD*)pitd)
  {
   if((*(DWORD*)pitd & THUNK_INDEXMASK) == THUNK_INDEXMASK)
   {
    piibn = MakePtr(PIMAGE_IMPORT_BY_NAME, pidh, (*(DWORD*)pitd & ~THUNK_INDEXMASK));
    dwFuncAddr = GetFunctionAddrWithIndex(hModule, piibn);
   }
   else
   {
    piibn = MakePtr(PIMAGE_IMPORT_BY_NAME, pidh, *(DWORD*)pitd);
    dwFuncAddr = GetFunctionAddrWithName(hModule, piibn);
   }
   if(!dwFuncAddr)
   {
    _tprintf("Function address return NULL. abort...\n");
    return FALSE;
   }
   //
   // Patch to import table.
   //
   pFirstThunk->u1.AddressOfData = dwFuncAddr;

   pFirstThunk++;
   pitd++;
  }

  if(!VirtualProtect(mbi.BaseAddress, si.dwPageSize, mbi.Protect, &mbi.Protect))
    return FALSE;

  piid++;
 }

 return TRUE;
}

//////////////////////////////////////////////////////////////////////////

int _tmain(int argc, LPCTSTR argv[])
{
 BOOL bDone = FALSE;
 DWORD dwOffset;
 PIMAGE_DOS_HEADER  pidh;
 PIMAGE_NT_HEADERS  pinhs;
 LPSTR lpCmdLine;
 LPWSTR lpwCmdLine;
 WCHAR lpwArgv1[MAX_PATH];

 CopyRight();

 if(argc != 2)
 {
  Usage();
  return 1;
 }

/*
#ifdef _DEBUG
 LoadLibrary("User32.dll");
 WalkWithImportTable(GetModuleHandle("user32.dll"));
#endif
*/
 
 //
 // We should handle GetModuelhandle() function
 //
 lpfnGetModulehandleA = (LPFNGETMODULEHANDLEA)
  GetProcAddress(GetModuleHandle("kernel32.dll"), "GetModuleHandleA");
 lpfnGetModulehandleW = (LPFNGETMODULEHANDLEW)
  GetProcAddress(GetModuleHandle("kernel32.dll"), "GetModuleHandleW");

 __try
 {
  //
  // Validate this file is a executable PE file
  //
  GetFileAttributes(argv[1]);
  if(GetLastError() != ERROR_SUCCESS)
  {
   _tprintf("%s File not found!\n", argv[1]);
   __leave;
  }
  
  //
  // Load file with DONT_RESOLVE_DLL_REFERENCES will not redirect import table,
  // so we will do it manual
  //
  hInst = LoadLibraryEx(argv[1], NULL, DONT_RESOLVE_DLL_REFERENCES);

  pidh = MakePtr(PIMAGE_DOS_HEADER, hInst, 0);
  if(pidh->e_magic != IMAGE_DOS_SIGNATURE)
  {
   _tprintf("Invalidate file format.\n");
   __leave;
  }
  pinhs = MakePtr(PIMAGE_NT_HEADERS, hInst, pidh->e_lfanew);
  if(pinhs->Signature != IMAGE_NT_SIGNATURE)
  {
   _tprintf("Invalidate file format.\n");
   __leave;
  }
  
  dwOffset = pinhs->OptionalHeader.AddressOfEntryPoint + (DWORD)hInst;

  //
  // Redirect import table of PE file.
  //
  if(!WalkWithImportTable(hInst))
  {
   _tprintf("Redirect file import table failed. abort...\n");
   __leave;
  }

  //
  // We will patch the command line, There is no error handler,
  // if it is failed, I could say nothing....
  //
  lpCmdLine = GetCommandLine();
  strcpy(lpCmdLine, argv[1]);

  lpwCmdLine = GetCommandLineW(); 
  MultiByteToWideChar(CP_ACP, 0, argv[1], -1, lpwArgv1, MAX_PATH);
  wcscpy(lpwCmdLine, lpwArgv1);

  __try
  {
   //
   // Goto call entrypoint.
   //
   ((FARPROC)(dwOffset))();
   //
   // If the exe call exitprocess() directly, We will never goto next.
   // so if you want to do some post-processes, please hook this functions.
   //
  }
  __finally {}

  bDone = TRUE;

 }
 __finally {}

 getchar();

 return 0;
}

基本思路是这样的:

首先装载exe文件,然后自己为它进行导出函数的重定向,把控制转移到exe文件的入口点,代码中有一些会有问题,我都作了注释,希望你看得时候注意。

其中未邦定的API定位部分我没有时间实现了,不过如果你有兴趣可以自己加。have fun。

posted on 2005-01-30 03:20 Coder Jozu 阅读(4947) 评论(10)  编辑 收藏

评论

# re: 装载一个exe,并且执行 2005-01-31 07:08 freedk
看不懂,收藏一下

# re: 装载一个exe,并且执行 2005-01-31 23:07 周星星
牛啦,up!

# hoho~~~ 2005-02-02 06:06 ahakin
我刚有个提议你就写出来了,hiahia,那我就照抄啦,那个非绑定的你什么时候搞定啊?搞定了说一声哦


# 倒,你自己搞定吧 2005-02-02 22:30 Jozu
我没有时间弄

# ((FARPROC)(dwOffset))()运行进去出错怎么回事 2005-02-10 23:05 我的名字
装载一个HelloWorld,每次运行都不行
(
我用VC6.0的WindowsApplication向导做的一个HelloWorld,然后用bind.exe搞一下之后的一个程序
)
执行的时候dwOffset 的值是对的好像

# re: 装载一个exe,并且执行 2005-07-28 16:47 x_uy_u_n
不太明白啊,EXE里面好象不但要搞API,还要搞字符串啊,不然的话碰到字符串会不行的,可能你的HelloWorld不行就是这个原因.我用的是BCB,不知道是不是这个原因.

# re: 装载一个exe,并且执行 2008-09-25 06:10 gxk
hao,好好好

标题  
姓名  
主页
验证码 *
内容   
  登录  使用高级评论  Top
[使用Ctrl+Enter键可以直接提交]