Skip to content

Commit

Permalink
vmray: record command line info
Browse files Browse the repository at this point in the history
  • Loading branch information
mr-tz committed Dec 2, 2024
1 parent abe8084 commit 7a8551b
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
### New Features

- allow call as valid subscope for call scoped rules @mr-tz
- vmray: record command line details @mr-tz

### Breaking Changes

Expand Down
21 changes: 19 additions & 2 deletions capa/features/extractors/vmray/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,15 @@
from dataclasses import dataclass

from capa.exceptions import UnsupportedFormatError
from capa.features.extractors.vmray.models import File, Flog, SummaryV2, StaticData, FunctionCall, xml_to_dict
from capa.features.extractors.vmray.models import (
File,
Flog,
SummaryV2,
StaticData,
FunctionCall,
xml_to_dict,
sanitize_string,
)

logger = logging.getLogger(__name__)

Expand All @@ -35,6 +43,8 @@ class VMRayMonitorProcess:
ppid: int # parent process ID assigned by OS
monitor_id: int # unique ID assigned to process by VMRay
image_name: str
filename: str
cmd_line: str


class VMRayAnalysis:
Expand Down Expand Up @@ -160,7 +170,12 @@ def _compute_monitor_processes(self):
self.sv2.processes[process.ref_parent_process.path[1]].os_pid if process.ref_parent_process else 0
)
self.monitor_processes[process.monitor_id] = VMRayMonitorProcess(
process.os_pid, ppid, process.monitor_id, process.image_name
process.os_pid,
ppid,
process.monitor_id,
process.image_name,
sanitize_string(process.filename),
sanitize_string(process.cmd_line),
)

# not all processes are recorded in SummaryV2.json, get missing data from flog.xml, see #2394
Expand All @@ -170,6 +185,8 @@ def _compute_monitor_processes(self):
monitor_process.os_parent_pid,
monitor_process.process_id,
monitor_process.image_name,
monitor_process.filename,
monitor_process.cmd_line,
)

if monitor_process.process_id not in self.monitor_processes:
Expand Down
2 changes: 1 addition & 1 deletion capa/features/extractors/vmray/extractor.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def extract_process_features(self, ph: ProcessHandle) -> Iterator[tuple[Feature,

def get_process_name(self, ph) -> str:
monitor_process: VMRayMonitorProcess = ph.inner
return monitor_process.image_name
return f"{monitor_process.image_name} ({monitor_process.cmd_line})"

def get_threads(self, ph: ProcessHandle) -> Iterator[ThreadHandle]:
for monitor_thread_id in self.analysis.monitor_threads_by_monitor_process[ph.inner.monitor_id]:
Expand Down
14 changes: 12 additions & 2 deletions capa/features/extractors/vmray/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,19 +136,28 @@ class FunctionReturn(BaseModel):
from_addr: HexInt = Field(alias="from")


def sanitize_string(value: str) -> str:
# e.g. "cmd_line": "\"C:\\Users\\38lTTV5Kii\\Desktop\\filename.exe\" ",
return value.replace("\\\\", "\\").strip(' "')


# unify representation
SanitizedString = Annotated[str, BeforeValidator(sanitize_string)]


class MonitorProcess(BaseModel):
ts: HexInt
process_id: int
image_name: str
filename: str
filename: SanitizedString
# page_root: HexInt
os_pid: HexInt
# os_integrity_level: HexInt
# os_privileges: HexInt
monitor_reason: str
parent_id: int
os_parent_pid: HexInt
# cmd_line: str
cmd_line: SanitizedString
# cur_dir: str
# os_username: str
# bitness: int
Expand Down Expand Up @@ -308,6 +317,7 @@ class Process(BaseModel):
os_pid: int
filename: str
image_name: str
cmd_line: str
ref_parent_process: Optional[GenericReference] = None


Expand Down

0 comments on commit 7a8551b

Please sign in to comment.