Stack backtrace

Тема в разделе "WASM.ASSEMBLER", создана пользователем wasm_test, 18 дек 2008.

  1. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Хотел реализовать stack backtrace для своего отладчика ядра.
    Пока что в юзермоде решил потренироваться.
    Лукап по EBP-фреймам, ясное дело, отпадает как основной вариант, поскольку функции их могут не создавать.
    Решил крутить стек на предмет адресов, где лежит call (E8 и некоторые подмножества опкода FF). В принципе, работает, проблема лишь в том, что в качестве параметра где-то может лежать адрес куска данных где лежит нечто, похожее на call. Это в принципе решается лукапом по загруженным модулям и их BaseOfCode/SizeOfCode.
    Но так же может лежать какого-либо кода, где лежит call. Это уже хуже. Как бы от этого избавиться?
    Смотрел сорцы StackWalk из imagehlp в сорцах win2000, но пока что читать их немножко ломает по причине того хотя бы, что walkx86.c весит 51 килобайт.
    Кто что предложит?
     
  2. Dian

    Dian Member

    Публикаций:
    0
    Регистрация:
    19 июн 2008
    Сообщения:
    222
    http://code.google.com/p/mdf/wiki/TracedCallStack
     
  3. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    с трассировкой идея интересная, спасибо за ссыль. попробую
     
  4. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    У меня была дикая мысль подменять call на int3 и регистрировать вызовы ф-ий в отладчике. Но это абсолютно не годится для самомодифицирующегося кода.
     
  5. z0mailbox

    z0mailbox z0

    Публикаций:
    0
    Регистрация:
    3 фев 2005
    Сообщения:
    635
    Адрес:
    Russia СПБ
    в юзермоде StackWalk64
    в ядре - тоже :)
    как? - см. драйвер ProcessExplorera от Руссиновича
    все гениальное просто!
     
  6. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    z0mailbox
    Код (Text):
    1. void f4 (int a3, int a4)
    2. {
    3.        // здесь интересует stack backtrace
    4.        StackBacktrace()
    5. }
    6.  
    7. __declspec(naked) void f5 (int b1, int b2)
    8. {
    9.     f4 (b1+b2, b2-b1);
    10.     __asm ret
    11. }
    12.  
    13. void f3(int a1, int a2, int a3)
    14. {
    15.     f5 (a3, 0xAB0);
    16. }
    17.  
    18.  
    19. int main()
    20. {
    21.     f3 (0x100, 0x200, 0x300);
    22.     return 0;
    23. }
    Должно быть : mainCRTStartup -> main -> f3 -> f5 -> f4 -> StackBacktrace( EIP )

    Получается же так:
    (process explorer)
    Код (Text):
    1. vctest.exe!StackBacktrace+0x6c
    2. vctest.exe!f4+0x25
    3. vctest.exe!f5+0x13
    4. vctest.exe!main+0x34
    5. vctest.exe!Module32Next+0x160      // криво распознал mainCRTStartup
    6. kernel32.dll!RegisterWaitForInputIdle+0x49    // криво распознал BaseProcessStart
    (windbg)
    Код (Text):
    1. 0:000> k
    2. ChildEBP RetAddr  
    3. 0012ff28 00402405 vctest!StackBacktrace+0x6c [d:\progs\vctest\vctest.cpp @ 490]
    4. 0012ff48 00402423 vctest!f4+0x25 [d:\progs\vctest\vctest.cpp @ 602]
    5. 0012ff64 00402484 vctest!f5+0x13 [d:\progs\vctest\vctest.cpp @ 607]
    6. 0012ff7c 0040116c vctest!main+0x34 [d:\progs\vctest\vctest.cpp @ 633]
    7. 0012ffc0 7c817067 vctest!Module32Next+0x160 [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 582]    // криво распознал mainCRTStartup
    8. 0012fff0 00000000 kernel32!BaseProcessStart+0x23
    НАсколько я помню, WinDbg использует StackWalk. поэтому эти варианты отпадают.
    Мой бэктрейс:
    У меня выходит верно. Но мой бектрейс слетает если в стеке будет любой адрес, перед которым идет call. А это нехорошо.
     
  7. z0mailbox

    z0mailbox z0

    Публикаций:
    0
    Регистрация:
    3 фев 2005
    Сообщения:
    635
    Адрес:
    Russia СПБ
    разница между PE и windbg - наверное у тебя в PE пдбшки не подцепились

    я делал частично эвристический бактрейсер, не такой как у тебя правда
    идея с поиском по стеку адресов за call-ами теоретически неплохая, надо смотреть статистику попаданий
    [+] - процедур с возвратом не на стеке очень мало, экзотика
    [-] - коллизии адресов на мусоре в стеке
    [-] - обратное дизассемблирование тоже ненадежная фишка, тоже коллизии

    лично мне фреймовой раскрутки хватало всегда. Безфреймовые процедуры это обычно мелочи всякие типа memcpy. Они легко вычисляются в процессе анализа фреймовых, которые образуют скелет