Анти-руткит для Userland-RootKit Azazel «на коленке»

    Вот шикарная новость от пользователя ValdikSSНовый Userland-RootKit Azazel. Позволю себе процитировать первый абзац:

    Возможно вы слышали про руткиты Jynx и Jynx2. Это так называемые userland-руткиты, они используют возможность переменной LD_PRELOAD, которая позволяет подгружать любые библиотеки до того, как будет запущена программа. Они уже относительно старые, но все еще хорошо работают.
    2 дня назад, Github-пользователь Chokepoint выложил rootkit Azazel. Он основан на исходном коде Jynx и имеет много новых фич:

    Антиотладочные механизмы
    Скрытие от unhide, lsof, ps, ldd
    Скрытие файлов и директорий
    Скрытие удаленных подключений
    Скрытие процессов
    Скрытие логинов
    Скрытие от локального сниффинга трафика через PCAP
    2 бекдора с полноценными шеллами (с PTY):
    — Crypthook accept()-бекдор
    — Обычный accept()-бекдор
    PAM-бекдор для аутентификации под любым пользователем
    Очистка логов utmp/wtmp для PTY
    Обфускация строк скомпилированной библиотеки через xor.


    Таким образом, в рутките используется штатная возможность подгружать через LD_PRELOAD любую библиотеку. Встаёт вопрос, а можно ли это как-то контролировать?



    Чтобы не быть многословным, сразу представлю простое решение для ядра Linux, которое, перехватывая функцию execve (а точнее — sys_execve), сканирует параметры списка переменных окружения (известного как envp) на наличие в них определённой строки, а именно той самой LD_PRELOAD.

    Итак, решение оформлено в виде модуля ядра. Перехват функции основывается на методах, описанных ранее в статьях:



    Для перехвата функции sys_execve используется следующий код:

    DECLARE_KHOOK(sys_execve);
    long khook_sys_execve( const char __user * file,
    		       const char __user * const __user * argv,
    		       const char __user * const __user * envp )
    {
    	long result;
    
    	KHOOK_USAGE_INC(sys_execve);
    
    	scan_env_for((void *)file, (void *)envp, env_token);
    	result = KHOOK_ORIGIN(sys_execve, file, argv, envp);
    
    	KHOOK_USAGE_DEC(sys_execve);
    
    	return result;
    }
    


    Непосредственно перед осуществлением оригинального вызова перехваченной функции sys_execve выполняется поиск соответствия переменных окружения заданной строке env_token. Это делает простая функция scan_env_for:

    void scan_env_for(char * file, char * envp[], const char * token)
    {
    	int i;
    
    	char * string;
    	char * string_ptr;
    
    	if (!envp || !token)
    		return;
    
    	string = kmalloc(MAX_ARG_STRLEN + 1, GFP_KERNEL);
    	if (!string) {
    		debug("Can't get memory for the environ string\n");
    		return;
    	}
    
    	for (i = 0; i < MAX_ARG_STRINGS; i++) {
    		if (get_user(string_ptr, envp + i)) {
    			debug("Can't get user pointer value\n");
    			goto out_kfree;
    		}
    
    		if (string_ptr == NULL)
    			goto out_kfree;
    
    		if (strncpy_from_user(string, string_ptr, MAX_ARG_STRLEN) == -EFAULT) {
    			debug("Can't get user string\n");
    			goto out_kfree;
    		}
    
    		string[MAX_ARG_STRLEN] = 0;
    
    		if (strncmp(string, token, strlen(token)) == 0) {
    			char * filename;
    
    			filename = kmalloc(PATH_MAX + 1, GFP_KERNEL);
    			if (filename) {
    				strncpy_from_user(filename, file, PATH_MAX + 1);
    				filename[PATH_MAX] = 0;
    			}
    
    			debug("Attention, task \"%s\" trying to execute \"%s\" with \"%s\"\n", \
    				current->comm, filename ? filename : "(unknown)", string);
    
    			kfree(filename);
    
    			goto out_kfree;
    		}
    	}
    
    out_kfree:
    	kfree(string);
    }
    


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

    Для проверки работоспособности модуля, после его сборки, можно выполнить следующее:

    $ sudo insmod envscan.ko env_token=\"LD_PRELOAD=\"
    $ dmesg | grep envscan
      [37713.809903] [envscan] Symbol "module_free" found @ ffffffff810bdcd0
      [37713.810190] [envscan] Symbol "module_alloc" found @ ffffffff810407e0
      [37713.810523] [envscan] Symbol "sort_extable" found @ ffffffff81048a90
      [37713.810524] [envscan] Hunting for "LD_PRELOAD="
      [37713.811798] [envscan] Symbol "sys_execve" found @ ffffffff8119ba30
    $ LD_PRELOAD=/lib/ld-linux.so.2 ls
      [37743.786499] [envscan] Attention, task "bash" trying to execute "/bin/ls" with "LD_PRELOAD=/lib/ld-linux.so.2"
    


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

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

    Код модуля доступен на github.
    Share post

    Similar posts

    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 12

      +3
      Ждем Анти-анти-руткит для Userland-RootKit Azazel.
        +2
        Собственно, сам автор (руткита, разумеется) уже написал статью о менее изощрённом способе его детектить. Впрочем, на него тоже найдётся анти-анти-руткит:)
          +1
          Да, в общем-то, было очевидно, что такие руткиты из-под ядра легко детектить. Гораздо интересней, на мой взгляд, все-таки детектить в юзерленде. Есть как минимум еще один способ детекта — детектить скрытые файлы по несовпадению количества инодов.
            0
            Ну а количество инодов вы как хотите узнавать?
              0
              Как угодно. Azazel не скрывает иноды, как и не перехватывает libdl (ну, это пока).
              0
              Можно ли снять общее кол-во инод и всё дерево каталогов одним снепшотом, транзакционно?
          –1
          Вы действительно, считаете, что Ваш пост:
          может служит источником информации о том, как работать с ядром, а именно перехватывать его функции и модифицировать поведение системы.
          ?
            0
            Так не «может служить» же, а «может, служит».
              0
              Исправил :)
              +1
              Вообще-то, да
              0
              Познавательно, но почему бы не использовать systemtap?
                0
                Познавательно же :)

              Only users with full accounts can post comments. Log in, please.