PE loader

Раздел посвящен программированию с использованием Power Basic.
HouseMD
Начинающий
Начинающий
 
Сообщения: 17
Зарегистрирован: 22.09.2011 (Чт) 19:06

PE loader

Сообщение HouseMD » 22.09.2011 (Чт) 19:18

Нашёл вот такой код для загрузки exe из памяти.

Код: Выделить всё
#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.
как бы его вклинить? ай нид хелп. :D

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: PE loader

Сообщение Хакер » 22.09.2011 (Чт) 21:01

Без секции релоков ничего нельзя сделать. То есть либо вообще ничего, либо самому загружаться по нестандартной базе, чтобы осталось свободное место для подгружаемого образа без его релокации.

Либо есть вариант с дизассемблированием всего того кода и ручной генерацией релоков. Я кое-что подобное делал, но цель была немного другой. Дело в том, что такой способ с дизасмом обнаружит не все места, которые нуждаются в релокации, плюс бывают места не в коде, а в данных, которые нуждаются в релокациях.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

jangle
Википедик
Википедик
Аватара пользователя
 
Сообщения: 3013
Зарегистрирован: 03.06.2005 (Пт) 12:02
Откуда: Нидерланды

Re: PE loader

Сообщение jangle » 23.09.2011 (Пт) 15:38

Как вариант, напиши автору кода - Матусовскому, и попроси его переписать загрузчик без релоков, не бесплатно конечно.

HouseMD
Начинающий
Начинающий
 
Сообщения: 17
Зарегистрирован: 22.09.2011 (Чт) 19:06

Re: PE loader

Сообщение HouseMD » 24.09.2011 (Сб) 14:44

jangle писал(а):Как вариант, напиши автору кода - Матусовскому, и попроси его переписать загрузчик без релоков, не бесплатно конечно.

может у тебя есть его актуальные контакты? :D

jangle
Википедик
Википедик
Аватара пользователя
 
Сообщения: 3013
Зарегистрирован: 03.06.2005 (Пт) 12:02
Откуда: Нидерланды

Re: PE loader

Сообщение jangle » 25.09.2011 (Вс) 16:18

HouseMD писал(а):может у тебя есть его актуальные контакты? :D


Были раньше, сейчас не могу найти. Попробуй его старый майл: matus@perevozki.ru


Вернуться в Power Basic

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 37

    TopList