LinuxForum.Fans
Тема

Перехват сискола читающего содержимое директории в ядре linux

Автор: atropos 20 сообщений 10893 просмотров
#206161

сабж. необходимо написать руткит для курсача.

на данный момент пытаюсь заставить работать код взятый из старых источников вроде "хакера". если конкретнее, то я хочу воспользоваться функцией скрытия каталогов. но на ядре 2.6.39, которое я взял для курсача, этот код не работает. в то же время, если верить копирайтам, исходник linux/fs/readdir.c не менялся с 2005 года. так что мне кажется странным то, что "патч" которому уже лет 5, не работает с исходниками которым лет 15. довольно отвлечённых разговоров, вопросы:
1 для того что бы скрыть все каталоги с именем abcde нужно перехватить системный вызов. самым лучшим вызовом для перехвата является getdents64 или можно сделать проще?
2 если я хочу написать свою реализацию getdents64 и снабдить её "фильтром", то где мне найти описание оригинального getdents'а?
3 можно ли сделать некий враппер для getdents64? я много пытался, но ничего не вышло. наверное из-за того что если это вообще можно, то есть какая-то специальная методика?
4 есть ли литература которая затрагивала бы программирование ядра в целом и работу с файловой подсистемой ядра linux в частности? ну или про руткиты. на нашем, буржуйском, испанском или французском языках.

ещё на всякий случай напишу, что:
я знаю, что ядро развивается очень динамично и что копирайты могут врать.
с ядром я работаю впервые.

#206279
atropos написал:
4 есть ли литература которая затрагивала бы программирование ядра в целом и работу с файловой подсистемой ядра linux в частности? ну или про руткиты. на нашем, буржуйском, испанском или французском языках.

лучше всего ИМХО:
"Linux Device Drivers" - переводится в нескольких местах, до конца ещё ни кто не перевёл.
Бовет Чезатти "Ядро linux" - есть на русском.
ещё говорят в "Linux kernel Internals" что-то неплохо описано...(не читал)

atropos написал:
я знаю, что ядро развивается очень динамично и что копирайты могут врать.

изменения всегда можно посмотреть в гите на kernel.org

atropos написал:
2 если я хочу написать свою реализацию getdents64 и снабдить её "фильтром", то где мне найти описание оригинального getdents'а?

grep -r getdents64 .
среди прочего выдаст fs/readdir.c

atropos написал:
на данный момент пытаюсь заставить работать код взятый из старых источников вроде "хакера". если конкретнее, то я хочу воспользоваться функцией скрытия каталогов.

ссылку в студию. его здесь ни кто в глаза не видел...

atropos написал:
1 для того что бы скрыть все каталоги с именем abcde нужно перехватить системный вызов. самым лучшим вызовом для перехвата является getdents64 или можно сделать проще?

в 2.6 перехват сисколов считается злом и sys_call_table не экспортируется... при большом желании можно нагуглить способы изменить её, но всё это грязные вещи... как всё это сделать без внедрения своего кода в ядро - не скажу...

#206375

ptrace может перехватить системный вызов, прочитать данные на входе и выходе, а так же модифицировать их.
ДОБАВЛЕНО: Где-то на wikipedia видел ссылку на исследовательскую работу, я её сохранил, однако эту статью на википедии не могу найти (зато нашлась статья Эякуляция на лицо :O)

#211526
Fat-Zer написал:
[quote=atropos]4 есть ли литература которая затрагивала бы программирование ядра в целом и работу с файловой подсистемой ядра linux в частности? ну или про руткиты. на нашем, буржуйском, испанском или французском языках.

лучше всего ИМХО:
"Linux Device Drivers" - переводится в нескольких местах, до конца ещё ни кто не перевёл.
[/quote]

Неправда wink

Полный перевод от 2010-го года:
http://dmilvdv.narod.ru/Translate/LDD3/index.html?linux_device_drivers.html
(но только online)

#211527
Fat-Zer написал:
в 2.6 перехват сисколов считается злом и sys_call_table не экспортируется... при большом желании можно нагуглить способы изменить её, но всё это грязные вещи... как всё это сделать без внедрения своего кода в ядро - не скажу...

