Malware Analysis Report: Sample SmokeScreen
Basic Facts
Malware Type: Injector/Info-Stealer
Windows PE | C# (stage 1) | Nim (stage 2)
High-Level Technical Summary
Applicable MITRE TTPs: T1566.001 (Spearphishing Attachment), T1036.007 (Double File Extension), T1036.008 (Masquerade File Type), T1204.002 (User Exec: Malicious File), T1622 (Debugger Evasion), T1087 (Account Discovery), T1033 (User Discovery), T1140 (Deobfuscate/Decode Files or Information), T1055.012 (Process Hollowing), T1620 (Reflective Code Loading), T1055.002 (Portable Executable Injection), T1569.002 (Service Execution), T1036.004 (Masquerade Task or Service), T1218.004 (InstallUtil.exe) , T1005 (Local System Data), T1119 (Automated Collection), T1083 (File and Directory Discovery), T1552.001 (Unsecureds Credentials in File), T1552.004 (Private Keys), T1657 (Financial Theft), T1020 (Automated Exfiltration), T1071.001 (HTTP), T1571 (Non Standard Port) , T1132.001 (Standard Encoding), T1041 (Exfiltration Over C2 Channel)
--*--*--
Basic Static Analysis
Strings analysis revealed that the file was not an OLE structured file but rather a binary written in C#.

The binary was written in C#, further analysis revealed the existence of another binary in it, which is reversed.
There was also mention of InstallUtil.exe:
The assumption of the other binary being reversed is based on the reversed strings found in the binary:
The packed binary would be ‘Program1.main.exe’ as the ‘Program1.exe’ is the name for the PE as can be seen from the PEstudio analysis.
Looking the IAT in PEstudio hinted towards the PE having functionality for process injection and debugger evasion.
--*--*--
Basic
Dynamic Analysis
No changes to the system or anything of interest.
--*--*--
Advanced Static Analysis
Since the binary was written in C#, it could be fully decompiled with dnSpy.
The application checks for Debugger presence then goes on to check if the current user is actually the target, and only proceeds if both these checks pass.
This was likely the reason there were no results in the
Dynamic Analysis.
Following these checks bytes are read in reverse order into an array from a resource called ‘Program1.main.exe’, i.e., the second stage payload.
It also creates a process for InstallUtil.exe, with the creation flags (0x08000004) set to create the process with no window and create the process in a suspended state.
The array of bytes of the second stage is stored in `intPtr`
When the process is created successfully, it goes to
retrieve the thread context of the newly created process.
The Context64 struct is created with all flags to store all the information from the target thread, memory is allocated for it and then the context of the newly created thread is stored into it.
A new address is calculated with the value in RDX register
and stored in a var called 'num'.
The ‘num’ var is then used to reads bytes from the process memory at the calculated address and stores it in ‘intPtr3’, which is used to unmap section to set up for process injection.
It then checks if the unmapping is successful by
comparing the return value with NT status code (0xC0000022) for STATUS_ACCESS_DENIED.
The number of bytes read is stored in intPtr4, which is later used to write the specified number of bytes into memory.
After the unmapping is done, it moves onto retrieving the headers from the second stage.
It gets the PE Header Base in num2 (DOS Head + 0x3C).
That header value is used to get the Image Base Address (64-bit PE Base + 0x30) and Size of Image (64-bit PE Base + 0x50) values into num3 and num4 respectively.
Then allocates memory with the base address as the start address and size of image values as the size of allocation. Allocation type being Commit & Reserve, and ExecuteReadWrite protection.
The size of
headers is read into num5, again using the PE header base, and then is written to the memory of the suspended process.
After writing the from the PE bytes in `intPtr` it moves onto writing the sections.
It reads the number of sections into num6, the size of optional header into num7 and the normal size of section header struct into num8.
A loop is initiated for the number of section headers, it iterates through each section and writes the corresponding header into the target memory.
For each iteration it:
Then it writes the Image Base Address to process memory.
It gets the Address of Entry in num9, sets the RCX to entry point address.
Copies the modified context back to the pointer to initial context, thus altering the thread context of the process and finally resumes thread to execute the payload.
After reviewing the functionality of the initial stage, I went forward with extracting the second stage for analysis.
Strings analysis of the binary revealed that this was a Nim compiled binary, and it was calling back to ‘hxxp[://]freesoftwareapk[.]org:60744’.
There were also keywords and search paths which it seemed to look around in.
Looking at it inside cutter, its main function was conducting multiple append string and copy string operations.
More specifically, it was all being stored in two variables, ‘arg1’ as seen above and ‘arg2’.
Towards the very end of the main function, after these append/copy routines was the real interesting portion of code.
The strings built in ‘arg1’ and ‘arg2’ are passed onto the aptly named function ‘findInterestingData’. Then the data it found it passed onto ‘exfiltrateToServer’, to exfiltrate to the remote server.
This cycle repeats in the infinite loop every 6 seconds.
Inside findInteresting data, it looks for the files and compares the result with ‘-1’, to check for failure.
If the file search succeeds, it checks for ‘.’ (period) at a calculated address.
If the
period is present, it will then split and extract the file name and join it to
the path, likely to return to caller.
Following the flow of exfiltration function, it reads the file found and then calls to a function called ‘encode’ which processed the data to be encoded in base64 before being sent over to the remote server.
--*--*--
Advanced Dynamic Analysis
The advanced analysis was directly conducted on the second
stage payload as the first stage was fully decompiled and understandable.
After locating the main function, the string append/copy functions turned up as the path building routine.
Which led to the find and exfiltration function calls.
Inside the find function, it loops through the keywords in a path, and it found the history from the browser to be interesting, this passed onto exfil routine.
The data was received by the listener set up on remnux box at port 60744.
This on decoding showed all the data the binary smuggled out to the remote server.
--*--*--Indicators of Compromise
Network Indicators
Host-based Indicators
--*--*--YARA Rule
global rule Program_Injector
{
meta:
description = "Detects an Injector Malware which tries to deploy a payload in the memory of InstallUtil to evade detection."
author = "Prajwal Nautiyal"
date = "2024-08-19"
version = "1.0"
strings:
$MagicByte = "MZ"
$Target = "keith.chattams" wide
$PayloadName = "Program1.main.exe" wide
$Evasion = "C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\InstallUtil.exe" wide
condition:
$MagicByte at 0
and ($Target and $PayloadName and $Evasion)
}
rule Injected_Payload
{
meta:
description = "Detects a payload which tries exfiltrate data as InstallUtil to evade detection."
author = "Prajwal Nautiyal"
date = "2024-08-19"
version = "1.0"
strings:
$exfilURL = "44706:gro.kpaerawtfoseerf//:ptth@" // reversed as the packed binary is initially reversed
condition:
$exfilURL
}
Comments
Post a Comment