Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.142.156.255] |
|
Сообщ.
#1
,
|
|
|
Доброго времени суток. Необходимо определить параметры функции в .dll.
Можно ли как нибудь поставить breakpoint в dll например с помощью IDA и определить значения передающихся аргументов ??? Как это сделать? |
Сообщ.
#2
,
|
|
|
НУ если именно значения - то разве что потрассировать и по мере обращения к аргументам фиксировать, что берётся и каким типом интерпретируется...
|
Сообщ.
#3
,
|
|
|
Как выполнить эту самую трассировку? Есть .exe есть .dll
пихаю .exe в IDA , как мне теперь найти функции этой .dll ? Если закидываю .dll их видно, короче ничего не понятно. Вот аргументы функции в интерпретации IDA: .text:00401538 var_28 = dword ptr -28h .text:00401538 var_18 = word ptr -18h .text:00401538 var_4 = dword ptr -4 .text:00401538 arg_0 = dword ptr 8 Добавлено Такс, зашёл по бреку в функцию. Как теперь посмотреть значения переменных приведённых выше, или они начнут появляться после popов ??? Добавлено Как теперь значения стека связать с переменными идущими сразу же после названия процедуры (функции) ??? .text:00401538 var_28 = dword ptr -28h .text:00401538 var_18 = word ptr -18h .text:00401538 var_4 = dword ptr -4 .text:00401538 arg_0 = dword ptr 8 Добавлено Вот взял снимок стека: Stack[00001250]:0018E3A8 db 0E8h ; ш Stack[00001250]:0018E3A9 db 0E3h ; у Stack[00001250]:0018E3AA db 18h Stack[00001250]:0018E3AB db 0 Stack[00001250]:0018E3AC db 90h ; Р Stack[00001250]:0018E3AD db 0E7h ; ч Stack[00001250]:0018E3AE db 0AAh ; к Stack[00001250]:0018E3AF db 6 Stack[00001250]:0018E3B0 db 0C0h ; L Stack[00001250]:0018E3B1 db 21h ; ! Stack[00001250]:0018E3B2 db 9Ah ; Ъ Stack[00001250]:0018E3B3 db 4 Stack[00001250]:0018E3B4 db 74h ; t Stack[00001250]:0018E3B5 db 0E7h ; ч Stack[00001250]:0018E3B6 db 18h Stack[00001250]:0018E3B7 db 0 Получается, как я понял стек растёт в сторону уменьшения адреса. Данные пихаются старшими байтами вперёд, т.к. Stack[00001250]:0018E3A8 db 0E8h ; ш Stack[00001250]:0018E3A9 db 0E3h ; у Stack[00001250]:0018E3AA db 18h Stack[00001250]:0018E3AB db 0 <- 0 с большой вероятность что старший байт Какое тогда получается соглашение вызова ??? Или что то я наврал здесь. Добавлено Попробовал перезагрузить процесс, значения аргументов не поменялись, значит это не адреса (не указатели). Почему в стек пихается старшими байтами вперёд? |
Сообщ.
#4
,
|
|
|
Ааа, ну всё правильно, это stdcall, главное чтобы я правильно интерпретировал стек (растёт к 0x00000000 адресу).
Правда всё равно ничего не понятно)))) |
Сообщ.
#5
,
|
|
|
Цитата Abraziv @ Вот аргументы функции в интерпретации IDA: В интерпретации IDA аргумент всего один - arg_0 по смещению +8, а var_X по отрицательным смещениям - это локальные переменные функции. Цитата Abraziv @ Как теперь значения стека связать с переменными идущими сразу же после названия процедуры (функции) ??? Если функция имеет стандартный пролог типа (push EBP, mov EBP,ESP), то адреса аргументов и локальных переменных задаются смещениями относительно значения в регистре EBP, т.е. адрес arg_0 будет = EBP+8 Цитата Abraziv @ как я понял стек растёт в сторону уменьшения адреса Да Цитата Abraziv @ Почему в стек пихается старшими байтами вперёд? Не "вперед", а как обычно для x86 - старшими байтами по старшим адресам (см. little endian) Цитата Abraziv @ Какое тогда получается соглашение вызова ??? Если функция имеет стандартный эпилог, то при соглашении stdcall возврат из функции осуществляется командой ret(n) X, где X - число, равное суммарному размеру всех аргументов функции (с учетом их выравнивания на 4 для x32). Если возврат осуществляется командой ret(n) без аргумента, то это либо cdecl, либо stdcall без аргументов. Цитата Abraziv @ Попробовал перезагрузить процесс, значения аргументов не поменялись, значит это не адреса (не указатели) Это ни о чем не говорит, т.к. с одной стороны это м.б. указатель на глобальную переменную, адрес которой не изменяется от запуска к запуску, а с другой стороны некоторые значения (не указатели) также могут изменяться при перезапуске (например, всевозможные дескрипторы типа виндовых HWND и т.п.) PS: Ты уверен, что исследуемая dll является приватной\"самопальной" для данного приложения, а не какой-нибудь общеизвестной, для которой можно найти описания функций в интернете? |
Сообщ.
#6
,
|
|
|
leo спасибо за расширенный ответ и ссылку. Разобрался со всем, всё работает.
Цитата leo @ PS: Ты уверен, что исследуемая dll является приватной\"самопальной" для данного приложения, а не какой-нибудь общеизвестной, для которой можно найти описания функций в интернете? Да уверен, .dll самопальные, писал другой человек. Единственное, у меня получилось их использовать только через Loadlibrary(). Пытался использовать libу, но вижуал требует чтобы ссылки были вида func@4 для одного аргумента (к примеру int) и func@0 для void. Как я понял это COFF формат. В целевой dll же они просто хранятся в виде func. Как я понял это билдеровский формат OMF. Иными словами если в .def описать без @, то линкер будет ругаться, если же с @ то во время запуска напишет что не может найти func@ в .dll Как побороть проблему так и не понял. |
Сообщ.
#7
,
|
|
|
Цитата Abraziv @ COFF и OMF - это форматы объектных модулей, к DLL они не имеют отношения.Как я понял это COFF формат. В целевой dll же они просто хранятся в виде func. Как я понял это билдеровский формат OMF. А чем LoadLibrary не устраивает, собственно? |
Сообщ.
#8
,
|
|
|
Хочу разобраться, для опыта.
|
Сообщ.
#9
,
|
|
|
Эмм. Кстати вы не правы. Coff и OMF это не только формат объектных библиотек, это ещё формат библиотек импорта для .dll.
|
Сообщ.
#10
,
|
|
|
Цитата Abraziv @ В чём тут неправда? Кстати вы не правы. Coff и OMF это не только формат объектных библиотек, это ещё формат библиотек импорта для .dll. Библиотеки импорта генерируются на основе DLL, но не являются частью DLL. Аналогия: я могу записать звук и сохранить его в WAV, MP3, OGG, Opus или ещё в какой-то формате. Но сам формат MP3 не имеет отношения к инструменту, который воспроизвёл этот звук . Или формат ZIP не имеет отношения к EXE-файлу, который лежит в этом архиве. Из obj'ей, кстати, тоже делают библиотеки, так что библиотеки - это нечто вроде "архива" obj'ей в том числе. |
Сообщ.
#11
,
|
|
|
Это я конечно же понимаю. Как проблему то решить? Теория теорией, а на практике .dllки билдера и Майкрософт отличаются.
|
Сообщ.
#12
,
|
|
|
Цитата Abraziv @ если же с @ то во время запуска напишет что не может найти func@ в .dll Как побороть проблему так и не понял Задать импорт функции по ординалу в виде: func@4 @X где X - ординал функции func, который можно узнать утилитой dumpbin /EXPORTS PS: Формат def-файла допускает задание алиаса имени функции в виде func@4=func, но, говорят, что lib такую конструкцию игнорирует. Поэтому приходится использовать ординал. |
Сообщ.
#13
,
|
|
|
Спасибо, попробую.
|
Сообщ.
#14
,
|
|
|
leo спасибо огромное, сделал через ординалы, всё отлично работает.
Вы настоящий спец. |
Сообщ.
#15
,
|
|
|
А вот ещё вопрос:
Почему если в .h объявить прототип вида: extern "C" void func(int); то линкер будет всё равно искать декорированное имя _func, несмотря на то, что в C не используется декорирование. А если же extern "C" void __stdcall func(int); то ищет func. Правда при это в .lib они определены как func@4 |