THM Honeynet Collapse – Zadanie 5

Po analizie systemów na żywo w CTFie Honeynet Collapse czekało na mnie zadanie 5. Polegało na analizie zrzutu pamięci RAM serwera. Autorzy zadania użyli kilkunastu modułów frameworku Volatility i zapisali ich wyniki w plikach tekstowych.

Pytania 1., 2., 3. i 4. — złowrogi plik

  • Poziom trudności: łatwy 🟢, łatwy 🟢, średni 🟡 i średni 🟡
  • Liczba punktów: 30, 30, 60 i 60
  • Treść (1): Jaka jest bezwzględna ścieżka do początkowego złośliwego pliku uruchomionego na analizowanym hoście?
  • Treść (2): Który identyfikator procesu (PID) został przypisany do procesu użytego do wykonania początkowego ładunku?
  • Treść (3): Jakie było pełne polecenie użyte przez atakującego do uruchomienia początkowego wykonania na tym hoście?
  • Treść (4): Atak uruchomił różne procesy. Jak nazywa się ostatni proces w łańcuchu?

Zacząłem od analizowania wyjścia modułu windows.pstree, który wyświetla drzewko uruchomionych procesów w systemie.

Skróciłem wyjście niektórych modułów, żeby były bardziej czytelne.

Szybko rzucił mi się w oczy ciąg rozpoczynający się od PSEXESVC.exe.

Volatility 3 Framework 2.26.0

PID, PPID, reszta

[...]
** 2996 576	
C:\Windows\PSEXESVC.exe

*** 2100 2996	
C:\Windows\system32\cmd.exe

**** 2200 2100	
C:\Windows\system32\conhost.exe 0x4

**** xxxx 2100	
C:\Windows\System32\rundll32.exe 
rundll32.exe yyyyyy\MicrosoftUpdate.dll, RunMe

***** 2676 xxxx	
C:\Windows\Tasks\windows-update.exe

****** 2680 2676
C:\Windows\system32\conhost.exe 0x4

****** 1444 2676
C:\Users\matthew.collins\Downloads\security-update.exe

******* 836 1444 
C:\Windows\SYSTEM32\zzzzzzz.exe

******** 1652 836
C:\Windows\system32\cmd.exe

[...]

Ktoś zdalnie uruchomił plik nazywający się… MicrosoftUpdate.dll, który znajdował się w katalogu… „Tasks„? Wygląda na to, że znaleźliśmy nasz złowrogi plik. Poza tym, zaczynając od modułu windows.pstree, znaleźliśmy odpowiedzi na cztery pozostałe pytania:

  • Pytanie pierwsze: ścieżka do MicrosoftUpdate.dll
  • Pytanie drugie: PID procesu rundll32.exe (xxxx)
  • Pytanie trzecie: rundll32.exe yyyyyy\MicrosoftUpdate.dll, RunMe
  • Pytanie czwarte: zzzzzzz.exe

Tylko czemu proces zzzzzzz.exe jest tym ostatnim, skoro w drewku widać jeszcze cmd.exe? Z prostego powodu: proces 'z’ to bardzo popularne i proste narzędzie znajdujące się na każdym Windowsie. Z uwagi na to, że nie jest ono w stanie uruchamiać żadnych procesów samodzielnie, wywnioskowałem, że coś zmusiło ten proces do uruchomienia (i dlatego wybrałem z jako ostatni proces w pierwszej fazie ataku).

Pytanie 5. — shellcode

  • Poziom trudności: trudny 🔴
  • Liczba punktów: 120
  • Treść: Jakie jest pierwsze pięć bajtów (w systemie szesnastkowym, np. 4d5a9000) shellcodu Meterpreter wstrzykniętego do niego (procesu zzzzzzz.exe)?

W piątym pytaniu miałem znaleźć pierwsze pięć bajtu shellcodu Meterpretera wstrzykniętego w proces z. To wyjaśniałoby, jakim cudem proste narzędzie zaczęło uruchamiać inne programy. Meterpreter potrafi migrować do innych procesów — i tak najwyraźniej stało się w tym przypadku.

Do znalezenia shellcodu w z użyłem modułu windows.malware.malfind, który szuka podejrzanych segmentów w pamięci procesów.

W zapisanym wyjściu modułu znajdowały się dwa interesujące wyniki:

Volatility 3 Framework 2.26.0

PID	Process	Start VPN	End VPN	Tag	Protection	CommitCharge	PrivateMemory	File output	Notes	Hexdump	Disasm

