www.pudn.com > remote_thread.zip > DecImage.cpp, change:2001-08-21,size:12493b


/*  Remote Run Library 
    Copyright (C) 2001, Sting Feng(冯越) 
 
    This program is free software; you can redistribute it and/or modify 
    it under the terms of the GNU General Public License as published by 
    the Free Software Foundation; either version 2 of the License, or 
    (at your option) any later version. 
 
    This program is distributed in the hope that it will be useful, 
    but WITHOUT ANY WARRANTY; without even the implied warranty of 
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
    GNU General Public License for more details. 
 
    You should have received a copy of the GNU General Public License 
    along with this program; if not, write to the Free Software 
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 
	The author of this program may be contacted at fenny@163.net. */ 
 
 
#include  
#include "dll_load.h" 
#include "pedef.h" 
#include "DecImage.h" 
 
typedef LPVOID (WINAPI *VIRTUALALLOCEX)(HANDLE hProcess, LPVOID lpAddress, DWORD dwSize, DWORD flAllocationType, DWORD flProtect); 
typedef BOOL (WINAPI *VIRTUALFREEEX)(HANDLE hProcess, LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType); 
typedef BOOL (WINAPI *VIRTUALPROTECTEX)(HANDLE hProcess, LPVOID lpAddress, DWORD dwSize, DWORD flNewProtect, PDWORD lpflOldProtect); 
typedef DWORD (WINAPI *VIRTUALQUERYEX)(HANDLE hProcess, LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, DWORD dwLength); 
typedef BOOL (WINAPI *WRITEPROCESSMEMORY)(HANDLE hProcess,LPVOID lpBaseAddress,LPVOID lpBuffer,DWORD nSize,LPDWORD lpNumberOfBytesWritten); 
typedef BOOL (WINAPI *CLOSEHANDLE)(HANDLE hObject); 
typedef BOOL (WINAPI *UNMAPVIEWOFFILE)(LPCVOID lpBaseAddress); 
typedef BOOL (WINAPI *FREELIBRARY)( HMODULE hModule); 
 
typedef struct _CopyImageStruc { 
	char* pSrc; 
	char* pDst; 
	HANDLE hProc; 
	DWORD dwSize; 
	DWORD dwFlags; 
	VIRTUALALLOCEX pVirtualAllocEx; 
	VIRTUALFREEEX pVirtualFreeEx; 
	VIRTUALQUERYEX pVirtualQueryEx; 
	VIRTUALPROTECTEX pVirtualProtectEx; 
	WRITEPROCESSMEMORY pWriteProcessMemory; 
	CLOSEHANDLE pCloseHandle; 
	UNMAPVIEWOFFILE pUnmapViewOfFile; 
	FREELIBRARY pFreeLibrary; 
}COPYIMAGE; 
 