Да, легальных способов перехвата нет.

А всё (!!!) трюкачество относительно ядер 2.6.Х которое я встречал - это хакерское бахвальство, которое переставало работать к следующей подверсии ядра.
Даже примеры 2010 года не работают на сегодня :P

#211528
atropos написал:

4 есть ли литература которая затрагивала бы программирование ядра в целом и работу с файловой подсистемой ядра linux в частности? ну или про руткиты. на нашем, буржуйском, испанском или французском языках.

Посмотрите:
http://rus-linux.net/forum/viewtopic.php?f=3&t=1549
Может чем пригодится?
... и "на вашем" wink

#211530
atropos написал:
код взятый из старых источников вроде "хакера"
atropos написал:
мне кажется странным то, что "патч" которому уже лет 5, не работает с исходниками которым лет 15.

вы уверены, что что этот патч вообще работал когда-то?

atropos написал:
1 для того что бы скрыть все каталоги с именем abcde нужно перехватить системный вызов.

простите, я не понял. Почему вы не хотите этот вызов попросту переделать? Встроить туда свой фильтр например? Что мешает? Места нету? Ну сломайте что-нить ненужное на целевой системе (которую вы ломаете).

Olej написал:
А всё (!!!) трюкачество относительно ядер 2.6.Х которое я встречал - это хакерское бахвальство, которое переставало работать к следующей подверсии ядра.

естественно. А оно нужно? У нас задача - сломать целевую систему. Задачи написать вирус никто не ставил wink

Olej написал:
Посмотрите:

сколько можно этот свой руслинукс и к месту и не к месту пиарить?

#211531
drBatty написал:

[quote=Olej]Посмотрите:

сколько можно этот свой руслинукс и к месту и не к месту пиарить?[/quote]

Потому, что это ответ на прямой вопрос.

К вам это не относится, так что можете не тревожиться по пустякам wink

#213354

В разборку вопроса писал, писал тест-модуль ... и написал wink
Про то, что в 2.6.х ядре из числа экспортируемых имён убрали таблицу системных вызовов sys_call_table - это только ленивый не знает...
Так вот модулёк, который "достаёт" sys_call_table, а затем и точку входа любого обработчика sys_*(). Так что дальше подменить его (для мониторинга, например) уже совсем проще простого.
Вот модуль:

text

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/moduleparam.h>

static char* file = "/proc/kallsyms"; module_param( file, charp, 0 ); static int debug = 0; module_param( debug, int, 0 );

static unsigned long hex2adr( char *b ) { unsigned long res = 0; char *p = b, *d; const char *dig = "0123456789abcdef"; while( ( d = strchr( dig, *p ) ) != NULL ) { res = ( res << 4 ) + ( d - dig ); p++; } return res; }

int verify_close( unsigned long *a ) { extern int sys_close( int fd ); int cmp; unsigned long ca = *( a + __NR_close ); cmp = ( (void*)ca == (void*)sys_close ) ? 0 : 1; return cmp; }

void put_table( char *b ) { int i; char table[ 120 ] = "sys_call_table : "; unsigned long *a; unsigned long s = hex2adr( b ); a = (void*)s; printk( "+ sys_call_table address = %p\n", a ); if( verify_close( a ) != 0 ) { printk( "+ sys_close address not valid!\n" ); return; } for( i = 0; i < 10; i++ ) { unsigned long sa = *( a + i ); sprintf( table + strlen( table ), "%p ", (void*)sa ); } printk( "+ %s ...\n", table ); }

#define BUF_LEN 255 static int __init stread_init( void ) { struct file *f; size_t n = 0; char buff[ BUF_LEN + 1 ] = "";

f = filp_open( file, O_RDONLY, 0 ); if( IS_ERR( f ) ) { printk( "+ failed to open: %s\n", file ); return -ENOENT; } printk( "+ openning file: %s\n", file );

