Возможен-ли полный дамп функций из DLL?
Например выдрать из php5ts.dll только 5 нужных функций и ничего лишнего, для создания удобной компактной DLL для портабельности скриптов? Всё-таки php5ts весит почти 5 мб.
Мне нужно знать, насколько это сложно и что мне для этого понадобится. Или... может существуют уже готовые дамперы функций?
да всё возможно! (если захотеть..... :) )
1. загрузить DLL в свой процесс
2. Найти адрес нужной функции через GetProcAddress
3. Определить её размер (вот в этом то и основная проблема),
4. Записать в файл эту область памяти
предлагаю определять длину функции через поиск команды ret, или retn. но не факт, что будет работать, ведь может быть такой код функции
jz .next
ret
.next
mov ....
ret
Ещё одна проблема: функции могут использовать глобальные данные из искомой DLL, вот с ними как быть?
Я тоже именно так и думал. Каждую процедуру и её ответвления нужно будет загрузить в отдельный файл, а уж потом можно какой-нибудь анализатор использовать, ту же иду например.
Данные и другие куски кода можно искать с помощью адресов после опкодов push, call, mov, lea (jmp и её вариации я вроде не видел, что за пределы одной функций делается) и подобному, у них есть статичные опкоды (разные для считывания напрямую или указателю), по которым и можно сверять.
ret последние в функциях php5ts находятся перед скопом nop'ов (не менее 5). Только как проверить? Если я пытаюсь оборвать скрипт на "if(chr1==0x90) break;", то читается вообще не переставая. Не опознаёт он нопы и всё-тут...
Правильно ли я считываю байт из памяти? Или есть полегче что-то?
__asm{
pushad
mov esi, c
lodsb
mov chr1, al // <- char chr1;
popad
}
debug << chr1; // <- ofstream debug("debug.txt", ios::binary);
}
ret последние в функциях php5ts находятся перед скопом nop'ов (не менее 5). Только как проверить?
в общем такой алгоритм: если находим последовательность
либо вот такую последовательность
(С2h xxh xxh это опкод retn)
то мы точно в конце функции. Также может быть случай что вместо 90h будут нули.
Если первое - дизассемблер тебе в руки и делаешь это вручную. Может быть получится.
Если второе - то ещё раз повторю: сделать это в общем случае ОЧЕНЬ СЛОЖНО даже руками, а уж тем более автоматически.
Ребята, вы пользовались дизассемблерами? Занимались реверс-инженерингом? По-моему нет. Попробуйте сделать задачу, которую вы хотите реализовать автоматически, ручками на реальном примере и посмотрите на сколько это будет нетривиально.
Я тоже именно так и думал. Каждую процедуру и её ответвления нужно будет загрузить в отдельный файл, а уж потом можно какой-нибудь анализатор использовать, ту же иду например.
Зачем?
Данные и другие куски кода можно искать с помощью адресов после опкодов push, call, mov, lea (jmp и её вариации я вроде не видел, что за пределы одной функций делается) и подобному, у них есть статичные опкоды (разные для считывания напрямую или указателю), по которым и можно сверять.
Для начала, чтоб найти эти инструкции, тебе надо полностью дизассемблировать весь файл и проанализировать его. Допустим, что файл дизассемблировался, что тоже не всегда просто.
Как ты собираешься обрабатывать такие вещи:
call eax
call dword ptr [eax]
call dword ptr ds:[7C801254h]
jmp eax
jmp [eax]
JMP "за пределы одной функции"? Легко.
Далеко ходить не буду, открываю kernel32 в IDA, например функция CreateFileMappingW:
.text:7C8093CE jz loc_7C80B957 ; - jmp за "пределы функции"
.text:7C8093D4 mov eax, _gpTermsrvFormatObjectName ; - обращение к ранее инициализированному указателю
.text:7C8093D9 test eax, eax
.text:7C8093DB jnz loc_7C83CDDC ; - jmp за "пределы функции"
Отсюда вопрос, как собираетесь обрабатывать статические данные?
В данном случа это указатель, который инициализируется совсем в другой функции.
В другом случае это может быть не указатель, а структура, как будете вычислять её размер?
либо вот такую последовательность
(С2h xxh xxh это опкод retn)
то мы точно в конце функции. Также может быть случай что вместо 90h будут нули.
Кто тебе сказал, что у функции может быть только один ret?
Кто тебе сказал, что функция расположена линейно?
Рекомендую попользоваться IDA и посмотреть, как она анализирует код:
.text:7C80952A
.text:7C80952A ; --------------- S U B R O U T I N E ---------------------------------------
.text:7C80952A
.text:7C80952A ; Attributes: bp-based frame
.text:7C80952A
.text:7C80952A ; DWORD __stdcall WaitForMultipleObjectsEx(DWORD nCount,const HANDLE *lpHandles,BOOL bWaitAll,DWORD dwMilliseconds,BOOL bAlertable)
.text:7C80952A public _WaitForMultipleObjectsEx@20
.text:7C80952A _WaitForMultipleObjectsEx@20 proc near ; CODE XREF: WaitForMultipleObjects(x,x,x,x)+13p
.text:7C80952A
.text:7C80952A var_74 = dword ptr -74h
<skip>
.text:7C80952A ; FUNCTION CHUNK AT .text:7C8094B6 SIZE 0000005F BYTES
.text:7C80952A ; FUNCTION CHUNK AT .text:7C8095E4 SIZE 00000010 BYTES
.text:7C80952A ; FUNCTION CHUNK AT .text:7C83085B SIZE 0000004D BYTES
.text:7C80952A ; FUNCTION CHUNK AT .text:7C843BFF SIZE 00000065 BYTES
.text:7C80952A
<skip>
.text:7C8095D0 jmp short loc_7C80958B
.text:7C8095D0 _WaitForMultipleObjectsEx@20 endp
.text:7C8095D0
.text:7C8095D0 ; ---------------------------------------------------------------------------
.text:7C8095D2 align 8
.text:7C8095D8 dword_7C8095D8 dd 0FFFFFFFFh, 0 ; DATA XREF: WaitForMultipleObjectsEx(x,x,x,x,x)+2o
.text:7C8095E0 dd offset sub_7C80951A
.text:7C8095E4 ; ---------------------------------------------------------------------------
.text:7C8095E4 ; START OF FUNCTION CHUNK FOR _WaitForMultipleObjectsEx@20
.text:7C8095E4
.text:7C8095E4 loc_7C8095E4: ; CODE XREF: WaitForMultipleObjectsEx(x,x,x,x,x)-3Aj
.text:7C8095E4 cmp eax, 101h
.text:7C8095E9 jnz loc_7C8094F6
.text:7C8095EF jmp loc_7C8094C5
.text:7C8095EF ; END OF FUNCTION CHUNK FOR _WaitForMultipleObjectsEx@20
.text:7C8095EF ; ---------------------------------------------------------------------------
.text:7C8095F4 dd 90909090h
FUNCTION CHUNK - сообщает нам, что функция разбита на 4 куска кода.
Как видите никаким ret-ом блок кода не заканчивается.
NOP - тоже опциональны. Они служат для выравнивания, если же блок кода (CHUNK) закончится как раз на границе выравнивания, то NOP-ов не будет.
И это все ещё цветочки, т.к. есть еще TLS. Как собираетесь бороться с ним?
Конкретно с php не работал, но я так полагаю что исходники для него имеются и перекомпилировать с нужными функциями труда не составит.
А если вы собираетесь сделать подобного рода инструмент, то бросьте эту затею.
P.S. хотя подобный инструмент мне бы понравился.
Хотел именно php5ts разбивать причем автоматически, для попытки сделать php-компилер. (ведь BamCompiler в себе носит полную DLL, причем 4-й версии, и его автор возможно с радостью примет дампер, если нет, то хочется попробовать самому тогда написать компилер)
В том то и дело, опыта пока у меня маловато, но ведь я бы и не постил вопрос тогда, не так-ли?
call eax
call dword ptr [eax]
call dword ptr ds:[7C801254h]
jmp eax
jmp [eax]
статические данные?
В данном случа это указатель, который инициализируется совсем в другой функции.
В другом случае это может быть не указатель, а структура, как будете вычислять её размер?
И это все ещё цветочки, т.к. есть еще TLS. Как собираетесь бороться с ним?
Всё, убедили. Гиблое это дело, как я понял.
Скачать можно http://www10.egoshare.com/files/f373e4dfdaef2cc8b0b8dc884ce42187/52.rar?good=yes
Пароль к архиву: ruboard
P.S. так что все возможно стоит только этого захотеть.
Скачать можно http://www10.egoshare.com/files/f373e4dfdaef2cc8b0b8dc884ce42187/52.rar?good=yes
Пароль к архиву: ruboard
P.S. так что все возможно стоит только этого захотеть.
koval, ты сам статью прочел? От начала до конца? :)
Какое отношение она имеет к теме топика?
Тема топика содержала вопрос об автоматическом инструменте по выдергиванию функции из DLL.
Приведенная статья же описывает инструмент упрощающий реверс-инженеринг.
Я не вижу связи.
С помощью реверс-инженеринга можно понять как работает та или иная функция из DLL и на основе этой инф. создать новую DLL. Но это процесс ручной и творческий, и HexRays здесь лишь для упрощения (если поможет).
Если говорить о самом HexRays, то распознавать библиотечные куски в коде ЗНАААЧИтельно проще, чем то, что надо для выкусывания функции из DLL. Проще на столько, на сколько проще поиск слов со всеми словоформами в тексте от понимания смысла этого текста.
Что касается статьи не касательно контекста темы топика:
1) очень "научно-популярно",
2) слишком рекламно,
3) не смотря на п.2, сделаны выводы:
HexRays – это, безусловно, большой шаг вперед и неплохое подспорье для начинающих, но… он не стоит тех денег, которые за него просят, к тому же (это касается начинающих), однажды потратив время на изучение ассемблера, мы обретаем возможность реверсировать что угодно и в чем угодно (на худой конец с помощью утилиты DUMPBIN.EXE, входящей в состав SDK)
Но понту-то с того - названия есть, а вот кол-во и тип параметров, а также возвращаемый тип - неизвестен. Но, помнится, методом подбора для какой-то ф-ции таки угадал и заюзал ее.
Но понту-то с того - названия есть, а вот кол-во и тип параметров, а также возвращаемый тип - неизвестен. Но, помнится, методом подбора для какой-то ф-ции таки угадал и заюзал ее.
Что в твоем понимании "дампит"?
Выдает список экспорта? Это можно сделать за 5 минут, но ни какого отношения к обсуждаемой теме не имеет.
Выдает список экспорта? Это можно сделать за 5 минут, но ни какого отношения к обсуждаемой теме не имеет.
Да, это и имел ввиду. Поскольку, к сожалению, не знаю особенностей постоение РЕ-шника, то может и сморозил глупость. Но это таки имеет отношение к теме, так как цель автора - получить список ф-ций из ДЛЛки. Вопрос "как" - это уже относится к методам решения :)
На сколько я понял, цель автора - "выдрать из php5ts.dll только 5 нужных функций и ничего лишнего, для создания удобной компактной DLL".
Т.е. ему нужны не имена этих функций, а их тела.