Здравствуйте, в общем ситуация такая: есть программа, для работы с аппаратурой, имеющая в своем составе драйвер и длл, и есть некая тестовая программа использующая эту длл. Длл чем-то упакована (PeID пишет что ASPack 2.12, но 3 скачанных мной распаковщика для аспака сказали что тип "аспак не найден, ничего я делать не буду") В лоб IDA ее не открывает, точнее открывает, но там что-то не то, в секции .data расположен код, что указывает на наличие запаковщика. Необходимо достать алгоритм 1й из функций экспортируемых длл. Тестовая программа эту функцию использует. Так как необходимая функция работает с аппаратурой, то она должна общаться с драйвером. При анализе драйвера в нем регистрируется 4 обработчика на создание, закрытие, выгрузку драйвера и обработчик IOCTL-кодов. Код (Text): mov dword ptr [esi+34h], offset UnloadDriver mov dword ptr [esi+70h], offset IOCTLDispatcher mov dword ptr [esi+38h], offset Create mov dword ptr [esi+40h], offset Close Я ставил Syser'ом точку останова на обработчик IOCTL (остальные обработчики точно не реализуют нужный функционал), но при вызове интересующей функции он не останавливался(. Поэтому возник вариант используя приложение спуститься в библиотеку и посмотреть как там это сделано, но я не понял как это сделать, так как опыта подобного рода у меня очень мало. Приложение написано на C# и в нем есть отдельная кнопка вызывающая интересующую функцию, и я не понял как остановиться на этом нажатии и спуститься в глубь библиотеки. Думал syser'ом поставить точку останова на обработчик кнопки, я нашел этот обработчик в IDA, но не понял какой адрес он имеет и как его узнать. Подскажите, что мне делать в этой ситуации и как добраться до необходимой функции? Если нужны программа/драйвер/библиотека я могу их скинуть.
drem1lin Если функция экспортируется из DLL, то что мешает приаттачиться отладчиком и поставить бряк на ее начало? Или она загружается динамически при нажатии на эту отдельную кнопку? Тогда, соответсвенно, бряк на LoadLibraryExW и после загрузки DLL опять же бряк на функцию.
можно найти его в отладчике по сигнатуре - берёшь характерную последовательность байт из кода обработчика и ищешь её поиском.
Что-то я об этом забыл, надо будет попробовать, просто IDA странно отображает ассемблерный код для этого файла. да и в его уникальности я не уверен
Ида вам отображает MSIL. При загрузке нужно выбрать PE. Да и толку ковыряться в этом коде нет. У библиотеки есть экспорт? Не припомню пакеров, сносящих таблицу экспорта. Откройте библиотеку в Иде и нажмите ctrl-E. Там должна быть интересющая вас функция. Вычислить ее адрес в уже загруженной длл - не должно представлять проблему.
Точку останова можно поставить на саму ф-ию DeviceIoControl в kernel32.dll, а не в импорте. А при вызове посмотреть и запомнить адрес возврата, если уж очень интересно. Кроме того, для C# есть декомпилятор -- reflector.
Я ставил, на него точку останова, но утонул в вызовах, а какой фильтр написать не знаю. Да и драйвер мне сейчас менее интересен чем библиотека
Думаю, можно попробовать сделать так: 1. Поставить точку останова на CreateFile с целью поймать открытие файла. После этого можно ставить условную точку останова на DeviceIoControl с условием, что [esp + 4] == HANDLE_VALUE. 2. Более быстрый, но ресурсоемкий вариант: склонировать две VM с чистой XP (как, у вас нет шаблонной VM с чистой XP?! ), затем на одну поставить целевую программу и тщательно сверить результаты работы WinObj (или еще как перебрать объекты, не знаю). Тогда получится вычислить имя устройства (символическую ссылку) и поставить условную точку останова на CreateFile. Получить значение HANDLE и действовать по пункту 1. Я бы сделал так, но может кто-нибудь предложит более короткий путь?
У меня есть символическая ссылка, я дизассемблировал драйвер и нашел. Это тоже я попробую и в пятницу отпишусь
Судя из кода дизассемблированного драйвера и документации IoCreateSymbolicLink: Код (Text): RtlInitUnicodeString(&SymbolicLinkName, L"\\??\\DDCHELPER"); RtlInitUnicodeString(&DestinationString, L"\\Device\\WinI2C"); v6 = IoCreateSymbolicLink(&SymbolicLinkName, &DestinationString); то символьная ссылка это "\\??\\DDCHELPER", вспоминая соглашение о занесении параметров, я в Syser поставил следующий брейк поинт: bpx createfilea(w) if *(esp+4)=="\\??". Но отладчик не всплыл ни разу(. Может я что-то не так делаю?
Я открыл библиотеку в ИДЕ, в таблице экспорта указан адрес 10003670, а как вычислить ее адрес в загруженной длл, для меня это преставляет проблему, я это 1й раз делаю(. Я пытаюсь что-нибудь нагуглить по данному вопросу, но пока не получается
drem1lin Почитайте про RVA и VA. 0x10003670 - это VA. Чтобы получить RVA надо сделать VA - ImageBase. Далее смотрим по какому адресу будет загружена эта длл и прибавляем к нему RVA. Базовые вещи конечно нужно почитать. Пе-файлы, адресация и т.п.
Продолжая свою тему, я добился некоторого успеха, а точнее я смог достать код необходимой мне функции. Это дизассемблированный листинг из IDA. Код (Text): seg000:100038B0 public function seg000:100038B0 function proc near seg000:100038B0 seg000:100038B0 arg_0 = dword ptr 4 seg000:100038B0 seg000:100038B0 push 1198238h ;function name seg000:100038B5 call WriteLogToFile seg000:100038BA mov eax, [esp+4+arg_0] seg000:100038BE add esp, 4 seg000:100038C1 cmp eax, ds:11A0234h seg000:100038C7 jnb short loc_100038D4 seg000:100038C9 mov eax, ds:119FBE0h[eax*4] seg000:100038D0 test eax, eax seg000:100038D2 jnz short loc_100038DC seg000:100038D4 seg000:100038D4 loc_100038D4: ; CODE XREF: function+17j seg000:100038D4 mov eax, 70000018h seg000:100038D9 retn 4 seg000:100038DC ; --------------------------------------------------------------------------- seg000:100038DC seg000:100038DC loc_100038DC: ; CODE XREF: function+22j seg000:100038DC cmp dword ptr [eax+128h], 0 seg000:100038E3 jnz short loc_100038FA seg000:100038E5 push 119820Ch ;error seg000:100038EA call WriteLogToFile seg000:100038EF add esp, 4 seg000:100038F2 mov eax, 70000021h seg000:100038F7 retn 4 seg000:100038FA ; --------------------------------------------------------------------------- seg000:100038FA seg000:100038FA loc_100038FA: ; CODE XREF: function+33j seg000:100038FA push esi seg000:100038FB mov esi, [eax] seg000:100038FD cmp esi, 200h seg000:10003903 jnb short loc_1000391B seg000:10003905 push 11981E8h ;error seg000:1000390A call WriteLogToFile seg000:1000390F add esp, 4 seg000:10003912 mov eax, 7000001Ch seg000:10003917 pop esi seg000:10003918 retn 4 seg000:1000391B ; --------------------------------------------------------------------------- seg000:1000391B seg000:1000391B loc_1000391B: ; CODE XREF: function+53j seg000:1000391B cmp dword ptr [esi], 0 seg000:1000391E jz short loc_10003936 seg000:10003920 push 1198078h ;error seg000:10003925 call WriteLogToFile seg000:1000392A add esp, 4 seg000:1000392D mov eax, 7000001Fh seg000:10003932 pop esi seg000:10003933 retn 4 seg000:10003936 ; --------------------------------------------------------------------------- seg000:10003936 seg000:10003936 loc_10003936: ; CODE XREF: function+6Ej seg000:10003936 mov eax, [esi+44h] seg000:10003939 push edi seg000:1000393A push eax seg000:1000393B call dword ptr ds:1197044h ; RtlEnterCriticalSession seg000:10003941 mov ecx, [esi+40h] seg000:10003944 push esi seg000:10003945 call ecx seg000:10003947 mov edx, [esi+44h] seg000:1000394A add esp, 4 seg000:1000394D push edx seg000:1000394E mov edi, eax seg000:10003950 call dword ptr ds:1197040h ; RtlLeaveCriticalSession seg000:10003956 push edi seg000:10003957 push 11981D4h ; all is ok %x seg000:1000395C call WriteLogToFile seg000:10003961 add esp, 8 seg000:10003964 mov eax, edi seg000:10003966 pop edi seg000:10003967 pop esi seg000:10003968 retn 4 seg000:10003968 function endp Как видно из кода, функция 4 раза проверяет введенные параметры и является оболочкой над функцией, которая вызывается по адресу 10003945. Я смог достать этот код сдампив библиотеку, но теперь я не могу понять куда следует вызов call ecx. Отладчиком я выпадаю на этих проверках и даже если Syserом изменяю регистр флагов что бы проити через них, то получаю exсeption (в строке 38dc обращение с адресу 128h, так как eax == 0). И соответственно возникает вопрос как узнать значение ecx? Я пока придумал только 1 способ - как нибудь поставиьт брейкпоинт нафункцию RtlEnterCriticalSection с каким-нибудь фильтром. Есть ли еще другие варианты?