Титла: LKM rootkit Публикувано от: gat3way в Nov 10, 2008, 23:18 Обхванала ме е една нова краста - пиша си един прост kernel rootkit, просто за да видя дали ще мога да се справя и защото ми е интересно (както винаги като ми дойде такава краста откривам разни забавни нови неща).
Методът, който ползвам е много прост и изтъркан - hijack-вам sys_call_table[]. Понеже таблицата в 2.6 не се експорт-ва съм си реализирал един procfs интерфейс, чрез който подавам от userspace-a адреса на sys_call_table[] (който вземам от System.map). Сега това е доста малоумно като цяло, знам че има доста по-advanced методи, като например тези дето си играят с debug регистрите, знам също и че зависи от System.map (това не е особен проблем, мога да го накарам да зависи и от /proc/kallsyms и да сканира област от паметта, но това не е толкова важно). Засега успях вече да реализирам криене на файлове (това е елементарно, пипам sys_getdents() и където видя въпросният файл просто го подменям с "..\0" доста просто и ефективно). Реализирах и криене на процеси (също не е голяма философия). В случаят правя един глупав номер - прихващам sys_chdir() и ако директорията е един определен стринг, слагам на current (тоя отдето е влезнато в kernelmode) task_struct-а полето pid=0. Убийствено ефективно, процесът престава да съществува запред procfs и никой не може да го види. Единственият проблем е ако процесът някъде викне exit() което краш-ва ядрото. За целта прихванах и sys_exit()/sys_exit_group() така че ако current task_struct->pid ==0, да го смени на current task_struct->tgid и чак тогава да викне оригиналният sys_exit(). Стана си стабилно и работи много добре. Просто трябва като си викнете bash shell-a да напишете "cd secretstring" и шела престава да съществува. Реализирах и ескалиране на привилегии - по елементарен начин, много подобно на горния пример - на current task_struct->uid се дава стойност 0. При което процесът започва да работи с root привилегии, което е доста забавно :) Сега остава да почна да крия сокети, за което имам идея как да стане - ще трябва обаче да прихвана sys_read() най-вероятно. Другото което е - да скрия модула от списъка със заредени такива - не съм убеден, че ще стане, но доколкото знам всички заредени модули се пазят в някакъв свързан списък - просто ще разкарам моят оттам ако е възможно. Това още не съм го проучил, но не мисля, че ще е проблем. Ако ли не, ще видя дали не мога да направя нещо по въпроса с четенето от /proc/modules. Сега остава най-забавното, за което нямам много идея как да стане - да си осигурим remote достъп. Разбира се мога да bind-на един сокет с nc, той да вика шел когато се вържеш (nc -l port -c /bin/bash) и да ги скрия, ама това не е много умно. Първо защото ще има слухтящ сокет, дори да го скрия от procfs (съответно netstat), едно сканиране на машината с nmap ще го покаже и ще почнат подозрения. За целта мисля да пробвам с нещо, дето се занимавах преди време - netfilter hooks. Ще сет-на един такъв, който дроп-ва пакетите на този порт освен ако не са от определен source адрес. Ще е малко грубо, но ще свърши работа. Обаче не знам...само това ли трябва да се очаква от един rootkit? Гледах значи 1-2 писани неща...там те крият когато някой интерфейс влезе в promiscuous режим (това нямам идея как да го направя). Могат да логват нещата минали през tty-та, което ми се вижда леко безсмислено. И въпреки това, каква още функционалност би следвало да има (освен криене на процеси/сокети/файлове)? Другото което ми е много интересно е някакъв начин това да може да се зарежда автоматично при reboot (достатъчно скрито - като редактираш инитскриптове това обикновено се забелязва). Може би може да се измисли някаква схема с инитскриптовете където модификацията се "скрива" от администратора, но това ми се вижда ужасно сложна работа за реализация в kernelmode. Дали няма някакъв по-лесен начин? Също така ми е интересно какво още би трябвало да се скрие? Аз мислех по въпроса че ще е добре да се предпазя от възможността скрит процес да пише неща в syslog, би било голяма простотия. Също така хахорската намеса просто лъщи като разгледаш /proc/kallsyms, поради което и там ще трябва да направя нещо по въпроса. Но честно казано идеите ми са дотам. Та ми е интересно да чуя вие какво мислите? Примерно ако се усъмните, че някой ви е хахорнал машинката, какво бихте проверили? А, да, срещу rkhunter още не съм правил тестове, рано е още :) Титла: Re: LKM rootkit Публикувано от: ANTIADMIN в Nov 11, 2008, 00:05 цитат->Та ми е интересно да чуя вие какво мислите? Примерно ако се усъмните, че някой ви е хахорнал машинката, какво бихте проверили?
sniff, sniff ;D паля tripwire и веднага лъсваш, имаше още няква глупост ossec май се казваше ;D А какво те притеснява рибута? Според мен ще е грешка да е универсален, т.е. само да се крие и да прави нещо, да краде, да те пуска вътре, но не всичко наведнъж. Ма аз съм с БСД, не вървиш с тоя руткит ;D Титла: Re: LKM rootkit Публикувано от: gat3way в Nov 11, 2008, 00:10 Ами tripwire прави MD5 суми на всички файлове от файловите системи, поради което ще намери дедовия си :) Красотата на kernel-базираните rootkits е че не се модифицират binaries или библиотеки, вместо това зареждаш модул за ядрото, който прихваща системни извиквания и прави каквото си знае с тях :) Което е по-бруталното, прихващайки системни извиквания за четене на файлове на теория би могъл да накараш програми като tripwire да вярват, че модифициран файл няма никаква промяна. Но това си е чисто на теория. Специално в случаят tripwire не ми пречи - по-скоро някакви гадости, които имат навика да проверяват интегритета на sys_call_table[] ще го открият веднага, защото адресите на някои функции са променени.
Титла: Re: LKM rootkit Публикувано от: ANTIADMIN в Nov 11, 2008, 00:16 IntoXonia - LKM rootkit for Linux Kernel 2.6.x
Код: (*) скрытие файлов/каталогов (*) скрытие процессов (*) имитация полного удаления файлов (*) перенаправление обращения к файлам (*) перенаправление входа в директории (*) запрет на обращение к файлам (*) запрет на вход в каталог (*) добавление фиктивной строки в файл (*) скрытие строки из файла (*) замена строк в файле при чтении (*) защита файла от удаления (*) сохранение файла при удалении (*) защита процессов (*) создание алиасов для команд (*) перенаправление запуска бинарников (*) запрет на запуск программ (*) запись всех нажатых клавиш (кейлоггер) (*) сниффер POP3/FTP паролей (*) сохранение настроек в файл (*) загрузка настроек из файла (*) получение прав root (*) смена uid/gid процесса (*) защищенное удаление файлов (*) настройка с помощью фиктивного бинарника (*) защита всех настроек паролем http://damagelab.org/index.php?showtopic=5633&hl=intoxonia Ето например тоя какво прави ;D Ти да не четеш в оня сайт от США на издателите на книгата за уиндоус кърнъла? Като си готов, ще си пожелаем и други функции ;D Титла: Re: LKM rootkit Публикувано от: gat3way в Nov 11, 2008, 00:30 Да живее google translate :D
(*) To hide files / directories (*) to hide processes това е готово (*) imitation of a complete removal of the files (*) това е идейно :) redirection of the files (*) redirecting the entrance to the directory не виждам смисъл, ама ОК - и sys_open() можем да бутнем. ban on entry in the directory ( *) не ми допада като идея. Adding fictitious line in the file (*) to hide file lines Идейно. Върху това може да се поработи. (*) replacement strings in the file while reading Дефакто същото като горното. (*) file protection from removal не, тъпо е - само буди подозрения. (*) save the file when you remove И това е интересно (*) Creating an alias for a command ( *) Redirect start binaries (*) ban on launching programs (*) record all keystrokes (keyloggers) (*) sniffer POP3/FTP passwords Не ми допада като идея. (*) save settings file (*) to retrieve configuration file ?!? (*) rights root Направено е. (*) Change uid / gid process Няма нужда. (*) securely delete files Интересно, но няма особен смисъл - мога да си ги занулявам и без да пиша код по въпроса. (*) setting using fictitious binaries Това е забавната странична черта на това че ползвам procfs. При мен може и с echo > procfs. (*) protection of all settings, password Ммм не. Russian » English Translate Мдам. Титла: Re: LKM rootkit Публикувано от: gat3way в Nov 11, 2008, 23:56 Хм много грубо.
Когато един скрит процес форк-не нов такъв, той има "нормален" PID (не 0). Следователно всякакви форкнати процеси се виждат. Мислех известно време как да реша този проблем, първо реших, че може да прихвана sys_execve(), но това се оказа ОГРОМНА грешка, костваща много крашвания. Прихващането на точно тая функция е едно безумие. Мислех какво да направя, strace-вах известно време bash шела и установих една забавна зависимост - когато се създаде нов процес, libc веднага след зареждането на ELF binary-то увеличава малко големината на heap-а чрез brk(), това за да се грижи за малки заделяния на памет предполагам без да се налага да се влиза в kernelmode. Та воала - прихванах sys_brk() и всеки новосъздаден процес бива скрит. Дотук много добре... ...ооообаче както горе бях споменал, унищожаването на процес, който има pid==0 води до kernel panic и един тъп надпис "attempting to kill an idle task". Сега аз хубаво прихващам sys_exit() но понякога процесите отиват в нищото и поради други причини, примерно щото са получили сигнал някакъв, знам ли, факт е че форк-на ли скрит процес и ако го убия с ctrl-c дефакто убивам машината :) Рових се пак из сорса на ядрото и установих че това се вика от do_exit(). Рових се из гугъл и там на едно място даваха идея как да се оправят нещата. За жалост архитектурно-зависимо. Те предлагат просто този малък регион от паметта, заета от do_exit() който прави CALL panic да се презапише с NOP (0x90). Което звучи не особено сложно, обаче всъшност хич не е така. За мое добро, на 2 машини гледах, тези две функции и на двете се намират една след друга в паметта, примерно така: ffffffff802376f7 T do_exit ffffffff80237dab T do_group_exit Така че аз знам каква част от паметта заема do_exit() и къде се намира. Остава в рамките на този регион да потърся за стойност, отговаряща на адреса на panic (тук примерно според System.map: ffffffff8023482a T panic ) и доволно добре да презапиша с 0x90 стойността, както и за всеки случай малко преди и след нея. Разбира се това ще стане успешно след бая експерименти. А, да, криенето на модула се оказа доста лесно - разкарах го от въпросния свързан списък и модулът вече не се води зареден. Тъпото е че няма rmmod-ване веднъж заредиш ли го, поне не и докато не ребуут-неш машината. И да, голямо приключение се оказва засега. Скоро ще науча наизуст sched.h и syscalls.h ако продължавам в тоя дух :) Титла: Re: LKM rootkit Публикувано от: tarator в Nov 12, 2008, 00:33 Хмм... Не, няма да казвам нищо. Малоумните начинания не трябва да се поощряват :)
Титла: Re: LKM rootkit Публикувано от: gat3way в Nov 12, 2008, 00:37 Мда, докато някой не си строши достатъчно главата с тях :) Съгласен съм, обаче ми е забавно и няма да мирясам, докато не го докарам до работещо състояние :)
Титла: Re: LKM rootkit Публикувано от: tarator в Nov 12, 2008, 02:04 alright. Защо се опитваш да прехванеш sys_exec вместо sys_fork (sys_clone и т.н.)? exec не създава нов процес :Р
Титла: Re: LKM rootkit Публикувано от: gat3way в Nov 12, 2008, 08:46 Не, това наистина го реших вече :)
Защо brk(), а не clone() или fork() - ами малко по-лесно ми излезе :) Апропо, викането на clone() с CLONE_PID от скрит процес автоматично пръква скрито дете. Забавно :) Титла: Re: LKM rootkit Публикувано от: gat3way в Nov 12, 2008, 10:20 Хммм...значи в един форум свързан с kernel програмиране има една тема за intercept-ване на sys_call_table[], където един пич обяснява, че от 2.6.21 нататък това е невъзможно. Когато му казах че е възможно, защото съм го правил вкъщи с 2.6.26 ядро, той вика следното:
Цитат I don't know whether or not this has been changed in Linux 2.6.26-1-amd64, but in Linux 2.6.21.5 as taken from http://kernel.org puts the sys_call_table in a read-only section of the memory. This means that you still cannot fiddle with it. Аз тествам на 2.6.16 (където нямам проблеми) и на 2.6.26 (64-битов) - където пак нямам проблеми. От друга страна, на 2.6.26 има два файла: arch/x86/kernel/entry_32.S: Цитат .section .rodata,"a" и arch/x86/kernel/entry_64.S, който не съдържа такова нещо. Мене ми е интересно дали въобще ядрото признава read-only секции от паметта или не. Обаче нямам i386 машина с ядро над 2.6.21 на която да мога да тествам. Значи направих една много орязана версия на rootkit-а , която дефакто няма rootkit функционалност - не може да крие процеси и файлове, единственото което прави е да patch-не sys_call_table[] и да прихване sys_chdir(). Когато се опитате да влезете в една определена директория (която вие си определяте) ще ви даде грешка и ще излезе едно съобщение в dmesg (TEST SUCCEEDED!). Може ли някой с 32-битов линукс и с ядро > 2.6.21 да го изтества това нещо? Най-лошото, което може да се случи е да крашне системата и да се наложи рестарт, няма други рискове :) http://www.maxishare.net/en/file/8948/rktest-tgz.html Значи в архива има един шел-скрипт (inittest.sh) който трябва да се изпълни, това е почти всичко. Той компилира, зарежда модула, подава му през procfs каквото трябва. Единствено ще трябва да си въведете някакъв secretstring, след края на скрипта да напишете cd secretstring и да видите дали ще се изпише нещо в dmesg. После да разкарате модула с rmmod rktest Може ли някой да го пробва, моля? Титла: Re: LKM rootkit Публикувано от: manul в Nov 12, 2008, 14:28 Цитат root@wattman:/home/manul/Desktop# cd rktest/ При cd magicstring-a изби от рут в обикновен юзер... после при връщане в рут Segmentation fault. Ядро 2.6.27 Титла: Re: LKM rootkit Публикувано от: gat3way в Nov 12, 2008, 15:21 Хм, да, утрепал ти е root-ския шел.
В hacked_chdir() най-вероятното място където съм бъркал неща указани от NULL pointer е онази memcpy() функция, но обяснение за случилото се нямам. Срам, не срам, ще те помоля да пейстнеш make.err, може оттам да излезе някакво обяснение. Това е странно поведение и е моя грешката че ме мързи да проверявам за NULL стойности указателите, преди да ги ползвам. Титла: Re: LKM rootkit Публикувано от: manul в Nov 12, 2008, 15:34 Цитат root@wattman:/home/manul/Desktop/rktest# cat make.err Eто... Титла: Re: LKM rootkit Публикувано от: gat3way в Nov 12, 2008, 15:45 Бафмааму, много странно.
Ако ти се занимава, пробвай да разкоментираш този ред от rktest.c: // printk("xname=%s\n",exname); и после му дай пак ./inittest.sh НЕДЕЙ ДА ИЗПЪЛНЯВАШ cd secretstring!!! Просто след това rmmod модула и виж какво ще изпише в dmesg накрая. Може би има някакъв проблем когато се опитва да си вземе secretstring-a, защо - не знам. А може и да не е там проблема. Иначе поне съм сигурен че sys_call_table[] успява да се презапише, щом ти изгърмява на cd <нещоси>... Титла: Re: LKM rootkit Публикувано от: tarator в Nov 12, 2008, 17:19 gat3way, ще извиняваш, ама скриването при brk е напълно малоумно :) Какво ще стане ако приложението не използва glibc? Какво ще стане ако приложението просто вика fork? :P Дори и в случая когато приложението използва glibc, пак има определен интервал от време, когато процеса е видим и теоретично може да бъде открит. Което пък ми напомня, че ld-linux.so може да се използва доста успешно за откриване на "скрити" процеси :Р
Титла: Re: LKM rootkit Публикувано от: gat3way в Nov 12, 2008, 18:29 И да не използва glibc, рано или късно (твърде вероятно рано) ще опре до brk(), защото heap-а му ще расте и трябва ядрото да му мап-ва физическа памет върху адресното пространство.
Освен ако разбира се не използва някаква memory allocation библиотека, която не използва brk(), а само mmap(). Например предполагам е вероятно някаква jvm да не може да се скрие по този начин. Да, при това положение няма да се скрие. Всъщност това с brk() в началото го прави ld-linux.so, значи статично-билднато нещо при форкване няма да се скрие...веднага. Ще се скрие обаче на първото място където викне malloc(). Та да, не е перфектен механизъма, защото в някои гранични случаи няма да успее. Ако прихвана и mmap() ще се гарантира по-голяма успевяемост. Ти си прав обаче, че трябва да се прихване и fork(). Защото при създаването на child process докато не се викне brk() нямам никаква гаранция че няма да се види. А brk() може и да не вдигне, поради което разни multiprocess неща няма да могат да се скрият. Например ако реша да скрия apache (колкото и тъпо да звучи) твърде вероятно разните worker процеси ще се виждат от време на време. А, да, друго интересно нещо, за което съм много любопитен - memcmp() "безопасна" операция ли е? В смисъл гледам, че човекът го тества с PREEMPT ядро, кво става ако се прекъсне изпълнението на кода точно докато се изпълнява (ако е възможно)? Титла: Re: LKM rootkit Публикувано от: tarator в Nov 12, 2008, 18:54 Доколкото виждам си пропуснал __user в дефиницията на параметъра filename на hacked_chdir. Трябва да използваш getname или strncpy_from_user преди да правиш memcmp. A защо не strcmp? :P
Иначе самата memcmp си е напълно безопасна дори и при PREEMPT. Титла: Re: LKM rootkit Публикувано от: gat3way в Nov 12, 2008, 20:57 Ами в случаят не знам дали е наложително, знам че не е хубаво толкова брутално да пипам данни от userspace-а, от друга страна, не мисля че в случаят това е толкова рисковано.
Защо? Ами никъде в ядрото не пазя указател към тези данни, който да ми трябва при следващо влизане в kernelspace от някой syscall (и където много вероятно указателят ми ще сочи към съвсем друго място разбира се). Обаче съм леко глупав и не знам дали на SMP системи няма вариант това да се окаже проблем. Както и да е, много съм разочарован. Областта от памет, където се намира do_exit не съдържа адреса на panic. Пуснах objdump -D срещу /proc/kcore и установих че (на x86_64) се прави: callq <adresa_na_panic()>, което преведено на машинен код е някаква 5-байтова (?!?) последователност, нямаща нищо общо с адреса на panic(). Понеже пак да кажа че съм тъп и не разбирам от асемблер, нямам идея как със сигурност да намеря къде се намира тая тъпа callq инструкция. Затва ще отеба идеята да нулирам pid-ове. Минавам на план Б - ще крия procfs entries за скритите процеси, това е тъпо щото така по-лесно ще се открива моя зъл rootkit (дали с налучкване на cd /proc/<pid>, дали с налучкване с kill -signal <pid>). Ужасно съм разочарован, но за жалост не съм особено умен да се справя с тоя проблем... |