1 | |
Перехват и подмена вызываемых функций09.08.2009, 03:57. Показов 24891. Ответов 25
Метки нет (Все метки)
Здравствуйте.
Нужно подменить вызов таких функций как open(), lstat[64](), stat[64](), read(), write(), mkdir(), chdir(), getcwd() для определенного процесса. Интересует мнение других. Как бы вы реализовали эту задачу. Спасибо!
0
|
09.08.2009, 03:57 | |
Ответы с готовыми решениями:
25
Программа для определения функций WinAPI, вызываемых программой с GUI Инлайн функций вызываемых через указатель на функцию Насколько хорошо компилятор производит оптимизацию часто вызываемых функций? Создать программу, которая состоит из отдельных функций, вызываемых к методе main () |
7175 / 3234 / 81
Регистрация: 17.06.2009
Сообщений: 14,164
|
|
09.08.2009, 20:42 | 2 |
Установить переменную LD_PRELOAD. И вообще прочитай man ld.so про работу runtume loader-а.
1
|
09.08.2009, 23:19 | 3 |
Все системные вызовы реализованы в виде WEAK процедур. Т.е. это означает, что их можно подменать (путём заведения GLOBAL символя с таким же именем). Т.е. пишешь динамическую библиотеку, в которой реализована функция с именем "open", затем в переменную окружения LD_PRELOAD прописываешь полный путь до библиотеки, затем запускаешь программу. Для контроля можешь запустить "ldd <prog_name>" чтобы убедиться, что твоя библиотека реально подцепилась.
При этом остаётся возможность обратиться к "настоящему" системному вызову по имени "__open"
2
|
10.08.2009, 10:44 | 5 | ||||||||||
Сообщение было отмечено как решение
Решение
Код
Собираем нашу читерскую библиотеку $ gcc tt.c -fPIC -c $ gcc tt.o -shared -o libshaman.so Собираем исполняемый файл $ gcc t.c Честный запуск файла $ ./a.out abc Читерский запуск файла $ export LD_PRELOAD=`pwd`/libshaman.so $ ./a.out trampampam abc Снова честный $ unset LD_PRELOAD $ ./a.out abc
12
|
10.08.2009, 19:59 | 9 |
$ readelf -s /lib/libc-2.7.so
glibc - системная библиотека самого низкого уровня, а потому в идеале она вообще ничего не должна импортировать. Реально ld.so является составной частью библиотеки, а потому оттуда импортируются какие-то функции. В печати они в самом начале и помечены UND (undefined) в графе Ndx. При этом если в поле Bind стоит WEAK, то такой символ может и отсуствовать (т.е. он необязательный)
2
|
10.08.2009, 20:19 | 11 |
Этими хреновинами они поддерживают совместимость версий. Т.е. была некая "старая" динамическая glibc, у которой версионный символ для fopen был выставлен в GLIBC_2.0. В какой-то момент там что-то поменялось в реализации, что стало несовместимо со старыми версиями, поэтому они сделали новую реализациюю, пометили её символом GLIBC_2.1 (уже с двумя символнами @) и теперь у них есть динамическая библиотека, которая одновременно работает и со старыми и с новыми бинарниками. При этом в бинарниках, использующих glibc должен быть соотвествующий символ, помеченный как UNDEF
Имя файла libc.so.6 чем-то мне говорит, что у тебя старая версия glibc'ей чтоли. Покажи, что выдаётся по "ls /lib/libc* /lib/ld-linux*" Добавлено через 1 минуту 16 секунд А вообще, если я буду отвечать на такие частные вопросы, врядли у тебя появится какое-то нормальное понимание того, что там происходит. Разве что очень поверхностное. Тебе надо читать, что такое объектный файл, динамическая библиотека, исполняемый файл с точки зрения бинарного формата и как вообще работает линковка
0
|
10.08.2009, 20:30 [ТС] | 12 |
Еще вопрос. Как узнать какие функции вызывает функция "fopen", или другие? Что означают одинарный и двойной подчерки перед названием функции? Добавлено через 4 минуты 0 секунд Я не новичек. Я программист С/С++ с 10 летним стажем. Т.е. склад ума соответствующий Просто раньше не возникало подобной необходимости. Я очень благодарен Вам за подробные ответы. Добавлено через 2 минуты 39 секунд Согласитесь, что не каждый день(а может быть и за всю карьеру) приходится подменять стандартные функции. Да и программированием это особо не назовешь, скорее хак
0
|
10.08.2009, 21:07 | 13 |
Понятно, видимо старое имя для совместимости оставлено
Чуть позже отвечу Значит всё гораздо проще Но в любом случае всё это - системная специфика. Понятно, что программисту с 10-летним стажем это гораздо проще понять, чем новичку, но просто сразу предупреждаю, что у тебя будут ответы на вопросы, но каких-то полезных знаний таким макаром сложно будет приобрести. Ты выполняешь задачу, которая всё-таки требует понимания специфики всего этого дела. К сожалению, с ходу не могу сказать, где и что можно почитать - я как-то по работе в течение нескольких лет с этим общаюсь, а потому это всё опытным путём добывалось. В любом случае на вопросы отвечу Да и сам ты всё прекрасно понимаешь, о чём я написал выше Добавлено через 2 минуты 22 секунды > Чуть позже отвечу Просто на работе мы используем немного другие утилиты (самодельные), а потому надо сообразить, как со стандартными работать Добавлено через 12 минут 15 секунд В общем как-то не совсем удобно стандартными gnu'шными утилитами работать, но тем не менее. Смотрим выдачу по readelf -s: Код
177: 00059220 50 FUNC GLOBAL DEFAULT 11 fopen@@GLIBC_2.1 Далее делаем дизассемблер от библиотеки: Код
$ objdump -d /lib/libc-2.7.so > DD Щас напишу ещё один вариант - со статической библиотекой. В теории код там должен быть такой же (хотя в некоторых случаях он различается для статической и динамической версий). Но статическая библиотека представляет собой архив отдельных объектных файлов, а потому там копаться иногда проще Добавлено через 7 минут 14 секунд Смотрим, из каких файлов состоит статическая библиотека, отфильтруем те, у которых есть fopen в названии Код
$ ar t /usr/lib/libc.a | grep fopen iofopen.o iofopen64.o Выдираем файл из архива Код
$ ar x /usr/lib/libc.a iofopen.o $ ls iofopen.o iofopen.o Код
$ readelf -s iofopen.o Symbol table '.symtab' contains 23 entries: Num: Value Size Type Bind Vis Ndx Name 0: 00000000 0 NOTYPE LOCAL DEFAULT UND 1: 00000000 0 SECTION LOCAL DEFAULT 1 2: 00000000 0 SECTION LOCAL DEFAULT 3 3: 00000000 0 SECTION LOCAL DEFAULT 4 4: 00000000 0 SECTION LOCAL DEFAULT 5 5: 00000000 0 SECTION LOCAL DEFAULT 7 6: 00000000 0 SECTION LOCAL DEFAULT 8 7: 00000000 63 FUNC GLOBAL DEFAULT 1 __fopen_maybe_mmap 8: 00000000 0 NOTYPE GLOBAL DEFAULT UND _IO_wfile_jumps_maybe_mma 9: 00000000 0 NOTYPE GLOBAL DEFAULT UND _IO_file_jumps_maybe_mmap 10: 00000040 196 FUNC GLOBAL DEFAULT 1 __fopen_internal 11: 00000000 0 NOTYPE GLOBAL DEFAULT UND malloc 12: 00000000 0 NOTYPE GLOBAL DEFAULT UND _IO_wfile_jumps 13: 00000000 0 NOTYPE GLOBAL DEFAULT UND _IO_no_init 14: 00000000 0 NOTYPE GLOBAL DEFAULT UND _IO_file_jumps 15: 00000000 0 NOTYPE GLOBAL DEFAULT UND _IO_file_init 16: 00000000 0 NOTYPE GLOBAL DEFAULT UND _IO_file_fopen 17: 00000000 0 NOTYPE GLOBAL DEFAULT UND _IO_un_link 18: 00000000 0 NOTYPE GLOBAL DEFAULT UND free 19: 00000110 34 FUNC GLOBAL DEFAULT 1 _IO_new_fopen 20: 00000110 34 FUNC GLOBAL DEFAULT 1 __new_fopen 21: 00000110 34 FUNC WEAK DEFAULT 1 _IO_fopen 22: 00000110 34 FUNC WEAK DEFAULT 1 fopen Добавлено через 4 минуты 12 секунд Пардон, ошибся. Там ещё есть __fopen_maybe_mmap и __fopen_internal. Т.е. всего три процедуры. И надо разбираться, какие из UNDEF'ов растут из каких процедур Код
$ readelf -r iofopen.o Relocation section '.rel.text' at offset 0x690 contains 13 entries: Offset Info Type Sym.Value Sym. Name 0000001e 00000801 R_386_32 00000000 _IO_wfile_jumps_maybe_ 0000002b 00000801 R_386_32 00000000 _IO_wfile_jumps_maybe_ 00000039 00000901 R_386_32 00000000 _IO_file_jumps_maybe_m 00000063 00000b02 R_386_PC32 00000000 malloc 00000088 00000c01 R_386_32 00000000 _IO_wfile_jumps 000000a0 00000d02 R_386_PC32 00000000 _IO_no_init 000000aa 00000e01 R_386_32 00000000 _IO_file_jumps 000000b2 00000f02 R_386_PC32 00000000 _IO_file_init 000000c9 00001002 R_386_PC32 00000000 _IO_file_fopen 000000e9 00001102 R_386_PC32 00000000 _IO_un_link 000000f1 00001202 R_386_PC32 00000000 free 0000012c 00000a02 R_386_PC32 00000040 __fopen_internal 000000e1 00000702 R_386_PC32 00000000 __fopen_maybe_mmap Relocation section '.rel.eh_frame' at offset 0x6f8 contains 2 entries: Offset Info Type Sym.Value Sym. Name 0000001c 00000101 R_386_32 00000000 .text 0000004c 00000101 R_386_32 00000000 .text Добавлено через 2 минуты 29 секунд А можно вообще сделать дизассемблеирование, и там всё станет понятно Код
$ objdump -d iofopen.o iofopen.o: file format elf32-i386 Disassembly of section .text: 00000000 <__fopen_maybe_mmap>: 0: 55 push %ebp 1: 89 e5 mov %esp,%ebp 3: 8b 55 08 mov 0x8(%ebp),%edx 6: f6 42 3c 01 testb $0x1,0x3c(%edx) a: 74 23 je 2f <__fopen_maybe_mmap+0x2f> c: f6 02 08 testb $0x8,(%edx) f: 74 1e je 2f <__fopen_maybe_mmap+0x2f> 11: 8b 42 68 mov 0x68(%edx),%eax 14: 85 c0 test %eax,%eax 16: 7e 1b jle 33 <__fopen_maybe_mmap+0x33> 18: c7 82 94 00 00 00 00 movl $0x0,0x94(%edx) 1f: 00 00 00 22: 8b 42 58 mov 0x58(%edx),%eax 25: c7 80 b8 00 00 00 00 movl $0x0,0xb8(%eax) 2c: 00 00 00 2f: 5d pop %ebp 30: 89 d0 mov %edx,%eax 32: c3 ret 33: c7 82 94 00 00 00 00 movl $0x0,0x94(%edx) 3a: 00 00 00 3d: eb e3 jmp 22 <__fopen_maybe_mmap+0x22> 3f: 90 nop 00000040 <__fopen_internal>: 40: 55 push %ebp 41: 89 e5 mov %esp,%ebp 43: 83 ec 24 sub $0x24,%esp 46: 8b 45 08 mov 0x8(%ebp),%eax 49: 89 5d f4 mov %ebx,-0xc(%ebp) 4c: 89 75 f8 mov %esi,-0x8(%ebp) 4f: 8b 75 10 mov 0x10(%ebp),%esi 52: 89 7d fc mov %edi,-0x4(%ebp) 55: 8b 7d 0c mov 0xc(%ebp),%edi 58: 89 45 f0 mov %eax,-0x10(%ebp) 5b: c7 04 24 60 01 00 00 movl $0x160,(%esp) 62: e8 fc ff ff ff call 63 <__fopen_internal+0x23> 67: 85 c0 test %eax,%eax 69: 89 c3 mov %eax,%ebx 6b: 0f 84 84 00 00 00 je f5 <__fopen_internal+0xb5> 71: 8d 80 98 00 00 00 lea 0x98(%eax),%eax 77: 89 43 48 mov %eax,0x48(%ebx) 7a: 8d 83 a4 00 00 00 lea 0xa4(%ebx),%eax 80: 89 44 24 0c mov %eax,0xc(%esp) 84: c7 44 24 10 00 00 00 movl $0x0,0x10(%esp) 8b: 00 8c: c7 44 24 08 00 00 00 movl $0x0,0x8(%esp) 93: 00 94: c7 44 24 04 00 00 00 movl $0x0,0x4(%esp) 9b: 00 9c: 89 1c 24 mov %ebx,(%esp) 9f: e8 fc ff ff ff call a0 <__fopen_internal+0x60> a4: c7 83 94 00 00 00 00 movl $0x0,0x94(%ebx) ab: 00 00 00 ae: 89 1c 24 mov %ebx,(%esp) b1: e8 fc ff ff ff call b2 <__fopen_internal+0x72> b6: 89 74 24 0c mov %esi,0xc(%esp) ba: 89 7c 24 08 mov %edi,0x8(%esp) be: 8b 45 f0 mov -0x10(%ebp),%eax c1: 89 1c 24 mov %ebx,(%esp) c4: 89 44 24 04 mov %eax,0x4(%esp) c8: e8 fc ff ff ff call c9 <__fopen_internal+0x89> cd: 85 c0 test %eax,%eax cf: 74 14 je e5 <__fopen_internal+0xa5> d1: 89 5d 08 mov %ebx,0x8(%ebp) d4: 8b 75 f8 mov -0x8(%ebp),%esi d7: 8b 5d f4 mov -0xc(%ebp),%ebx da: 8b 7d fc mov -0x4(%ebp),%edi dd: 89 ec mov %ebp,%esp df: 5d pop %ebp e0: e9 fc ff ff ff jmp e1 <__fopen_internal+0xa1> e5: 89 1c 24 mov %ebx,(%esp) e8: e8 fc ff ff ff call e9 <__fopen_internal+0xa9> ed: 89 1c 24 mov %ebx,(%esp) f0: e8 fc ff ff ff call f1 <__fopen_internal+0xb1> f5: 8b 5d f4 mov -0xc(%ebp),%ebx f8: 31 c0 xor %eax,%eax fa: 8b 75 f8 mov -0x8(%ebp),%esi fd: 8b 7d fc mov -0x4(%ebp),%edi 100: 89 ec mov %ebp,%esp 102: 5d pop %ebp 103: c3 ret 104: 8d b6 00 00 00 00 lea 0x0(%esi),%esi 10a: 8d bf 00 00 00 00 lea 0x0(%edi),%edi 00000110 <_IO_new_fopen>: 110: 55 push %ebp 111: 89 e5 mov %esp,%ebp 113: 83 ec 0c sub $0xc,%esp 116: 8b 45 0c mov 0xc(%ebp),%eax 119: c7 44 24 08 01 00 00 movl $0x1,0x8(%esp) 120: 00 121: 89 44 24 04 mov %eax,0x4(%esp) 125: 8b 45 08 mov 0x8(%ebp),%eax 128: 89 04 24 mov %eax,(%esp) 12b: e8 fc ff ff ff call 12c <_IO_new_fopen+0x1c> 130: c9 leave 131: c3 ret Добавлено через 1 минуту 58 секунд Не, с дизассемблером лажа, там использование внешних имён не подставляется. Так что вычислять надо, как я указал выше - по двум дампам "readelf -s" и "readelf -r"
1
|
10.08.2009, 22:45 [ТС] | 14 |
Спасибо
Буду пробовать. Добавлено через 1 час 26 минут 23 секунды
0
|
11.08.2009, 00:04 [ТС] | 16 |
Нет. Объясняю для чего все это. Есть чужой проект. В него нужно внести изменения. Но, так как проект этот очень большой и очень глючный(я это знаю ), я не хочу влезать в его коды. Так как потом, меня обвинят в том, что это после моего вмешательства все начало дико глючить. По этой причине я и выбрал такой способ. Вот клиент сильно удивится. Возможно он и надеется что я полезу в коды, для того чтоб бесплатно вылечить глюки. вот.
0
|
11.08.2009, 00:06 | 17 |
Ну тогда пишется отдельный скрипт-пускач, в нём выставляется переменная и запускается бинарник
Но надо иметь в виду, что подсунуть ты можешь только те функции, которые в бибилиотеке WEAK. Хотя чёрт его знает, можно и GLOBAL'ы переопределять - поэкспериментируй
0
|
12.08.2009, 11:15 [ТС] | 18 |
Еще проблемка.
Хочу использовать функции _init(), _fini(). Линкер сообщает: Добавлено через 1 час 43 минуты 32 секунды Понял в чем дело. Нужно добавить -nostartfiles
0
|
12.08.2009, 12:17 | 19 |
Если хочешь нормально переопределить _init и _fini - надо их оформить в виде стартовых модулей. Плюс там свои тонкости, потому что без этого библиотека нормально не проинициализируется. Описывать слишком долго, а потому не рекомендую их трогать
Вкратце могу сказать, в модуле crti.o надодится начало процедуры _init, в модуеле crtn.o находится её конец, а тело размазано по куче модулей из библиотек. Аналогично с _fini
0
|
12.08.2009, 12:29 [ТС] | 20 |
Понял.
Мне в любом случае нужны две функции. Одна для инициализации, другая для очистки. Эта библиотека переопределяет некоторые функции, ну я выше писал... Так вот. Помимо переопределения, в ней содержатся некоторые функции, при помощи которых, демон, снабжает ее необходимой информацией(т.е. динамически подгружает, и т.д.). Т.е. я вместо _init(), _fini() назову их к примеру myinit(), myfinish() и вызову их из него. Так нормально? А вообще, что порекомендуете почитать по динамическим библиотекам? Спасибо!
0
|
12.08.2009, 12:29 | |
12.08.2009, 12:29 | |
Помогаю со студенческими работами здесь
20
Перехват и подмена пакетов Перехват сетевых пакетов и их подмена Перехват / подмена потока с микрофона Перехват и подмена имени .dll файла Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |