- Код: Выделить всё
#COMPILE EXE "EXE_Loader.exe"
#DIM ALL
#OPTION VERSION5
#REGISTER NONE
#TOOLS OFF
#INCLUDE "Win32Api.Inc"
%IMAGE_ORDINAL_FLAG = &H80000000
TYPE IMAGE_IMPORT_BY_NAME
Hint AS WORD
ImpName AS ASCIIZ * 254
END TYPE
TYPE IMAGE_IMPORT_DESCRIPTOR
OriginalFirstThunk AS DWORD
TimeDateStamp AS DWORD
ForwarderChain AS DWORD
pName AS DWORD
FirstThunk AS DWORD
END TYPE
TYPE IMAGE_BASE_RELOCATION
VirtualAddress AS DWORD
SizeOfBlock AS DWORD
END TYPE
DECLARE FUNCTION LoadEXE ( BYVAL PE_HEADER_PTR AS DWORD) AS DWORD
DECLARE FUNCTION LoadExeFileFromMemory(BYVAL lpRawDll AS DWORD, lpImageDll AS DWORD) AS DWORD
DECLARE FUNCTION MyGetModuleHandleA (BYVAL lpFileName AS DWORD) AS DWORD
DECLARE FUNCTION MyGetModuleHandleW (BYVAL lpFileName AS DWORD) AS DWORD
GLOBAL hExe AS DWORD
GLOBAL hGetModuleHandleA AS DWORD
GLOBAL hGetModuleHandleW AS DWORD
FUNCTION MyGetModuleHandleA (BYVAL lpFileName AS DWORD) AS DWORD
DIM i AS LOCAL DWORD
IF lpFileName = 0 THEN i = hExe ELSE CALL DWORD hGetModuleHandleA USING GetModuleHandle(BYVAL lpFileName) TO i
FUNCTION = i
END FUNCTION
FUNCTION MyGetModuleHandleW (BYVAL lpFileName AS DWORD) AS DWORD
DIM i AS LOCAL DWORD
IF lpFileName = 0 THEN i = hExe ELSE CALL DWORD hGetModuleHandleW USING GetModuleHandle(BYVAL lpFileName) TO i
FUNCTION = i
END FUNCTION
FUNCTION ActivateExe (BYVAL FileHwnd AS DWORD) AS DWORD
DIM sSysInfo AS LOCAL SYSTEM_INFO
DIM ImagePages AS LOCAL DWORD
DIM lpImageDosHeader AS LOCAL IMAGE_DOS_HEADER PTR
DIM lpImageNtHeaders AS LOCAL IMAGE_NT_HEADERS PTR
DIM lpImageSectionHeader AS LOCAL IMAGE_SECTION_HEADER PTR
DIM lpImageImportDescriptor AS LOCAL IMAGE_IMPORT_DESCRIPTOR PTR
DIM lpImageImportByName AS LOCAL IMAGE_IMPORT_BY_NAME PTR
DIM lpImageBaseRelocTable AS LOCAL IMAGE_BASE_RELOCATION PTR
DIM lpDllName AS LOCAL ASCIIZ PTR
DIM szDllName AS LOCAL STRING
DIM hDll AS LOCAL DWORD
DIM lpFuncNameRef AS LOCAL DWORD PTR
DIM lpFuncAddr AS LOCAL DWORD PTR
DIM lpTypeOffset AS WORD PTR
DIM TpOffset AS WORD
DIM lpLink AS LOCAL DWORD PTR
DIM fOldProtect AS LOCAL DWORD
DIM i AS LOCAL DWORD
DIM j AS LOCAL DWORD
DIM k AS LOCAL DWORD
DIM Protection() AS LOCAL BYTE
DIM Addr1 AS LOCAL DWORD
DIM Addr2 AS LOCAL DWORD
DIM Pg AS LOCAL DWORD
DIM Pg1 AS LOCAL DWORD
DIM Pg2 AS LOCAL DWORD
LoadExeFileFromMemory(FileHwnd, hExe)
lpImageDosHeader = hExe
IF @lpImageDosHeader.e_magic <> %IMAGE_DOS_SIGNATURE THEN FUNCTION = 1: EXIT FUNCTION ' invalid DOS signature
lpImageNtHeaders = lpImageDosHeader + @lpImageDosHeader.e_lfanew
IF @lpImageNtHeaders.Signature <> %IMAGE_NT_SIGNATURE THEN FUNCTION = 1: EXIT FUNCTION ' invalid NT signature
IF @lpImageNtHeaders.FileHeader.SizeOfOptionalHeader <> SIZEOF(@lpImageNtHeaders.OptionalHeader) OR _
@lpImageNtHeaders.OptionalHeader.Magic <> %IMAGE_NT_OPTIONAL_HDR32_MAGIC THEN FUNCTION = 1: EXIT FUNCTION
IF @lpImageNtHeaders.FileHeader.NumberOfSections < 1 THEN FUNCTION = 1: EXIT FUNCTION
lpImageSectionHeader = lpImageNtHeaders + SIZEOF(IMAGE_NT_HEADERS)
k = lpImageSectionHeader - lpImageDosHeader + SIZEOF(IMAGE_SECTION_HEADER) * @lpImageNtHeaders.FileHeader.NumberOfSections
j = k
FOR i = 0 TO @lpImageNtHeaders.FileHeader.NumberOfSections - 1
j = MAX(j, @lpImageSectionHeader[i].VirtualAddress + @lpImageSectionHeader[i].SizeOfRawData)
NEXT
IF VirtualProtect (BYVAL lpImageDosHeader, j, %PAGE_EXECUTE_READWRITE, fOldProtect) = 0 THEN FUNCTION = 4: EXIT FUNCTION
GetSystemInfo sSysInfo
ImagePages = j \ sSysInfo.dwPageSize: IF (j MOD sSysInfo.dwPageSize) THEN INCR ImagePages
' Import section
lpImageImportDescriptor = @lpImageNtHeaders.OptionalHeader.DataDirectory(%IMAGE_DIRECTORY_ENTRY_IMPORT).VirtualAddress
IF lpImageImportDescriptor <> 0 THEN
lpImageImportDescriptor = lpImageImportDescriptor + lpImageDosHeader
WHILE @lpImageImportDescriptor.OriginalFirstThunk <> 0 ' Dlls
lpDllName = @lpImageImportDescriptor.pName + lpImageDosHeader
szDllName = @lpDllName
hDll = GetModuleHandle(BYVAL STRPTR(szDllName))
IF hDll = 0 THEN hDll = LoadLibrary(BYVAL STRPTR(szDllName))
IF hDll = 0 THEN FUNCTION = 2: EXIT FUNCTION ' Can't find
lpFuncNameRef = @lpImageImportDescriptor.OriginalFirstThunk + lpImageDosHeader
lpFuncAddr = @lpImageImportDescriptor.FirstThunk + lpImageDosHeader
WHILE @lpFuncNameRef <> 0
lpImageImportByName = @lpFuncNameRef + lpImageDosHeader
IF (@lpFuncNameRef AND %IMAGE_ORDINAL_FLAG) THEN
@lpFuncAddr = GetProcAddress(hDll, BYVAL @lpFuncNameRef AND &HFFFF???)
ELSE
@lpFuncAddr = GetProcAddress(hDll, @lpImageImportByName.ImpName)
IF @lpImageImportByName.ImpName = "GetModuleHandleA" THEN _
hGetModuleHandleA = @lpFuncAddr: @lpFuncAddr = CODEPTR(MyGetModuleHandleA)
IF @lpImageImportByName.ImpName = "GetModuleHandleW" THEN _
hGetModuleHandleW = @lpFuncAddr: @lpFuncAddr = CODEPTR(MyGetModuleHandleW)
END IF
IF @lpFuncAddr = 0 THEN FUNCTION = 2: EXIT FUNCTION
INCR lpFuncAddr
INCR lpFuncNameRef
WEND
INCR lpImageImportDescriptor
WEND
END IF
lpImageBaseRelocTable = @lpImageNtHeaders.OptionalHeader.DataDirectory(%IMAGE_DIRECTORY_ENTRY_BASERELOC).VirtualAddress
''''''''''''''''''''''
IF lpImageBaseRelocTable <> 0 THEN
lpImageBaseRelocTable = lpImageBaseRelocTable + lpImageDosHeader
WHILE @lpImageBaseRelocTable.VirtualAddress <> 0
lpTypeOffset = lpImageBaseRelocTable + SIZEOF(IMAGE_BASE_RELOCATION)
WHILE lpTypeOffset < lpImageBaseRelocTable + @lpImageBaseRelocTable.SizeOfBlock
TpOffset = @lpTypeOffset AND &HF000??
IF TpOffset = &H3000 THEN
lpLink = lpImageDosHeader + @lpImageBaseRelocTable.VirtualAddress + (@lpTypeOffset AND &HFFF??)
@lpLink = @lpLink - @lpImageNtHeaders.OptionalHeader.ImageBase + lpImageDosHeader
ELSEIF TpOffSet = 0 THEN
ELSE
FUNCTION = 3: EXIT FUNCTION ' Uknown type
END IF
INCR lpTypeOffset
WEND
lpImageBaseRelocTable = lpImageBaseRelocTable + @lpImageBaseRelocTable.SizeOfBlock
WEND
END IF
REDIM Protection(ImagePages - 1)
FOR i = 0 TO @lpImageNtHeaders.FileHeader.NumberOfSections
IF i = @lpImageNtHeaders.FileHeader.NumberOfSections THEN
Addr1 = 0: Addr2 = k: j = &H60000000??? ' %PAGE_EXECUTE_READ
ELSE
Addr1 = @lpImageSectionHeader[i].VirtualAddress
Addr2 = @lpImageSectionHeader[i].SizeOfRawData
j = @lpImageSectionHeader[i].Characteristics
END IF
Addr2 = Addr1 + Addr2 - 1
Pg1 = Addr1 \ sSysInfo.dwPageSize
Pg2 = Addr2 \ sSysInfo.dwPageSize
FOR Pg = Pg1 TO Pg2
IF (j AND &H20000000???) THEN Protection(Pg) = Protection(Pg) OR 1 ' Execute
IF (j AND &H40000000???) THEN Protection(Pg) = Protection(Pg) OR 2 ' Read
IF (j AND &H80000000???) THEN Protection(Pg) = Protection(Pg) OR 4 ' Write
NEXT
NEXT
Addr1 = lpImageDosHeader
FOR Pg = 0 TO ImagePages - 1
SELECT CASE AS LONG Protection(Pg)
CASE 2: fOldProtect = %PAGE_READONLY
CASE 3: fOldProtect = %PAGE_EXECUTE_READ
CASE 6: fOldProtect = %PAGE_READWRITE
CASE ELSE: fOldProtect = %PAGE_EXECUTE_READWRITE ' Ignore strange combinations
END SELECT
IF fOldProtect <> %PAGE_EXECUTE_READWRITE THEN _
IF VirtualProtect (BYVAL Addr1, sSysInfo.dwPageSize, fOldProtect, fOldProtect) = 0 THEN FUNCTION = 4 : EXIT FUNCTION
Addr1 = Addr1 + sSysInfo.dwPageSize
NEXT
i = @lpImageNtHeaders.OptionalHeader.AddressOfEntryPoint + lpImageDosHeader
CALL DWORD i USING WINMAIN (BYVAL 0,BYVAL 0, BYVAL 0 , %SW_SHOW)
END FUNCTION
FUNCTION LoadExeFileFromMemory(BYVAL lpRawDll AS DWORD, lpImageDll AS DWORD) AS DWORD
DIM sSysInfo AS LOCAL SYSTEM_INFO
DIM ImagePages AS LOCAL DWORD
DIM lpImageDosHeader AS LOCAL IMAGE_DOS_HEADER PTR
DIM lpImageNtHeaders AS LOCAL IMAGE_NT_HEADERS PTR
DIM lpImageSectionHeader AS LOCAL IMAGE_SECTION_HEADER PTR
DIM lpImageImportDescriptor AS LOCAL IMAGE_IMPORT_DESCRIPTOR PTR
DIM lpImageImportByName AS LOCAL IMAGE_IMPORT_BY_NAME PTR
DIM lpImageBaseRelocTable AS LOCAL IMAGE_BASE_RELOCATION PTR
DIM lpDllName AS LOCAL ASCIIZ PTR
DIM szDllName AS LOCAL STRING
DIM lpFuncNameRef AS LOCAL DWORD PTR
DIM lpFuncAddr AS LOCAL DWORD PTR
DIM lpTypeOffset AS WORD PTR
DIM i AS LOCAL DWORD
DIM j AS LOCAL DWORD
DIM k AS LOCAL DWORD
DIM lpIMAGE_FILE AS LOCAL IMAGE_FILE_HEADER
lpImageDosHeader = lpRawDll
IF @lpImageDosHeader.e_magic <> %IMAGE_DOS_SIGNATURE THEN FUNCTION = 1: EXIT FUNCTION ' invalid DOS signature
lpImageNtHeaders = lpImageDosHeader + @lpImageDosHeader.e_lfanew
IF @lpImageNtHeaders.Signature <> %IMAGE_NT_SIGNATURE THEN FUNCTION = 1: EXIT FUNCTION ' invalid NT signature
IF @lpImageNtHeaders.FileHeader.SizeOfOptionalHeader <> SIZEOF(@lpImageNtHeaders.OptionalHeader) OR _
@lpImageNtHeaders.OptionalHeader.Magic <> %IMAGE_NT_OPTIONAL_HDR32_MAGIC THEN FUNCTION = 1: EXIT FUNCTION
IF @lpImageNtHeaders.FileHeader.NumberOfSections < 1 THEN FUNCTION = 1: EXIT FUNCTION
lpImageSectionHeader = lpImageNtHeaders + SIZEOF(IMAGE_NT_HEADERS)
k = lpImageSectionHeader - lpImageDosHeader + SIZEOF(IMAGE_SECTION_HEADER) * @lpImageNtHeaders.FileHeader.NumberOfSections
j = k
FOR i = 0 TO @lpImageNtHeaders.FileHeader.NumberOfSections - 1
j = MAX(j, @lpImageSectionHeader[i].VirtualAddress + @lpImageSectionHeader[i].SizeOfRawData)
NEXT
GetSystemInfo sSysInfo
ImagePages = j \ sSysInfo.dwPageSize: IF (j MOD sSysInfo.dwPageSize) THEN INCR ImagePages
lpImageDll = VirtualAlloc(BYVAL 0, CDWD(ImagePages * sSysInfo.dwPageSize), %MEM_COMMIT, %PAGE_EXECUTE_READWRITE)
IF lpImageDll = 0 THEN FUNCTION = 5: EXIT FUNCTION
MoveMemory BYVAL lpImageDll, BYVAL lpRawDll, k
FOR i = 0 TO @lpImageNtHeaders.FileHeader.NumberOfSections - 1
MoveMemory BYVAL CDWD(lpImageDll + @lpImageSectionHeader[i].VirtualAddress), _
BYVAL CDWD(lpRawDll + @lpImageSectionHeader[i].PointerToRawData), @lpImageSectionHeader[i].SizeOfRawData
NEXT
lpImageDosHeader = lpImageDll
FUNCTION= lpImageDosHeader
END FUNCTION
FUNCTION LoadEXE ALIAS "LoadEXE" ( BYVAL PE_HEADER_PTR AS DWORD) EXPORT AS DWORD
LOCAL Hwnd AS DWORD
ActivateEXE (PE_HEADER_PTR)
END FUNCTION
FUNCTION PBMAIN () AS LONG
DIM tmp AS STRING
OPEN "TEST.EXE" FOR BINARY SHARED AS #1
IF ERR = 0 THEN GET$ #1, LOF(1), tmp
CLOSE #1
CALL LoadEXE(STRPTR(tmp))
END FUNCTION
Проблема в том, что программы, в которых нет секции .reloc слетают в GPF
На просторах интернетов нашёл ещё вот такой загрузчик на сях
- Код: Выделить всё
/*
* Загрузчик PE
*/
#include <windows.h>
#include <stdio.h>
// Фиксапы
typedef struct
{
WORD Offset:12;
WORD Type:4;
} IMAGE_FIXUP_ENTRY, *PIMAGE_FIXUP_ENTRY;
// Быстро получаем хидеры
void GetHeaders(PCHAR ibase, PIMAGE_FILE_HEADER *pfh, PIMAGE_OPTIONAL_HEADER *poh, PIMAGE_SECTION_HEADER *psh)
{
PIMAGE_DOS_HEADER mzhead = (PIMAGE_DOS_HEADER)ibase;
*pfh = (PIMAGE_FILE_HEADER)&ibase[mzhead->e_lfanew];
*pfh = (PIMAGE_FILE_HEADER)((PBYTE)*pfh + sizeof(IMAGE_NT_SIGNATURE));
*poh = (PIMAGE_OPTIONAL_HEADER)((PBYTE)*pfh + sizeof(IMAGE_FILE_HEADER));
*psh = (PIMAGE_SECTION_HEADER)((PBYTE)*poh + sizeof(IMAGE_OPTIONAL_HEADER));
}
// Смещение + База = Виртуальный Адрес
#define RVATOVA( base, offset )(((DWORD)(base) + (DWORD)(offset)))
// Process Envorinment Block
typedef struct _PEB {
DWORD smth[2]; // doesn't matter
PVOID ImageBaseAddress;
} PEB, *PPEB;
// Thread Environment Block
typedef struct _TEB {
DWORD smth[12]; // doesn't matter
PPEB Peb;
} TEB, *PTEB;
// получаем текущий PEB
PPEB GetPEB( )
{
TEB* teb;
__asm
{
mov eax, dword ptr fs:[18h]
mov teb, eax
}
return teb->Peb;
}
HMODULE
LoadExecutable (
IN LPSTR path,
IN PVOID base = 0
)
/*
Загружает образ с пути path по адресу base.
Если base=0, используется поле IMAGE_OPTIONAL_HEADER.ImageBase
*/
{
HANDLE hFile;
PIMAGE_FILE_HEADER pfh;
PIMAGE_SECTION_HEADER psh;
PIMAGE_OPTIONAL_HEADER poh;
char buffer[ 0x1000 ];
DWORD read;
LPBYTE Mapping;
//
// Открываем файл образа
//
printf("Opening file '%s'\n", path);
hFile = CreateFile( path, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0 );
if( hFile == INVALID_HANDLE_VALUE )
return NULL;
//
// Читаем хидеры
//
printf("Reading header\n");
if( !ReadFile( hFile, buffer, 1024, &read, 0 ) || !read )
{
CloseHandle( hFile );
return NULL;
}
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER) buffer;
pfh = (PIMAGE_FILE_HEADER)( (DWORD)buffer + dos->e_lfanew + 4 );
poh = (PIMAGE_OPTIONAL_HEADER)( pfh+1 );
psh = (PIMAGE_SECTION_HEADER)( (DWORD)poh + sizeof(IMAGE_OPTIONAL_HEADER) );
//
// Резервируем пространство под образ
//
if( !base )
base = (PVOID) poh->ImageBase;
printf("Reserving pages[ OriginalBase = %08x, Base = %08x, Size = %08x ]\n", poh->ImageBase, base, poh->SizeOfImage);
UnmapViewOfFile( (PVOID)poh->ImageBase );
VirtualFree( (PVOID)poh->ImageBase, poh->SizeOfImage, MEM_DECOMMIT );
VirtualFree( (PVOID)poh->ImageBase, poh->SizeOfImage, MEM_RELEASE );
Mapping = (LPBYTE) VirtualAlloc( base, poh->SizeOfImage, MEM_RESERVE, PAGE_NOACCESS );
if( !Mapping )
{
CloseHandle( hFile );
return NULL;
}
//
// Копируем хидеры
//
Mapping = (LPBYTE) VirtualAlloc( base, 0x1000, MEM_COMMIT, PAGE_READWRITE );
if( !Mapping )
{
CloseHandle( hFile );
return NULL;
}
memcpy( Mapping, buffer, read );
//
// Читаем секции из файла и грузим их по соответствующим виртуальным адресам
//
printf("\nReading sections\n");
printf("%-15s %-15s %-15s %-15s %-15s\n", "Section", "VirtAddress", "VirtSize", "RawData", "SizeOfRawData" );
for( int i=0; i < pfh->NumberOfSections ; i++, psh++ )
{
DWORD VirtualSize = (i==pfh->NumberOfSections-1)?
(poh->SizeOfImage-psh->VirtualAddress)
:(psh+1)->VirtualAddress - psh->VirtualAddress;
LPVOID va = (LPVOID)( Mapping + psh->VirtualAddress );
OVERLAPPED lp = {0};
printf(" %-14s %08x %08x %08x %08x\n",
psh->Name,
psh->VirtualAddress,
VirtualSize,
psh->PointerToRawData,
psh->SizeOfRawData
);
lp.Offset = psh->PointerToRawData;
// выделяем память под секцию
LPVOID m = VirtualAlloc( va, VirtualSize, MEM_COMMIT, PAGE_READWRITE );
if( m != va )
{
printf("ERROR %d\n", GetLastError());
VirtualFree( base, poh->SizeOfImage, MEM_DECOMMIT );
VirtualFree( base, poh->SizeOfImage, MEM_RELEASE );
CloseHandle( hFile );
return NULL;
}
// читаем секцию
if( !ReadFile( hFile, va, psh->SizeOfRawData, &read, &lp ) || read!=psh->SizeOfRawData )
{
printf("Cannot read section [%d]\n", GetLastError());
VirtualFree( base, poh->SizeOfImage, MEM_DECOMMIT );
VirtualFree( base, poh->SizeOfImage, MEM_RELEASE );
CloseHandle( hFile );
return NULL;
}
}
//
// Корректируем фиксапы
//
DWORD ImageBaseDelta = (DWORD)base - (DWORD)poh->ImageBase;
// требуется корректировка
if( ImageBaseDelta )
{
printf("\nApplying fixups, ImageBaseDelta = %08x\n", ImageBaseDelta);
if( !poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress )
{
// нет фиксапов
printf("Decided to load at different base, but no relocs present\n");
VirtualFree( base, poh->SizeOfImage, MEM_DECOMMIT );
VirtualFree( base, poh->SizeOfImage, MEM_RELEASE );
CloseHandle( hFile );
return NULL;
}
PIMAGE_BASE_RELOCATION Reloc = (PIMAGE_BASE_RELOCATION) RVATOVA(poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress, base);
int i = 0;
// проходим по фиксапам
for( PIMAGE_FIXUP_ENTRY Fixup = (PIMAGE_FIXUP_ENTRY)( (DWORD)Reloc + sizeof(IMAGE_BASE_RELOCATION) );
(DWORD)Fixup < (DWORD)Reloc + Reloc->SizeOfBlock;
Fixup ++, i ++
)
{
if( Fixup->Type == IMAGE_REL_BASED_HIGHLOW )
{
// адрес инструкции для патча
DWORD* Patch = (DWORD*)RVATOVA( Reloc->VirtualAddress + Fixup->Offset, base );
printf("Fixup #%d: Type = %d, Offset %08x [%08x -> %08x]\n",
i,
Fixup->Type,
RVATOVA( Reloc->VirtualAddress + Fixup->Offset, base ),
*Patch,
*Patch+ImageBaseDelta
);
// патч
*Patch += ImageBaseDelta;
}
// другие типы фиксапов не обрабатываем
else
{
printf("Incorrect fixup type %d\n", Fixup->Type);
VirtualFree( base, poh->SizeOfImage, MEM_DECOMMIT );
VirtualFree( base, poh->SizeOfImage, MEM_RELEASE );
CloseHandle( hFile );
return NULL;
}
}
}
//
// Обрабатываем таблицу импорта
//
printf("\nProcessing import [");
// Первый дескриптор импорта
PIMAGE_IMPORT_DESCRIPTOR impdesc = (PIMAGE_IMPORT_DESCRIPTOR) RVATOVA(poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress, Mapping);
printf("IMAGE_IMPORT_DESCRIPTOR: %08x]\n", impdesc);
printf(" DLL Name TimeDateStamp Import\n");
for( ; impdesc->Characteristics ; impdesc++ )
{
// Получаем имя DLL
char* dllname = (LPTSTR) RVATOVA(impdesc->Name, Mapping);
printf("%-15s %08x ", dllname, impdesc->TimeDateStamp);
// Грузим DLL
HMODULE hDll = LoadLibrary( dllname );
if( !hDll )
{
// не вышло...
printf("Error loading '%s'. Application initialization failed\n");
VirtualFree( base, poh->SizeOfImage, MEM_DECOMMIT );
VirtualFree( base, poh->SizeOfImage, MEM_RELEASE );
CloseHandle( hFile );
return NULL;
}
// откуда брать функции - из FirstThunk или из OriginalFirstThunk
DWORD RvaOfThunks = impdesc->FirstThunk;
// Импорт забинден?
if( impdesc->TimeDateStamp == -1 )
{
// Да, чекаем на валидность тупой проверкой первой функции
PDWORD Func;
// грузим первую функци.
PIMAGE_THUNK_DATA OriginalThunk = (PIMAGE_THUNK_DATA)RVATOVA(impdesc->OriginalFirstThunk, Mapping);
PIMAGE_THUNK_DATA Thunk = (PIMAGE_THUNK_DATA)RVATOVA(impdesc->FirstThunk, Mapping);
if( OriginalThunk->u1.Ordinal & 0xf0000000 )
{
OriginalThunk->u1.Ordinal &= 0xffff;
Func = (PDWORD) GetProcAddress( hDll, (char*) OriginalThunk->u1.Ordinal );
}
else
{
PIMAGE_IMPORT_BY_NAME Name = (PIMAGE_IMPORT_BY_NAME) RVATOVA(OriginalThunk->u1.AddressOfData, base);
Func = (PDWORD) GetProcAddress( hDll, (char*) Name->Name );
}
// сравниваем
if( Thunk->u1.Function == Func )
{
printf("CORRECT\n");
continue;
}
// адреса не совпадают, пробинденный импорт надо перестроить
else
{
printf("FAILED [needs rebuilding]\n");
RvaOfThunks = impdesc->OriginalFirstThunk; // для ребиндинга брать функции из OriginalFirstThunk
}
}
else
printf("NOT BOUND\n");
// Обрабатываем thunk'и
for( PIMAGE_THUNK_DATA Thunk = (PIMAGE_THUNK_DATA)RVATOVA(RvaOfThunks, Mapping); Thunk->u1.Ordinal ; Thunk++ )
{
// Функция задана ординатой?
if( Thunk->u1.Ordinal & 0xf0000000 )
{
Thunk->u1.Ordinal &= 0xffff;
printf("Ordinal: %04x, ", Thunk->u1.Ordinal);
Thunk->u1.Function = (PDWORD) GetProcAddress( hDll, (char*) Thunk->u1.Ordinal );
if( !Thunk->u1.Function )
{
printf("Can't find address for this function\n");
VirtualFree( base, poh->SizeOfImage, MEM_DECOMMIT );
VirtualFree( base, poh->SizeOfImage, MEM_RELEASE );
CloseHandle( hFile );
return NULL;
}
printf("got address %08x\n", Thunk->u1.Function);
}
// функция задана по имени
else
{
PIMAGE_IMPORT_BY_NAME Name = (PIMAGE_IMPORT_BY_NAME) RVATOVA(Thunk->u1.AddressOfData, base);
printf("%03d(0x%04x) \t %-20s ", Name->Hint, Name->Hint, Name->Name );
Thunk->u1.Function = (PDWORD) GetProcAddress( hDll, (char*) Name->Name );
printf("= %08x\n", Thunk->u1.Function);
}
// не важно откуда читали, записываем все равно в FirstThunk
PIMAGE_THUNK_DATA ThunkToWrite;
ThunkToWrite = (PIMAGE_THUNK_DATA)(
(DWORD)RVATOVA(impdesc->FirstThunk,Mapping) + ((DWORD)Thunk - (DWORD)RVATOVA(RvaOfThunks, Mapping))
);
ThunkToWrite->u1.Function = Thunk->u1.Function;
}
}
//
// Выставляем атрибуты секций
//
printf("\nProtecting sections\n");
psh = (PIMAGE_SECTION_HEADER)( (DWORD)poh + sizeof(IMAGE_OPTIONAL_HEADER) );
for( i=0; i < pfh->NumberOfSections ; i++, psh++ )
{
DWORD VirtualSize = (i==pfh->NumberOfSections-1)?
(poh->SizeOfImage-psh->VirtualAddress)
:(psh+1)->VirtualAddress - psh->VirtualAddress;
LPVOID va = (LPVOID)( Mapping + psh->VirtualAddress );
// считаем атрибуты
DWORD Attributes = PAGE_READWRITE;
if( psh->Characteristics & IMAGE_SCN_MEM_EXECUTE || psh->Characteristics & IMAGE_SCN_MEM_READ )
{
if( psh->Characteristics & IMAGE_SCN_MEM_WRITE )
Attributes = PAGE_READWRITE;
else
Attributes = PAGE_READONLY;
}
else if( psh->Characteristics & IMAGE_SCN_MEM_WRITE )
Attributes = PAGE_READWRITE;
// ставим атрибуты
if( !VirtualProtect( va, VirtualSize, Attributes, &Attributes ) )
{
printf("Cannot protect section [%d]\n", GetLastError());
VirtualFree( base, poh->SizeOfImage, MEM_DECOMMIT );
VirtualFree( base, poh->SizeOfImage, MEM_RELEASE );
CloseHandle( hFile );
return NULL;
}
}
//
// Все удачно, закрываем файл и возвращаем базу
//
// Важно! Файл не готов к запуску. Чтобы запустить этот образ
// нужно еще скорректировать поле PEB.ImageBaseAddress в PEB,
// иначе не будут работать функции Win32 для работы с ресурсами.
//
CloseHandle( hFile );
return (HMODULE) Mapping;
}
void
CallLoadedImage (
IN HMODULE hModule
)
/*
Запускает загруженный образ
*/
{
PIMAGE_FILE_HEADER pfh;
PIMAGE_OPTIONAL_HEADER poh;
PIMAGE_SECTION_HEADER psh;
GetHeaders((PCHAR) hModule, &pfh, &poh, &psh);
//
// Фиксим PEB.ImageBaseAddress
//
printf("\nPreparing to start image, fixing PEB\n");
PPEB peb = GetPEB( );
peb->ImageBaseAddress = (PVOID) hModule;
// Все ок. Запускаем
printf("Ready. Running....\n");
LPVOID entry = (LPVOID)( (DWORD)hModule + poh->AddressOfEntryPoint );
__asm call dword ptr [entry];
}
void UnloadExecutable( HMODULE hModule )
{
PIMAGE_FILE_HEADER pfh;
PIMAGE_OPTIONAL_HEADER poh;
PIMAGE_SECTION_HEADER psh;
GetHeaders((PCHAR) hModule, &pfh, &poh, &psh);
VirtualFree( hModule, poh->SizeOfImage, MEM_DECOMMIT );
VirtualFree( hModule, poh->SizeOfImage, MEM_RELEASE );
}
int main()
{
HMODULE hModule;
hModule = LoadExecutable( "test.exe", (void*)0x7F000000 );
//hModule = LoadExecutable( "h:\\windows\\system32\\notepad.exe" );
if( !hModule )
return printf("Failed to load PE\n"), 0;
__try {
__asm int 3;
} __except(EXCEPTION_EXECUTE_HANDLER) { }
CallLoadedImage( hModule );
//never reach here
return 0;
}
по идее меня должен интересовать вот этот кусок
- Код: Выделить всё
//
// Корректируем фиксапы
//
DWORD ImageBaseDelta = (DWORD)base - (DWORD)poh->ImageBase;
// требуется корректировка
if( ImageBaseDelta )
{
printf("\nApplying fixups, ImageBaseDelta = %08x\n", ImageBaseDelta);
if( !poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress )
{
// нет фиксапов
printf("Decided to load at different base, but no relocs present\n");
VirtualFree( base, poh->SizeOfImage, MEM_DECOMMIT );
VirtualFree( base, poh->SizeOfImage, MEM_RELEASE );
CloseHandle( hFile );
return NULL;
}
PIMAGE_BASE_RELOCATION Reloc = (PIMAGE_BASE_RELOCATION) RVATOVA(poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress, base);
int i = 0;
// проходим по фиксапам
for( PIMAGE_FIXUP_ENTRY Fixup = (PIMAGE_FIXUP_ENTRY)( (DWORD)Reloc + sizeof(IMAGE_BASE_RELOCATION) );
(DWORD)Fixup < (DWORD)Reloc + Reloc->SizeOfBlock;
Fixup ++, i ++
)
{
if( Fixup->Type == IMAGE_REL_BASED_HIGHLOW )
{
// адрес инструкции для патча
DWORD* Patch = (DWORD*)RVATOVA( Reloc->VirtualAddress + Fixup->Offset, base );
printf("Fixup #%d: Type = %d, Offset %08x [%08x -> %08x]\n",
i,
Fixup->Type,
RVATOVA( Reloc->VirtualAddress + Fixup->Offset, base ),
*Patch,
*Patch+ImageBaseDelta
);
// патч
*Patch += ImageBaseDelta;
}
// другие типы фиксапов не обрабатываем
else
{
printf("Incorrect fixup type %d\n", Fixup->Type);
VirtualFree( base, poh->SizeOfImage, MEM_DECOMMIT );
VirtualFree( base, poh->SizeOfImage, MEM_RELEASE );
CloseHandle( hFile );
return NULL;
}
}
}
но есть проблемы с переводом на powerbasic.
как бы его вклинить? ай нид хелп.