while( 1 ) { char *p = buff, *find; int k; *p = '\0'; do { if( ( k = kernel_read( f, n, p++, 1 ) ) < 0 ) { printk( "+ failed to read\n" ); return -EIO; }; *p = '\0'; if( 0 == k ) break; n += k; if( '\n' == *( p - 1 ) ) break; } while( 1 ); if( ( debug != 0 ) && ( strlen( buff ) > 0 ) ) { if( '\n' == buff[ strlen( buff ) - 1 ] ) printk( "+ %s", buff ); else printk( "+ %s|\n", buff ); } if( 0 == k ) break; // EOF

if( NULL == ( find = strstr( buff, "sys_call_table" ) ) ) continue; put_table( buff ); } printk( "+ close file: %s\n", file ); filp_close( f, NULL ); return -EPERM; }

module_init( stread_init ); MODULE_LICENSE( "GPL" ); MODULE_AUTHOR( "Oleg Tsiliuric <olej@front.ru>" );

А вот его результат (если без debug параметра запускать):

text

[olej@notebook call_table]$ sudo insmod mod_rct.ko
insmod: error inserting 'mod_rct.ko': -1 Operation not permitted

[olej@notebook call_table]$ dmesg | tail -n50 | grep + + openning file: /proc/kallsyms + sys_call_table address = c07ab3d8 + sys_call_table : c044ec61 c0444f63 c040929c c04e149d c04e12fc c04dec35 c04dea99 c0444767 c04dec60 c04ecb22 ... + close file: /proc/kallsyms

А вот что это есть? проверка обратным путём:

text

[olej@notebook ~]$ cat /proc/kallsyms | grep c044ec61
c044ec61 T sys_restart_syscall
[olej@notebook ~]$ cat /proc/kallsyms | grep c0444f63
c0444f63 T sys_exit
[olej@notebook ~]$ cat /proc/kallsyms | grep c040929c
c040929c t ptregs_fork
[olej@notebook ~]$ cat /proc/kallsyms | grep c04e149d
c04e149d T sys_read
[olej@notebook ~]$ cat /proc/kallsyms | grep c04e12fc
c04e12fc T sys_write
[olej@notebook ~]$ cat /proc/kallsyms | grep c04dec35
c04dec35 T sys_open
[olej@notebook ~]$ cat /proc/kallsyms | grep c04dea99
c04dea99 T sys_close
[olej@notebook ~]$ cat /proc/kallsyms | grep c0444767
c0444767 T sys_waitpid
[olej@notebook ~]$ cat /proc/kallsyms | grep c04dec60
c04dec60 T sys_creat
[olej@notebook ~]$ cat /proc/kallsyms | grep c04ecb22
c04ecb22 T sys_link

И те же вызовы по номерам:

text

[olej@notebook etc]$ cat /usr/include/asm/unistd_32.h | head -n20
...
#define __NR_restart_syscall      0
#define __NR_exit                 1
#define __NR_fork                 2
#define __NR_read                 3
#define __NR_write                4
#define __NR_open                 5
#define __NR_close                6
#define __NR_waitpid              7
#define __NR_creat                8
#define __NR_link                 9
#define __NR_unlink              10
...

Вот вам и "не экспортируется"!

#213377

месье знает толк в извращениях =)
всё куда проще:

text
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/kallsyms.h>

static int __init ksys_call_tbl_init(void) { void** sct = (void**)kallsyms_lookup_name("sys_call_table"); printk(KERN_ALERT "sys_call_table = %lx\n", (long)sct); if(sct) printk(KERN_ALERT "%lx %lx %lx\n", (long)sct[0], (long)sct[1], (long)sct[2]); return -100500; }

module_init(ksys_call_tbl_init); MODULE_LICENSE( "GPL" );

#213417
Fat-Zer написал:

всё куда проще:

Fat-Zer, это здорово, если это работает wink , посмотрю...
Но мне кажется, что вы противоречите сами себе:

Fat-Zer написал:

[quote=atropos]
1 для того что бы скрыть все каталоги с именем abcde нужно перехватить системный вызов. самым лучшим вызовом для перехвата является getdents64 или можно сделать проще?

