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;
}