LINUX.ORG.RU

Ответ на: комментарий от true_admin

Я пытаюсь вызвать функцию readdir по своему указателелю this_readdir который указывает на функцию readdir из структуры struct file_operations ядра. При попытке вызова, вылазит данная ошибка:

[ 8477.038921] kernel tried to execute NX-protected page - exploit attempt? (uid: 0)
[ 8477.039038] BUG: unable to handle kernel paging request at c1904ea0

[ 8477.039135] IP: [<c1904ea0>] quota_genl_family+0x60/0x60
[ 8477.039256] *pdpt = 0000000001a45001 *pde = 0000000033591063 *pte = 8000000001904163 
[ 8477.039336] Oops: 0011 [#1] SMP 

[ 8477.039413] Modules linked in: test_module(OF) nls_utf8 isofs(F) vboxsf(OF) vesafb(F) snd_intel8x0 snd_ac97_codec joydev(F) ac97_bus hid_generic snd_pcm(F) usbhid hid snd_page_alloc(F) snd_seq_midi(F) snd_seq_midi_event(F) snd_rawmidi(F) snd_seq(F) vboxvideo(OF) drm snd_seq_device(F) snd_timer(F) ppdev(F) microcode(F) rfcomm psmouse(F) bnep bluetooth snd(F) i2c_piix4 serio_raw(F) ohci_pci soundcore(F) vboxguest(OF) parport_pc(F) mac_hid lp(F) parport(F) ahci(F) libahci(F) e1000(F)

[ 8477.039508] CPU: 0 PID: 2925 Comm: ls Tainted: GF          O 3.11.0-12-generic #19-Ubuntu
[ 8477.039567] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
[ 8477.039620] task: e504b380 ti: dc946000 task.ti: dc946000

[ 8477.039668] EIP: 0060:[<c1904ea0>] EFLAGS: 00010296 CPU: 0
[ 8477.039712] EIP is at proc_root+0x0/0x54
[ 8477.039752] EAX: dc883b40 EBX: dc947f84 ECX: 00000022 EDX: dc947f84
[ 8477.039788] ESI: dc883b40 EDI: dc883b40 EBP: dc947f58 ESP: dc947f44
[ 8477.039821]  DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
[ 8477.039854] CR0: 80050033 CR2: c1904ea0 CR3: 22378000 CR4: 000006f0

[ 8477.039885] Stack:
[ 8477.039909]  f970e07b f97120e4 c1904ea0 c164ff00 dc947f84 dc947f74 c117a4a6 00000001
[ 8477.039935]  f542208c dc883b40 00008000 00000000 dc947fac c117a9ae 00000000 00000000
[ 8477.039943]  c117a6d0 00000000 00000000 08d51454 00000000 00008000 00000000 00000003

[ 8477.039954] Call Trace:
[ 8477.039967]  [<f970e07b>] ? this_readdir+0x6b/0x90 [test_module]   // это указатель через который вызываю функцию ядра
[ 8477.039984]  [<c117a9ae>] SyS_getdents64+0x6e/0xe0
[ 8477.039987]  [<c117a6d0>] ? filldir+0xf0/0xf0
[ 8477.039996]  [<c1632ccd>] sysenter_do_call+0x12/0x28

[ 8477.039998] Code: 4e 90 c1 38 12 b2 c1 38 12 b2 c1 80 4e 90 c1 80 4e 90 c1 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 <01> 00 00 00 6d 41 00 00 0d 00 00 00 00 00 00 00 00 00 00 00 00
[ 8477.040020] EIP: [<c1904ea0>] proc_root+0x0/0x54 SS:ESP 0068:dc947f44
[ 8477.040023] CR2: 00000000c1904ea0
[ 8477.040032] ---[ end trace 0033d851cd910468 ]---



Пробовал использовать такой код, чтоб снять NX bit


/* снятие защиты */
int set_kernel_exec(unsigned long vaddr, int enable)
{
	pte_t *pte;
        unsigned int level = 0;
	int ret = 1;

	pte = lookup_address(vaddr, &level);

	if (pte_val(*pte) & _PAGE_NX) ret = 0;

	if (enable){	pte->pte_high &= ~(1 << (_PAGE_BIT_NX - 32));}
	else
        {pte->pte_high |= 1 << (_PAGE_BIT_NX - 32);}
	__flush_tlb_all();
out:
	return ret;
}

/* вызывал функцию так */
set_kernel_exec((unsigned long)this_readdir, 1);


После этого, при попытке вызова this_readdir система виснет.
Прошу помощи, т.к. сам уже опустил руки. Находил в сети https://github.com/cormander этот человек задавал точно такойже вопрос на англоязычном форуме, но несколько лет назад. Скачивал его исходники, искал код который может пригодится. Но нужного не нашёл.
Очень рассчитываю на помощь.

linuxcore ()
Ответ на: комментарий от linuxcore

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

Krieger_Od ★★ ()
Ответ на: комментарий от derlafff

Мне нужно заменить обработку одной функции ядра, другой (своей).
Тут замена функции ядра идёт, но полагаю замена syscall должна быть полностью аналогична.

Если у Вас есть какой-то код, который может мне помочь, то буду благодарен, очень.

linuxcore ()
Ответ на: комментарий от linuxcore

Тут замена функции ядра идёт, но полагаю замена syscall должна быть полностью аналогична.

Вообще, нет. Там тупой массив с указателями на функции-обработчики системных вызовов, достаточно снять защиту от записи и отредактировать

Именно мой код прямо сейчас не могу дать, но недавно натыкался на годного чувака:

http://habrahabr.ru/users/milabs/topics/

https://github.com/milabs?tab=repositories

и вроде вот: https://github.com/milabs/kmod_hooking

derlafff ★★★★★ ()
Последнее исправление: derlafff (всего исправлений: 1)
Ответ на: комментарий от linuxcore

Я пытаюсь вызвать функцию readdir по своему указателелю this_readdir который указывает на функцию readdir из структуры struct file_operations ядра.

ты пытаешься прыгнуть на указатель по своему указателю вместо вызова функции?

exception13 ★★★★★ ()

Тут недавно один с таким же вопросом ходил, это не ты часом вторую попытку предпринял?

false ★★★★★ ()
Ответ на: комментарий от linuxcore

По-моему, замена syscall это типовая задача, есть куча кода в инете. Но у тебя может быть совсем другой случай. Не уверен что тебе это поможет, но.. ты видел эти ссылки?

http://stackoverflow.com/questions/16957892/replacing-static-function-in-kern... http://stackoverflow.com/questions/1196944/can-i-replace-a-linux-kernel-funct...

true_admin ★★★★★ ()
Ответ на: комментарий от linuxcore

Тут замена функции ядра идёт, но полагаю замена syscall должна быть полностью аналогична.

Ты полагаешь неправильно. Да и вообще ты похож на крякера-малолетку - хочешь обойти NX, настоящую задачу формулировать отказываешься.

tailgunner ★★★★★ ()

Оффтоп: а я ядре Linux есть хоть какая-то защита чтобы одна подсистема не нагадила по ошибке в другую подсистему? Хотя бы минимальная защита памяти есть? Подробнее... Ну если не полная изоляция процессов как в микроядре, но хоть что то...

I-Love-Microsoft ★★★★★ ()
Ответ на: комментарий от exception13

«ты пытаешься прыгнуть на указатель по своему указателю вместо вызова функции?»
Я пробую сделать свой обрабочик функции readdir который в конце вызывает оригинальную функцию readdir ядра.


выглядит так

  int (*this_readdir) (struct file *, void *, filldir_t); // оригинальная функция обрабочик
  
  int my_readdir (struct file *, void *, filldir_t)
  {
    // моя функция обработчик, в неё попадаем без проблем
    return this_readdir(struct file *, void *, filldir_t); // код который не удаётся выполнить
  }


// в структуре struct file_operations ядра изменяю указатель readdir на my_readdir  
// (далее код корректно заходит в функцию my_readdir  
// но выдаёт ошибку при вызове оригинальной функции)



true_admin ссылки не видел, почитаю. спасибо.
tailgunner Вы сказали что замена syscall не аналогична , замене функции обработчика самого ядра. Если не сложно объясните в чём различие.
Задача котороая передомной стоит изложена выше, если подскажите как её решить, буду благодарен.
derlafff
Спасибо за ссылки! интересно почитать про http://habrahabr.ru/post/206778/
И ещё смотрел код kmod_hooking. Пока не разобрался, досконально как он работает, постараюсь сейчас понять принцип работы и попробую.

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

linuxcore ()
Ответ на: комментарий от I-Love-Microsoft

а я ядре Linux есть хоть какая-то защита чтобы одна подсистема не нагадила по ошибке в другую подсистему?

Ну, с моей обывательской точки зрения, нет т.к. всё крутится в одном адресном пространстве. Но какая-то изоляция от сбоев есть. Начиная от макроса BUG_ON и заканчивая некоторыми специфичными обработчиками исключений и вещами типа nmi_watchdog итп. Т.е. разыменовывание нулевого указателя в обычном модуле ядра вряд ли подвесит систему.

true_admin ★★★★★ ()
Ответ на: комментарий от linuxcore

Похожий use-case, правда другая OS. Но думаю паралелли есть: подмена syscall'а и последующий вызов оригинальной функции.

rlimit — мой простенький модуль для OpenBSD (NX, между прочим, в опене был чуть ли не одним из первых)

Вообще, ошибка с NX говорит мне только, что где-то у тебя стек портится.

beastie ★★★★★ ()
Последнее исправление: beastie (всего исправлений: 3)
Ответ на: комментарий от linuxcore

Не вчитывался — не знаю. Вообще-то NX выключается/выключался в BIOS'е. Но это абсолютно неправильное решение. Ищи проблемы в своём коде, а не пытайся их решить через заднепроходнее отверстие. На то NX и создавался, что бы исключить подобные грязные хаки, ломающие всё и вся.

beastie ★★★★★ ()
Последнее исправление: beastie (всего исправлений: 1)
Ответ на: комментарий от linuxcore

return this_readdir(struct file *, void *, filldir_t); // код который не удаётся выполнить

Ты издеваешься? Этот код даже не скомпилируется.

tailgunner ★★★★★ ()
Ответ на: комментарий от linuxcore

У тебя или пседо-код, или мы что-то не поняли.

Код вот такой?

int
my_readdir (struct file *fd, void *v, filldir_t f)
{
    return this_readdir(fd, v, f);
}

Пардон за глупость вопроса, но всё же.

beastie ★★★★★ ()
Последнее исправление: beastie (всего исправлений: 1)
Ответ на: комментарий от linuxcore

Всё таки, показал бы ты лучше код. А так гадание на кофейной гуще выходит. Может у тебя там большие локальные структуры, а стек IIRC в кернеле ограничен — часто имеет смысл (? но тут я не эксперт) их определить глобально.

beastie ★★★★★ ()
Ответ на: комментарий от beastie

Тут дело не в стеке, нет больших структур (кстати как помню, в стеке может быть 1024 байта, для одной функции) . Тут ошибка именно с защитой памяти от выполнения. Надо блокировку снять и должно заработать, а как это сделать ума не приложу.
Толькочто подумал, можно попробовать снять блокировку на выполнение кода в ядре, через команду системе (с прикладного уровня) а дальше уже грузить модуль для теста, посмотреть что будет. Кто знает? как сделать?

linuxcore ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.