в 2.6 перехват сисколов считается злом и sys_call_table не экспортируется... при большом желании можно нагуглить способы изменить её, но всё это грязные вещи... как всё это сделать без внедрения своего кода в ядро - не скажу...
[/quote]
Какие тогда это "грязные вещи", если вы использовали для этого легальный kernel API.
Да, я встречал описания, разные способы получения таблицы sys_call_table ... но все они изощрённые + перестают работать от версии к версии ядра. Но если это вызов API, то какой тогда смысл не экспортировать sys_call_table?

#213453
Olej написал:
Но мне кажется, что вы противоречите сами себе:

заблуждался: получить адрес - реально, а вот использовать его - не хорошо... можно купить топор, но вот зарубить им на соседа всё равно не хорошо...

Olej написал:
какой тогда смысл не экспортировать sys_call_table?

чтобы его не использовали, ибо тогда у обычных разработчиков появляется соблазн сотворить всякую фигню(типа подмены системных вызовов).

ЗЫ: не знаю, в какой версии появилась эта функция. в .2.6.39 - она есть

#213506
Fat-Zer написал:
[quote=Olej]Но мне кажется, что вы противоречите сами себе:

заблуждался: получить адрес - реально, а вот использовать его - не хорошо... можно купить топор, но вот зарубить им на соседа всё равно не хорошо...
[/quote]
Всё равно как-то непоследовательно... убрать из экспорта, но сохранить доступ?

Fat-Zer написал:

[quote=Olej]какой тогда смысл не экспортировать sys_call_table?

чтобы его не использовали, ибо тогда у обычных разработчиков появляется соблазн сотворить всякую фигню(типа подмены системных вызовов).
[/quote]
Совершенно не обязательно фигню, такой техникой делалось (и делается!) множество вещей в самых разных ОС, начиная с MS-DOS и ещё раньше: и мониторинг разный, и статистики, и отладочные цели...
А от использования "в фигню" здесь страхует, в гораздо большей степени, чем устранение из экспорта, необходимость для всех этих дел прав root.

#213524
Fat-Zer написал:
ЗЫ: не знаю, в какой версии появилась эта функция. в .2.6.39 - она есть
text

[olej@nvidia ~]$ uname -r
2.6.35.14-96.fc14.i686.PAE

[olej@nvidia ~]$ cat /proc/kallsyms | grep kallsyms_lookup_name | grep T c0469a0e T module_kallsyms_lookup_name c046a0ae T kallsyms_lookup_name

[olej@notebook ~]$ uname -r 2.6.32.9-70.fc12.i686.PAE

[olej@notebook ~]$ cat /proc/kallsyms | grep kallsyms_lookup_name | grep T c046e815 T module_kallsyms_lookup_name c04717f2 T kallsyms_lookup_name

что делает 1-й из вызовов? символы из модулей?

#213535

kallsyms_lookup_name проверяет только символьные таблицы ядра. если ничего не нашёл, то он вызывает module_kallsyms_lookup_name, который проверяет модули. Последний не экспортируется.

#213539
Olej написал:
[quote=Fat-Zer]ЗЫ: не знаю, в какой версии появилась эта функция. в .2.6.39 - она есть
text

[olej@nvidia ~]$ uname -r
2.6.35.14-96.fc14.i686.PAE

[olej@nvidia ~]$ cat /proc/kallsyms | grep kallsyms_lookup_name | grep T c0469a0e T module_kallsyms_lookup_name c046a0ae T kallsyms_lookup_name

[olej@notebook ~]$ uname -r 2.6.32.9-70.fc12.i686.PAE

[olej@notebook ~]$ cat /proc/kallsyms | grep kallsyms_lookup_name | grep T c046e815 T module_kallsyms_lookup_name c04717f2 T kallsyms_lookup_name

[/quote]

Но

text

[olej@notebook call_table]$ uname -r
2.6.32.9-70.fc12.i686.PAE
[olej@notebook call_table]$ make
make -C /lib/modules/2.6.32.9-70.fc12.i686.PAE/build M=/home/olej/2011_WORK/LINUX-books/examples.DRAFT/sys_call_table/call_table modules
...
WARNING: "kallsyms_lookup_name" [/home/olej/2011_WORK/LINUX-books/examples.DRAFT/sys_call_table/call_table/mod_kct.ko] undefined!
...  
#213541