//------------------------------------------------ 
// Clone映像文件,从一块内存区域copy到另一块区域 
//------------------------------------------------ 
static BOOL WINAPI CloneImage( COPYIMAGE* p ) 
{ 
	char *s, *d; 
	DWORD dwOldProt,dwNumBytes,i; 
	MEMORY_BASIC_INFORMATION mbi; 
 
	if( p->dwFlags & UNMAP_IMAGE_FILE ) 
		p->pUnmapViewOfFile(p->pDst); 
	if( p->dwFlags & UNLOAD_MODULE ) 
		p->pFreeLibrary((HMODULE)p->pDst); 
	if( p->dwFlags & CLOSE_IMAGE_HANDLE ) 
		p->pCloseHandle((HANDLE)4); 
 
	//---------------------------------------------------------- 
	// 分配一块内存,如果p->pDst不为NULL,则在指定的地址处分配 
	//---------------------------------------------------------- 
	p->pDst = (char *)p->pVirtualAllocEx(p->hProc,p->pDst,p->dwSize,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE); 
	if( p->pDst == NULL ) return FALSE; 
 
	d = p->pDst; 
	s = p->pSrc; 
 
	//--------------------------------------------------- 
	// Lets copy the entire process into this space. 
	//--------------------------------------------------- 
	p->pVirtualQueryEx(p->hProc,p->pSrc,&mbi,sizeof(MEMORY_BASIC_INFORMATION)); 
	while(mbi.Protect!=PAGE_NOACCESS && mbi.RegionSize!=0) { 
		if(!(mbi.Protect & PAGE_GUARD)) { 
			for(i=0;ipVirtualProtectEx(p->hProc,d+i,0x1000,PAGE_EXECUTE_READWRITE,&dwOldProt); 
				p->pWriteProcessMemory(p->hProc,d+i,s+i,0x1000,&dwNumBytes); 
			} 
		} 
		 
		d += mbi.RegionSize; 
		s += mbi.RegionSize; 
		p->pVirtualQueryEx(p->hProc,s,&mbi,sizeof(MEMORY_BASIC_INFORMATION));	 
	} 
	return TRUE; 
} 
 
 
//------------------------------------------------------- 
// DecorticateImage把指定模块脱离文件,这样可以隐藏模块, 
// 或对这些文件做任何读写操作 
//------------------------------------------------------- 
BOOL WINAPI DecorticateImage( HMODULE hModule, DWORD dwFlags, BOOL (WINAPI *pfnFreeLibrary)(HMODULE) ) 
{ 
	COPYIMAGE c; 
	BOOL retval; 
 
	c.pSrc = (char*)hModule; 
	c.pDst = NULL; 
	c.hProc = GetCurrentProcess(); 
	c.dwSize = ((PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET(c.pSrc))->SizeOfImage; 
	c.dwFlags = 0; 
	c.pVirtualAllocEx = VirtualAllocEx; 
	c.pVirtualFreeEx = VirtualFreeEx; 
	c.pVirtualProtectEx = VirtualProtectEx; 
	c.pVirtualQueryEx = VirtualQueryEx; 
	c.pWriteProcessMemory = WriteProcessMemory; 
	c.pCloseHandle = CloseHandle; 
	c.pUnmapViewOfFile = UnmapViewOfFile; 
	c.pFreeLibrary = pfnFreeLibrary; 
 
	//------------------------------------------------ 
	// 做一个image备份 
	//------------------------------------------------ 
	if( !CloneImage( &c ) ) { 
		if( c.pDst != NULL ) 
			VirtualFreeEx(c.hProc,c.pDst,0,MEM_RELEASE); 
		return FALSE; 
	} 
	 
	char* p = c.pDst; 
	c.pDst = c.pSrc; 
	c.pSrc = p; 
 
	if( hModule == GetModuleHandle(NULL) ) 
		c.dwFlags = CLOSE_IMAGE_HANDLE| UNMAP_IMAGE_FILE; // hModule是进程基本模块 
	else 
		c.dwFlags = dwFlags; // hModule是一个DLL 
 
 
	//------------------------------------------ 
	// prepare codes to run on stack 
	// 由于可能是Decorticate自己,有必要把代码 
	// copy到一个动态分配的内存中运行 
	//------------------------------------------ 
	char *pMem=(char *)VirtualAllocEx(c.hProc,NULL,0x1000,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE); 
	if( pMem == NULL ) { 
		if( c.pSrc != NULL ) 
			VirtualFreeEx(c.hProc,c.pSrc,0,MEM_RELEASE); 
		return FALSE; 
	} 
 
	DWORD dwNumBytes; 
	//-------------------------------------------- 
	// 把CloneImage写进内存 
	//-------------------------------------------- 
	WriteProcessMemory(c.hProc,pMem,CloneImage,0x1000,&dwNumBytes); 
 
	typedef BOOL (WINAPI *PFN_CloneImage)( COPYIMAGE* p ); 
	PFN_CloneImage fnCloneImage = (PFN_CloneImage)pMem; 
 
	//------------------------------------- 
	// 从备份中恢复image数据 
	//------------------------------------- 
	retval = fnCloneImage( &c ); 
 
/*	__asm { 
		lea		edx,c; 
		push	edx; 
		call	pMem; 
		mov		retval, eax; 
	} 
*/ 
 
	//------------------------------------------ 
	// Let's clean 
	//------------------------------------------ 
	VirtualFreeEx(c.hProc,c.pSrc,0,MEM_RELEASE); 
	VirtualFreeEx(c.hProc,pMem,0,MEM_RELEASE); 
 
	return retval; 
} 
 
static BOOL ResetImageInitializedData( HMODULE hModule, HMODULE hOldModule ) 
{ 
	WCHAR szModuleName[MAX_PATH]; 
	void* baseaddr = NULL; 
	HANDLE hmapping = NULL; 
 
	//----------------------------------------------- 
	// 我们需要从原始文件中恢复那些脏数据 
	//----------------------------------------------- 
	if( GetModuleFileNameW( hOldModule, szModuleName, MAX_PATH ) ) 
	{ 
		//----------------------------------------------------- 
		// Open File 
		//----------------------------------------------------- 
		HANDLE hfile=CreateFileW(szModuleName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL); 
		if(hfile==INVALID_HANDLE_VALUE) return NULL; 
		 
		//----------------------------------------------------- 
		// Create a file mapping 
		//----------------------------------------------------- 
		hmapping=CreateFileMapping(hfile, NULL, PAGE_READONLY, 0, 0, NULL); 
 
		//----------------------------------------------------- 
		// Close file handle since we don't need it anymore 
		//----------------------------------------------------- 
		CloseHandle(hfile); 
 
		//----------------------------------------------------- 
		// Map file mapping object to memory image 
		//----------------------------------------------------- 
		baseaddr=MapViewOfFile(hmapping,FILE_MAP_READ,0,0,0); 
		if(baseaddr==NULL) { 
			CloseHandle(hmapping); 
			return NULL; 
		} 
	} 
	if( baseaddr == NULL ) { 
		CloseHandle( hmapping ); 
		return FALSE; 
	} 
 
	//----------------------------------------------------- 
	// Get Number of Sections 
	//----------------------------------------------------- 
	PIMAGE_FILE_HEADER pfh; 
	int nSectionCount; 
	 
	pfh=(PIMAGE_FILE_HEADER) PEFHDROFFSET(hModule); 
	nSectionCount=pfh->NumberOfSections; 
 
	//----------------------------------------------------- 
	// Get PE Header Length + Section Header Length 
	//----------------------------------------------------- 
	PIMAGE_OPTIONAL_HEADER poh; 
	DWORD hdrlen; 
 
	poh=(PIMAGE_OPTIONAL_HEADER) OPTHDROFFSET(hModule); 
	hdrlen=poh->SizeOfHeaders; 
 
	//----------------------------------------------------- 
	// restore imagebase 
	//----------------------------------------------------- 
	poh->ImageBase = ((PIMAGE_OPTIONAL_HEADER) OPTHDROFFSET(baseaddr))->ImageBase; 
 
	//----------------------------------------------------- 
	// Protect sections one by one 
	//----------------------------------------------------- 
	int i; 
	PIMAGE_SECTION_HEADER psh; 
 
	psh=(PIMAGE_SECTION_HEADER) SECHDROFFSET(hModule); 
	for(i=0;iVirtualAddress); 
		secMemAddrOrigin  = (char *)RVATOVA(baseaddr, psh->PointerToRawData); 
		secLen = psh->SizeOfRawData; 
 
		//----------------------------------------------------- 
		// 确保洗掉所有脏数据 
		// 一般来说,.data section的VirtualSize大于RawDataSize, 
		// RawDataSize只包含那些不为0的初始化数据。 
		//----------------------------------------------------- 
		if( psh->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA && 
			psh->Characteristics & IMAGE_SCN_MEM_WRITE && 
			psh->Misc.VirtualSize > psh->SizeOfRawData ) 
		{ 
			memset( secMemAddr, 0, psh->Misc.VirtualSize ); 
		} 
		memcpy( secMemAddr, secMemAddrOrigin, secLen ); 
 
		psh++; 
	} 
 
 
	UnmapViewOfFile( baseaddr ); 
	CloseHandle( hmapping ); 
 
	return TRUE; 
} 
 
 
//------------------------------------------------------- 
// 从内存中复制一份image,并初始化所有数据 
// 这个实现还有点儿问题,工作的不太好 
//------------------------------------------------------- 
HMODULE WINAPI DuplicateImage( HMODULE hOldModule ) 
{ 
	char *s, *d; 
	DWORD dwOldProt, i; 
	MEMORY_BASIC_INFORMATION mbi; 
	DWORD dwSize = ((PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET(hOldModule))->SizeOfImage; 
 
	HMODULE hNewModule = (HMODULE)VirtualAlloc( NULL, dwSize, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE ); 
	if( hNewModule == NULL ) return NULL; 
 
 
	//------------------------------------------------- 
	// Lets copy the entire process into this space. 
	//------------------------------------------------- 
	s = (char*)hOldModule; 
	d = (char*)hNewModule; 
	VirtualQuery( s, &mbi, sizeof(MEMORY_BASIC_INFORMATION) ); 
	while( mbi.Protect != PAGE_NOACCESS && mbi.RegionSize != 0 ) { 
		if( !(mbi.Protect & PAGE_GUARD) ) { 
			for( i = 0; i < mbi.RegionSize; i += 0x1000) { 
				memcpy( d+i, s+i, 0x1000 ); 
			} 
		} 
		 
		d += mbi.RegionSize; 
		s += mbi.RegionSize; 
		VirtualQuery( s, &mbi, sizeof(MEMORY_BASIC_INFORMATION) ); 
	} 
	 
	 
	//------------------------------------------------- 
	// 洗掉所有脏数据 
	//------------------------------------------------- 
	if( !ResetImageInitializedData( hNewModule, hOldModule ) ) 
	{ 
		VirtualFree( hNewModule, 0, MEM_RELEASE ); 
		return NULL; 
	} 
 
	 
	//------------------------------------------------- 
	// 修正重定位表和导入表 
	//------------------------------------------------- 
	if(	!PrepareDLLImage( hNewModule, dwSize, TRUE, TRUE ) ) 
	{ 
		VirtualFree( hNewModule, 0, MEM_RELEASE ); 
		return NULL; 
	} 
 
	 
	//------------------------------------------------- 
	// modify image base 
	//------------------------------------------------- 
	PIMAGE_OPTIONAL_HEADER poh; 
	poh=(PIMAGE_OPTIONAL_HEADER) OPTHDROFFSET(hNewModule); 
	poh->ImageBase = (DWORD)hNewModule; 
 
 
	//------------------------------------------------- 
	// 实施必要的保护 
	//------------------------------------------------- 
	 
	 
	s = (char*)hOldModule; 
	d = (char*)hNewModule; 
 
	//------------------------------------------------- 
	// protected image 
	//------------------------------------------------- 
	VirtualQuery( s, &mbi, sizeof(MEMORY_BASIC_INFORMATION) ); 
	while( mbi.Protect != PAGE_NOACCESS && mbi.RegionSize != 0 ) { 
		if( !(mbi.Protect & PAGE_GUARD) ) { 
			for( i = 0; i < mbi.RegionSize; i += 0x1000) { 
				VirtualProtect( d+i,0x1000,mbi.Protect,&dwOldProt); 
			} 
		} 
		 
		d += mbi.RegionSize; 
		s += mbi.RegionSize; 
		VirtualQuery( s, &mbi, sizeof(MEMORY_BASIC_INFORMATION) ); 
	} 
 
	return hNewModule; 
}