Malware Reversing: Insomnia

Converted from Blogger. Please excuse any layout errors! Insomnia is a .NET framework Windows PE commanded through IRC that has been around for quite a few years. It has been updated and sold online for $30-$50. I came across this sample, and ran it inside of Cuckoo sandbox. Cuckoo indicated it was part of an IRC botnet, so I immediately started to pick it apart.

Insomnia Overview

Purpose of Insomnia:
Mass IRC Botnet control
DDoS Attacks
Credential Stealer

Features of Insomnia include:
5 different DDoS methods to initiate distributed denial of service attacks against a wide variety of targets:
  • Apache Remote Memory Exhaustion (A.R.M.E.)
  • Slowloris
  • Layer7
  • Layer4
  • Latest Insomnia builder
  • UDP 
Filezilla Stealer
IM Stealer
Web Browser Password Stealer (Chrome and Firefox)
Twitter Spread
USB Spread
Registry monitor/persistence
Monitor computer power state
RusKill marks files for deletion upon reboot
BotKiller that is capable of removing bots that use injected threads in explorer.exe. Insomnia is coded to watch and detect many different attributes that malware display.

IRC Commands:
".v": Version information
        
".avinfo": Antivirus information

".chrome": Steal All Chrome Credentials
         
".firefox": Steal all Firefox Credentials

".j": Join Channel

".p": Part Channel
         
".sort": Joins channel by GeoIPCountry to Sort bots
        
".unsort": Leaves the GeoIPCountry channel

".permsort": if parameter is a, JOIN #admins. Else JOIN #users

".twitter": Twitter Spread

".ftp": Steal Filezilla saved credentials

".bk": BotKiller if parameter is -i, explorerFlash. Else just initiate botkiller
         
".rc": Reconnect bot

".up": Update Bot

".rm": Uninstall bot

".dl": Download Exe File

".m": if parameter = on, then IRC Muted = true. If parameter = off, Then IRC Muted = false

".arme": ARME flood
         
".layer7": Layer7 Flood
        
".layer4": Layer4 Flood
         
".udp": UDP Flood
         
".slow": Slowloris Flood
        
".stop": Stops all Floods
        
".read": execute commands from url
        
".ruskill": Turns on or off Ruskill
         
".socks": Connects through socks

".usb": Turns on or off usb spread

Reversing Insomnia

Sample SHA256:
0d2df9914ff16053817a2d31b4ccdb0e2113dc96d1c499465c0be65444cd3538

Tools Used:
Cuckoo Sandbox
Ollydbg
JetBrains DotPeek
Visual Studio 2013


Notable Strings:
$: strings 0d2df9914ff16053817a2d31b4ccdb0e2113dc96d1c499465c0be65444cd3538  | grep 'CorExeMain'
 _CorExeMain
"When a .NET executable loads, its entry point is usually a tiny stub of code. That stub just jumps to an exported function in MSCOREE.DLL (_CorExeMain or _CorDllMain)" (http://a5.tf/Dbg)

 $: strings 0d2df9914ff16053817a2d31b4ccdb0e2113dc96d1c499465c0be65444cd3538  | grep -i 'channel'
channel
_mainChannel
mainChannel
mainChannelKey

$: strings 0d2df9914ff16053817a2d31b4ccdb0e2113dc96d1c499465c0be65444cd3538  | grep -i 'botnick'
botNick
BotNick

The mainChannel and botNick strings were enough to give away it was joining an IRC server.


Because of the indicator that the executable was .NET framework. I switched over to DotPeak,

Insomnia Functions

DotPeek was very informative because it was able to disassemble the sample. The source code became cleartext, and I was able to fully understand what the sample was doing. The code was extremely well written compared to other samples I have seen.


I was able to export the sample from DotPeek into Visual Studio 2013, and begin to start debugging and reversing.












There is a snippet of code in Config.cs with all of the customizable configurations :

    public static string currentPath = Process.GetCurrentProcess().MainModule.FileName;
    public static string randomID = Functions.RandomString(7);
    public static string botNick = Functions.BotNick();
    public static string botMD5 = Functions.GetMD5Hash(Config.currentPath);
    public static string version = "2.2.0";
    public static string regLocation = "HKCU";
    public static string socksUser = Config.randomID;
    public static string socksPass = Convert.ToBase64String(Encoding.UTF8.GetBytes(Config.randomID)).Substring(0, 5);
    public static bool topicAct = false;
    private static string enc = "[Redacted Base64 String]";
    private static string toParse = Encoding.UTF8.GetString(Convert.FromBase64String(Config.enc));
    public static string customerID = Config.toParse.Substring(0, 8);
    private static string[] nfo = Functions.Chk(new Data().decrypt(Config.toParse.Remove(0, 8)), Convert.ToInt32(Config.customerID)).Split(new char[1]
    {
      '/'
    }); 
 
The problem is that all of the configurations stem from the string "enc". This is an encrypted string that needs to be reversed before we can figure out who the attacker is.
 
Decryption Algorithm:
enc Base64 - > UTF8 -> First 8 characters removed and go to CustID -> Converted to Int32,

Data.Decrypt Function on rest of characters (80 lines of character swapping)  -> Decrypted string with CustID used as key for Functions.Chk -> All split at "/" into nfo[] array

I ended up writing a C# program to reverse the encryption algorithm it uses.


 Source code can be found here.

Results:
Disassembling and reversing the encryption leads to a domain name which hosts the IRC server. Most of the server names are using a dynamic dns service like no-ip or dyndns.
We can connect to the IRC and start issuing commands, like in my other entry,  To Catch a Hacker.