Определение входных параметров блока кода

This post is also available in: Английский

С помощью BeaEngine сделал статический анализ блоков кода. Получилось следующее ( пример — одна из функций FunctionsTest.exe ):

Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00411104 jmp 00411A40h
Dataflow:Dataflow, (-,202) GetRegistersChanging(): registerInit: 00000000( ), registerUse:00000000( )
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00411A40 mov edi , edi
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00411A42 push ebp
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00411A43 mov ebp , esp
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00411A45 call 00411046h
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00411A4A call 00411A60h
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00411A4F pop ebp
Dataflow:Dataflow, (-,202) GetRegistersChanging(): registerInit: 000000b0( ESP EBP EDI ), registerUse:00000020( EBP )
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00411046 jmp 00412B10h
Dataflow:Dataflow, (-,202) GetRegistersChanging(): registerInit: 00000000( ), registerUse:00000000( )
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B10 mov edi , edi
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B12 push ebp
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B13 mov ebp , esp
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B15 sub esp , 00000018h
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B18 mov dword ptr [ebp-08h] , 00000000h
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B1F mov dword ptr [ebp-04h] , 00000000h
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B26 cmp dword ptr [0041702Ch] , BB40E64Eh
Dataflow:Dataflow, (-,202) GetRegistersChanging(): registerInit: 000000b0( ESP EBP EDI ), registerUse:00000020( EBP )
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B32 mov eax , dword ptr [0041702Ch]
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B37 and eax , FFFF0000h
Dataflow:Dataflow, (-,202) GetRegistersChanging(): registerInit: 00000001( EAX ), registerUse:00000000( )
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B3E mov ecx , dword ptr [0041702Ch]
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B44 not ecx
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B46 mov dword ptr [00417030h] , ecx
Dataflow:Dataflow, (-,202) GetRegistersChanging(): registerInit: 00000002( ECX ), registerUse:00000000( )
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412BB3 mov dword ptr [ebp-0Ch] , BB40E64Fh
Dataflow:Dataflow, (-,202) GetRegistersChanging(): registerInit: 00000000( ), registerUse:00000020( EBP )
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412BC7 mov eax , dword ptr [ebp-0Ch]
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412BCA or eax , 00004711h
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412BCF shl eax , 00000010h
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412BD2 or eax , dword ptr [ebp-0Ch]
Dataflow:Dataflow, (-,202) GetRegistersChanging(): registerInit: 00000001( EAX ), registerUse:00000020( EBP )
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412BEC mov esp , ebp
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412BEE pop ebp
Dataflow:Dataflow, (-,202) GetRegistersChanging(): registerInit: 00000030( ESP EBP ), registerUse:00000020( EBP )
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B51 lea edx , dword ptr [ebp-08h]
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B54 push edx
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B55 call dword ptr [004181C4h]
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B5B mov eax , dword ptr [ebp-08h]
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B5E mov dword ptr [ebp-0Ch] , eax
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B61 mov ecx , dword ptr [ebp-0Ch]
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B64 xor ecx , dword ptr [ebp-04h]
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B67 mov dword ptr [ebp-0Ch] , ecx
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B6A call dword ptr [004181C8h]
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B70 xor eax , dword ptr [ebp-0Ch]
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B73 mov dword ptr [ebp-0Ch] , eax
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B76 call dword ptr [004181CCh]
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B7C xor eax , dword ptr [ebp-0Ch]
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B7F mov dword ptr [ebp-0Ch] , eax
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B82 call dword ptr [004181D0h]
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B88 xor eax , dword ptr [ebp-0Ch]
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B8B mov dword ptr [ebp-0Ch] , eax
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B8E lea edx , dword ptr [ebp-18h]
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B91 push edx
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B92 call dword ptr [004181D4h]
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B98 mov eax , dword ptr [ebp-0Ch]
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B9B xor eax , dword ptr [ebp-18h]
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412B9E mov dword ptr [ebp-0Ch] , eax
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412BA1 mov ecx , dword ptr [ebp-0Ch]
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412BA4 xor ecx , dword ptr [ebp-14h]
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412BA7 mov dword ptr [ebp-0Ch] , ecx
Dataflow:Dataflow, (-,101) GetRegistersChanging(): 00412BAA cmp dword ptr [ebp-0Ch] , BB40E64Eh
Dataflow:Dataflow, (-,202) GetRegistersChanging(): registerInit: 00000017( EAX ECX EDX ESP ), registerUse:00000020( EBP )

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

Комментарии 3

  • не совсем хорошо понял, что вы понимаете под входными параметрами блока, не могли бы развернуто объяснить суть? =)

    • Я сейчас работаю над задачей восстановления прототипов функций по бинарному код. Это мне поднадобится что бы сделать «настоящий» in memory fuzzing. Т.е. фазинг произвольной точки программы.
      Ознакомившись с существующими call conventions я полнял, что восстанавливать, опираясь на описанные разработчиками компиляторов (или сторонними экспертами) правила не имеет смысла. В некоторых случаях (__fastcall, к примеру) точного алгоритма передачи параметров ( через стек, регистры ) может и не быть. Мол, внутренняя функция — что хотим то и делаем.
      В итоге я решил реализовать что-то вроде своего call convention. Все, что мне нужно знать: кто очищает память, сколько параметров через стек, и какие параметры через стек.
      С первыми двумя подзадачами вроде все более-менее понятно (закодирую скоро), а вот третья не такая тривиальная. Нужно понять, какие регистры используются в функции без инициализации. Такие регистры скорее всего параметры. Что бы определить регистры для функции я сначала определяю регистры для блока, а потом … фух, устал писать, пожалуй напишу еще один пост, когда код заработает 😉

      • Ага теперь понятно =)
        почитайте про слайсинг, с помощью него задача решается довольно просто. Делаете forward slice и смотрите на последнюю инициализацию регистра перед вызовом функции. А для построения слайса понадобятся cfg, dfg, pdg.

Добавить комментарий для izlesa Отменить ответ

Ваш адрес email не будет опубликован. Обязательные поля помечены *