Static Analysis of INCONTROLLER ICS Malware
CISA released a joint advisory on APT Cyber Tools Targeting ICS/SCADA Devices. This particular malware is said to have capabilities which can specifically target ICS/SCADA devices and cause major damage on target. The malware is modular in architecture and targets below mentioned products through use of ICS protocols.
- Schneider Electric MODICON and MODICON Nano PLCs, including (but may not be limited to) TM251, TM241, M258, M238, LMC058, and LMC078
- OMRON Sysmac NJ and NX PLCs, including (but may not be limited to) NEX NX1P2, NXSL3300, NX-ECC203, NJ501-1300, S8VK, and R88D-1SN10F-ECT
- OPC Unified Architecture (OPC UA) servers.
The malware uses Modbus protocol to communicate with the PLC. The attack surface is not only limited to above mentioned devices. It can interact with a wide variety of ICS devices from various vendors. Below are detailed analysis write-ups from Dragos & Mandiant.
- https://hub.dragos.com/hubfs/116-Whitepapers/Dragos_ChernoviteWP_v2b.pdf
- https://www.mandiant.com/resources/incontroller-state-sponsored-ics-tool
As, the sample was available I tried to perform static analysis of INCONTROLLER/PIPEDREAM malware. For the analysis I used a very nice distro called REMnux. It is loaded with lots of malware analysis tools by default. Let’s dive into the analysis part.
Static Analysis
We will start with the most basic utility to identify the type of file we are looking at. We can use file command for it.
$ file incontroller
As we see it is PE32+ Windows executable based on x86_64 arch. Now we can try another basic command strings to view all the ASCII strings in the sample.
$ strings incontroller
We can see some API calls from Bcrypt library which might be used for encryption purpose somewhere in the malware. Now I used a tool called signsrch to search for any cryptographic signatures in the sample.
$ signsrch incontroller
As we can see it found three signatures, one is anti-debug where malware check if debugger is present then it will try not to run which can slow down analysis of malware. Second was Windows CryptDecrypt and SSH RSA. It didn’t detected Bcrypt at all.
Next, I tried running ClamAV to find any known malicious signature based detection.
$ clamscan incontroller
💡 Update ClamAV definitions before running above command 💡
ClamAV had no detections. Next, I tried running Yara Rules to find any malicious behaviour in the sample.
$ yara-rules incontroller
It came back with many useful matches like, the sample has Anti-Debug mechanisms in place. It writes to Windows Registry. It contains some Debug data and other useful information. Again, this is static analysis so there can be False Positives as well.
Next, I used PE-Tree a very nice GUI tool to check PE headers in the sample.
$ pe-tree incontroller
We can see the PDB path inside the headers.
"C:\Users\User1\Desktop\dev projects\SignSploit1\x64\Release\AsrDrv_exploit.pdb"
As found by Mandiant and Dragos team as well. The AsRock Motherboard exploit is being used by APT to gain access and inject code in Windows kernel for further lateral movement. The specific exploit used is CVE-2020-15368
Next, I used a tool called FLOSS by Mandiant which finds obfuscated strings from the binary.
$ floss --no-static-strings incontroller
Copyright (C) 2012 ASRock Incorporation
OriginalFilename
AsrDrv.sys
ProductName
ASRock IO Driver
ProductVersion
1.00.00.0000
VarFileInfo
Translation
<<<Obsolete>>
CrossC
WARNING:envi:i386RegOper needs to implement getOperAddr!
WARNING:vivisect.base:_cb_opcode(0x140002f6b): LOCATION ALREADY EXISTS: loc: 'cccccccccc'
WARNING:vivisect.base:_cb_opcode(0x1400026ab): LOCATION ALREADY EXISTS: loc: 'cccccccccc'
WARNING:vivisect.base:_cb_opcode(0x14002c850): LOCATION ALREADY EXISTS: loc: 'BYTE: 0 (0x0)'
FLOSS decoded 2 strings
SystemRoot
#WVA
FLOSS extracted 3 stackstrings
C110DD4FE9434147B92A5A1E3FDBF29A
SystemRoot
PATH
We can see many interesting strings like AsrDrv.sys
and SystemRoot
etc.
Next I used a tool called Capa which is from Mandiant. This tool helps in identification of capabilities of the binary.
capa -vv incontroller
check for time delay via GetTickCount
namespace anti-analysis/anti-debugging/debugger-detection
author michael.hunhoff@fireeye.com
scope function
mbc Anti-Behavioral Analysis::Debugger Detection::Timing/Delay Check GetTickCount [B0001.032]
examples Practical Malware Analysis Lab 16-03.exe_:0x4013d0
function @ 0x140002140
and:
count(api(kernel32.GetTickCount)): 2 or more @ 0x1400021B6, 0x1400023E7
encrypt or decrypt data via BCrypt
namespace data-manipulation/encryption
author michael.hunhoff@fireeye.com
scope function
att&ck Defense Evasion::Obfuscated Files or Information [T1027]
mbc Cryptography::Decrypt Data [C0031], Cryptography::Encrypt Data [C0027]
function @ 0x140001B40
and:
or:
api: BCryptEncrypt @ 0x140001CE9
optional:
api: BCryptOpenAlgorithmProvider @ 0x140001B8C
api: BCryptCloseAlgorithmProvider @ 0x140001DCD
api: BCryptGenerateSymmetricKey @ 0x140001C40
api: BCryptDestroyKey @ 0x140001D7F
debug build
namespace executable/pe/debug
author william.ballenthin@fireeye.com
scope file
or:
string: "Assertion failed!" @ 0x513C8, 0x51A48
contains PDB path
namespace executable/pe/pdb
author moritz.raabe@fireeye.com
scope file
examples 464EF2CA59782CE697BC329713698CCC
regex: /:\\.*\.pdb/
- "C:\\Users\\User1\\Desktop\\dev projects\\SignSploit1\\x64\\Release\\AsrDrv_exploit.pdb" @ 0x5C284
- "c:\\asrock\\work\\asrocksdk_v0.0.69\\asrrw\\src\\driver\\src\\objfre_win7_amd64\\amd64\\AsrDrv103.pdb" @ 0x62C98
contain a resource (.rsrc) section
namespace executable/pe/section/rsrc
author moritz.raabe@fireeye.com
scope file
examples A933A1A402775CFA94B6BEE0963F4B46:0x41fd25
section: .rsrc @ 0x140071000
contain an embedded PE file
namespace executable/subfile/pe
author moritz.raabe@fireeye.com
scope file
mbc Execution::Install Additional Program [B0023]
examples Practical Malware Analysis Lab 01-04.exe_:0x4060
or:
count(characteristic(embedded pe)): 1 or more @ 0x60010
get file size
namespace host-interaction/file-system/meta
author michael.hunhoff@fireeye.com
scope function
att&ck Discovery::File and Directory Discovery [T1083]
examples mimikatz.exe_:0x40630D
function @ 0x140001060
or:
api: kernel32.GetFileSize @ 0x140001109
read file
namespace host-interaction/file-system/read
author moritz.raabe@fireeye.com
scope function
mbc File System::Read File [C0051]
examples BFB9B5391A13D0AFD787E87AB90F14F5:0x1314567B
function @ 0x140001060
or:
and:
or:
api: kernel32.ReadFile @ 0x140001135
write file
namespace host-interaction/file-system/write
author william.ballenthin@fireeye.com
scope function
mbc File System::Writes File [C0052]
examples Practical Malware Analysis Lab 01-04.exe_:0x4011FC, 563653399B82CD443F120ECEFF836EA3678D4CF11D9B351BB737573C2D856299:0x1400025C4
function @ 0x140001060
and:
or:
api: fwrite @ 0x140001179
print debug messages
namespace host-interaction/log/debug/write-event
author michael.hunhoff@fireeye.com
scope function
examples 493167E85E45363D09495D0841C30648:0x401000
function @ 0x14002B260
or:
api: kernel32.OutputDebugString @ 0x14002B271
create or open registry key
namespace host-interaction/registry
author michael.hunhoff@fireeye.com
scope basic block
mbc Operating System::Registry::Create Registry Key [C0036.004], Operating System::Registry::Open Registry Key [C0036.003]
examples Practical Malware Analysis Lab 03-02.dll_:0x10004706, Practical Malware Analysis Lab 11-01.exe_:0x401000, 493167E85E45363D09495D0841C30648:0x404D60, B5F85C26D7AA5A1FB4AF5821B6B5AB9B:0x4045F2, B5F85C26D7AA5A1FB4AF5821B6B5AB9B:0x40433E
basic block @ 0x140002730
or:
api: advapi32.RegOpenKeyEx @ 0x1400027C0
query or enumerate registry value
namespace host-interaction/registry
author william.ballenthin@fireeye.com, michael.hunhoff@fireeye.com
scope function
att&ck Discovery::Query Registry [T1012]
mbc Operating System::Registry::Query Registry Value [C0036.006]
examples BFB9B5391A13D0AFD787E87AB90F14F5:0x13145B5A, Practical Malware Analysis Lab 03-02.dll_:0x100047AD
function @ 0x140002730
and:
optional:
match: create or open registry key @ 0x140002730
or:
api: advapi32.RegOpenKeyEx @ 0x1400027C0
or:
api: advapi32.RegQueryValueEx @ 0x14000283C
create service
namespace host-interaction/service/create
author moritz.raabe@fireeye.com
scope function
att&ck Persistence::Create or Modify System Process::Windows Service [T1543.003], Execution::System Services::Service Execution [T1569.002]
examples Practical Malware Analysis Lab 03-02.dll_:0x10004706
function @ 0x140001060
and:
api: advapi32.CreateService @ 0x1400011ED
optional:
api: advapi32.OpenSCManager @ 0x14000118E
start service
namespace host-interaction/service/start
author moritz.raabe@fireeye.com
scope function
att&ck Persistence::Create or Modify System Process::Windows Service [T1543.003]
examples E544A4D616B60147D9774B48C2B65EF2:0x401FA0
function @ 0x140001060
and:
optional:
match: get service handle @ 0x140001060
or:
api: advapi32.CreateService @ 0x1400011ED
api: advapi32.OpenService @ 0x14000120B
api: advapi32.StartService @ 0x140001244
link function at runtime
namespace linking/runtime-linking
author moritz.raabe@fireeye.com
scope function
att&ck Execution::Shared Modules [T1129]
examples 9324D1A8AE37A36AE560C37448C9705A:0x404130, Practical Malware Analysis Lab 01-04.exe_:0x401350
function @ 0x140001000
and:
or:
api: kernel32.GetModuleHandle @ 0x14000100B
or:
api: kernel32.GetProcAddress @ 0x14000101B
We can see the malware is using GetTicketCount()
to measure the time delay from CPU to find if any debugger is attached for analysis. It is one of the standard anti-analysis techniques.
Next, I used a tool called RetDec from Avast which is a decompiler that support PE and ELF file formats. It is available in the form of docker image in REMnux.
$ docker run -it --rm -v <files_directory>:/tmp/files remnux/retdec bash
Once the sample file in available inside the container the decompiler command is like.
$ retdec-decomplier.py incontroller
The output will contain incontroller.c
file which can be analysed further manually. The C file is little human readable code.
if (v7 == 0) {
goto lab_0x14000151a;
} else {
int64_t * hFile = (int64_t *)(int64_t)v7; // 0x140001109
uint32_t v15 = GetFileSize(hFile, NULL); // 0x140001109
function_140001630(&v3, (int64_t)v15);
int32_t lpNumberOfBytesRead = 0; // bp-1360, 0x14000111b
ReadFile(hFile, NULL, 0, &lpNumberOfBytesRead, NULL);
CloseHandle(hFile);
int64_t file = function_140017870((int64_t)"C:\\AsRockDrv.sys", "wb"); // 0x140001155
v8 = (int64_t)"wb";
v9 = 0;
v13 = &lpNumberOfBytesRead;
v10 = (int64_t)"cant drop and load exploatable driver ! \n";
if (file == 0) {
goto lab_0x14000151a;
} else {
// 0x140001166
function_140018290(&g77, 0x8708, 1, file);
fclose((struct _IO_FILE *)file);
hSCManager = OpenSCManagerW(NULL, NULL, 2);
v8 = 0;
v9 = 2;
v13 = file;
v10 = (int64_t)"cant drop and load exploatable driver ! \n";
if (hSCManager == NULL) {
goto lab_0x14000151a;
} else {
int64_t * v16 = CreateServiceA(hSCManager, "AsRockDrv", "AsRockDrv", 0xf01ff, 1, 2, 1, "C:\\AsRockDrv.sys", NULL, NULL, NULL, NULL, NULL); // 0x1400011ed
hService = v16;
v12 = (int64_t)"AsRockDrv";
if (v16 != NULL) {
goto lab_0x14000122e;
} else {
// 0x1400011fb
hService = OpenServiceA(hSCManager, "AsRockDrv", 0xf01ff);
hSCObject = hSCManager;
v14 = (int64_t)"AsRockDrv";
v11 = 0xf01ff;
v12 = 0xf01ff;
if (hService != NULL) {
goto lab_0x14000122e;
} else {
goto lab_0x14000121c;
}
}
}
}
}
Above is a snippet from the C file. We can read and understand the code where the malware tries to drop the AsRock exploit.
Final Notes
This was my quick static analysis for INCONTROLLER malware. The malware is modular in nature and targets OT environment specifically. It uses ICS protocols such as Modbus, OPC UA servers to implant the packets on the equipment which can persist on them for a long time and can cause major outage in operations. The APT group has made it modular so that it could have more modules in future for other protocols/OEM’s It is best of interest for anyone using this equipments to apply the countermeasures suggested by CISA in their report. Also, for detecting activity from this malware the Yara Rule shared in Mandiant’s blog can be useful.
Below are some other analysis reports I referred while writing this blogpost. Thanks, until next time Happy Hacking 🙂 🏭
Other Analysis Reports
- https://www.virustotal.com/gui/file/69296ca3575d9bc04ce0250d734d1a83c1348f5b6da756944933af0578bd41d2/behavior
- https://www.hybrid-analysis.com/sample/69296ca3575d9bc04ce0250d734d1a83c1348f5b6da756944933af0578bd41d2/625824266f552f1a82127ffc
- https://tria.ge/220414-nv7m6scccj/behavioral1
- https://metadefender.opswat.com/results/file/bzIyMDQxM2tXcTJZUnFQd2JxYTlYNnRjaVg/regular/overview
Leave a comment