Хотел реализовать stack backtrace для своего отладчика ядра. Пока что в юзермоде решил потренироваться. Лукап по EBP-фреймам, ясное дело, отпадает как основной вариант, поскольку функции их могут не создавать. Решил крутить стек на предмет адресов, где лежит call (E8 и некоторые подмножества опкода FF). В принципе, работает, проблема лишь в том, что в качестве параметра где-то может лежать адрес куска данных где лежит нечто, похожее на call. Это в принципе решается лукапом по загруженным модулям и их BaseOfCode/SizeOfCode. Но так же может лежать какого-либо кода, где лежит call. Это уже хуже. Как бы от этого избавиться? Смотрел сорцы StackWalk из imagehlp в сорцах win2000, но пока что читать их немножко ломает по причине того хотя бы, что walkx86.c весит 51 килобайт. Кто что предложит?
У меня была дикая мысль подменять call на int3 и регистрировать вызовы ф-ий в отладчике. Но это абсолютно не годится для самомодифицирующегося кода.
в юзермоде StackWalk64 в ядре - тоже как? - см. драйвер ProcessExplorera от Руссиновича все гениальное просто!
z0mailbox Код (Text): void f4 (int a3, int a4) { // здесь интересует stack backtrace StackBacktrace() } __declspec(naked) void f5 (int b1, int b2) { f4 (b1+b2, b2-b1); __asm ret } void f3(int a1, int a2, int a3) { f5 (a3, 0xAB0); } int main() { f3 (0x100, 0x200, 0x300); return 0; } Должно быть : mainCRTStartup -> main -> f3 -> f5 -> f4 -> StackBacktrace( EIP ) Получается же так: (process explorer) Код (Text): vctest.exe!StackBacktrace+0x6c vctest.exe!f4+0x25 vctest.exe!f5+0x13 vctest.exe!main+0x34 vctest.exe!Module32Next+0x160 // криво распознал mainCRTStartup kernel32.dll!RegisterWaitForInputIdle+0x49 // криво распознал BaseProcessStart (windbg) Код (Text): 0:000> k ChildEBP RetAddr 0012ff28 00402405 vctest!StackBacktrace+0x6c [d:\progs\vctest\vctest.cpp @ 490] 0012ff48 00402423 vctest!f4+0x25 [d:\progs\vctest\vctest.cpp @ 602] 0012ff64 00402484 vctest!f5+0x13 [d:\progs\vctest\vctest.cpp @ 607] 0012ff7c 0040116c vctest!main+0x34 [d:\progs\vctest\vctest.cpp @ 633] 0012ffc0 7c817067 vctest!Module32Next+0x160 [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 582] // криво распознал mainCRTStartup 0012fff0 00000000 kernel32!BaseProcessStart+0x23 НАсколько я помню, WinDbg использует StackWalk. поэтому эти варианты отпадают. Мой бэктрейс: У меня выходит верно. Но мой бектрейс слетает если в стеке будет любой адрес, перед которым идет call. А это нехорошо.
разница между PE и windbg - наверное у тебя в PE пдбшки не подцепились я делал частично эвристический бактрейсер, не такой как у тебя правда идея с поиском по стеку адресов за call-ами теоретически неплохая, надо смотреть статистику попаданий [+] - процедур с возвратом не на стеке очень мало, экзотика [-] - коллизии адресов на мусоре в стеке [-] - обратное дизассемблирование тоже ненадежная фишка, тоже коллизии лично мне фреймовой раскрутки хватало всегда. Безфреймовые процедуры это обычно мелочи всякие типа memcpy. Они легко вычисляются в процессе анализа фреймовых, которые образуют скелет