Windows.Carving.SystemBC

This artifact extracts SystemBC RAT configuration from a byte stream, process or file on disk.

The User can define bytes, file glob, process name or pid regex as a target. The artifact firstly discovers configuration and extracts bytes, before parsing with Velociraptor Binary Parser.

This content simply carves the configuration and does not unpack files on disk. That means pointing this artifact as a packed or obfuscated file may not obtain the expected results.


name: Windows.Carving.SystemBC
author: Matt Green - @mgreen27
description: |
  This artifact extracts SystemBC RAT configuration from a byte stream, 
  process or file on disk.
  
  The User can define bytes, file glob, process name or pid regex as a target.
  The artifact firstly discovers configuration and extracts bytes, 
  before parsing with Velociraptor Binary Parser.
  
  This content simply carves the configuration and does not unpack files on
  disk. That means pointing this artifact as a packed or obfuscated file may not
  obtain the expected results.

reference:
  - https://malpedia.caad.fkie.fraunhofer.de/details/win.systembc
  

parameters:
  - name: TargetBytes
    default:
  - name: TargetFileGlob
    default:
  - name: PidRegex
    default: .
    type: regex
  - name: ProcessRegex
    default: .
    type: regex
  - name: FindConfig
    type: hidden
    description: Final Yara option and the default if no other options provided.
    default: |
        rule SystemBC_Config
            {
                meta:
                    author = "Matt Green - @mgreen27"
                    description = "SystemBC configuration"
            
                strings:
                    $BEGINDATA = { 00 42 45 47 49 4e 44 41 54 41 00 } //BEGINDATA
                    $ = "HOST1:" ascii wide fullword
                    $ = "HOST2:" ascii wide fullword
                    $ = "PORT1:" ascii wide fullword
                    $ = "TOR:" ascii wide fullword
                    $ = "-WindowStyle Hidden -ep bypass -file" ascii wide
            
                condition:
                    $BEGINDATA and 3 of them
            }
sources:
  - precondition:
      SELECT OS From info() where OS = 'windows'

    query: |
      -- binary parse profile to extract SystemBC configuration.
      LET PROFILE = '''[
                [SystemBC, 0, [
                    ["__FindHost1",0, "String",{term: "HOST1:"}],
                    ["HOST1","x=>len(list=x.__FindHost1) + 6", "String",{term_hex: "0000"}],
                    ["__FindHost2",0, "String",{term: "HOST2:"}],
                    ["HOST2","x=>len(list=x.__FindHost2) + 6", "String",{term_hex: "0000"}],
                    ["__FindPort1",0, "String",{term: "PORT1:"}],
                    ["PORT1","x=>len(list=x.__FindPort1) + 6", "String",{term_hex: "0000"}],
                    ["__FindTOR",0, "String",{term: "TOR:"}],
                    ["TOR","x=>len(list=x.__FindTOR) + 4", "String",{term_hex: "0000"}],
                    ["__FindUserAgent",0, "String",{term: "\r\nUser-Agent: "}],
                    ["User-Agent","x=>len(list=x.__FindUserAgent) + 14", "String",{term: "\r\n"}],
                ]
            ]]'''
            
      
      -- Bytes usecase: scan DataBytes for config
      LET ByteConfiguration = SELECT
            Rule,
            len(list=TargetBytes) as Size,
            hash(path=TargetBytes,accessor='data') as Hash,
            String.Offset as HitOffset,
            read_file(accessor="data",filename=TargetBytes, offset=String.Offset, length=1000) as _RawConfig
        FROM yara(
                files=TargetBytes,
                accessor='data',
                rules=FindConfig,
                number=99,
                context=1000
            )
        GROUP BY _RawConfig
      
      -- Glob usecase: find target files
      LET TargetFiles = SELECT OSPath,Size
        FROM glob(globs=TargetFileGlob) WHERE NOT IsDir

      -- Glob usecase: Extract config from files in scope
      LET FileConfiguration = SELECT * FROM foreach(row=TargetFiles,
            query={
                SELECT 
                    Rule,
                    OSPath, Size,
                    hash(path=OSPath) as Hash,
                    String.Offset as HitOffset,
                    read_file(filename=OSPath, offset=String.Offset, length=1000) as _RawConfig
                FROM yara(
                        files=OSPath,
                        rules=FindConfig,
                        number=99,
                        context=1000
                    )
                GROUP BY OSPath,_RawConfig
            })
            
      -- find velociraptor process
      LET me <= SELECT * FROM if(condition= NOT ( TargetFileGlob OR TargetBytes ),
                    then = { SELECT Pid FROM pslist(pid=getpid()) })

      -- find all processes and add filters
      LET processes = SELECT Name as ProcessName, Exe, CommandLine, Pid
        FROM pslist()
        WHERE
            Name =~ ProcessRegex
            AND format(format="%d", args=Pid) =~ PidRegex
            AND NOT Pid in me.Pid
      
      -- scan processes in scope with our rule, limit 1 hit and extract context to parse
      LET ProcessConfiguration = SELECT * FROM foreach(
        row=processes,
        query={
            SELECT
                Rule,
                Pid, ProcessName, CommandLine,
                String.Offset as HitOffset,
                read_file(accessor="process", filename=format(format="/%d", args=Pid), offset=String.Offset, length=1000) as _RawConfig
            FROM yara( 
                    files=format(format="/%d", args=Pid),
                    accessor='process',
                    rules=FindConfig,
                    number=99,
                    context=1000
                )
            GROUP BY Pid, ProcessName, CommandLine,_RawConfig
          })
        


      -- generate results remove any FPs
      SELECT *,
        parse_binary(accessor="data", filename=_RawConfig, profile=PROFILE, struct='SystemBC') AS SystemBC,
        _RawConfig
      FROM if(condition=TargetBytes,
            then=ByteConfiguration,
            else= if(condition=TargetFileGlob,
                then= FileConfiguration,
                else= ProcessConfiguration))
      WHERE SystemBC.HOST1 OR SystemBC.HOST2 OR SystemBC.TOR