Переписать функцию в dll

Тема в разделе "WASM.RESEARCH", создана пользователем snpik, 12 май 2006.

  1. snpik

    snpik New Member

    Публикаций:
    0
    Регистрация:
    12 май 2006
    Сообщения:
    10
    Адрес:
    Ukraine
    Добрый день, воины дзена!



    Я особо никогда не занимался работй по профилю этого форума,

    но жинь заставляет. Я прошу прощения, что не разместил свой

    первый "профильный" вопрос в тему для новичков, т.к. я

    надеюсь, что он достоин этого раздела (если мне "старшие

    товарищи" скажут, чо это не так - я извинюсь).



    Я хочу поправить dll.

    Хочу заменить функцию недающую нормально работать приложению

    на "хорошую" функцию. Вообще-то "плохих" функций несколько,

    но всех их я могу просто "обойти" или меняя j** на jmp

    сделать их "плохую" роботу бессмысленной. Эта же функция -

    делает кроме "плохой" работы много полезного. И я ее должен

    не править, а пактически написать заново.

    т.к. моя функция оказалась больше оригинальной я решил

    использовать для размещения "правильной" функции тело большой

    "плохой" уже никогда неиспользуемой функции.



    1.Я за-nop-ил (чтобы освободить место для "правильной") из нее

    все кроме:



    push ebp

    mov ebp, esp

    push ebp

    add esp, 0FFFFFFF8 , выделяющие локальную память в начале



    и:



    mov al, 1

    mov esp, ebp

    pop ebp

    retn,строк выравнивающих память и возврат 1 из функции в конце.



    2.Передал управление на эту пустую "болванку"... и был очень

    неприятно удивлен. Я зпускал и выключал форму и получал

    случайным образом то ошибку

    - 'Privileged instruction';

    то ошибку

    - 'Acsess violation at address XXXXXXXX in odule 'my.dll'

    причем XXXXXXXX - адрес внутри "болванки";

    - пару раз вызов "болванки" прошел нормально (как я ожидал).



    3. В конце концов я идентифицировал "проблемные" инструкции которые

    "нельзя" удалять. Вот примеры:



    .text:0040BB4A 8B058B104B00 mov eax, _dword_4B108B_Const_000000AF

    или

    .text:0040BBB8 FF15E4774B00 call _dword_4B77E4_OtherDLLFuncNamePoint

    или

    .text:0040BB5C 833D80104B00FF cmp _dword_4B1080_Handler, 0FFFFFFFFh



    (причем последняя легко патчиться, например, на

    .text:0040BB5C 8B0580104B00 mov eax, _dword_4B1080_Handler [а эта

    инструкция нужна мне в "хорошей" функции].

    т.е главное чтобы адресс 4B1080 - оставался на том-же месте).



    Всех их объединяет одно - они обращаються "очень далеко" от исполняемого кода.

    Если я оставляю эти инструции - все OK (В том смысле, что ошибок нет).



    4.Попытки вызвать инструкцию

    .text:0040BB5C 8B0580104B00 mov eax, _dword_4B1080_Handler

    [для "хорошей" функции] в удбном для меня месте приводит к ошибке:

    'Acsess violation at address XXXXXXXX in odule 'my.dll'. Read 4B1080'.

    причем XXXXXXXX - удобный для меня адрес по которому размещен вызов;



    5. Я понял, что в моем понимании фразы "пропатчить функцию" есть

    серъезные пробелы и я решил написать на WASM.RU. Собственно вопрос:



    Что я должен понять, чтобы вычистить свою "болванку" от "проблемных"

    инструкций и затем использовать их же в свом патче?



    Если вопрос ламерский - прошу сделать снисхождение, т.к. за свое

    невежество я уже наказан потерей времени - 2 дня посто "полягло".

    Кажеться вот оно решение вот..вот и затягивает - невозможно

    оторваться - хуже футбола.
     
  2. asd

    asd New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2005
    Сообщения:
    952
    Адрес:
    Russia


    Т.е. при передачи управления на
    Код (Text):
    1. push ebp
    2. mov ebp, esp
    3. push ebp
    4. add esp, 0FFFFFFF8
    5. nop
    6. nop
    7. mov al, 1
    8. mov esp, ebp
    9. pop ebp
    10. retn


    вылетает Acsess violation? Быть такого не должно здесь обращений к памяти нет, кроме как к стеку. Наверное нопы не туда вставляются. под отладчиком смотрел?



    Что-то моло чего понял дальше.

    Если переписывать участок кода на новое место, то переписываемый код должен быть базонезависимым. Он базонезависим?
     
  3. snpik

    snpik New Member

    Публикаций:
    0
    Регистрация:
    12 май 2006
    Сообщения:
    10
    Адрес:
    Ukraine
    Код не есть базонезависимым,

    но полтора десятка смещений в коде (функция небольшая - до 300 байт) я откорректировал. Но результат - как с пустой болванкой (в смысле те же проблемы)



    push ebp

    mov ebp, esp

    push ebp

    add esp, 0FFFFFFF8

    nop

    nop

    mov al, 1

    mov esp, ebp

    pop ebp

    retn

    В том то и дело что именно так!!!

    Причем j** на jmp меняй не хочу, а эти участки с

    text:0040BB4A 8B058B104B00 mov eax, _dword_4B108B_Const_000000AF

    как заколдованные - тронишь или переместишь на байт - Acsess violation.



    Причем сам код

    text:0040BB4A 8B058B104B00 mov eax, _dword_4B108B_Const_000000AF

    абсолютно базо-независимый
     
  4. asd

    asd New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2005
    Сообщения:
    952
    Адрес:
    Russia
    А отладчик что показавфет?
     
  5. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine




    Надо ещё релоки править (Чем можно отредактировать релоки в DLL?) или попробуй свой exe'шник перелинковать на другой imagebase (0x00600000 к примеру)
     
  6. Quantum

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

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    snpik

    Эти инструкции как раз базозависимые! Поэтому их частично перезаписывают релоки. "Проблемные" инструкции лучше всего "обходить", вставляя короткий безусловный jmp перед ними, который ведёт на следующий после проблемной инттрукции адрес:
    Код (Text):
    1. jmp after_bad_instruction
    2. some_bad_instruction
    3. after_bad_instruction:


    ЗЫ: bogrus быстрее печатает :)
     
  7. crypto

    crypto Active Member

    Публикаций:
    0
    Регистрация:
    13 дек 2005
    Сообщения:
    2.533
    snpik

    Передал управление на эту пустую "болванку"... и был очень



    В тело твоей пустой болванки попали релоки...
     
  8. snpik

    snpik New Member

    Публикаций:
    0
    Регистрация:
    12 май 2006
    Сообщения:
    10
    Адрес:
    Ukraine
    Большое спасибо asd, bogrus, Quantum и crypto за участие!!!

    Понятно.Ключевое слово "релоки".

    1. Делаю поиск и нахожу следующие:

    ---------------------------------------------------------------------- -------

    Базовая поправка - это настройка по отношению к инструкции или значению

    инициализированной переменной; ЕХЕ-файлы или DLL нуждаются в такой поправке,

    если загрузчик не может загрузить файл по адресу, который предполагался компоновщиком.

    Если загрузчику удается загрузить отображение по указанному компоновщиком базовому адресу,

    загрузчик игнорирует поправочную информацию в этой секции.

    Если вам хочется попытать счастья и вы надеетесь, что загрузчик всегда сможет загрузить

    отображение по указанному компоновщиком базовому адресу, используйте ключ /FIXED.



    (На этом месте я вспоминаю, что при некоторых запусках у меня проблем небыло)



    Поправки обычно требуются только для инструкций, использующих 32-разрядные

    смещения для данных.

    (На этом месте я вспоминаю, что мои "проблемные" инструкции имеют такую же структуру.)

    ---------------------------------------------------------------------- -------

    Симптомы моей dll получают объяснение в свете прочитанного.

    2. Запускаю PETools.exe и скармливаю свою dll

    RelocRebuilder.dll - плагину PETools.exe

    dll увеличелась на килобайт 20.



    (Поруччик Кржевский, как Вам удается так легко сближаться с женщинами?

    - спрашивает молодой корнет.

    Знаете ли, корнет, я подхожу к даме и спрашиваю: "Мадам, можно Вас запердолить?"

    - Фу, поруччик, так можно же по морде...

    - Можно по морде, а можно и запердолить...)



    Получаем по морде - dll не запускаеться.



    3. Запускаю PETools.exe снова и через меню Tools -> PE Editor

    гружу свою dll, жму "Sections" и вижу секцию .reloc с кучей адресов.

    Смотрю в HEX - редакторе все адреса в файле в надежде найти что нибудь

    осмысленное и вроде бы нахожу. Raw offset - это адрес в файле dll.

    Секция .reloc занимает весь огромный хвост dll.

    В этом я убеждаюсь окончательно когда жму

    PETools.exe "Directories" -> "Base Relocation Table".

    По адресу .reloc -> Raw offset из "Sections" я вижу

    RVA (4 bytes) и Size of Block (4 bytes) .

    В секции Items, как я понял, находиться количество элементов в блоке.

    Размер блока (в Word) за вычетом 4 word на описание RVA и Size of Block

    совпадает с Items. То есть 1 Item описываеться двумя байтами.

    Но что это за такие Items???

    4. Позицианирую курсор на одном из блоков в "Directories" -> "Base Relocation Table".

    В окне Block Items появляються эти самые Items.

    Каждая Items имеет порядковый номер, два адреса (RVA и offset), отличающихся на

    одно число и параметр Type, который у меня один и тотже (помоему это вторй байт

    описывающий Item и равный везде $30).

    Открываю Ida беру RVA добавляя к нему $400 000 и вижу исполняемый код.

    Получившийся адрес указывает на средину инструкции.

    Беру другой RVA (другой Item), опять добавляю $400 000 и я опять в средине инструкции.

    По инерции делаю тоже еще пару раз. Результат тот-же:

    Я в средине инструкции. Е ма е - так это же как раз те "проблемные" инструкции,

    и только они. А внутри их я именно в том месте, где в инструкции

    начинаеться четырехбайтное смещение, которое я еще вчера считал абсолютным.

    Понятно теперь, что это за Items!



    4.Отрезаю всю секцию .reloc от dll,

    Запускаю PETools.exe и скармливаю свою dll

    RelocRebuilder.dll - плагину PETools.exe

    Acsess Violation на этапе работы RelocRebuilder.dll.

    Ладно по морде так по морде.



    5. Так, что я могу сделать руками:

    а)Определить границы своей функции, и идентифицировать Block (Blocks)

    из секции .reloc к которому (которым) пренадлежат эти границы.



    б)Посчитать количество уже описанных Items для старой функции.



    в)Посчитать количество инструкций с 32-разрядным смещением для "правильной" функции.

    (конечно лучше, чтобы они не отличались)



    г)на разницу чисел полученых в п. б) и в) скорректировать:

    - рамер dll.

    - Константу Size of Block (Size of Blocks).

    В результате мы должны получить Block (Blocks) с новым (скорректированным)

    количеством Items (местом для Items).



    д)Откорректировать Items (правя смещения Item от RVA Block-а).



    6)Собственно вопрос:



    а) ПОЛНОСТЬЮ ЛИ отражает п.5. идею фразы "править релоки",

    или я что-то опять упустил???



    б)Вопрос косвенно относящийся к предмету разговора.

    Я dll с "правильной" функцией и правлеными смещениями,

    но без исправленых релоков отдал Иде 4.9.

    строка кода которая ссылается на локальную переменную var_9 (смещение -9 от ebp;),

    и по моему пониманию, обязанная выглядеть приблизительно как:

    0040BC3B 8B45F7 mov eax, [ebp+var_9]

    при последнем обращении к ней (в конце "правильной" функции) выглядит как:

    0040BC3B 8B45F7 mov eax, [ebp-9] [причем -9 на красном фоне].

    до этого с пол десятка обращений к этой локальной переменной транслировалось

    ожидаемым образом ([ebp+var_9]).

    Это просто моя ошибка или следствие несбалансированности dll с секцией .reloc??

    И если это моя ошибка то что может вызывать ее??

    (Самому в голову пока ничего не идет).

    Заранее большое спасибо.
     
  9. crypto

    crypto Active Member

    Публикаций:
    0
    Регистрация:
    13 дек 2005
    Сообщения:
    2.533
    Я dll с "правильной" функцией и правлеными смещениями но без исправленых релоков отдал Иде 4.9



    Ты файл просто перегрузил? Тогда можно удалить код (U), а потом его снова создать (C).
     
  10. snpik

    snpik New Member

    Публикаций:
    0
    Регистрация:
    12 май 2006
    Сообщения:
    10
    Адрес:
    Ukraine
    Убил буквой "U" две инструкции с обращением к var_9

    1. 0040BC3B 8B45F7 mov eax, [ebp+var_9] ;

    2. 0040BC4B 8B45F7 mov eax, [ebp-9]

    Нажал "С" обе стали выглядеть как mov eax, [ebp-9],

    но во второй как был красный фон под 9, так и остался,

    а первая, где было [ebp+var_9] до "U" - c нормальным белым фоном. Ida чует какую-то непонятку.



    Что - то мне кажеться, что тут только практика нужна.



    Просто хочеться быть уверенным, что я правильно понял

    как "править релоки" перед практикой. Потому как воспользоватся

    советом Quantuma (спасибо за совет, конечно) с

    jmp after_bad_instruction

    some_bad_instruction

    after_bad_instruction:

    не светит. У меня у самого (в "хорошей" функции) полно таких "проблемных инструкций", причем с такой плотностью, что их ни как не наложишь на те, что были до чистки.
     
  11. asd

    asd New Member

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

    1.snpik





    Я вот думаю, если случится такая ситуация, что исправляемый блок релоков не последний? Тогда, как будут обрабатываться последующие блоки, ведь за концом исправленного блока останется мусор от старых релоков. Наверное следует сдвинуть последующие блоки релоков на количество убранных элементов?



    Проще всего мне представляется убить старые релоки, которые портят новую функцию, а свои релоки пропатчить самому. Всё это имхо, так как не пробовал.



    P.s. А dll большая?
     
  12. crypto

    crypto Active Member

    Публикаций:
    0
    Регистрация:
    13 дек 2005
    Сообщения:
    2.533
    snpik

    Похоже, в стеке стали наблюдаться непонятки.
     
  13. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine
    snpik




    да, $3'ка это IMAGE_REL_BASED_HIGHLOW, тебе необходимо найти для своих проблемных инструкций соотв. Item'ы и изменить $3-ку на $0 (IMAGE_REL_BASED_ABSOLUTE), тогда загрузчик должен их пропустить
     
  14. Quantum

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

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    snpik

    В самом начале была такая "проблемная" инструкция:
    Код (Text):
    1. .text:0040BB4A 8B058B104B00 mov eax, _dword_4B108B_Const_000000AF


    Если слегка исправить 2 первых байта:
    Код (Text):
    1. [b]90[/b]          nop
    2. [b]BE[/b] 8B104B00 mov esi,4B108B


    Оригинальный релок при этом не пострадал! Зато в регистре esi (можно и любой другой заюзать) получаем фактически значение дельты от релока, которое можно использовать далее в функции как базу! Т.е. теперь вместо ds:[4B108C] можно писать [esi + 1] и т.д. Таким образом можно оставить первый релок как есть а все остальные прибить.
     
  15. crypto

    crypto Active Member

    Публикаций:
    0
    Регистрация:
    13 дек 2005
    Сообщения:
    2.533
    Quantum

    Это уже изощренный способ - можно тулзу попробовать такую реализовать, которая будет максимально использовать имеющиеся релоки и текст изменений. Хорошая курсовая работа...
     
  16. GrayFace

    GrayFace New Member

    Публикаций:
    0
    Регистрация:
    11 май 2006
    Сообщения:
    11
    Адрес:
    Russia
    LordPE может редактировать релоки. Правда он может еще некоторый мусор добавить в exe-шку. Например, при добавлении моего импорта, он написал [LordPE] где-то в начале файла. Еще добавил новую секцию под именем ".Silvana", но это ожидаемо. Кстати, если патчить надо много, можно подключить свою библиотеку - добавить импорт любой ее функции - и патчить все (или не все, а только те места, где нужен дополнительный код) в момент загрузки библиотеки. Я так и сделал с H3WMapEd.exe
     
  17. snpik

    snpik New Member

    Публикаций:
    0
    Регистрация:
    12 май 2006
    Сообщения:
    10
    Адрес:
    Ukraine
    Отчет о проделаной работе:





    Релоки удалось поправить вручную!!!

    В старой функции их оказалось на 1 больше.

    Я в общих чертах воспользовался советами Quantuma ("строить код так,

    чтобы с релоками было меньше мороки") чтобы не резать dll

    и не двигать блоки. Я оставил самую безобидную инструкцию

    из старой функции с ее оригинальным релоком. Остальные

    релоки поправил. Type менять необходимость отпала.

    Я с этим параметром и не игрался.

    Var_9 выбросил и обошелся без этой переменной. Что хотела Ida, раскрашивая

    смещение от ebp в красный цвет (за что спаибо Ide), так и не узнал.

    Пока думаю, что п.5 всетаки отражает идею фразы "править релоки".

    Есть, првда, уточнения:

    - надо еще менять параметр размера секции .reloc если таковой изменяеться.

    - да, и, конено, блоки после правки, должны идти один за другим без всяких

    щелей и налезаний блоков друг на друга; тут, я думаю, прав asd - это логично.

    Хотя изменение размера - не проверено.

    На данный момент "хорошая" функция ведет себя предсказуемо (хотя до конца

    протестировать ее работу смогу только в понедельник) т.е. без скндалов со

    стороны Windows (что и требовалось доказать в задаче),

    за что большое СПАСИБО всем услышавшим мои крики о помощи.





    GrayFace

    Кстати, если патчить надо много, можно подключить свою библиотеку - добавить импорт любой ее функции - и патчить все (или не все, а только те места, где нужен дополнительный код) в момент загрузки библиотеки.





    Кстати это хорошее альтернативное решение, особенно когда нет возможности сбалансировать релоки "старого" и "нового".