|
Флудер
Регистрация: 27.12.2005
Сообщений: 2,372
С нами:
10721066
Репутация:
4360
|
|
Перенос программы в другое адресное пространство.
Был замечательный метод по инжекту кода в другую программу - вся наша программа постранично копировалась в чужое АП (адресное пространство) по тем же адресам со всеми заголовками, секциями и прочим.
Все было бы хорошо, пока там память свободна. Если там память занята, метод не предусматривал решения в этом случае.
Предлагаю модификацию: поиск наилучшего достаточного места в другом АП, копирование программы, коррекция фиксапов:
Код:
// Get VA
#define RVATOVA( base, offset )(((DWORD)(base) + (DWORD)(offset)))
// Move program's memory
void __CopyMemoryAcrossProcesses( HANDLE hProcess, char* pMemLocal, char* pMemRemote )
{
DWORD dwOldProt, dwNumBytes, i;
MEMORY_BASIC_INFORMATION mbi;
VirtualQueryEx(hProcess, pMemRemote, &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)
{
VirtualProtectEx(hProcess, pMemRemote + i, 0x1000,PAGE_EXECUTE_READWRITE, &dwOldProt);
WriteProcessMemory(hProcess, pMemRemote + i, pMemLocal + i, 0x1000, &dwNumBytes);
}
}
pMemLocal += mbi.RegionSize;
pMemRemote += mbi.RegionSize;
VirtualQueryEx(hProcess, pMemRemote, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
}
}
bool TransferProgram(HANDLE hProcess)
{
HMODULE g_module = GetModuleHandle(0);
VirtualFreeEx(hProcess, g_module, 0, MEM_RELEASE);
DWORD dwSize = ((PIMAGE_OPTIONAL_HEADER)((LPVOID)((BYTE *)(g_module) + ((PIMAGE_DOS_HEADER)(g_module))->e_lfanew +
sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER))))->SizeOfImage;
char *pMem = (char *)VirtualAllocEx(hProcess, g_module, dwSize, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if(pMem == NULL) return FALSE;
__CopyMemoryAcrossProcesses( hProcess, (char*) g_module, pMem );
return true;
}
DWORD TransferProgramEx(HANDLE hProcess)
/*
Return value: image base delta, -1 on error
*/
{
HMODULE hmodule = GetModuleHandle(0);
DWORD dwSize = ((PIMAGE_OPTIONAL_HEADER)((LPVOID)((BYTE *)(hmodule) + ((PIMAGE_DOS_HEADER)(hmodule))->e_lfanew +
sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER))))->SizeOfImage;
MEMORY_BASIC_INFORMATION mbi = {0};
VirtualQueryEx( hProcess, hmodule, &mbi, sizeof(mbi) );
LPVOID Allocated;
// Memory isn't free, relocate
if( mbi.Protect!=PAGE_NOACCESS && mbi.RegionSize!=0 )
{
__try_relocate:
LPVOID DesiredAddress = hmodule;
*(DWORD*)&DesiredAddress += mbi.RegionSize;
for(;;)
{
Allocated = VirtualAllocEx( hProcess, DesiredAddress, dwSize, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );
if( Allocated )
break;
*(DWORD*)&DesiredAddress += dwSize;
}
}
else
{
Allocated = VirtualAllocEx( hProcess, hmodule, dwSize, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );
if( !Allocated )
goto __try_relocate;
}
// move memory
__CopyMemoryAcrossProcesses( hProcess, (char*) hmodule, (char*) Allocated );
DWORD ImageBaseDelta = (DWORD)Allocated - (DWORD)hmodule;
// Nonzero imagebase delta
if( ImageBaseDelta )
{
// Apply fixups
typedef struct
{
WORD Offset:12;
WORD Type:4;
} IMAGE_FIXUP_ENTRY, *PIMAGE_FIXUP_ENTRY;
PIMAGE_OPTIONAL_HEADER poh =
(PIMAGE_OPTIONAL_HEADER)(
(DWORD)hmodule
+ ((PIMAGE_DOS_HEADER)hmodule)->e_lfanew
+ sizeof(IMAGE_NT_SIGNATURE)
+ sizeof(IMAGE_FILE_HEADER)
);
// No fixups?
if( !poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress )
{
VirtualFreeEx( hProcess, Allocated, dwSize, MEM_DECOMMIT );
VirtualFreeEx( hProcess, Allocated, dwSize, MEM_RELEASE );
return -1;
}
PIMAGE_BASE_RELOCATION Reloc = (PIMAGE_BASE_RELOCATION) RVATOVA(poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress, hmodule);
int i = 0;
// Process fixups
for( PIMAGE_FIXUP_ENTRY Fixup = (PIMAGE_FIXUP_ENTRY)( (DWORD)Reloc + sizeof(IMAGE_BASE_RELOCATION) );
(DWORD)Fixup < (DWORD)Reloc + Reloc->SizeOfBlock -2;
Fixup ++, i ++
)
{
if( Fixup->Type == IMAGE_REL_BASED_HIGHLOW )
{
DWORD* Patch = (DWORD*)RVATOVA( Reloc->VirtualAddress + Fixup->Offset, Allocated );
DWORD t, r;
BOOL b = 1;
// correct fixup
b &= ReadProcessMemory( hProcess, Patch, &t, 4, &r );
t += ImageBaseDelta;
b &= WriteProcessMemory( hProcess, Patch, &t, 4, &r );
if( !b )
{
// smth wrong
VirtualFreeEx( hProcess, Allocated, dwSize, MEM_DECOMMIT );
VirtualFreeEx( hProcess, Allocated, dwSize, MEM_RELEASE );
return -1;
}
}
else
{
// unsupported fixup type
VirtualFreeEx( hProcess, Allocated, dwSize, MEM_DECOMMIT );
VirtualFreeEx( hProcess, Allocated, dwSize, MEM_RELEASE );
return -1;
}
}
}
return ImageBaseDelta;
}
TransferProgram - старый вариант
TransferProgramEx - моя модификация
Использовать примерно так:
Код:
DWORD ImageBaseDelta = TransferProgramEx( hProcess );
switch(ImageBaseDelta)
{
case -1:
return printf("Cannot copy body\n"), 0;
case 0:
printf("Program copied at the same addresses\n");
break;
default:
printf("Program relocated (delta = 0x%08x)\n", ImageBaseDelta);
break;
}
DWORD thID;
HANDLE hTh;
hTh = CreateRemoteThread( hProcess, 0, 0, (LPTHREAD_START_ROUTINE)((char*)RemoteThread+ImageBaseDelta), 0, 0, &thID);
WaitForSingleObject( hTh, INFINITE );
|