нуда... значит он не экспортируется.... из того, что у меня под рукой было:

text

alexander@goblin /tmp $ tar -xjf /usr/portage/distfiles/linux-2.6.32.tar.bz2
alexander@goblin /tmp $ cd linux-2.6.32/
alexander@goblin /tmp/linux-2.6.32 $ grep kallsyms_lookup_name kernel/kallsyms.c
unsigned long kallsyms_lookup_name(const char *name)
        return module_kallsyms_lookup_name(name);
alexander@goblin /tmp/linux-2.6.32 $ grep kallsyms_lookup_name /usr/src/linux-2.6.39-gentoo-r3/kernel/kallsyms.c
unsigned long kallsyms_lookup_name(const char *name)
        return module_kallsyms_lookup_name(name);
EXPORT_SYMBOL_GPL(kallsyms_lookup_name);
alexander@goblin /tmp/linux-2.6.32 $ grep kallsyms_lookup_name /usr/src/linux-3.0./kernel/kallsyms.c
linux-3.0.4/        linux-3.0.6-gentoo/
alexander@goblin /tmp/linux-2.6.32 $ grep kallsyms_lookup_name /usr/src/linux-3.0.6-gentoo/kernel/kallsyms.c
unsigned long kallsyms_lookup_name(const char *name)
        return module_kallsyms_lookup_name(name);
EXPORT_SYMBOL_GPL(kallsyms_lookup_name);
alexander@goblin /tmp/linux-2.6.32 $ grep kallsyms_lookup_name /usr/src/linux-3.0.4/kernel/kallsyms.c
unsigned long kallsyms_lookup_name(const char *name)
        return module_kallsyms_lookup_name(name);
EXPORT_SYMBOL_GPL(kallsyms_lookup_name);
alexander@goblin /tmp/linux-2.6.32 $ cd ..
alexander@goblin /tmp $ tar -xjf /usr/portage/distfiles/linux-2.6.36.tar.bz2
alexander@goblin /tmp $ grep kallsyms_lookup_name linux-2.6.36/kernel/kallsyms.c
unsigned long kallsyms_lookup_name(const char *name)
        return module_kallsyms_lookup_name(name);
EXPORT_SYMBOL_GPL(kallsyms_lookup_name);
alexander@goblin /tmp $

можно обойти все символы через kallsyms_on_each_symbol.
всё разумней, чем читать файл из proc wink

#213543
Fat-Zer написал:
нуда... значит он не экспортируется....

А вот

text

[olej@nvidia call_table]$ uname -r
2.6.35.14-96.fc14.i686.PAE
text

[olej@nvidia call_table]$ make
...

[olej@nvidia call_table]$ sudo insmod mod_kct.ko insmod: error inserting 'mod_kct.ko': -100500 Success

[olej@nvidia call_table]$ dmesg | tail -n2 [ 7438.397186] sys_call_table = c07c2438 [ 7438.397190] c044e80c c0443af8 c0408a04

text

[olej@nvidia call_table]$ cat /proc/kallsyms | grep c07c2438
c07c2438 R sys_call_table
[olej@nvidia call_table]$ cat /proc/kallsyms | grep c044e80c
c044e80c T sys_restart_syscall
[olej@nvidia call_table]$ cat /proc/kallsyms | grep c0443af8
c0443af8 T sys_exit
[olej@nvidia call_table]$ cat /proc/kallsyms | grep c0408a04
c0408a04 t ptregs_fork

Всё ОК.
Так и запишем : wink ... начинает экспортироваться где-то между 2.6.32 и. 2.6.35

#213544
Fat-Zer написал:
можно обойти все символы через kallsyms_on_each_symbol.
всё разумней, чем читать файл из proc wink

Посмотрю.

#213560
Fat-Zer написал:
можно обойти все символы через kallsyms_on_each_symbol.
всё разумней, чем читать файл из proc wink

Мне в чтении /proc/kallsyms самым интересным было проверить как будет происходить последовательное чтение очень большого файла, без lseek().
Всё сложилось.

Войдите или зарегистрируйтесь, чтобы ответить.