
Ein Befehlszeilen-Tool zum Windows-API-Tracing für Golang-Binärdateien.
Ein Kommandozeilen-Tool zur Verfolgung von Windows-API-Aufrufen in Golang-Binärdateien.
Hinweis: Dieses Tool ist ein PoC und ein work-in-progress-Prototyp, daher behandeln Sie es bitte als solches. Rückmeldungen sind jederzeit willkommen!
Obwohl Golang-Programme viele Nuancen in Bezug auf ihre Erstellung und ihr Laufzeitverhalten enthalten, müssen sie dennoch mit der Betriebssystemebene interagieren, was bedeutet, dass sie irgendwann Funktionen der Windows-API aufrufen müssen.
Das Go-Runtime-Paket enthält eine Funktion namens asmstdcall, und diese Funktion ist eine Art „Gateway“, das zur Interaktion mit der Windows-API verwendet wird. Da erwartet wird, dass diese Funktion die Windows-API-Funktionen aufruft, können wir annehmen, dass sie Zugriff auf Informationen wie die Adresse der Funktion und ihre Parameter benötigt – und hier wird es interessant.
Asmstdcall empfängt einen einzelnen Parameter, der ein Zeiger auf etwas Ähnliches wie die folgende Struktur ist:
struct LIBCALL {
DWORD_PTR Addr;
DWORD Argc;
DWORD_PTR Argv;
DWORD_PTR ReturnValue;
[...]
}
Einige dieser Felder werden nach dem Aufruf der API-Funktion ausgefüllt, wie der Rückgabewert, andere werden von asmstdcall empfangen, wie die Funktionsadresse, die Anzahl der Argumente und die Liste der Argumente. Unabhängig davon, wann diese gesetzt werden, ist klar, dass die asmstdcall-Funktion viele interessante Informationen über die Ausführung von in Golang kompilierten Programmen manipuliert.
Das gftrace nutzt asmstdcall und dessen Funktionsweise, um bestimmte Felder der genannten Struktur zu überwachen und dem Benutzer zu protokollieren. Das Tool kann den Funktionsnamen, seine Parameter und auch den Rückgabewert jeder von einer Golang-Anwendung aufgerufenen Windows-Funktion protokollieren. All dies ohne die Notwendigkeit, eine einzige API-Funktion zu hooken oder eine Signatur dafür zu haben.
Das Tool versucht auch, das ganze Rauschen aus der Go-Runtime-Initialisierung zu ignorieren und nur Funktionen zu protokollieren, die danach aufgerufen werden (d.h. Funktionen aus dem main-Paket).
Wenn Sie mehr über dieses Projekt und die Forschung erfahren möchten, lesen Sie den Blogbeitrag.
Laden Sie die neueste Version herunter.
gftrace.exe <filepath> <params>
Alles, was Sie tun müssen, ist, die Funktionen, die Sie verfolgen möchten, in der Datei gftrace.cfg anzugeben, getrennt durch Kommata ohne Leerzeichen:
CreateFileW,ReadFile,CreateProcessW
Die genauen Windows-API-Funktionen, die eine Golang-Methode X eines Pakets Y in einem bestimmten Szenario aufrufen würde, können nur durch Analyse der Methode selbst oder durch Versuch, sie zu erraten, bestimmt werden. Es gibt einige interessante Merkmale, die zur Bestimmung verwendet werden können, zum Beispiel scheinen Golang-Anwendungen immer Funktionen aus dem „Wide“- und „Ex“-Satz zu bevorzugen (z.B. CreateFileW, CreateProcessW, GetComputerNameExW, usw.), so dass Sie dies bei Ihrer Analyse berücksichtigen können.
Die Standard-Konfigurationsdatei enthält mehrere Funktionen, die ich bereits getestet habe (zumindest die meisten von ihnen) und kann mit Sicherheit sagen, dass sie von einer Golang-Anwendung irgendwann aufgerufen werden können. Ich werde versuchen, sie irgendwann zu aktualisieren.
Verfolgung von CreateFileW() und ReadFile() in einer einfachen Golang-Datei, die zweimal "os.ReadFile" aufruft:
- CreateFileW("C:\Users\user\Desktop\doc.txt", 0x80000000, 0x3, 0x0, 0x3, 0x1, 0x0) = 0x168 (360)
- ReadFile(0x168, 0xc000108000, 0x200, 0xc000075d64, 0x0) = 0x1 (1)
- CreateFileW("C:\Users\user\Desktop\doc2.txt", 0x80000000, 0x3, 0x0, 0x3, 0x1, 0x0) = 0x168 (360)
- ReadFile(0x168, 0xc000108200, 0x200, 0xc000075d64, 0x0) = 0x1 (1)
Verfolgung von CreateProcessW() in der TunnelFish-Malware:
- CreateProcessW("C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe", "powershell /c "Add-PSSnapin Microsoft.Exchange.Management.PowerShell.SnapIn; Get-Recipient | Select Name -ExpandProperty EmailAddresses -first 1 | Select SmtpAddress | ft -hidetableheaders"", 0x0, 0x0, 0x1, 0x80400, "=C:=C:\Users\user\Desktop", 0x0, 0xc0000ace98, 0xc0000acd68) = 0x1 (1)
- CreateProcessW("C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe", "powershell /c "Add-PSSnapin Microsoft.Exchange.Management.PowerShell.SnapIn; Get-Recipient | Select Name -ExpandProperty EmailAddresses -first 1 | Select SmtpAddress | ft -hidetableheaders"", 0x0, 0x0, 0x1, 0x80400, "=C:=C:\Users\user\Desktop", 0x0, 0xc0000c4ec8, 0xc0000c4d98) = 0x1 (1)
- CreateProcessW("C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe", "powershell /c "Add-PSSnapin Microsoft.Exchange.Management.PowerShell.SnapIn; Get-Recipient | Select Name -ExpandProperty EmailAddresses -first 1 | Select SmtpAddress | ft -hidetableheaders"", 0x0, 0x0, 0x1, 0x80400, "=C:=C:\Users\user\Desktop", 0x0, 0xc00005eec8, 0xc00005ed98) = 0x1 (1)
- CreateProcessW("C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe", "powershell /c "Add-PSSnapin Microsoft.Exchange.Management.PowerShell.SnapIn; Get-Recipient | Select Name -ExpandProperty EmailAddresses -first 1 | Select SmtpAddress | ft -hidetableheaders"", 0x0, 0x0, 0x1, 0x80400, "=C:=C:\Users\user\Desktop", 0x0, 0xc0000bce98, 0xc0000bcd68) = 0x1 (1)
- CreateProcessW("C:\WINDOWS\system32\cmd.exe", "cmd /c "wmic computersystem get domain"", 0x0, 0x0, 0x1, 0x80400, "=C:=C:\Users\user\Desktop", 0x0, 0xc0000c4ef0, 0xc0000c4dc0) = 0x1 (1)
- CreateProcessW("C:\WINDOWS\system32\cmd.exe", "cmd /c "wmic computersystem get domain"", 0x0, 0x0, 0x1, 0x80400, "=C:=C:\Users\user\Desktop", 0x0, 0xc0000acec0, 0xc0000acd90) = 0x1 (1)
- CreateProcessW("C:\WINDOWS\system32\cmd.exe", "cmd /c "wmic computersystem get domain"", 0x0, 0x0, 0x1, 0x80400, "=C:=C:\Users\user\Desktop", 0x0, 0xc0000bcec0, 0xc0000bcd90) = 0x1 (1)
[...]
Verfolgung mehrerer Funktionen in der Sunshuttle-Malware:
- CreateFileW("config.dat.tmp", 0x80000000, 0x3, 0x0, 0x3, 0x1, 0x0) = 0xffffffffffffffff (-1)
- CreateFileW("config.dat.tmp", 0xc0000000, 0x3, 0x0, 0x2, 0x80, 0x0) = 0x198 (408)
- CreateFileW("config.dat.tmp", 0xc0000000, 0x3, 0x0, 0x3, 0x80, 0x0) = 0x1a4 (420)
- WriteFile(0x1a4, 0xc000112780, 0xeb, 0xc0000c79d4, 0x0) = 0x1 (1)
- GetAddrInfoW("reyweb.com", 0x0, 0xc000031f18, 0xc000031e88) = 0x0 (0)
- WSASocketW(0x2, 0x1, 0x0, 0x0, 0x0, 0x81) = 0x1f0 (496)
- WSASend(0x1f0, 0xc00004f038, 0x1, 0xc00004f020, 0x0, 0xc00004eff0, 0x0) = 0x0 (0)
- WSARecv(0x1f0, 0xc00004ef60, 0x1, 0xc00004ef48, 0xc00004efd0, 0xc00004ef18, 0x0) = 0xffffffff (-1)
- GetAddrInfoW("reyweb.com", 0x0, 0xc000031f18, 0xc000031e88) = 0x0 (0)
- WSASocketW(0x2, 0x1, 0x0, 0x0, 0x0, 0x81) = 0x200 (512)
- WSASend(0x200, 0xc00004f2b8, 0x1, 0xc00004f2a0, 0x0, 0xc00004f270, 0x0) = 0x0 (0)
- WSARecv(0x200, 0xc00004f1e0, 0x1, 0xc00004f1c8, 0xc00004f250, 0xc00004f198, 0x0) = 0xffffffff (-1)
[...]
Verfolgung mehrerer Funktionen im DeimosC2-Framework-Agenten:
- WSASocketW(0x2, 0x1, 0x0, 0x0, 0x0, 0x81) = 0x130 (304)
- setsockopt(0x130, 0xffff, 0x20, 0xc0000b7838, 0x4) = 0xffffffff (-1)
- socket(0x2, 0x1, 0x6) = 0x138 (312)
- WSAIoctl(0x138, 0xc8000006, 0xaf0870, 0x10, 0xb38730, 0x8, 0xc0000b746c, 0x0, 0x0) = 0x0 (0)
- GetModuleFileNameW(0x0, "C:\Users\user\Desktop\samples\deimos.exe", 0x400) = 0x2f (47)
- GetUserProfileDirectoryW(0x140, "C:\Users\user", 0xc0000b7a08) = 0x1 (1)
- LookupAccountSidw(0x0, 0xc00000e250, "user", 0xc0000b796c, "DESKTOP-TEST", 0xc0000b7970, 0xc0000b79f0) = 0x1 (1)
- NetUserGetInfo("DESKTOP-TEST", "user", 0xa, 0xc0000b7930) = 0x0 (0)
- GetComputerNameExW(0x5, "DESKTOP-TEST", 0xc0000b7b78) = 0x1 (1)
- GetAdaptersAddresses(0x0, 0x10, 0x0, 0xc000120000, 0xc0000b79d0) = 0x0 (0)
- CreateToolhelp32Snapshot(0x2, 0x0) = 0x1b8 (440)
- GetCurrentProcessId() = 0x2584 (9604)
- GetCurrentDirectoryW(0x12c, "C:\Users\user\AppData\Local\Programs\retoolkit\bin") = 0x39 (57)
[...]
Das gftrace wird unter der GPL v3-Lizenz veröffentlicht. Weitere Informationen finden Sie in der Datei LICENSE.