Разбираюсь с устройством LoadLibrary

Тема в разделе "WASM.BEGINNERS", создана пользователем yurza, 23 сен 2010.

  1. yurza

    yurza New Member

    Публикаций:
    0
    Регистрация:
    5 мар 2008
    Сообщения:
    69
    Народ помогите разобраться с этой функцией
    Есть простая dll
    Код (Text):
    1. BOOL APIENTRY DllMain(HINSTANCE hinstDLL,
    2.       DWORD fdwReason, LPVOID lpvReserved)
    3. {
    4.   if(fdwReason==DLL_PROCESS_ATTACH) MessageBox(0,"DLL","DLL",1);
    5.    return TRUE;
    6. }
    При обыкновенном вызове
    Код (Text):
    1. UNICODE_STRING string1;
    2. HANDLE mod;
    3. RtlInitUnicodeString(&string1,L"D:\\dell\\Erunda\\ffffffff\\dll\\Project1.dll");
    4. LdrLoadDll(NULL,0,&string1,&mod);
    MessageBox появляется я пытаюсь написать свой аналог

    Код (Text):
    1. RtlInitUnicodeString( &DllName,L"\\??\\D:\\dell\\Erunda\\ffffffff\\dll\\Project1.dll");
    2. InitializeObjectAttributes(&ob, &DllName, OBJ_CASE_INSENSITIVE, 0, 0);
    3. ZwOpenFile(&hFile, FILE_EXECUTE | SYNCHRONIZE, &ob, &iosb, FILE_SHARE_READ | FILE_SHARE_DELETE,
    4.                 FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
    5. ob.pObjectName = 0;
    6. PVOID ViewBase;
    7. SIZE_T ViewSize;
    8. st=NtCreateSection(&hSection,SECTION_ALL_ACCESS,&ob,NULL,PAGE_EXECUTE,SEC_IMAGE,hFile);
    9. ZwMapViewOfSection(hSection,GetCurrentProcess(),(PVOID *)&ViewBase,0L,0L,NULL,&ViewSize,ViewShare,0L,PAGE_EXECUTE_READWRITE);
    10. Entry=LdrpAllocateDataTableEntry (ViewBase);
    11. Entry->EntryPoint = LdrpFetchAddressOfEntryPoint(Entry->DllBase);
    12. st = (NTSTATUS)LdrRelocateImage(ViewBase,
    13.                             "LDR",
    14.                             (ULONG)STATUS_SUCCESS,
    15.                             (ULONG)STATUS_CONFLICTING_ADDRESSES,
    16.                             (ULONG)STATUS_INVALID_IMAGE_FORMAT
    17.                             )
    Теперь как я понимаю мы находим таблицу импорта в моей библиотеке (Bound-импортом и тому подобное отбросим для простаты)
    Код (Text):
    1. ImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)RtlImageDirectoryEntryToData(
    2.                         Entry->DllBase,
    3.                         TRUE,
    4.                         IMAGE_DIRECTORY_ENTRY_IMPORT,
    5.                         &ImportSize
    6.                         );
    теперь получается надо бежать по импорту и проецировать библиотеки
    Код (Text):
    1. while (ImportDescriptor->Characteristics!=0) {
    2.                         ImportName = (PSZ)((ULONG_PTR)Entry->DllBase + ImportDescriptor->Name);
    3.                         FirstThunk = (PIMAGE_THUNK_DATA)((ULONG_PTR)Entry->DllBase + ImportDescriptor->FirstThunk);
    4.                         ImportDescriptor++;
    5.        }
    И одновременно проверить не проецирована ли уже данная библиотека на процесс в моей dll это kernel32 и user32 т.е. они уже есть
    и вот что дальше я как то растерялся смотрю виртуальное адресное пространство процесса библиотека спроецирована
    За ранее благодарен
     
  2. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.315
    ахахах... поцталом))))

    по теме: в интернете есть куча примеров как грузить dll, как настраивать релоки, как настраивать таблицу импорта, как настраивать таблицу экспорта и тд... гугли)
     
  3. mikityak

    mikityak Забанен

    Публикаций:
    0
    Регистрация:
    5 авг 2007
    Сообщения:
    160
  4. ziral2088

    ziral2088 New Member

    Публикаций:
    0
    Регистрация:
    16 авг 2009
    Сообщения:
    283
    х64 на рсдене выкладывал рабочий код по загрузке длл вручную. Еще на забугорном сайте видел тоже рабочий код. Их валом.
     
  5. yurza

    yurza New Member

    Публикаций:
    0
    Регистрация:
    5 мар 2008
    Сообщения:
    69
    _mikityak_ Спасибо за ссылку но что такое dll я как то в курсе
    Но вот видишь и тебе настроение поднял но LdrRelocateImage как раз и отвечает за настройку релоков особенно слышать это от тебя когда ты сам спрашивал о релоках http://wasm.ru/forum/viewtopic.php?id=38491
    за ссылку х64 спасибо посмотрел практически такая же реализация какую и я хочу реализовать единственное надо покумекать над настройкой таблицы импорта а вот при чем тут таблица экспорта (хотя не уверен может и надо) реализовать свою GetProcAddress легко а разобрать экспорт легко легче чем импорт
    За желание помочь спасибо.
    Хоти вот к примеру такая ерунда а вот если вместо имени Project1.dll подать какой-нибудь Project да еще и подправить так чтобы он выглядел как просто мусор интересно антивирус сможет эмулировать его работы (пищу выпимщий могу ошибаться :))
     
  6. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    ziral2088
    Выкиньте тот код. Загрузка должна быть выполнена средствами системного загрузчика.
    yurza
    Это довольно обширная тема, смотрите сурцы.
     
  7. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.315
    блин... так в чем твоя проблема-то тогда? импорт вообще по-моему самое простое в загрузке dll... пробегаешь по таблице импорта, для каждой dll от которой зависит твоя dll, находишь их базовые адреса, если dll нет, то загружаешь... пробегаешь по всем функциям для каждой из dll, находишь их адреса, подставляешь... в интернете куча примеров, я же говорил... и еще была функция что-то типа LdrpWalkImportDescriptor)))

    ЗЫ исходники той функции мне нужны были, чтобы уметь настроить один редкий тип релоков, если ты не понял...
    ЗЗЫ таблицу экспорта нужно настраивать, если она у тебя есть...
    ЗЗЗЫ кстати а как вы все находите адреса функций из ntdll.dll, которые не находятся в таблице экспорта? (LdrRelocateImage например)
    ЗЗЗЗЫ а ты добавляешь свою dll в "базу данных загрузщика"?)
     
  8. yurza

    yurza New Member

    Публикаций:
    0
    Регистрация:
    5 мар 2008
    Сообщения:
    69
    Честно и откровенно роюсь в инете + обрывки исподников а дальше сам пытаюсь восстановить логику
    Дальше посмотрел так и в правда что LoadLibrary действительно загружает экспорт (получается функция по проецированию динамических библиотек использует будущие функции ведь при нармальной загрузке сначало LoadLibrary получила адрес потом GetProcAddress а в загрузчике идет LdrGetprocessAdresss)

    только вот вопрос смотрю через IDA на свою dll том в Export есть типа функция start как я понял это и есть DllEntry от сюда вопрос IDA думает что это экспорт что ли
     
  9. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    yurza
    Как у вас всё запутано. Нэйтивный лодер самодостаточный. Винапи это только надстройка.
     
  10. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.315
    то есть по сути ты переписываешь загрузщик))) а я вот хотел отойти от этого, но к сожалению не знаю как адекватно найти адреса этих самых функций, а встраивать какой-либо дисасм не хотелось бы в принципе...

    чет я не понял... виндовый загрузщик настраивает таблицу экспорта, так как предполагается, что dll - в первую очередь библиотека с каким то функционалом для программиста, который будет ее использовать... если таблицы экспорта нет, то и настраивать нечего...

    точка входа (EntryPoint) не имеет отношения к экспорту, насколько я знаю... более того dll может не иметь точки входа, если ей не нужно производить какие-либо действия по инициализации перед использованием dll программой...

    вообще по прочтенному в этой теме я сделал вывод, что ты делаешь малварю... не в обиду, но мне кажется, что тебе следует сначала прочитать про формат PE-файлов и про работу загрузщика, прежде чем его переписывать... ну хотя бы, чтобы знать про таблицы импорта, экспорта, ресурсы и тд... на васме есть статьи об этом, поищи например статьи "об упаковщиках в последний раз" или как-то так...
     
  11. MSoft

    MSoft New Member

    Публикаций:
    0
    Регистрация:
    16 дек 2006
    Сообщения:
    2.854
    это как так?
     
  12. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.315
    допустим в линкере студии это делается флагом /NOENTRY... msdn призывает ставить этот флаг для dll содержащих только ресурсы, без кода... я не в курсе, что в итоге ставится в поле EntryPoint pe-формата, и как это обрабатывается загрузщиком, может там ставится смещение какой-нить заглушки или ноль... но можно погуглить об этом)))
     
  13. sl0n

    sl0n Мамонт дзена **

    Публикаций:
    0
    Регистрация:
    26 сен 2003
    Сообщения:
    701
    да есть ресурсные длл которые просто как архив всяких ресурсов и грузятся как данные
     
  14. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Rel
    Весьма просто. Для большинства функций имена определены для отладочного вывода. Например стандартный сех-пролог имеет ссылку массив хэндлеров, выполняющих отладочный вывод. Это например LdrpGenericExceptionFilter(). Ищите в модуле строку, например "LdrpLoadDll", затем фиксап для неё, один из них будет находится в хэндлере. Ищем его начало, а затем фиксап для него - он будет принадлежать прологу LdrpLoadDll(). Так можно найти функции(в XP):
    Код (Text):
    1. LdrpLoadDll
    2. LdrpSnapIAT
    3. LdrpCallTlsInitializers
    4. LdrpGetProcedureAddress
    5. LdrpSendDllLoadedNotifications
    6. LdrpSendDllUnloadedNotifications
    7. LdrLockLoaderLock
    8. LdrUnlockLoaderLock
    9. LdrEnumerateLoadedModules
    10. LdrUnloadDll
    11. LdrpLoadDll
    12. LdrQueryApplicationCompatibilityGoo
    13. LdrpCheckForLoadedDll
    14. LdrpMapDll
    15. LdrReadMemory
    16. LdrpTouchThreadStack
    Используя поиск по переменным ShowSnaps можно найти вобще всё. Но тут уже нужно граф создавать.
     
  15. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.315
    хех... я обычно слабо понимаю ваше "весьма просто"))))

    спасибо, попробую... пока еще не представляю, как определить, что фиксап строки находится в хендлере и как определить начала хендлера, там должен лежать стандартный пролог видимо)))
     
  16. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    > как определить, что фиксап строки находится в хендлере
    хендлеры построены одинаково.
    стандартного пролога чаще всего нет, кстати.
     
  17. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    n0name
    Стандартный пролог есть в болшинстве "тяжёлых" процедур, кстати. Он формирует seh/sfc/cookie фрейм и сохраняет ргп.
    Код (Text):
    1.  push размер фрейма.
    2.  push линк на список хэндлеров сех.
    3.  Call _SEH_prolog
     
  18. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    > Стандартный пролог есть в болшинстве "тяжёлых" процедур, кстати
    ну да, но не в хедлерах :)
    Код (Text):
    1. .text:77EC661E                 mov     eax, [ebp-14h]
    2. .text:77EC6621                 mov     ecx, [eax]
    3. .text:77EC6623                 mov     ecx, [ecx]
    4. .text:77EC6625                 mov     [ebp-30h], ecx
    5. .text:77EC6628                 push    offset aLdrpsnapiat ; "LdrpSnapIAT"
    6. .text:77EC662D                 push    eax
    7. .text:77EC662E                 call    _LdrpGenericExceptionFilter@8 ; LdrpGenericExceptionFilter(x,x)
    8. .text:77EC6633                 retn
    > как определить начала хендлера
    ищем ближайший фиксап.
     
  19. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Семпл, ищет LdrpResolveDllName(глубоко в загрузчике находится) - создаёт граф для LdrLoadDll(), ищет в нём линк на имя, затем ищет начало функции. Код не оптимизирован по размеру буфера(следует использовать расширяемые буфера) и скорости исполнения(следует использовать усечение графа посредством задания уровня вложенности(NestingLevel)), но в данном случае это не важно. Фиксапы не используем.
    http://files.virustech.org/indy/Code/GCBE/NL/