Мое почтение всем. Иногда мне надо посмотреть, в каком порядке и какие ф-ии вызывались в целевой программе. Для этого думаю сделать такой трюк: присоединиться к целевому процессу с помощью ptrace, проставить int3 наначало каждой ф-ии и ждать улова. Таблица символов у исполняемого всегда есть, поэтому проблема определения начал ф-ий и их имен отпадает. Вопрос в том, как лучше такое сделать? ptrace? Не будет ли это слишком медленно? (Исполняемые большие и со сложной логикой). Есть ли существующие аналоги такого инструмента? Заранее благодарю за ответы.
Если критична скорость то можно инжектнуться в нужный процесс через LD_PRELOAD и просплайсить все функции джампом на свой мини-переходник, который будет логировать куда-либо факт вызова и вызывать callgate c оригинальным прологом функции.
_Sl4yer Нет, меня интересуют локальные вызовы, системные как раз не очень-то интересны. Cr4sh Ага, была такая мысль. Проблема в том, что никаких заглушек типа 'mov edi, edi' и пяти байт перед функцией там нет. Приложение, как я уже говорил, сложное и многопоточное, соответственно найти достаточно длинную инструкцию в начале ф-ии довольно сложно. С другой стороны, быстродействие меня волнует. Есть мысль поменять сами вызовы ф-ий, но тут есть проблемы: 1. В исполняемом файле, вероятно, нет релокаций, значит инструкции call надо искать самому. 2. Некоторые ф-ии вызываются косвенно, они буду упущены. Беда в том, что я примерно даже не представляю стоимость ptrace и передачи исключения в другой процесс.
Mika0x65 А зачем они нужны? Библиотека, прописанная в LD_PRELOAD, будет загружаться раньше всех остальных, и никаких активных потоков на тот момент времени не будет.
Cr4sh Да, точно, не подумал. Если подключить дизассемблер длин, то можно достаточно просто все это проделать. Спасибо за наводку. Единственное, что меня пугает (эта проблема присутствует в обоих вариантах) -- надо как-то определять, какой поток выполняется в данный момент. Думаю, опеределение потока будет проще в варианте с LD_PRELOAD, но пока не уверен.
vg ж вроде все это умеет. все переходы и вызова отмечает. ну и в зависимости от плугина. можно в принципе и свой написать если уж собрались с дизасмом мудиться.
qqwe А можно подробнее? Возможности пересобрать проект не будет, только таблица символов в наличии есть. И есть ли в нем тот функционал, который мне нужен? И насколько шустро работает? (Основная мишень -- ОЧЕНЬ крупная программа.)
Cr4sh Решил попробовать LD_PRELOAD, написал простенькую библиотеку, получаю странный эффект: export LD_PRELOAD=/tratata/tracer.so exec ls после чего терминал закрывается (Это вообще непонятно). Когда пытаюсь отладить библиотеку, запуская ее в отладчике, получаю SIGSEGV при вызове ф-ии exit. Судя по всему, вызов exit некорректно обрабатывается в PLT. Почему так происходит -- не знаю.
Пардон, выяснилось, что LD_PRELOAD здесь не при чем. Если сделать 'exec ls' без установки переменной среды, терминал все равно закрывается. Буду копать дальше.
Тьфу, черт, до меня не дошло, что exec ls действует также, как exec(2). Вполне логично, что терминал закрывается .
В общем, поковыряв LD_PRELOAD, думаю, это не самый лучший способ внедрения. Дело в том, что загрузчик не делает релокацию таких объектов, что очень затрудняет использование загруженного модуля.
Нет, не поэтому. Да и проблемы нет -- я ошибся. Писать не стал, т.к. надоело вести этот монолог. Суть в том, что я перехватывал mmap, чтобы получить базу загруженного модуля, после чего с помощью ptrace(PTRACE_SETREGS, ...) меня eip на его точку входа. Естественно, сразу после mmap объект не релоцирован и ничего путного с ним делать нельзя. В итоге проблема решилась просто: я поставил точку останова на первую инструкцию точки входа, и, когда она сработала, передал управление объекту описанным выше способом. Думаю, что есть более цивильные способы отследить загрузку модулей, но я пока только догадываюсь как. А опция -fpic просто создает базонезависимый код с использованием таблицы GOT.
Mika0x65 подскажи плиз как ты реализовал перехват в линухе. а конкретно как в линухе патчить секцию кода, по умолчанию естесственно права только READ, я так и не нашел легальный способ(может плохо искал), все методы связаны с вызовами int 80.
Хозяйке на заметку - www.pintool.org Eсли проект коммерческий, проверь лицензию, но вообще у них эта проблема решена довольно красиво. Как - пересказывать не буду, есть описание в документации.
Rustem А что нелегального в вызове int 0x80? А так -- mprotect (который в итоге и сведется к int 0x80) меняет атрибуты отображенных страниц. С его помощью можно выставить PROT_WRITE требуемым страницам. bolkin Спасибо, посмотрю. Может подхвачу какие-нибудь идеи оттуда.