DLL из памяти

Тема в разделе "WASM.WIN32", создана пользователем provocateur, 6 дек 2006.

  1. provocateur

    provocateur Member

    Публикаций:
    0
    Регистрация:
    5 дек 2006
    Сообщения:
    118
    в ресурс засовываю DLL.
    при запуске программы этот ресурс пишется в темповскую папку и грузиться стандартным LoadLibrary. видел на этом сайте статью "запуск программы из памяти".
    возможно ли сделать это с dll ?
    у меня есть совсем уж неприличная версия : просто тупо записать адреса нужных функций и вызывать их через call . как считаете это возможно или есть лучший и простой вариант?
     
  2. gilg

    gilg New Member

    Публикаций:
    0
    Регистрация:
    19 май 2005
    Сообщения:
    527
    Лучший и простой вариант:
    1) выделяется память
    2) в нее грузится образ DLL с учетом выравнивания из заголовка
    3) выполняется релокайшн
    4) разрешаются все импорты
    5) библиотекой уже о пользоваться, если узнавать адреса экспортируемых функций вручную; чтобы использовать GetProcAddress нужно добавить библиотеку в список PEB_LDR_DATA процесса
    6) вызвать DllMain с флагом DLL_PROCESS_ATTACH
    7) выгружать библиотеку лучше руками, хотя если поковырять немного, то можно попробовать и с помощью FreeLibrary

    PS: Для 1 - 4 пунктов исходники выкладывались на форуме несколько раз
     
  3. provocateur

    provocateur Member

    Публикаций:
    0
    Регистрация:
    5 дек 2006
    Сообщения:
    118
    а немного поподробнее . а то я не шибкий специалист )))
    вот таким макаром вместо специально выделения памяти можно сделать:

    resP = FindResource ( hInstance, (LPSTR)4000, (LPSTR)1000 );
    hP = LoadResource ( hInstance, resP );
    sizeP = SizeofResource ( hInstance, resP );
    pP = (LPSTR) LockResource ( hP );

    ?

    и поподробнее пункты 3-6 можно расписать ? :)
     
  4. gilg

    gilg New Member

    Публикаций:
    0
    Регистрация:
    19 май 2005
    Сообщения:
    527
    http://www.wasm.ru/article.php?article=apihook_2 , раздел "Усовершенствованный метод DLL Injection"
     
  5. asd

    asd New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2005
    Сообщения:
    952
    Адрес:
    Russia
    Для чужих длл-ок косяки возникают непонятные. Для своих смотри то, что gilg написал. Кто-нибудь видел прогу, которая бы любые длл-ки из памяти могла грузить?
     
  6. PE_Kill

    PE_Kill New Member

    Публикаций:
    0
    Регистрация:
    16 янв 2006
    Сообщения:
    107
    на RSDN была стотья с сорсами, много нового от туда узнал
     
  7. gilg

    gilg New Member

    Публикаций:
    0
    Регистрация:
    19 май 2005
    Сообщения:
    527
    Если все правильно реализовано, косяки могут быть только с вызовом DllMain. Например, если в DllMain создается поток, загрузить вручную такую длл гораздо геморрнее - надо в Peb изменять флаги. Еще в Peb поддерживается хэш-очередь загруженных библиотек, используемая лоадером. В нее влезть похоже что невозможно, а без этого не работают некоторые приятные фичи.

    Собс-но, вывод - полный аналог виндового лоадера написать не получится, по-любому будут ограничения.
     
  8. censored

    censored New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2005
    Сообщения:
    1.615
    Адрес:
    деревня "Анонимные Прокси"
    gilg
    какие например?
     
  9. Cr4sh

    Cr4sh New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2006
    Сообщения:
    668
    вот, писал когда-то давно РЕ-загрузчик... вроде работает, хотя не исключены лаги))
    Код (Text):
    1. DWORD GetSectionProtection(DWORD SC)
    2. {
    3.     DWORD result=0;
    4.  
    5.     if (SC && IMAGE_SCN_MEM_NOT_CACHED != 0)
    6.         result = result || PAGE_NOCACHE;
    7.  
    8.     if (SC && IMAGE_SCN_MEM_EXECUTE != 0)
    9.     {
    10.         if (SC && IMAGE_SCN_MEM_READ != 0)     
    11.         {
    12.             if (SC && IMAGE_SCN_MEM_WRITE != 0)
    13.                 result = result || PAGE_EXECUTE_READWRITE;
    14.             else result = result || PAGE_EXECUTE_READ;
    15.         }
    16.         else if (SC && IMAGE_SCN_MEM_WRITE != 0)
    17.             result = result || PAGE_EXECUTE_WRITECOPY;
    18.         else result = result || PAGE_EXECUTE;
    19.     }
    20.     else if (SC && IMAGE_SCN_MEM_READ != 0)
    21.     {
    22.         if (SC && IMAGE_SCN_MEM_WRITE != 0)
    23.             result = result || PAGE_READWRITE;
    24.         else result = result || PAGE_READONLY;
    25.     }
    26.     else if (SC || IMAGE_SCN_MEM_WRITE != 0)
    27.         result = result || PAGE_WRITECOPY;
    28.     else result = result || PAGE_NOACCESS;
    29.  
    30.     return result;
    31. }
    32.  
    33. BOOL ProcessRelocs(long hMap, DWORD dwImageBaseDelta)
    34. {
    35.     PIMAGE_NT_HEADERS pImageNtHeaders = (PIMAGE_NT_HEADERS)(hMap + ((PIMAGE_DOS_HEADER)hMap)->e_lfanew);
    36.    
    37.     ULONG pImageBaseRelocation = (ULONG)(RVATOVA(hMap,
    38.         pImageNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress));
    39.    
    40.     __try
    41.     {
    42.         while (((PIMAGE_BASE_RELOCATION)pImageBaseRelocation)->VirtualAddress != 0)
    43.         {
    44.             int number = (((PIMAGE_BASE_RELOCATION)pImageBaseRelocation)->SizeOfBlock - 8) / 2;
    45.             WORD* Rel = (WORD *)(pImageBaseRelocation + 8);
    46.            
    47.             for (int i = 0; i < number; i++)
    48.             {
    49.                 *(PDWORD)(RVATOVA(hMap,
    50.                     ((PIMAGE_BASE_RELOCATION)pImageBaseRelocation)->VirtualAddress + ((0x0FFF)&(Rel[i])))) +=
    51.                     dwImageBaseDelta;
    52.             }
    53.  
    54.             pImageBaseRelocation += ((PIMAGE_BASE_RELOCATION)pImageBaseRelocation)->SizeOfBlock;
    55.         }
    56.     } __except (EXCEPTION_EXECUTE_HANDLER)
    57.     {  
    58.         return FALSE;
    59.     }
    60.  
    61.     return TRUE;
    62. }
    63.  
    64. BOOL ProcessImports(long hMap)
    65. {
    66.     IMAGE_THUNK_DATA32 *pThunk;
    67.     HMODULE hLibModule;
    68.  
    69.     PIMAGE_NT_HEADERS pImageNtHeaders = (PIMAGE_NT_HEADERS)(hMap + ((PIMAGE_DOS_HEADER)hMap)->e_lfanew);
    70.  
    71.     PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(RVATOVA(hMap,
    72.         pImageNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress));
    73.  
    74.     __try
    75.     {
    76.         while (pImageImportDescriptor->Name != 0)
    77.         {  
    78.             char *name = (char *)RVATOVA(hMap, pImageImportDescriptor->Name);
    79.             hLibModule = LoadLibrary(name);
    80.            
    81.             if (hLibModule == NULL)
    82.                 return FALSE;
    83.  
    84.             if (pImageImportDescriptor->TimeDateStamp == 0)
    85.                 pThunk = (IMAGE_THUNK_DATA32 *)RVATOVA(hMap, pImageImportDescriptor->FirstThunk);
    86.             else pThunk = (IMAGE_THUNK_DATA32 *)RVATOVA(hMap, pImageImportDescriptor->OriginalFirstThunk);
    87.  
    88.             while (pThunk->u1.Ordinal != 0)
    89.             {
    90.                 DWORD dwProcAddr = 0;
    91.                 char *ImportedName;
    92.                 if (((pThunk->u1.Ordinal) & 0x80000000) != 0)
    93.                 {
    94.                     dwProcAddr = (DWORD)GetProcAddress(hLibModule, (char *)(pThunk && 0xFFFF));
    95.                 } else {
    96.                     PIMAGE_IMPORT_BY_NAME pImageImportByName = (PIMAGE_IMPORT_BY_NAME)
    97.                         RVATOVA(hMap, pThunk->u1.AddressOfData);
    98.                     ImportedName = (char *)&pImageImportByName->Name;
    99.                     dwProcAddr = (DWORD)GetProcAddress(hLibModule, ImportedName);
    100.                 }
    101.                 *(PDWORD)pThunk = dwProcAddr;
    102.                 pThunk++;
    103.             }
    104.  
    105.             pImageImportDescriptor++;
    106.         }
    107.     } __except (EXCEPTION_EXECUTE_HANDLER)
    108.     {  
    109.         return FALSE;
    110.     }
    111.  
    112.     return TRUE;
    113. }
    114.  
    115. DWORD xGetProcAdress(long hMap, int num)
    116. {
    117.     PIMAGE_NT_HEADERS pImageNtHeaders = (PIMAGE_NT_HEADERS)(hMap + ((PIMAGE_DOS_HEADER)hMap)->e_lfanew);
    118.  
    119.     PIMAGE_EXPORT_DIRECTORY pImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)RVATOVA(hMap,
    120.             pImageNtHeaders->OptionalHeader.DataDirectory[0].VirtualAddress);
    121.    
    122.     PDWORD AddressOfFunctions = (PDWORD)RVATOVA(hMap, pImageExportDirectory->AddressOfFunctions);
    123.  
    124.     for (int i = 0; i < pImageExportDirectory->NumberOfFunctions; i++)
    125.         if (i == num - 1)
    126.             return RVATOVA(hMap, AddressOfFunctions[i]);
    127.    
    128.     return 0;
    129. }
    130.  
    131. HMODULE xLoadLibrary(PBYTE pbDllBuff)
    132. {
    133.     HMODULE hRet = 0;
    134.     DWORD dwImageBase, dwImageSize, dwHeadersSize, dwImageBaseDelta;
    135.     PIMAGE_NT_HEADERS pImageNtHeaders;
    136.     PBYTE pbImage = NULL;
    137.  
    138.     __try
    139.     {
    140.         pImageNtHeaders = (PIMAGE_NT_HEADERS)
    141.             (pbDllBuff + ((PIMAGE_DOS_HEADER)pbDllBuff)->e_lfanew);
    142.  
    143.         dwImageBase   = pImageNtHeaders->OptionalHeader.ImageBase;
    144.         dwImageSize   = pImageNtHeaders->OptionalHeader.SizeOfImage;
    145.         dwHeadersSize = pImageNtHeaders->OptionalHeader.SizeOfHeaders;
    146.  
    147.         DWORD dwNewBase = dwImageBase;
    148.         while (pbImage == NULL)
    149.         {
    150.             pbImage = (PBYTE)GVirtualAlloc((LPVOID)dwNewBase, dwImageSize,
    151.                 MEM_RESERVE, PAGE_NOACCESS);
    152.             dwNewBase += 0x10000;
    153.         }
    154.  
    155.         dwImageBaseDelta = dwNewBase - dwImageBase - 0x10000;
    156.  
    157.         PBYTE pbHeaders = (PBYTE)GVirtualAlloc(pbImage, dwHeadersSize,
    158.             MEM_COMMIT, PAGE_READWRITE);
    159.        
    160.         memcpy(pbHeaders, pbDllBuff, dwHeadersSize);
    161.    
    162.         DWORD dwOldProtect;
    163.         VirtualProtect(pbHeaders, dwHeadersSize, PAGE_READONLY, &dwOldProtect);
    164.    
    165.         PIMAGE_SECTION_HEADER pImageSectionHeader = (PIMAGE_SECTION_HEADER)
    166.             (pImageNtHeaders->FileHeader.SizeOfOptionalHeader +
    167.             (long)&(pImageNtHeaders->OptionalHeader));
    168.  
    169.         PBYTE pbMem = NULL;
    170.         DWORD dwRawSectionSize = 0;
    171.  
    172.         for (int i = 0; i < pImageNtHeaders->FileHeader.NumberOfSections; i++)
    173.         {
    174.             if (pImageSectionHeader->SizeOfRawData > pImageSectionHeader->Misc.VirtualSize)
    175.                 dwRawSectionSize = pImageSectionHeader->Misc.VirtualSize;
    176.             else
    177.                 dwRawSectionSize = pImageSectionHeader->SizeOfRawData;
    178.  
    179.             pbMem = (PBYTE)VirtualAlloc((LPVOID)RVATOVA(pbImage, pImageSectionHeader->VirtualAddress),
    180.                 pImageSectionHeader->Misc.VirtualSize, MEM_COMMIT, PAGE_READWRITE);
    181.  
    182.             ZeroMemory(pbMem, pImageSectionHeader->Misc.VirtualSize);
    183.             memcpy(pbMem, (void *)RVATOVA(pbDllBuff, pImageSectionHeader->PointerToRawData), dwRawSectionSize);
    184.  
    185.             pImageSectionHeader++;
    186.         }
    187.  
    188.         for (int i = 0; i < pImageNtHeaders->FileHeader.NumberOfSections; i++)
    189.         {
    190.             VirtualProtect((LPVOID)RVATOVA(pbImage, pImageSectionHeader[i].VirtualAddress),
    191.                 pImageSectionHeader[i].Misc.VirtualSize,
    192.                 GetSectionProtection(pImageSectionHeader[i].Characteristics),
    193.                 &dwOldProtect);
    194.         }
    195.  
    196.         if (!ProcessRelocs((long)pbImage, dwImageBaseDelta))
    197.             goto end;
    198.         if (!ProcessImports((long)pbImage))
    199.             goto end;
    200.  
    201.     } __except (EXCEPTION_EXECUTE_HANDLER)
    202.     {  
    203.         goto end;
    204.     }
    205.  
    206.     hRet = (HMODULE)pbImage;
    207.  
    208. end:
    209.  
    210.     return hRet;
    211. }
     
  10. gilg

    gilg New Member

    Публикаций:
    0
    Регистрация:
    19 май 2005
    Сообщения:
    527
    Например, при создании нового потока GetModuleHandle вызывается для каждой загруженной длл, у которой не стоит флаг LDRP_DONT_CALL_FOR_THREADS. GetModuleHandle работает через хэш-таблицу и, соотв-но, не может найти там нашу длл. В результате создание потока обламывается.
    Чтобы GetModuleHandle работала нужно либо добавить длл в хэш-таблицу (практически нереально), либо прописать в LDR_DATA_TABLE_ENTRY существующий FullPath, т.е. привязаться к существующему файлу на диске.
     
  11. asd

    asd New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2005
    Сообщения:
    952
    Адрес:
    Russia
    Если брать мой случай и конкретную длл, то там не в дллмайн дело, а где-то ещё. Хотя я на правильность реализации и не претендую пока.

    gilg
    Слушай, а из каких источников столько информации взял?
     
  12. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    Не забывайте, что иногда DLL можно сконвертировать в статический LIB (с помощью Dll2Lib) и линковать прямо в экзешник без лишних ресурсов, эмоций и кода.
     
  13. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    сорцы ReactOS, Win2k =)
     
  14. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    Ещё wine есть - тоже много интересного.
     
  15. gilg

    gilg New Member

    Публикаций:
    0
    Регистрация:
    19 май 2005
    Сообщения:
    527
    Ну да, тип того.

    Кстати, по поводу FullPath еще один прикол есть. ProcessExplorer валится при попытке просмотра свойств инжектированной длл в которой он пустой.
     
  16. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    Многое из wine используется в ReactOS.
     
  17. fr0b-p

    fr0b-p New Member

    Публикаций:
    0
    Регистрация:
    1 окт 2006
    Сообщения:
    118
    объяните плиз зачем длл в ресурсы и потом загружать? помоему для всех случаев достаточно способа Quantum-а
     
  18. asd

    asd New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2005
    Сообщения:
    952
    Адрес:
    Russia
    fr0b-p
    Допустим пакер, который все длл-ки к ехешнику припаковывает.
     
  19. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    n0name
    Интересно, какой из 2х "из" нужно заменить на "в"? Думаю, что второй.

    fr0b-p
    Dll2Lib нормально работает далеко не со всеми Dll. С другой стороны, после конвертирования можно вооружиться отладчиком и пофиксить баги в Lib вручную, но это уже зависит от квалификации.
     
  20. Twister

    Twister New Member

    Публикаций:
    0
    Регистрация:
    12 окт 2005
    Сообщения:
    720
    Адрес:
    Алматы
    provocateur
    Вот линк на статью с РСДН. Отличная статья.