Detecting the Presence of a Debugger in Linux

    Published: 2024-11-19. Last Updated: 2024-11-19 05:12:58 UTC
    by Xavier Mertens (Version: 1)
    0 comment(s)

    Hello from Singapore where I'm with Johannes and Yee! This week, I'm teaching FOR710[1]. I spotted another Python script that looked interesting because, amongst the classic detection of virtualized environments, it also tries to detect the presence of a debugger. The script has been developed to target both environments: Windows & Linux.

    On Windows, it's pretty easy to detect if a debugger has been attached to a process. The microsoft ecosystems has many ways to check this: A stealthy method is to check the PEB ("Process Environment Block")[2] that provides a "BeingDebugged" member in its structure. Another easy way is to use the Microsoft API call IsDebuggerPresent()[3]. Note that they are a lot of alternative techniques but I won't cover them here.

    But how does it work in Linux? Because the malicious script is compatible with Linux, let's check the code:

    def check_debugging():
        if True:
            try:
                if CURRENT_OS == "Windows":
                    if ctypes.windll.kernel32.IsDebuggerPresent():
                        return True
                else:
                    import re
                    with open('/proc/self/status') as f:
                        status = f.read()
                        if re.search(r'TracerPid:\s+(?!0\n)', status):
                            return True
                    except:
                        pass
        return False

    If the script is executed on Windows, IsDebuggerPresent() will be called otherwise, the script will search for an interesting string in /proc/self/status:

    xavier@rog:/proc/self$ cat status
    Name:   bash
    Umask:  0022
    State:  S (sleeping)
    Tgid:   352
    Ngid:   0
    Pid:    352
    PPid:   351
    TracerPid:      0
    Uid:    1000    1000    1000    1000
    Gid:    1000    1000    1000    1000
    FDSize: 256
    Groups: 4 20 24 25 27 29 30 44 46 116 1000
    NStgid: 352
    NSpid:  352
    NSpgid: 352
    NSsid:  352
    VmPeak:     6216 kB
    VmSize:     6216 kB
    VmLck:         0 kB
    VmPin:         0 kB
    VmHWM:      5076 kB
    VmRSS:      5076 kB
    RssAnon:            1724 kB
    RssFile:            3352 kB
    RssShmem:              0 kB
    VmData:     1736 kB
    VmStk:       132 kB
    VmExe:       892 kB
    VmLib:      1864 kB
    VmPTE:        48 kB
    VmSwap:        0 kB
    HugetlbPages:          0 kB
    CoreDumping:    0
    THP_enabled:    1
    Threads:        1
    SigQ:   1/30158
    SigPnd: 0000000000000000
    ShdPnd: 0000000000000000
    SigBlk: 0000000000010000
    SigIgn: 0000000000384004
    SigCgt: 000000004b813efb
    CapInh: 0000000000000000
    CapPrm: 0000000000000000
    CapEff: 0000000000000000
    CapBnd: 000001ffffffffff
    CapAmb: 0000000000000000
    NoNewPrivs:     0
    Seccomp:        0
    Seccomp_filters:        0
    Speculation_Store_Bypass:       thread vulnerable
    SpeculationIndirectBranch:      conditional enabled
    Cpus_allowed:   ffff
    Cpus_allowed_list:      0-15
    Mems_allowed:   1
    Mems_allowed_list:      0
    voluntary_ctxt_switches:        91
    nonvoluntary_ctxt_switches:     1

    The highlighted "TracerPid" line with the "0" indicates that no process is "tracing" this one. In Linux, a common technique used to analyze the behavious of a process is to use a tool like strace[4] to log all the activity performed at system calls level:

    xavier@rog:/proc/self$ strace -f -p 352

    Let's recheck the /proc/self/status now that it's being "traced":

    xavier@rog:/proc/self$ cat status|grep TracerPid
    TracerPid:      9731

    The script (SHA256a9ba5856b97327cc6c68d461e903569e30d5bd507405b5ecb34b0c513c42d50e)[5] remains undetected by most AV (VT score: 2/64) but its final purpose remains unknown because the bytecode passed to exec() does not seems to work! I'm still investigating it...

    [1] https://www.sans.org/cyber-security-courses/reverse-engineering-malware-advanced-code-analysis/
    [2] https://learn.microsoft.com/en-us/windows/win32/api/winternl/ns-winternl-peb
    [3] https://learn.microsoft.com/en-us/windows/win32/api/debugapi/nf-debugapi-isdebuggerpresent
    [4] https://man7.org/linux/man-pages/man1/strace.1.html
    [5] https://www.virustotal.com/gui/file/a9ba5856b97327cc6c68d461e903569e30d5bd507405b5ecb34b0c513c42d50e/detection

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

    0 comment(s)
    ISC Stormcast For Tuesday, November 19th, 2024 https://isc.sans.edu/podcastdetail/9224

      Comments


      Diary Archives