Zamolxis666 Posted November 1, 2010 Report Posted November 1, 2010 Cu ceva in urma am intrebat pe forum ce inseamna shellcode, ce face el samd. Intrucat nu am fost suficient lamurit, m-am gandit sa ma documentez mai mult si asta a rezultat in urmatorul tutorial:1. Introduction1.1 Ce este shellcode-ul?In domeniul securitatii calculatoarelor, luat ad-literam, shellcode-ul inseamna scrierea de cod care returneaza un remote shell cand este executat. Intelesul cuvantaului, insa, a evoluat, in zilele noastre reprezentand orice cod care urmeaza a fi inserat intr-o vulnerabilitate cu scopul ca aplicatia exploatata sa indeplineasca anumite sarcini, altele decat si le-a dorit programatorul.1.2 PrerechiziteNe vom concentra pe scriere de cod pt sistem linux cu arhitectura x86. Aceleasi metode si principii pot fi aplicate si pe diferite variante de UNIX sau Win32, dar trebuie avute in vedere diferentele intre conventiile pentru apelul functiilor de sistem. Pentru a scrie cod in limbaj de asamblare vom folosi nasm. Vom avea nevoie si de un debugger sau de un tool pentru citirea object code-ului cum ar fi objdump. 1.3 Care sunt diferentele intre shellcode-ul de pe Windows si cel de pe Linux?Spre deosebire de Windows, Linux-ul ofera o interfata directa cu kernel-ul prin intermediul intreruperii (sau instructiunii, depinde de interpretare) int 0x80. De cealalta parte, Windows-ul nu dispune de o interfata directa cu kernel-ul. Sistemul lucreaza prin incarcarea adresei functiei care trebuie executata dintr-un DLL (Diynamic Link Library). Principala diferenta dintre cele doua sisteme este faptul ca adresele functiilor din Windows variaza de la o versiune la alta a sistemului de operare, in timp ce int 0x80 ramane aceeasi.1.4 Cum gasim adresele functiilor din DLL-uri?Exista o multime de cai de a gasi aceste adrese. Cele mai raspandite doua metode sunt: gasirea adresei functiei la runtime sau folosirea memoriei hard-codata. Singurul DLL care se mapeaza in mod sigur pe spatiul de adrese al shellcode-ului este kernel32.dll. Acest DLL contine LoadLibrary si GetProcAddress, functii necesare pentru obrinerea oricaror adrese de functii.1.5 NULL bytes.Problema NULL bytes consta in faptul ca shellcode-ul nu trebuie sa contina bytes nuli si asta deoarece codul inserat (exploit-ul) este un string. Dupa cum se stie, stringurile se termina cu NULL byte (in limbaje precum C sau C++). Daca avem NULL bytes in shellcode, acesta nu va functiona.2. Informatii de background? EAX, EBX, ECX si EDX sunt registri generali pe 32 de biti pe arhitecturi 80x86.? eax mai poarta numele de acumulator, fiind folosit pentru a stoca rezultate aritmetice, ebx – registru baza, folosit pentru adresarea bazata si indexata (baza si offset), ecx – registru numarator utilizat pentru cicluri, edx – registru data.? ah, bh, ch, dh – registre pe 16 biti (registrele superioare)? al, bl, cl, dl – registre pe 16 biti (registrele inferioare)? esi, edi – registre pe 32 de biti folosite de obicei ca indecsi si pentru apelul functiilor de sistem pe Linux3. Tool-uri necesare? gcc - compilator de C? ld – linker? nasm – asamblor? objdump – dezasamblor4. Linux ShellcodingCand se testeaza shellcode-ul, este frumos sa fie bagat intr-un program si lasat sa mearga. Programul C de mai jos este (si va fi) folosit pentru a testa shellcode-ul char shellcode[] = "bytecode will go here!"; int main(int argc, char **argv) { int (*shell)(); shell = code; shell(); }Exemplu 1 – Exit ProgramCea mai facila cale de a incepe este folosirea functiei de sistem exit, pentru simplitatea ei. Codul asm: ;exit.asm [SECTION .text] global _start _start: xor eax, eax ;curata registrul eax (eax = 0x000000 mov al, 1 ;codul pentru functia de sistem exit este 1 xor ebx,ebx ;curata ebx int 0x80 ;si…activeaza!Compilarea si extragerea byte code-ului se face in trei pasi simpli: ~$ nasm -felf exit.asm ~$ ld -o exit exit.o ~$ objdump -d exitSi obtinem: exiter: file format elf32-i386 Disassembly of section .text: 08048080 <_start>: 8048080: b0 01 mov $0x1,%al 8048082: 31 db xor %ebx,%ebx 8048084: cd 80 int $0x80Octetii care ne trebuie sunt: b0 01 31 db cd 80. Avemc codul in C: const char shellcode[] = “\xb0\x01\x31\xdb\xcd\x80“;int main(int argc, char **argv) { int (*shell)(); shell = code; shell(); }Exemplu 2 - HelloCand sunt accesate valori statice (in special stringuri) din shellcode, trebuie ca acesta sa fie scris astfel incat sa acceseze valorile statice fara a folosi in vreun fel maparea adresei acestora, si asta pentru ca programatorul nu stie in ce zona de memorie este incarcat codul. Acelasi lucru se intampla si cand se incearca executarea instructiunilor care au ca operand memoria (jmp, call, etc). Din fericire, se poate folosi adresarea relativa cu ajutorul familiei de instructiuni jmp/call.Pentru inceput, cosul in asmblare, neoptimizat: SEGMENT .text mov eax, 4 ; pune in eax valoare 4 (codul functiei de sistem write) mov ebx, 1 ; pune 1 in ebx (codul iesirii stdout) mov ecx, message ; pune pointerul la string in eax mov edx, 29 ; pune 11 in edx (lungimea stringului) int 80h ; si…activeaza! mov eax, 1 ; pune 1 in eax (codul functiei de sistem exit) mov ebx, 0 ; pune 0 in ebx (int status) int 80h ; si…activeaza! message db ‘hello world', 7, 10Se observa ca exista in cod NULL bytes si de asemenea nu este rezolvata problema independentei pozitiei. Pentru asta se recurge la urmatorul truc: SEGMENT .text xor ebx, ebx ; curata registrii mul ebx ; mov al, 4 ; pune 4 in eax codul (functiei de sistem write) inc ebx ; incrementeaza ebx => ebx = 1 (stdout, int fd) jmp short get_string ; Daca nu specificam sa faca un salt de 8 biti, nasm va face ; jmp near, ceea ce inseamna 16bit offset la eip, pe cand noi continue: ; avem nevoie de 1 octet pop ecx ; extrage pointerul de deasupra stivei la stringul ;nostru, in eax mov dl, 29 ; pune 11 edx (size_t len) int 80h ; si…activeaza! mov al, 1 ; pune 1 in eax (syscall number of exit) dec ebx ; decrementeaza ebx => ebx = 0 (int status) int 80h ; intra in modul kernel get_string: call continue ; salt la eticheta continue si incarca stringul ca ret db ‘hello world', 7, 10 ~$ nasm -felf hello.asm ~$ ld -o hello hello.o ~$ objdump -d hello write: file format elf32-i386 Disassembly of section .text: 08048100 <continue-0x9>: 8048100: 31 db xor %ebx,%ebx 8048102: f7 e3 mul %ebx,%eax 8048104: b0 04 mov $0x4,%al 8048106: 43 inc %ebx 8048107: eb 0a jmp 8048113 <string> 08048109 <continue>: 8048109: 59 pop %ecx 804810a: b2 1d mov $0x1d,%dl 804810c: cd 80 int $0x80 804810e: b0 01 mov $0x1,%al 8048110: 4b dec %ebx 8048111: cd 80 int $0x80 08048113 <get_string>: 8048113: e8 f1 ff ff ff call 8048109 <continue> 8048118: 6b 65 72 6e imul $0x6e,0x72(%ebp),%esp 804811c: 65 gs 804811d: 6c insb (%dx),%es:(%edi) 804811e: 65 64 3a 20 cmp %fs:%gs:(%eax),%ah 8048122: 61 popa 8048123: 72 65 jb 804818a <_etext+0x55> 8048125: 20 79 6f and %bh,0x6f(%ecx) 8048128: 75 20 jne 804814a <_etext+0x15> Shellcode-ul nostru este: "\x31\xdb\xf7\xe3\xb0\x04\x43\xeb\x0a\x59\xb2\x1d\xcd\x80\xb0\x01" "\x4b\xcd\x80\xe8\xf1\xff\xff\xffhello world\a\n";Tutorialul l-am tradus si adaptat pe cat am putut de bine din engleza. Sursele originale le gasiti aici:http://infosecwriters.com/hhworld/shellcode.txtWriting shellcodeShellcoding for Linux and Windows Tutorial 3 1 Quote
Krisler12™ Posted November 1, 2010 Report Posted November 1, 2010 Daca iti foloseste la ceva, eu ti-am dat reputatie ptr. ca ai facut ceva care ma intereseaza si pe mine !Multam' ! Quote
Krisler12™ Posted November 2, 2010 Report Posted November 2, 2010 Mersi frumos1. L-am citit acuma mai cu atentie.Nu sunt eu mare priceput in asm/shellcode, dar parca shellcod-ul se scria de la coada la cap si nu asa cum citesti dintr-o carte, asa cum l-ai scris tu conform codului in asm. Nu ?2. Tare as vrea sa faca cineva (tu sau oricine altcineva) un exemplu practic de scriere a unui shellcode atat ptr Windows ca vreau sa vad cum e cu adresele alea din dll-uri, cat si ptr. linux. Un video ceva sau macar un tutorial cu imagini despre cum se face asta.Multumesc ! Quote
Zamolxis666 Posted November 2, 2010 Author Report Posted November 2, 2010 1. L-am citit acuma mai cu atentie.Nu sunt eu mare priceput in asm/shellcode' date=' dar parca shellcod-ul se scria de la coada la cap si nu asa cum citesti dintr-o carte, asa cum l-ai scris tu conform codului in asm. Nu ?[/quote']Probabil te referi la arhitectura. Exista doua tipuri de arhitecturi: little-endian si big-endian. De exemplu: avem numarul 0x5566 pe care dorim sa il punem in stiva. Singurul mod in care punem in stiva este deasupra ei. Sa presupunem ca adresa stivei de unde incepem puerea este 0xAABBCC. La aceasta adresa, conform arhitecturii little-endian se va aseza octetul 66, iar imediat la adresa urmatoare, 0xAABBCD se va aseza octetul 55. La arhiectura big-endian va fi pe dos, mai intai octetul 55 apoi octetul 66. In ceea ce priveste opcode-ul instructiunilor, daca o sa dezasamblezi un executabil cu TurboDebugger (td) pe Windows, o sa observi ca instructiunile pe 2 octeti sunt afisate conform arhitecturii little-endian, adica instructiunea mov bx, ax care are opcode-ul D88B va fi afisata: 8BD8 (intai octetul inferior si apoi cel superior)O sa incerc sa fac un filmulet, cand imi permite timpul, cu shellcode pe windows si shellcode pe linux. Quote
Krisler12™ Posted November 2, 2010 Report Posted November 2, 2010 Probabil te referi la arhitectura. Exista doua tipuri de arhitecturi: little-endian si big-endian. De exemplu: avem numarul 0x5566 pe care dorim sa il punem in stiva. Singurul mod in care punem in stiva este deasupra ei. Sa presupunem ca adresa stivei de unde incepem puerea este 0xAABBCC. La aceasta adresa, conform arhitecturii little-endian se va aseza octetul 66, iar imediat la adresa urmatoare, 0xAABBCD se va aseza octetul 55. La arhiectura big-endian va fi pe dos, mai intai octetul 55 apoi octetul 66. In ceea ce priveste opcode-ul instructiunilor, daca o sa dezasamblezi un executabil cu TurboDebugger (td) pe Windows, o sa observi ca instructiunile pe 2 octeti sunt afisate conform arhitecturii little-endian, adica instructiunea mov bx, ax care are opcode-ul D88B va fi afisata: 8BD8 (intai octetul inferior si apoi cel superior)O sa incerc sa fac un filmulet, cand imi permite timpul, cu shellcode pe windows si shellcode pe linux.Nu prea inteleg ceea ce spui asa ca nu am de unde sa stiu daca ai dreptate sau nu.Ca sa iti dau un exemplu la ceea ce ma refer:Ai zis asa: Si obtinem: exiter: file format elf32-i386 Disassembly of section .text: 08048080 <_start>: 8048080: b0 01 mov $0x1,%al 8048082: 31 db xor %ebx,%ebx 8048084: cd 80 int $0x80Octetii care ne trebuie sunt: b0 01 31 db cd 80. Avemc codul in C: const char shellcode[] = “\xb0\x01\x31\xdb\xcd\x80“;int main(int argc, char **argv) { int (*shell)(); shell = code; shell(); }Ei bine eu ce zic si te intreb daca e gresit sau nu este urmatorul lucru:ai pus "const char shellcode[] = “\xb0\x01\x31\xdb\xcd\x80“;"cand de fapt eu stiu ca se pune exact de la coada la cap, adica asa:"const char shellcode[] = “x\80\xcd\xdb\x31\x01\xb0“;"Observi diferenta ?Dupa cum am zis eu nu sunt expert, doar asa am vazut ca se face. ....Am facut o pauza, am tras aer in piept, si acuma vad ca tu de fapt tot mie imi dai dreptate. Ceea ce zic eu este little indian dar am vazut si eu la unele tutoriale cum ca tu chiar daca vezi in OllyDbg opcod-urile ca fiind in ordine (adica de la cap la coada, adica Big indian), aia tot pe dos il puneau, adica de la coada la cap, adica little indian. Si, culmea, la dezasamblarea programului facut asa, opcod-urile erau tot in ordine , adica big indian, desi el le scria exact pe dos.=> Rezulta de aici, probabil (nu am incercat) ca daca le scria exact asa cum le vedea (adica de la cap la coada), iar fi iesit altceva la dezasamblare. Nu ?---------------------------------------------------Asteptam filmuletul ! >< Quote
Zamolxis666 Posted November 2, 2010 Author Report Posted November 2, 2010 exemplele postate de mine sunt bune. Le-am verificat. Daca la asta te referi. Quote
Krisler12™ Posted November 2, 2010 Report Posted November 2, 2010 exemplele postate de mine sunt bune. Le-am verificat. Daca la asta te referi.Nu la asta ma refer , ma refer la faptul ca eu am mai vazut si alta metoda de a scrie shellcodul.Mai faci filmuletul ala ? Quote
Zamolxis666 Posted November 2, 2010 Author Report Posted November 2, 2010 Nu la asta ma refer , ma refer la faptul ca eu am mai vazut si alta metoda de a scrie shellcodul.Mai faci filmuletul ala ? Nu stiu alta metoda. Am zis ca il fac cand imi permite timpul. Momentan nu pot. Tu o sa fi primul pe care il anunt Quote