Пишем плагин к Imprec 1.42Непонятно почему, но imprec иногда не восстанавливает функции вида: :012373C4 55 PUSH EBP :012373C5 8B EC MOV EBP,ESP :012373C7 56 PUSH ESI :012373C8 E9 xxxxxxxx JMP BFBABB63 Первые три команды - это кусок из вызываемой функции. Т.е. реально функция выглядит так: :BFBABB5F PUSH EBP :BFBABB60 MOV EBP,ESP :BFBABB62 PUSH ESI :BFBABB63 MOV ESI,[EBP+08] :BFBABB66 PUSH ESI :BFBABB67 CALL BFB74A08 :BFBABB6C TEST EAX,EAXи т.д. Т.е. происходит "эмуляция" вызова, т.к. вызов апи происходит не с первой команды, а как мы тут видим, с четвертой. Такие вызовы могут производится через 2 типа джампов: относительный и прямой. Если был бы прямой jmp то вот те xxxxxxxx = 63 BB BA BF. При относительном jmp эти xxxxxxxx содержат смещение относительно команды jmp. При таком вызове xxxxxxxx = BFBABB63-012373C8-5 (5 - длина команды jmp) т.е. xxxxxxxx = 96 47 97 BE. Еще может быть не jmp, а push - ret. Ну тут тоже самое просто опкод у push другой. Так вот в Imprec 1.42 есть исходник ихнего ASProtect 1.2x Emul.dll. Лежит он в \Plugin\Src\ASProtect\Delphi\ и называется aspr.dpr
Возьмем его за основу и напишем свой плагин. Находим в aspr.dpr цикл который идет после movememory (addr(to_trace),pointer(g_pointer),15);
Там идет for i := 0 to 27 do begin if (to_trace[i] = $e9) or (to_trace[i] = $68) then Begin val:=to_trace[4+i] shl 24 + to_trace[3+i] shl 16 + to_trace[2+i] shl 8 + to_trace[1+i]; if val<$400000 then continue; if IsBadReadPtr(pointer(val), 4) then val:=to_trace[4+i] shl 24 + to_trace[3+i] shl 16 + to_trace[2+i] shl 8 + to_trace[1+i]+g_pointer+5 else val:=to_trace[4+i] shl 24 + to_trace[3+i] shl 16 + to_trace[2+i] shl 8 + to_trace[1+i]-i; found := true; break; end; end;И еще надо поправить буфер в Var: to_trace :array[0..32] of BYTE; а то 16 байтов это маловато. Ну и естественно movememory (addr(to_trace),pointer(g_pointer),32); Теперь поясню. Плагин читает в массив to_trace 32 байта от адреса, который горит в Imprec. Дальше ищем байт $e9. Когда нашли - читаем четыре байта после него. Сначала делаю проверку, чтоб оно не схватило какой-нить push 00100000 (val<$400000). И этим же 4 байтам определяем какой это тип джампа: прямой или относительный. Определяю я это через по IsBadReadPtr. Еcли вернет true то это относительный джамп, иначе - прямой. g_pointer - это адрес который imprec увидел в IAT, т.е. тот, от которого мы начали анализ. Дальше нужно вернуть адрес в переменную val и сказать что мы успешно нашли, что искали (found:=true;). Компилим и скидываем скомпиленную dll в каталог Plugins. Вот и все. Можно юзать. P.S. Вероятный глюк. Может не определить функцию если смещение в относительном джампе попадет = адресу какой-нить области занятной левой dll и т.д. Т.е. IsBadReadPtr cкажет, что все нормально и будет возвращен неправильный адрес.
|