hiahia,被这个题目吓住了吧,一个CreateProcess不就可以吗,嘿嘿,可是你会看到两个进程存在,这里要干的是让进程管理器只能看到一个进程。好了,如果你有了Win32进程的基础理论,了解PE格式,再加上熟悉管理进程(当然你要是不知道这些,代码运行以后的效果你都不会看到。。。那我不是白忙了:P)开始:
先来看看代码:
// ExeLoader.cpp : Defines the entry point for the console application.
//
// Coder Jozu
#include
#include
#include
#include
#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。
|