Овощи.

Тема в разделе "WASM.HEAP", создана пользователем Clerk, 9 окт 2010.

  1. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Booster
    Берём мы адрес возврата из N-го стекового фрейма. Как определить что он принадлежит процедуре Y() ?
     
  2. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Clerk
    Я далее писал - ищем бинго, хотя с call[eax] без точного знания границ функции это работать не будет.
     
  3. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Ктонибудь решал эту задачу или может реально решить её ?
     
  4. qqwe

    qqwe New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2009
    Сообщения:
    2.914
    Clerk
    мы знаем адрес входа в Y, чтобы найти все все возможные точки возврата в Y нужен дизасм и небольшой эвристик. правда, ситуации вроде ниже найти будет сложно

    push M
    ... ; разные команды после которых стек останется на М
    jmp A


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

    (виртальная протекция, я так понимаю, не проходит тк эксцепции не разрешены)
     
  5. qqwe

    qqwe New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2009
    Сообщения:
    2.914
    Clerk
    нахождение вызовов из всех веток функции (исключая jmp|call <reg>. это тоже частично можно, но сложно) и соотв, точек возврата - вполне не сложная задача. и решаная. даже тут на форуме гдето кусок кода постил, хотя в нем нет ничего такого чтоб его искать.
     
  6. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Предложенной мной алгоритм достаточно прост в реализации, единственно что желательно знать размер стека данных Y, но думаю это не проблема. Так что могу. ^)
     
  7. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Booster
    Первое что пришло на ум - калбэк обрабатывающий манифесты LdrpManifestProberRoutine. Имеем последовательность вызовов:
    Код (Text):
    1. LdrpWalkImportDescriptor
    2. LdrpLoadImportModule
    3. LdrpHandleOneNewFormatImportDescriptor
    4. LdrpHandleNewFormatImportDescriptors
    5. LdrpWalkImportDescriptor
    6. LdrpLoadDll
    7. LdrLoadDll
    8. LoadLibraryExW
    9. LoadLibraryExA
    10. LoadLibraryA
    Имея адрес LoadLibraryA(), можите достать её стековый фрейм и заменить там адрес возврата(из калбэка LdrpManifestProberRoutine) ?
    Причём уровень вложенности не фиксирован(тоесть до калбэка может быть иное число процедур).
    Тогда плз по пунктам или семпл.
     
  8. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Clerk
    Тут по-моему не может быть 100% решения. А насчёт LdrpManifestProberRoutine, не знаю в чём там могут быть проблемы, если они там могут быть. А алгоритм я уже изложил, он очень прост, не вижу смысла его повторять.
     
  9. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Booster
    Ну меня интересует практическая реализация, а не бесполезная матчасть. Это всёравно что сказать заюзать иду.
     
  10. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.552
    Адрес:
    Russia
    Clerk
    Неужели вы хотите чтобы за вас все написали? Не верю своим глазам.
     
  11. Clerk

    Clerk Забанен

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

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Clerk
    Так определитесь, что Вы хотите. Лично мне интересна сама задача, реализация гораздо меньше. Тем более, что мне она не нужна, у меня есть более насущные задачи.
     
  13. qqwe

    qqwe New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2009
    Сообщения:
    2.914
    Clerk
    я на предыдущей странице написал - если все запрещено, у вас есть адрес начала Y. пробегитесь по веткам Y, найдите все адреса куда может быть возврат. это не сложно. а потом, ищете по ebp в стеке один из них. следующий адрес возврата по ebp и будет адресом куда вернется управление из Y. подменяйте его.
    сам код я вам дать не могу, тк он уже ушел. но есть прототип делающий нечто близкое, который я постил на этом форуме. тема както "прошу проверить ..." называлась. код там прототипный, те какнибудьный, но рабочий. если оно вам надо - можете посмотреть/взять. только вслед за TermoSINteZом немного удивляюсь.
     
  14. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Clerk
    Если Вы не совсем поняли, то повторю идею - перебираем "значения/адреса" стека снизу вверх, смотрим какая инструкция находится по очередному адресу возврата чуть выше него и если там call Y, то это то что нам надо. Проблема в том, что там может быть call [eax] и мы не знаем куда этот вызов идёт, тогда без анализа нижележащего вызова не обойтись и тут без знания адресов размещения Y не обойтись. Что тут ещё объяснять?
     
  15. qqwe

    qqwe New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2009
    Сообщения:
    2.914
    Booster
    тоже мысль.

    call Y
    call [Y_in_mem]

    если call прямо перед ret, то компилеры заменяют {call ХХ; ret} на jmp XX
    jmp short Y
    jmp near Y
    jmp [Y_in_mem]

    и более сложное. (если ret через c2 или push далеко, придется помудохаться)
    push Y; ret
    push [Y_in_mem]; ret

    регистровая адресация может быть слишком сложна, но она встречается редко.

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

    pop ebx
    div ebх

    или

    pop ecx
    mov eax,[ecx+4] ; мс С++ в есх this держит.

    но исключения запрещены, потому этот вариант отпадает.
     
  16. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    qqwe
    Я не прошу кода если вы так думаете, он мне ваш не нужен. Просто хочу знать кто юзал подобные решения.
    Вот на коленке собрал семпл к #27:
    Код (Text):
    1. .code GPECODE
    2.     include Gpe.inc
    3.  
    4. %NTERR macro
    5.     .if Eax
    6.     Int 3
    7.     .endif
    8. endm
    9.  
    10. %APIERR macro
    11.     .if !Eax
    12.     Int 3
    13.     .endif
    14. endm
    15.  
    16.     Public gChainDispatch
    17.     Public gLoadLibraryArg
    18. .data
    19. gSnapshot           GP_SNAPSHOT <>
    20. gChainDispatch      PVOID ?
    21. gLoadLibraryArg PSTR ?
    22.  
    23. .code
    24. LoadLibrary2ndDispatch proc C
    25.     pushad
    26.     invoke DbgPrint, gLoadLibraryArg
    27.     popad
    28.     jmp gChainDispatch
    29. LoadLibrary2ndDispatch endp
    30.    
    31. LdrpManifestProberRoutine proc DllBase:PVOID, FullDllPath:PCWSTR, ActivationContext:PVOID
    32. Local Caller:GP_CALLER
    33.     lea eax,Caller
    34.     push eax
    35.     push UserMode
    36.     push NULL
    37.     push offset gSnapshot
    38.     %GPCALL GP_FIND_CALLER_BELONG_TO_SNAPSHOT
    39.     .if !Eax
    40.     mov edx,Caller.Frame
    41.     lea ecx,LoadLibrary2ndDispatch
    42.     mov edx,STACK_FRAME.Next[edx]
    43.     xchg STACK_FRAME.Ip[edx],ecx
    44.     mov gChainDispatch,ecx
    45.     mov edx,dword ptr [edx + sizeof(STACK_FRAME)]   ; Arg.
    46.     mov gLoadLibraryArg,edx
    47.     .endif
    48.     xor eax,eax
    49.     ret
    50. LdrpManifestProberRoutine endp
    51.  
    52. LdrSetDllManifestProber proto :PVOID
    53.  
    54. _imp__LoadLibraryA proto :PSTR
    55.  
    56. $Dll    CHAR "psapi.dll",0
    57.  
    58. Ep proc
    59. Local GpSize:ULONG
    60. Local OldProtect:ULONG
    61.     mov gSnapshot.GpBase,NULL
    62.     mov GpSize,1000H * X86_PAGE_SIZE
    63.     invoke ZwAllocateVirtualMemory, NtCurrentProcess, addr gSnapshot.GpBase, 0, addr GpSize, MEM_COMMIT, PAGE_READWRITE
    64.     mov ebx,gSnapshot.GpBase
    65.     %NTERR
    66.     add gSnapshot.GpBase,0FFFH * X86_PAGE_SIZE
    67.     mov GpSize,X86_PAGE_SIZE
    68.     invoke ZwProtectVirtualMemory, NtCurrentProcess, addr gSnapshot.GpBase, addr GpSize, PAGE_NOACCESS, addr OldProtect
    69.     %NTERR
    70.     mov gSnapshot.GpLimit,ebx
    71.     mov gSnapshot.GpBase,ebx
    72.     lea ecx,gSnapshot.GpLimit
    73.     push eax
    74.     push eax
    75.     push eax
    76.     push eax
    77.     push eax
    78.     push 1
    79.     push GCBE_PARSE_SEPARATE
    80.     push ecx
    81.     push dword ptr [_imp__LoadLibraryA]
    82.     %GPCALL GP_PARSE
    83.     %NTERR
    84.     invoke LdrSetDllManifestProber, offset LdrpManifestProberRoutine
    85.     invoke LoadLibrary, addr $Dll
    86.     %APIERR
    87.     ret
    88. Ep endp
     
  17. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    qqwe
    Это проблема, если идёт цепочка таких прыжков и Y где-то посередине, то подмена адреса возврата здесь вообще не работает.
     
  18. qqwe

    qqwe New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2009
    Сообщения:
    2.914
    Clerk
    именно поэтому я упомянул про него, но ветку ту не искал
    лучше посмотрел на #27. библиотечная осевая функция? в них редко встречаются хитрые вызова и на сами переходы должны быть релоки. можно поискать по релокам call-ы или jmp-ы на Y, прикинуть куда будут возвраты и искать эти цифры в стеке.

    впрочем, этот путь плох. ваш лучше.
     
  19. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    qqwe
    Там всё просто. Строится граф с единичным уровнем вложенности, тоесть процедурные ветвления не раскрываются, описывается код только текущей процедуры. Затем в калбэке выполнятеся бактрейс и для каждого фрейма выполняется проверка на вхождение адреса возврата в граф, при этом выполняется подсчёт SFN и в целевом фрейме заменятеся адрес возврата. Таким образом исключается зависимость фрейма от уровня вложенности(SFN - SFN') и расположения вызывающей процедуры в коде, это универсальное решение.

    Тема к тому, что эти овощи ничего такого юзать не могут, сводя всё к стандартному элементарному функционалу(апк там всякие асинхронно не рабочие, модификация PTE руками, патчи и прочий унылый изврат). Есть продвинутые решения, так нужно всё свести к мсдн описалову и какимто там детектам, пичаль.

    http://www.wasm.ru/forum/viewtopic.php?id=38892
     
  20. qqwe

    qqwe New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2009
    Сообщения:
    2.914
    Clerk
    гдето это я и имел в виду. только вы не строите список возможных точек возврата, а просто проверяете на попадение в граф. это, да, и проще и универсальнее, но момент отмеченный Boosterом остается
    тут возврат не попадет в граф.