My next class:
Reverse-Engineering Malware: Advanced Code AnalysisOnline | Greenwich Mean TimeOct 28th - Nov 1st 2024

Multiple Layers of Anti-Sandboxing Techniques

Published: 2023-10-31. Last Updated: 2023-10-31 14:51:53 UTC
by Xavier Mertens (Version: 1)
1 comment(s)

It has been a while that I did not find an interesting malicious Python script. All the scripts that I recently spotted were always the same: a classic intostealer using Discord as C2 channel. Today I found one that contains a lot of anti-sanboxing techniques. Let's review them. For malware, it's key to detect the environment where they are executed. When detonated inside a sandbox (automatically or, manually, by an Analyst), they will be able to change their behaviour (most likely, do nothing)

Like all scripting languages running in the Windows eco-system, Python can call any Microsoft API call and there are useful to perform check at operating system. Here is what the scripts try to detect:

1. Is the script running inside a debugger?

from ctypes import *
XVeGwgv = windll.kernel32.IsDebuggerPresent()
if XVeGwgv == 0:

2. Does the host have enough physical memory?

import ctypes
class CaMiHTTSf (ctypes.Structure):
    _fields_ = [
        ("dwLength", ctypes.c_ulong),
        ("dwMemoryLoad", ctypes.c_ulong),
        ("ullTotalPhys", ctypes.c_ulonglong),
        ("ullAvailPhys", ctypes.c_ulonglong),
        ("ullTotalPageFile", ctypes.c_ulonglong),
        ("ullAvailPageFile", ctypes.c_ulonglong),
        ("ullTotalVirtual", ctypes.c_ulonglong),
        ("ullAvailVirtual", ctypes.c_ulonglong),
        ("sullAvailExtendedVirtual", ctypes.c_ulonglong),
    ]
jJrSHLb = CaMiHTTSf()
jJrSHLb.dwLength = ctypes.sizeof(CaMiHTTSf)
ctypes.windll.kernel32.GlobalMemoryStatusEx(ctypes.byref(jJrSHLb))
if jJrSHLb.ullTotalPhys/1073741824 > 3:

3. Is there a user behind the keyboard, pressing keys?

import win32api
nPnpCRlvJ = 0
CsZoAodMwrnNBW = 100
while nPnpCRlvJ < CsZoAodMwrnNBW:
    BBpvCYBI = win32api.GetAsyncKeyState(1)
    RkfbrNjlQLiYMc = win32api.GetAsyncKeyState(2)
    if BBpvCYBI % 2 == 1:
        nPnpCRlvJ += 1
    if RkfbrNjlQLiYMc % 2 == 1:
        nPnpCRlvJ += 1
if nPnpCRlvJ >= CsZoAodMwrnNBW:

4. Is the mouse moving?

from time import sleep
import win32api
dJpkzPW = 30
ESPKUCFSNpN, MNoTiqFAmrJb = win32api.GetCursorPos()
sleep(30)
sToXQq, nGVNgR = win32api.GetCursorPos()
if ESPKUCFSNpN - sToXQq != 0 or MNoTiqFAmrJb - nGVNgR != 0:

5. Is the script spending too much time in a debugger (ex: Python debugger)

from time import sleep
from socket import AF_INET, SOCK_DGRAM
import sys
import datetime
import time
import socket
import struct
client = socket.socket(AF_INET, SOCK_DGRAM)
client.sendto((bytes.fromhex("1b") + 47 * bytes.fromhex("01")), ("us.pool.ntp.org",123))
msg, address = client.recvfrom( 1024 )
BsaylVZq = datetime.datetime.fromtimestamp(struct.unpack("!12I",msg)[10] - 2208988800)
sleep(100000)
client.sendto((bytes.fromhex("1b") + 47 * bytes.fromhex("01")), ("us.pool.ntp.org",123))
msg, address = client.recvfrom( 1024 )
if ((datetime.datetime.fromtimestamp((struct.unpack("!12I",msg)[10] - 2208988800)) - BsaylVZq).seconds >= 100000):

Only if all these checks results are negative, then the Python will perform the malicious actions and inject a shellcode in memory...

Note that this script remains simple. They are plenty of sandbox-evasion techniques available[1].

The script (SHA256:a6eac5716bce341f14569d69fcac4f449e9c0f1e97adeb9cb4d02dc82962a30a) has a VT score of 12/61[2].

[1] https://evasions.checkpoint.com
[2] https://www.virustotal.com/gui/file/a6eac5716bce341f14569d69fcac4f449e9c0f1e97adeb9cb4d02dc82962a30a/detection

Xavier Mertens (@xme)
Xameco
Senior ISC Handler - Freelance Cyber Security Consultant
PGP Key

1 comment(s)
My next class:
Reverse-Engineering Malware: Advanced Code AnalysisOnline | Greenwich Mean TimeOct 28th - Nov 1st 2024

Comments

FYI, in example 3, it's detecting mouse button clicks rather than keyboard clicks. According to https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getasynckeystate, the values passed to GetAsyncKeyState() are these Virtual-Key Codes: https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes

Per that documentation, Virtual-Key Code 1 is a left mouse button click, and 2 is a right mouse button click. One could further augment that code to check for other keyboard clicks, but then the question becomes, which ones do you want to monitor?

Diary Archives