836	notepad.exe	0x1c8c6bd0000	0x1c8c6bd0fff	VadS	PAGE_EXECUTE_READWRITE	1	1	Disabled	N/A	
fc 55 57 56 48 89 e7 e9 01 01 00 00 5e 48 83 ec .UWVH.......^H..
78 e8 c8 00 00 00 41 51 41 50 52 51 56 48 31 d2 x.....AQAPRQVH1.
65 48 8b 52 60 48 8b 52 18 48 8b 52 20 48 8b 72 eH.R`H.R.H.R H.r
50 48 0f b7 4a 4a 4d 31 c9 48 31 c0 ac 3c 61 7c PH..JJM1.H1..<a|	
0x1c8c6bd0000:	cld	
0x1c8c6bd0001:	push	rbp
0x1c8c6bd0002:	push	rdi
0x1c8c6bd0003:	push	rsi
0x1c8c6bd0004:	mov	rdi, rsp
0x1c8c6bd0007:	jmp	0x1c8c6bd010d
0x1c8c6bd000c:	pop	rsi
0x1c8c6bd000d:	sub	rsp, 0x78
0x1c8c6bd0011:	call	0x1c8c6bd00de
0x1c8c6bd0016:	push	r9
0x1c8c6bd0018:	push	r8
0x1c8c6bd001a:	push	rdx
0x1c8c6bd001b:	push	rcx
0x1c8c6bd001c:	push	rsi
0x1c8c6bd001d:	xor	rdx, rdx
0x1c8c6bd0020:	mov	rdx, qword ptr gs:[rdx + 0x60]
0x1c8c6bd0025:	mov	rdx, qword ptr [rdx + 0x18]
0x1c8c6bd0029:	mov	rdx, qword ptr [rdx + 0x20]
0x1c8c6bd002d:	mov	rsi, qword ptr [rdx + 0x50]
0x1c8c6bd0031:	movzx	rcx, word ptr [rdx + 0x4a]
0x1c8c6bd0036:	xor	r9, r9
0x1c8c6bd0039:	xor	rax, rax
0x1c8c6bd003c:	lodsb	al, byte ptr [rsi]
0x1c8c6bd003d:	cmp	al, 0x61
836	notepad.exe	0x1c8c6dd0000	0x1c8c6e01fff	VadS	PAGE_EXECUTE_READWRITE	50	1	Disabled	N/A	
fc xx yy zz ee 81 ec 00 20 00 00 48 83 e4 f0 e8 .H..H... ..H....
cc 00 00 00 41 51 41 50 52 51 56 48 31 d2 65 48 ....AQAPRQVH1.eH
8b 52 60 48 8b 52 18 48 8b 52 20 48 0f b7 4a 4a .R`H.R.H.R H..JJ
4d 31 c9 48 8b 72 50 48 31 c0 ac 3c 61 7c 02 2c M1.H.rPH1..<a|.,	
0x1c8c6dd0000:	cld	
0x1c8c6dd0001:	mov	rsi, rcx
0x1c8c6dd0004:	sub	rsp, 0x2000
0x1c8c6dd000b:	and	rsp, 0xfffffffffffffff0
0x1c8c6dd000f:	call	0x1c8c6dd00e0
0x1c8c6dd0014:	push	r9
0x1c8c6dd0016:	push	r8
0x1c8c6dd0018:	push	rdx
0x1c8c6dd0019:	push	rcx
0x1c8c6dd001a:	push	rsi
0x1c8c6dd001b:	xor	rdx, rdx
0x1c8c6dd001e:	mov	rdx, qword ptr gs:[rdx + 0x60]
0x1c8c6dd0023:	mov	rdx, qword ptr [rdx + 0x18]
0x1c8c6dd0027:	mov	rdx, qword ptr [rdx + 0x20]
0x1c8c6dd002b:	movzx	rcx, word ptr [rdx + 0x4a]
0x1c8c6dd0030:	xor	r9, r9
0x1c8c6dd0033:	mov	rsi, qword ptr [rdx + 0x50]
0x1c8c6dd0037:	xor	rax, rax
0x1c8c6dd003a:	lodsb	al, byte ptr [rsi]
0x1c8c6dd003b:	cmp	al, 0x61
0x1c8c6dd003d:	jl	0x1c8c6dd0041

Pierwszy znaleziony fragment to malutki stub, ładujący większy kod. Ten większy kod również został wykryty przez moduł i to jest właśnie nasz drugi fragment. Zawiera on prawdziwy payload Meterpreter. Wystarczyło przekopiować pierwsze pięć bajtów: fc xx yy zz ee i… gotowe!

Pytanie 6. — ruch lateralny

  • Poziom trudności: bonus 🌟
  • Liczba punktów: 25
  • Treść: Który adres IP jest używany przez hosta do przeprowadzania ruchu lateralnego przy użyciu portu 3389?

W pytaniu bonusowym miałem znaleźć adres hosta, do którego atakujący podłączył się przez protokół RDP (port 3389).

W tym celu chciałem użyć modułu windows.netstat, ale nic w nim nie było (oprócz połączeń do portu 445). Z tego powodu rzuciłem okiem na windows.netscan, w którym było już o wiele więcej, w tym nasze szukane połączenie:

Volatility 3 Framework 2.26.0

Proto	LocalAddr	LocalPort	ForeignAddr	ForeignPort	State		PID	Owner		
Created

[...]

TCPv4	172.16.8.15	49750		xxx.yyy.zzz.ttt
3389		ESTABLISHED	464	powershell.exe	
2025-07-02 01:08:25.000000 UTC

[...]

Wartość w kolumnie ForeignPort to 3389, więc nasz szukany adres to xxx.yyy.zzz.ttt (wartość kolumny ForeignAddr).