Проблемы с патчами.

Тема в разделе "WASM.BEGINNERS", создана пользователем Clerk, 30 июл 2010.

  1. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    SZ
    Я же написал как, скопировать. Суть снова вызвать оригинальную функцию передав ей параметры переданные в перехваченную, классический wrapper. Шаманства с продвинутыми техниками конечно хорошо, но не стоит с ними перебарщивать, что можно сделать просто, лучше и делать просто.
     
  2. asd

    asd New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2005
    Сообщения:
    952
    Адрес:
    Russia
    ТЛС, имхо не сильно поможет, т.к. для рекурсивно вызываемых ф-ий всё равно придётся делать список. По мне так легче всего поступить так:
    Имеем функцию funk и адрес возврата из неё addr_ret
    в начало ф-ии вставляем стаб
    push addr1
    ret

    По addr1 находится код, который меняет адрес возврата из funk на addr2 и генерирует код по этому адресу следующего вида:
    push addr_ret
    call SomeFunk ; это и есть наша ф-ия перехватчик
    add3:

    В итоге имеем: при выходе из funk управление попадёт на addr2, а потом на SomeFunk, которой передан в качестве параметра адрес возврата addr_ret, на который следует подменить addr3, который лежит в стеке. Не забываем освободить память, которая занимается сгенерированным стабом.
     
  3. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Нашёл семпл с манипуляцией i31:
    http://files.virustech.org/indy/Code/NtIcp/
    Старший бит ссылки взводится:
    Код (Text):
    1.     bts LDR_DATA_TABLE_ENTRY.EntryPoint[eax],31 ; +0x80000000
    Обрабатывается #AV, старший бит сбрасывается в контексте:
    Код (Text):
    1. btr [edi].regEip,31
    Но там довольно сложный код.
     
  4. Zlyden

    Zlyden New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2008
    Сообщения:
    49
    Clerk
    Спасибо, пробовал ваш метод с таблицей ссылок, работает. Правда, приходится маяться с тем, чтобы не повредить регистры.
    Сейчас возникла другая проблема. Задача - в одной из развилок сделать так, чтобы при выборе одного условия в определенную переменную писалось 0, при выборе другого - 1. Вроде бы простая задача, но выполнить ее без вылета не получается. Вот начало функции, в которой осуществляется перехват, в 49D5FA нужно присвоить 0, в 49D614 1:
    Код (Text):
    1. _text:0049D540 ; void __cdecl UI_SaberDrawBlade(int, int, int, int)
    2. _text:0049D540 UI_SaberDrawBlade proc near             ; CODE XREF: sub_0_49E1B0+140p
    3. _text:0049D540
    4. _text:0049D540                 ;Описание переменных var_XX
    5. _text:0049D540
    6. _text:0049D540                 sub     esp, 0BCh
    7. _text:0049D546                 push    ebx
    8. _text:0049D547                 mov     ebx, eax
    9. _text:0049D549                 xor     eax, eax
    10. _text:0049D54B                 push    ebp
    11. _text:0049D54C                 push    esi
    12. _text:0049D54D                 mov     [esp+0C8h+var_84], eax
    13. _text:0049D551                 mov     esi, edx
    14. _text:0049D553                 mov     [esp+0C8h+var_80], eax
    15. _text:0049D557                 mov     eax, [esi+108h]
    16. _text:0049D55D                 test    al, 0Ch
    17. _text:0049D55F                 push    edi
    18. _text:0049D560                 mov     edi, ecx
    19. _text:0049D562                 mov     [esp+0CCh+var_88], 0
    20. _text:0049D56A                 jz      short loc_0_49D57D
    21.                                       ;Здесь был код, не относящийся к делу
    22. _text:0049D5DD loc_0_49D5DD:                           ; CODE XREF: UI_SaberDrawBlade+6Cj
    23. _text:0049D5DD                                         ; UI_SaberDrawBlade+83j
    24. _text:0049D5DD                 mov     eax, [esp+0D4h+var_4]
    25. _text:0049D5E4                 cmp     eax, edx
    26. _text:0049D5E6                 jge     loc_0_49E07D
    27. _text:0049D5EC                 test    byte ptr [esi+108h], 4
    28. _text:0049D5F3                 jz      short loc_0_49D614
    29. _text:0049D5F5                 cmp     eax, 2
    30. _text:0049D5F8                 jge     short loc_0_49D614
    31. _text:0049D5FA                 ;Здесь нужно присвоить   переменную 0
    32. _text:0049D5FA                 mov     edx, dword_0_F871DC
    33. _text:0049D600                 push    40h
    34. _text:0049D602                 lea     ecx, [esp+0D8h+var_48]
    35. _text:0049D609                 push    ecx
    36. _text:0049D60A                 push    offset aUi_saber_color ; "ui_saber_color"
    37. _text:0049D60F                 call    dword ptr [edx+34h]
    38. _text:0049D612                 jmp     short loc_0_49D62C
    39. _text:0049D614 ; ---------------------------------------------------------------------------
    40. _text:0049D614
    41. _text:0049D614                 ;Здесь нужно присвоить   переменную 1
    42. _text:0049D614 loc_0_49D614:                           ; CODE XREF: UI_SaberDrawBlade+B3j
    43. _text:0049D614                                         ; UI_SaberDrawBlade+B8j
    44. _text:0049D614                 mov     ecx, dword_0_F871DC
    45. _text:0049D61A                 push    40h
    46. _text:0049D61C                 lea     eax, [esp+0D8h+var_48]
    47. _text:0049D623                 push    eax
    48. _text:0049D624                 push    offset aUi_saber2_color ; "ui_saber2_color"
    49. _text:0049D629                 call    dword ptr [ecx+34h]
    50. _text:0049D62C
    51. _text:0049D62C loc_0_49D62C:                           ; CODE XREF: UI_SaberDrawBlade+D2j
    Как мне это сделать?
     
  5. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Zlyden
    Про какую переменную вы говорите ?
    0xF871DC это не переменная, а ссылка на массив методов(ссылок на процедуры). Можно поправить смещение в ветвлении на +4 байта, или поправить адрес массива на +4 байта(_text:0049D614: mov ecx,0xF871DC + 4).
     
  6. Zlyden

    Zlyden New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2008
    Сообщения:
    49
    Clerk
    0xF871DC не причем, переменная моя собственная, в коде программы ее нет. Т.е. моя функция, вызываемая позже, должна знать, что произошло в этом ветвлении, и для этого я выделил глобальную переменную, в которую записывается 0 или 1.
     
  7. Clerk

    Clerk Забанен

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

    Zlyden New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2008
    Сообщения:
    49
    Программа запускается и патчится в памяти. Пишу на С++, в винде. Функцию, вызываемую из UI_SaberDrawBlade, я полностью заменил, но для работе новой функции нужны некоторые данные, а именно - номер прорисовываемого лезвия (0 либо 1). Этот номер определяется в развилке, начинающейся по адресу 0049D5EC. Правда, результат функция нигде не сохраняет, а лишь берет соответствующие номеру данные. Последний метод, который я попробовал - записывать переход в начало блоков инструкций, соответствующих своей ветке. Т.е., по адресу 0049D5FA начинается блок инструкций, соответствующий варианту 0, а в блоке 0049D614 - вариант для 1. Я попробовал сделать так - размер первой инструкции у обоих блоков (mov edx, dword_0_F871DC для 0 и mov ecx, dword_0_F871DC для 1) равен 6 байтам, т.е. равен размеру инструкции call (far). Поэтому я записал вместо первых инструкций call на мои функции, в которых я сохранял номер лезвия, затем повторял стертую инструкцию и retn. Т.е. Выглядело для 0 это так:
    Код (Text):
    1. _text:0049D5FA         call my_function ; раньше была mov     edx, dword_0_F871DC
    2. _text:0049D600         push    40h
    Код (Text):
    1. my_function:
    2.         xor     eax, eax
    3.         mov     uisnum, eax
    4.         mov     edx, ds:0F871DCh
    5.         retn
    Вроде бы простой способ, ошибиться невозможно, но мне удалось - вызов UI_SaberDrawBlade вызывает вылет программы.
     
  9. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Zlyden
    Замените метод в таблице 0xF871DC[0x34], две части кода 0x49D5FA и 0x49D614 одинаковы. Затем в хэндлере определяйте откуда был произведён вызов по адресу возврата, либо по контексту.
     
  10. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    sizeof.'mov edx, ds:0F871DCh' == 6 байт, sizeof.'call my_function' == 5 байт. Байт после инструкции 'call my_function' заменен на nop или оставлен как есть? Если оставлен, то надо заменить. И что показывает отладчик?
     
  11. Zlyden

    Zlyden New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2008
    Сообщения:
    49
    Mika0x65
    Я использую call_far (0x15ff), она длиннее на один байт. Плюс раньше я использовал два push/ret для перехода на мой код и обратно, все равно программа вылетала
    Если бы он у меня был... Пробовал я ставить SoftIce, 4.2.7 и 4.0.5, патчил и так и сяк - ошибка 31. Попробую попозже за WinDBG взяться.
    Clerk
    Спасибо, попробую.
     
  12. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    Zlyden
    А по адресу, куда ссылается call far [0xXXXXXXXX] лежит корректный селектор:смещение? Без переходов между кольцами защиты? И селектор должен следовать за смещением, а не наоборот.

    И почему WinDbg? Это драйвер? Если это приложение из третьего кольца, можно использовать OllyDbg.
     
  13. Zlyden

    Zlyden New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2008
    Сообщения:
    49
    Mika0x65
    Спасибо! Оказалось, некорректный. Глупая ошибка, забыл инициализировать байт. Исправил, все заработало
     
  14. Zlyden

    Zlyden New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2008
    Сообщения:
    49
    Есть вопрос. Я сделал успешный перехват данных из DLL на Windows, теперь необходимо перехватывать те же данные из Shared Library на Linux. Для DLL я нашел адреса при помощи IDA и работал по ним, но вряд ли в линуксе так же, с их PIC. Хотя бы потому, что необходимо найти, где в памяти Shared Library теперь будет располагаться.
    Перехватываемая Shared Library и моя висят в памяти одного процесса. Мне нужно вызвать из этой Shared Library несколько функций и заменить значения нескольких переменных.
     
  15. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
  16. la2elpy

    la2elpy New Member

    Публикаций:
    0
    Регистрация:
    1 дек 2007
    Сообщения:
    6
    У меня вопрос, а возможно ли изменить атрибуты какого то куска в секции кода так
    VirtualProtect(addr,1,PAGE_READONLY,&old)
    или
    VirtualProtect(addr,1,PAGE_NOACCESS,&old)

    вообщем смысл, чтобы убрать у этого куска права выполнения для генерации исключения когда eip будет указывать на этот адрес, с последующим перехватом в своем обработчике.
    как ни пытался сделать, получаю 0xc0000005 при вызове VirtualProtect.

    upd
    кажется понял :) вызов VirtualProtect срабатывает, но он устанавливает права для всей страницы, а не конкретно по нужному адресу.
    то есть кроме хардварных бряков, трюков с перехватом, без модификации кода нету :)
    upd2
    разве что копировать всю страницу и фиксить в коде относительные адреса, и перенаправлять на нее управление из обработчика исключений
     
  17. GRAFik

    GRAFik Active Member

    Публикаций:
    0
    Регистрация:
    14 мар 2020
    Сообщения:
    352
    Всем доброго времени суток.

    Возможно ли, только с помощью правки секции импорта в exe-файле - подгрузить свою DLL и затем вызвать из нее сво(ю)(и) функц(ию)(ии) ? У меня ответ на этот вопрос примерно следующий: если функций в секции импорта немного, то можно, а если много, то можно, но это будет долго, нудно и "овчинка выделки не стоит" и нужно применять какой-нибудь более быстрый вариант. А то может я где-то "недогоняю" и сделать такое в любом случае несложно и недолго? Интересует именно грамотный вариант, а не просто патч IAT, от которого у кого-то этот exe-файл запустится, а у кого-то нет.
     
  18. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.955
    DllMain() будет вызвана у каждой либы в импорте.
     
  19. GRAFik

    GRAFik Active Member

    Публикаций:
    0
    Регистрация:
    14 мар 2020
    Сообщения:
    352
    f13nd, слишком лаконично, и как следствие - я не понял)) Идея такая пришла после прочтения статьи @Thetrik'а.
     
  20. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    GRAFik,

    Сам то понял что спросил?

    > если функций в секции импорта немного, то можно, а если много, то можно, но это будет долго

    Опиаты походу.