Execute exe from memory

Тема в разделе "WASM.BEGINNERS", создана пользователем xrc2, 5 апр 2008.

  1. xrc2

    xrc2 New Member

    Публикаций:
    0
    Регистрация:
    5 апр 2008
    Сообщения:
    47
    Здравствуйте.

    Не могу разобраться почему не запускается следующий файл из памяти, что еще не хватает?
    В примере http://www.wasm.ru/print.php?article=memfile загрузчик (proc alloced_area_start) копируется в виртуальную память или просто выполняется процедура, если копируется в память то как это сделать в с++ и для чего это нужно? На сколько я понял весь код процедуры копируется в виртуальную память, а для чего? Разве нельзя просто вызвать эту процедуру?

    Код (Text):
    1. #include "stdafx.h"
    2. #include <Windows.h>
    3.  
    4. DWORD GetSectionProtection(DWORD sc)
    5. {
    6.     DWORD dwResult=0;
    7.     if (sc & IMAGE_SCN_MEM_NOT_CACHED)
    8.         dwResult |= PAGE_NOCACHE;
    9.  
    10.     if (sc & IMAGE_SCN_MEM_EXECUTE)
    11.     {
    12.         if (sc & IMAGE_SCN_MEM_READ)
    13.         {
    14.             if (sc & IMAGE_SCN_MEM_WRITE)
    15.                 dwResult |= PAGE_EXECUTE_READWRITE;
    16.             else
    17.                 dwResult |= PAGE_EXECUTE_READ;
    18.         }
    19.         else
    20.         {
    21.             if (sc & IMAGE_SCN_MEM_WRITE)
    22.                 dwResult |= PAGE_EXECUTE_WRITECOPY;
    23.             else
    24.                 dwResult |= PAGE_EXECUTE;
    25.         }
    26.     }
    27.     else
    28.     {
    29.         if (sc & IMAGE_SCN_MEM_READ)
    30.         {
    31.             if (sc & IMAGE_SCN_MEM_WRITE)
    32.                 dwResult|=PAGE_READWRITE;
    33.             else
    34.                 dwResult|=PAGE_READONLY;
    35.         }
    36.         else
    37.         {
    38.             if (sc & IMAGE_SCN_MEM_WRITE)
    39.                 dwResult|=PAGE_WRITECOPY;
    40.             else
    41.                 dwResult|=PAGE_NOACCESS;
    42.         }
    43.     }
    44.  
    45.     return dwResult;
    46. }
    47.  
    48.  
    49. inline BOOL IsImportByOrdinal(DWORD ImportDescriptor)
    50. {
    51.     return (ImportDescriptor & IMAGE_ORDINAL_FLAG32)!=0;
    52. }
    53.  
    54. #ifndef MIN
    55. #define MIN(a,b) ((a)<(b)?(a):(b))
    56. #endif
    57.  
    58. //typedef BOOL (WINAPI *pointMAIN)(int , char*);
    59.  
    60. typedef BOOL (WINAPI *pointWINMAIN)(HINSTANCE, HINSTANCE, LPSTR, int);
    61.  
    62.  
    63. HMODULE MemLoadExe(PBYTE data)
    64. {
    65.     IMAGE_FILE_HEADER        *pFileHeader        = NULL;
    66.     IMAGE_OPTIONAL_HEADER    *pOptionalHeader    = NULL;
    67.     IMAGE_SECTION_HEADER    *pSectionHeader        = NULL;
    68.     IMAGE_IMPORT_DESCRIPTOR *pImportDscrtr        = NULL;
    69.     USHORT                    e_lfanew            = *((USHORT*)(data+0x3c));
    70.     PCHAR                    ImageBase            = NULL;
    71.     PCHAR                    SectionBase            = NULL;
    72.  
    73.    
    74.     DWORD dwSize, dwOldProt, ImageBaseDelta;
    75.     int i;
    76.  
    77.     pFileHeader = (IMAGE_FILE_HEADER *)(data+e_lfanew+4);
    78.     pOptionalHeader = (IMAGE_OPTIONAL_HEADER *)(data+e_lfanew+4+sizeof(IMAGE_FILE_HEADER));
    79.  
    80.     if (pOptionalHeader->Magic!=IMAGE_NT_OPTIONAL_HDR32_MAGIC)
    81.         return NULL;
    82.  
    83.     //    Let's try to reserv memory
    84.     ImageBase = (PCHAR)VirtualAlloc(
    85.         (PVOID)pOptionalHeader->ImageBase,
    86.         pOptionalHeader->SizeOfImage,
    87.         MEM_RESERVE,PAGE_NOACCESS);
    88.  
    89.     if(ImageBase==NULL)
    90.     {
    91.         ImageBase=(PCHAR)VirtualAlloc(NULL,
    92.             pOptionalHeader->SizeOfImage,
    93.             MEM_RESERVE,PAGE_NOACCESS);
    94.         if(ImageBase==NULL)
    95.             return NULL;
    96.     }
    97.  
    98.     //    copy the header
    99.     SectionBase=(PCHAR)VirtualAlloc(ImageBase,
    100.         pOptionalHeader->SizeOfHeaders,
    101.         MEM_COMMIT,PAGE_READWRITE);
    102.     memcpy(SectionBase,data,pOptionalHeader->SizeOfHeaders);
    103.     //    Do headers read-only (to be on the safe side)
    104.     VirtualProtect(SectionBase,pOptionalHeader->SizeOfHeaders,PAGE_READONLY,&dwOldProt);
    105.  
    106.     //    find sections ...
    107.     pSectionHeader = (IMAGE_SECTION_HEADER *)(pOptionalHeader+1);
    108.     for (i=0; i<pFileHeader->NumberOfSections; i++)
    109.     {
    110.         SectionBase = (PCHAR)VirtualAlloc(
    111.             ImageBase+pSectionHeader[i].VirtualAddress,
    112.             pSectionHeader[i].Misc.VirtualSize,
    113.             MEM_COMMIT,PAGE_READWRITE);
    114.         if (SectionBase==NULL)
    115.         {
    116.             VirtualFree(ImageBase, 0, MEM_RELEASE);
    117.             return NULL;
    118.         }
    119.         //    ... and copy initialization data
    120.         SectionBase = ImageBase+pSectionHeader[i].VirtualAddress;
    121.         dwSize = MIN(pSectionHeader[i].SizeOfRawData,pSectionHeader[i].Misc.VirtualSize);
    122.         memcpy(SectionBase, data+pSectionHeader[i].PointerToRawData,dwSize);
    123.     }
    124.  
    125.     pImportDscrtr = (IMAGE_IMPORT_DESCRIPTOR *)(ImageBase+
    126.         pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
    127.  
    128.     for (;pImportDscrtr->Name!=0; pImportDscrtr++)
    129.     {
    130.         PCHAR pLibName        = (PCHAR)(ImageBase+pImportDscrtr->Name);
    131.         PCHAR pImortName    = NULL;
    132.         HMODULE hLibModule    = LoadLibraryA(pLibName);
    133.         DWORD    *pImport    = NULL,
    134.             *pAddress    = NULL;
    135.         DWORD ProcAddress;
    136.  
    137.         pAddress=(DWORD *)(ImageBase+pImportDscrtr->/*Original*/FirstThunk);
    138.         if (pImportDscrtr->TimeDateStamp==0)
    139.             pImport=(DWORD *)(ImageBase+pImportDscrtr->FirstThunk);
    140.         else
    141.             pImport=(DWORD *)(ImageBase+pImportDscrtr->OriginalFirstThunk);
    142.         for (i=0; pImport[i]!=0; i++)
    143.         {
    144.             if (IsImportByOrdinal(pImport[i]))
    145.                 ProcAddress=(DWORD)GetProcAddress(hLibModule, (PCHAR)(pImport[i]&0xFFFF));
    146.             else  // import by name
    147.             {
    148.                 pImortName=(PCHAR)(ImageBase+(pImport[i])+2);
    149.                 ProcAddress=(DWORD)GetProcAddress(hLibModule, pImortName);
    150.             }
    151.             pAddress[i]=ProcAddress;
    152.         }
    153.     }
    154.  
    155.     //    set section protection
    156.     for (i=0; i<pFileHeader->NumberOfSections; i++)
    157.         VirtualProtect((PVOID)(ImageBase+pSectionHeader[i].VirtualAddress),
    158.         pSectionHeader[i].Misc.VirtualSize,
    159.         GetSectionProtection(pSectionHeader[i].Characteristics),
    160.         &dwOldProt);
    161.  
    162.     //    call MainFunc
    163.     if (pOptionalHeader->AddressOfEntryPoint!=0)
    164.     {
    165.         //pointMAIN pWinMain=(pointMAIN)(ImageBase+pOptionalHeader->AddressOfEntryPoint);
    166.         pointWINMAIN pWinMain=(pointWINMAIN)(ImageBase+pOptionalHeader->AddressOfEntryPoint);
    167.         if (!pWinMain((HINSTANCE)ImageBase, NULL, 0, SW_SHOWNORMAL))
    168.         {
    169.             VirtualFree(ImageBase, 0, MEM_RELEASE);
    170.             return NULL;
    171.         }
    172.     }
    173.  
    174.     return (HMODULE)ImageBase;
    175. }
    176.  
    177. int _tmain(int argc, _TCHAR* argv[])
    178. {
    179.     FILE *fp = fopen("c:\\WINDOWS\\system32\\calc.exe", "rb");
    180.     fseek(fp, 0, SEEK_END);
    181.     long fileSize = ftell(fp);
    182.     fseek(fp, 0, SEEK_SET);
    183.  
    184.     char *data = new char[fileSize];
    185.     fread(data, fileSize, 1, fp);
    186.  
    187.     //Load PE and run the File
    188.     MemLoadExe((PBYTE)data);
    189.    
    190.     delete[] data;
    191.     fclose(fp);
    192.  
    193.     return 0;
    194. }
     
  2. assorted

    assorted New Member

    Публикаций:
    0
    Регистрация:
    7 авг 2006
    Сообщения:
    227
    Если адреса (41000..) свободны то достаточно просто спроецировать туда exe, а если заняты придется выделять память в другом месте, и соответственно править релоки. Вывод - используй загрузчик с ImageBase отличным от 41000, если это возможно - не придется ковыряться с релоками.
     
  3. Freeman

    Freeman New Member

    Публикаций:
    0
    Регистрация:
    10 фев 2005
    Сообщения:
    1.385
    Адрес:
    Ukraine
    запуск на си вроде Great дето постел
     
  4. wsd

    wsd New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2007
    Сообщения:
    2.824
    Freeman
    да пелоадер называется :)
    у краша сайте висит.
     
  5. MSoft

    MSoft New Member

    Публикаций:
    0
    Регистрация:
    16 дек 2006
    Сообщения:
    2.854
    Не факт, не факт. Во-первых, не 41 000, а 400 000, а во вторых - память может быть элементарно занята какими-то системными ... эм... мусором. Вобщем, наличие релоков крайне необходимо за исключением редких случаев.
     
  6. xrc2

    xrc2 New Member

    Публикаций:
    0
    Регистрация:
    5 апр 2008
    Сообщения:
    47
    а вы не подскажите ссылку? А то в гугле все что нужно все на асме.
     
  7. assorted

    assorted New Member

    Публикаций:
    0
    Регистрация:
    7 авг 2006
    Сообщения:
    227
    MSoft
    то есть если секции релоков вообще нет в exe (я никогда ее не создаю) то файл вообще не запустится? что то на практике такого не наблюдал..
     
  8. MSoft

    MSoft New Member

    Публикаций:
    0
    Регистрация:
    16 дек 2006
    Сообщения:
    2.854
    assorted
    А я наблюдал. Я не говорю, что файл не будет работать, но скорее всего он не будет работать. Я проверял это на многих файлах. Хочешь сказать, что адреса 400 000 никогда не бывают заняты??? Загрузись по любой базе и посмотри сам.

    А что касается принципиальной работы из памяти, так тут будет туева хуча камней. В частности, работа с ресурсами - база образа в данном случае берется из PEB, в котором прописана база загрузчика, а не твоего файла.

    Вобщем, запуск без релоков - это конечно зря. Оно и с релокам и не всегда будет работать, а без релоков тем более. Использовать такое в мальваре крайне не рекомендую.
     
  9. assorted

    assorted New Member

    Публикаций:
    0
    Регистрация:
    7 авг 2006
    Сообщения:
    227
    MSoft

    Я вот о чем берем notepad.exe смотрим секции .text, .data, .rsrc
    Берем calc.exe смотрим секции .text, .data, .rsrc
    (для достоверности глянул в оле она показывает не только имя но и тип секции)

    Секцией релоков не пахнет. Это зачит что данные приложения просто бы не запускались. Можно пример - когда при запуске процесса адреса будут заняты?
     
  10. MSoft

    MSoft New Member

    Публикаций:
    0
    Регистрация:
    16 дек 2006
    Сообщения:
    2.854
    ты название топика читал? это когда 1 файл запускает другой файл в своем адресном пространстве
     
  11. assorted

    assorted New Member

    Публикаций:
    0
    Регистрация:
    7 авг 2006
    Сообщения:
    227
    MSoft

    Какие релоки ты собираешся править если их в большинстве случаев нет?
     
  12. xrc2

    xrc2 New Member

    Публикаций:
    0
    Регистрация:
    5 апр 2008
    Сообщения:
    47
    assorted прав в большинстве случаев релоков нет - это оч. легко проверить (не нужно спорить) - открываем PEview.exe где то сдесь я ее скачивал -> заходим в раздел IMAGE_NT_HEDARES -> IMAGE_OPTIONAL_HEADERS -> находим каталог "base relocation table" - вот и все доказательства, тем более что больше интересует вариант без релоков!


    Возвращаясь к моему вопросу:
    Этот код без осложнений запускает freecell.exe - правда без картинок.. т.е. кажется что программа не может достучаться до ресурсов. Как быть?

    Ну так вопрос пока отрыт!
     
  13. assorted

    assorted New Member

    Публикаций:
    0
    Регистрация:
    7 авг 2006
    Сообщения:
    227
    xrc2

    Только же на эту тему распинался уважаемый MSoft. см PEB
     
  14. MSoft

    MSoft New Member

    Публикаций:
    0
    Регистрация:
    16 дек 2006
    Сообщения:
    2.854
    Блин, тебе ShellExecute вызвать или правильно настроить и выполнить файл в памяти??? У меня ощущение, что ты хочешь одно, но говоришь о другом.
     
  15. MSoft

    MSoft New Member

    Публикаций:
    0
    Регистрация:
    16 дек 2006
    Сообщения:
    2.854
    Тогда ты и не запустишь файл из памяти. Если твой загрузчик имеет базу X, а файл надо загрузить по базе Y, то скорее всего (ну по крайней мере вероятно), что база Y будет занята чем-то системным. А релоки... Если нет релоков, то по другой базе просто нет смысла запускать файл - маловероятно, что он не исполььзует абсолютную адресацию.
     
  16. assorted

    assorted New Member

    Публикаций:
    0
    Регистрация:
    7 авг 2006
    Сообщения:
    227
    MSoft что база Y будет занята чем-то системным

    Не в первый раз спрашиваю, чем будет занято 400000 к тому моменту как загрузчик будет работать?

    Сейчас не поленился собрал файл с базой
    format PE GUI at 70000000h

    все чудесно работает, адреса 400000 свободны, проецируй чего хочешь.

    Ну и ради эксперемента
    format PE GUI at 7C800000h (тут у меня располагается кернел)
    Все - файл не запускается.
     
  17. xrc2

    xrc2 New Member

    Публикаций:
    0
    Регистрация:
    5 апр 2008
    Сообщения:
    47
    PEB - помог частично!

    т.е. делаю следующее:
    1) Компилю загрузчик стандартными настройками VC7 (Загрузчик должен быть обязательно GUI, т.к. запускаемый файл Б - гуишный, когда загрузчик был консольный у меня запускался файл Б и сразу имирал.)
    2) Базовый адрес запускаемого файла Б должен быть выше 0х01000000 (как стоит у calc. exe и mspaint.exe и т.д.)
    3) Правим PEB в код выше добавилось следующее

    Код (Text):
    1. typedef struct _PEB
    2. {
    3.     UCHAR InheritedAddressSpace;                     /* 00h */
    4.     UCHAR ReadImageFileExecOptions;                  /* 01h */
    5.     UCHAR BeingDebugged;                             /* 02h */
    6.     BOOLEAN SpareBool;                               /* 03h */
    7.     HANDLE Mutant;                                   /* 04h */
    8.     PVOID ImageBaseAddress;                          /* 08h */
    9.     //PPEB_LDR_DATA Ldr;                               /* 0Ch */
    10. }PEB, *PPEB;
    11.  
    12. typedef struct _TEB
    13. {
    14.     NT_TIB Tib;                         /* 00h */
    15.     PVOID EnvironmentPointer;           /* 1Ch */
    16.     DWORD Cid[2];                       /* 20h */
    17.     PVOID ActiveRpcInfo;                /* 28h */
    18.     PVOID ThreadLocalStoragePointer;    /* 2Ch */
    19.     PPEB Peb;                           /* 30h */
    20.     ULONG LastErrorValue;               /* 34h */
    21. }TEB, *PTEB;
    22.  
    23. _TEB * GetTEB()
    24. {
    25.     __asm mov eax, fs:[18h];
    26. #pragma warning(disable:4035)
    27. }
    Запуск файла в функции MemLoadExe теперь выглядит так:

    Код (Text):
    1. if (pOptionalHeader->AddressOfEntryPoint!=0)
    2.     {
    3.         // Get TEB
    4.         TEB* teb = GetTEB();
    5.         // Get PEB
    6.         PEB* peb = teb->Peb;
    7.         peb->ImageBaseAddress = ImageBase;
    8.  
    9.         //pOptionalHeader->ImageBase = (DWORD)ImageBase;
    10.         LPVOID entry = (LPVOID)( (DWORD)ImageBase + pOptionalHeader->AddressOfEntryPoint );
    11.         __asm call [entry];
    12.     }
    Результат:
    1) Почти все запускается из каталога c:\windows\system32\*.exe
    2) Приложения скомпиленые мною не запускаются в дебаг режиме если мой файл Б весит от 2 до 8 метров (приблизительно). Проблема решилась так: в файл Б поменял базовый адрес на 0x10000000 - проблема решилась для мелких файлах около 2-3 метров. Или проблему можно было решить так - в режиме релиза! Видимо памяти не хватало!
    3) Я уже не говорю о Viste

    Какие будут мнения на этот счет?
     
  18. UTeX

    UTeX New Member

    Публикаций:
    0
    Регистрация:
    19 окт 2007
    Сообщения:
    584
  19. UTeX

    UTeX New Member

    Публикаций:
    0
    Регистрация:
    19 окт 2007
    Сообщения:
    584
  20. UTeX

    UTeX New Member

    Публикаций:
    0
    Регистрация:
    19 окт 2007
    Сообщения:
    584