Skip to content

Commit

Permalink
Merge pull request #478 from CybercentreCanada/cccs-mog-patch-2
Browse files Browse the repository at this point in the history
Cccs mog patch 2[dev]
  • Loading branch information
cccs-mog authored Nov 7, 2024
2 parents 0aee6ef + 2ca1fc2 commit a11b2dd
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 17 deletions.
40 changes: 36 additions & 4 deletions cape/cape_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ def generate_al_result(
al_result.add_subsection(noexec_res)
else:
# Otherwise, moving on!
main_process_tuples = process_behaviour(behaviour, safelist, ontres)
main_process_tuples = process_behaviour(behaviour, process_map, safelist, ontres)

if ontres.get_processes():
_update_process_map(process_map, ontres.get_processes())
Expand Down Expand Up @@ -501,6 +501,7 @@ def process_debug(debug: Dict[str, Any], parent_result_section: ResultSection) -

def process_behaviour(
behaviour: Dict[str, Any],
process_map: Dict[int, Dict[str, Any]],
safelist: Dict[str, Dict[str, List[str]]],
ontres: OntologyResults,
) -> List[Tuple[int, str]]:
Expand All @@ -515,7 +516,7 @@ def process_behaviour(
# Preparing CAPE processes to match the OntologyResults format
processes = behaviour["processes"]
if processes:
convert_cape_processes(processes, safelist, ontres)
convert_cape_processes(processes, process_map, safelist, ontres)

if len(processes) < 1:
return []
Expand Down Expand Up @@ -559,6 +560,7 @@ def get_process_api_sums(apistats: Dict[str, Dict[str, int]]) -> Dict[str, int]:

def convert_cape_processes(
cape_processes: List[Dict[str, Any]],
process_map: Dict[int, Dict[str, Any]],
safelist: Dict[str, Dict[str, List[str]]],
ontres: OntologyResults,
) -> None:
Expand Down Expand Up @@ -614,6 +616,8 @@ def convert_cape_processes(
command_line=command_line,
start_time=first_seen,
pguid=pguid,
loaded_modules = process_map[item["process_id"]]["loaded_modules"],
services_involved = process_map[item["process_id"]]["services_involved"],
)


Expand Down Expand Up @@ -689,6 +693,7 @@ def process_signatures(
data = {
"name": sig_name,
"type": "CUCKOO",
"classification": Classification.UNRESTRICTED,
}
s_tag = SignatureModel.get_tag(data)
s_oid = SignatureModel.get_oid(data)
Expand All @@ -701,6 +706,7 @@ def process_signatures(
name=sig_name,
type="CUCKOO",
score=translated_score,
classification= Classification.UNRESTRICTED,
)
sig_res = _create_signature_result_section(
sig_name,
Expand Down Expand Up @@ -2474,6 +2480,13 @@ def get_process_map(
"""
process_map: Dict[int, Dict[str, Any]] = {}
api_calls_of_interest = {
"LdrLoadDll": ["filename"],
"LoadLibraryExW": ["lplibfilename"],
"LdrGetDllHandle": ["filename"],
"CreateServiceA": ["servicename", "displayname", "starttype", "binarypathname"],
"CreateServiceW": ["servicename", "displayname", "starttype", "binarypathname"],
"StartServiceA": ["servicename", "arguments"],
"StartServiceW": ["servicename", "arguments"],
"getaddrinfo": ["hostname", "nodename"], # DNS
"GetAddrInfoW": ["hostname", "nodename"], # DNS
"gethostbyname": ["hostname"], # DNS
Expand Down Expand Up @@ -2517,6 +2530,8 @@ def get_process_map(
for process in processes:
process_name = process["module_path"] if process.get("module_path") else process["process_name"]
network_calls = []
loaded_dlls = []
services_involved = []
decrypted_buffers = []
calls = process["calls"]
for call in calls:
Expand All @@ -2541,18 +2556,35 @@ def get_process_map(
continue
args_of_interest[arg] = kv["value"]
break
elif category == "system" and "api" not in kv["value"]:
args_of_interest[arg] = kv["value"].lower().replace(".dll", "")
break
if args_of_interest:
item_to_add = {api: args_of_interest}
if category == "network" and item_to_add not in network_calls:
network_calls.append(item_to_add)
elif category in ["crypto", "system"] and item_to_add not in decrypted_buffers:
elif next(iter(item_to_add)) in ["LdrLoadDll", "LoadLibraryExW", "LdrGetDllHandle"] and next(iter(next(iter(item_to_add.values())).values())) not in loaded_dlls:
dll_name = next(iter(next(iter(item_to_add.values())).values()))
adding_dll = True
for loaded_dll in loaded_dlls:
dll_chunck = loaded_dll.split("\\")
if dll_name in dll_chunck:
adding_dll = False
elif dll_chunck[-1] in dll_name.split("\\"):
adding_dll = False
if adding_dll:
loaded_dlls.append(next(iter(next(iter(item_to_add.values())).values())))
elif next(iter(item_to_add)) in ["CreateServiceA", "CreateServiceW", "StartServiceA", "StartServiceW"] and item_to_add not in services_involved:
services_involved.append(item_to_add)
elif category in ["crypto", "system"] and next(iter(item_to_add)) not in ["LdrLoadDll", "LoadLibraryExW", "LdrGetDllHandle", "CreateServiceA", "CreateServiceW", "StartServiceA", "StartServiceW"] and item_to_add not in decrypted_buffers:
decrypted_buffers.append(item_to_add)

pid = process["process_id"]
process_map[pid] = {
"name": process_name,
"network_calls": network_calls,
"decrypted_buffers": decrypted_buffers,
"loaded_modules": loaded_dlls,
"services_involved": services_involved,
}
return process_map

Expand Down
2 changes: 2 additions & 0 deletions cape/signatures.py
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,7 @@
"packer_armadillo_regkey": "Packer",
"packer_entropy": "Packer",
"packer_nspack": "Packer",
"packer_themida": "Packer",
"packer_unknown_pe_section_name": "Packer",
"packer_upx": "Packer",
"packer_yoda": "Packer",
Expand Down Expand Up @@ -661,6 +662,7 @@
"suricata_alert": "Network",
"suspicious_certutil_use": "Command",
"suspicious_command_tools": "Command",
"suspicious_html_name": "Phishing",
"suspicious_html_title": "Phishing",
"suspicious_ioctl_scsipassthough": "Bootkit",
"suspicious_js_script": "Downloader",
Expand Down
48 changes: 35 additions & 13 deletions tests/test_cape_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,14 +300,15 @@ def test_process_debug(debug, correct_body):

@staticmethod
@pytest.mark.parametrize(
"behaviour, expected",
"behaviour, process_map, expected",
[
({"processes": []}, []),
({"processes": []}, {}, []),
(
{
"processes": [{"parent_id": 123, "process_id": 321, "process_name": "blah.exe"}],
"apistats": {"blah": "blah"},
},
{321: { "loaded_modules": [], "services_involved": []}},
[(321, "blah.exe")],
),
(
Expand All @@ -318,16 +319,17 @@ def test_process_debug(debug, correct_body):
],
"apistats": {"blah": "blah"},
},
{321: { "loaded_modules": [], "services_involved": []}},
[(321, "iexplore.exe"), (999, "iexplore.exe")],
),
],
)
def test_process_behaviour(behaviour, expected, mocker):
def test_process_behaviour(behaviour, process_map, expected, mocker):
mocker.patch("cape.cape_result.get_process_api_sums", return_value={"blah": "blah"})
mocker.patch("cape.cape_result.convert_cape_processes")
safelist = {}
so = OntologyResults()
main_process_tuples = process_behaviour(behaviour, safelist, so)
main_process_tuples = process_behaviour(behaviour, process_map, safelist, so)
assert main_process_tuples == expected

@staticmethod
Expand All @@ -343,7 +345,7 @@ def test_get_process_api_sums(apistats, correct_api_sums):

@staticmethod
@pytest.mark.parametrize(
"processes, correct_event",
"processes, process_map, correct_event",
[
(
[
Expand All @@ -357,6 +359,7 @@ def test_get_process_api_sums(apistats, correct_api_sums):
"first_seen": "1970-01-01 00:00:01,000",
}
],
{0: { "loaded_modules": [], "services_involved": []}},
{
"start_time": "1970-01-01 00:00:01.000",
"end_time": "9999-12-31 23:59:59.999999",
Expand Down Expand Up @@ -392,16 +395,17 @@ def test_get_process_api_sums(apistats, correct_api_sums):
"first_seen": "1970-01-01 00:00:01,000",
}
],
{0: { "loaded_modules": [], "services_involved": []}},
{},
),
([], {}),
([], {}, {}),
],
)
def test_convert_cape_processes(processes, correct_event, mocker):
def test_convert_cape_processes(processes, process_map, correct_event, mocker):
safelist = {}
so = OntologyResults(service_name="CAPE")
mocker.patch.object(so, "sandboxes", return_value="blah")
convert_cape_processes(processes, safelist, so)
convert_cape_processes(processes, process_map, safelist, so)
if correct_event:
proc_as_prims = so.get_processes()[0].as_primitives()
_ = proc_as_prims["objectid"].pop("session")
Expand Down Expand Up @@ -31937,15 +31941,15 @@ def test_process_cape(input, expected_cape_artifacts, expected_result_section):
# We are no longer safelisting by dynamic.process.name tag values. So lsass should be included in the process map
(
[{"module_path": "C:\\windows\\System32\\lsass.exe", "calls": [], "process_id": 1}],
{1: {"name": "C:\\windows\\System32\\lsass.exe", "network_calls": [], "decrypted_buffers": []}},
{1: {"name": "C:\\windows\\System32\\lsass.exe", "network_calls": [], "decrypted_buffers": [], 'loaded_modules': [], 'services_involved': []}},
),
(
[{"module_path": "blah.exe", "calls": [], "process_id": 1}],
{1: {"name": "blah.exe", "network_calls": [], "decrypted_buffers": []}},
{1: {"name": "blah.exe", "network_calls": [], "decrypted_buffers": [], 'loaded_modules': [], 'services_involved': []}},
),
(
[{"module_path": "blah.exe", "calls": [{"api": "blah"}], "process_id": 1}],
{1: {"name": "blah.exe", "network_calls": [], "decrypted_buffers": []}},
{1: {"name": "blah.exe", "network_calls": [], "decrypted_buffers": [], 'loaded_modules': [], 'services_involved': []}},
),
(
[
Expand All @@ -31966,6 +31970,8 @@ def test_process_cape(input, expected_cape_artifacts, expected_result_section):
"name": "blah.exe",
"network_calls": [{"getaddrinfo": {"hostname": "blah"}}],
"decrypted_buffers": [],
'loaded_modules': [],
'services_involved': []
}
},
),
Expand All @@ -31988,6 +31994,8 @@ def test_process_cape(input, expected_cape_artifacts, expected_result_section):
"name": "blah.exe",
"network_calls": [{"GetAddrInfoW": {"hostname": "blah"}}],
"decrypted_buffers": [],
'loaded_modules': [],
'services_involved': []
}
},
),
Expand All @@ -32010,6 +32018,8 @@ def test_process_cape(input, expected_cape_artifacts, expected_result_section):
"name": "blah.exe",
"network_calls": [{"connect": {"ip_address": "blah", "port": 123}}],
"decrypted_buffers": [],
'loaded_modules': [],
'services_involved': []
}
},
),
Expand Down Expand Up @@ -32048,6 +32058,8 @@ def test_process_cape(input, expected_cape_artifacts, expected_result_section):
}
],
"decrypted_buffers": [],
'loaded_modules': [],
'services_involved': []
}
},
),
Expand Down Expand Up @@ -32086,6 +32098,8 @@ def test_process_cape(input, expected_cape_artifacts, expected_result_section):
}
],
"decrypted_buffers": [],
'loaded_modules': [],
'services_involved': []
}
},
),
Expand All @@ -32099,7 +32113,7 @@ def test_process_cape(input, expected_cape_artifacts, expected_result_section):
"process_id": 1,
}
],
{1: {"name": "blah.exe", "network_calls": [{"send": {"buffer": "blah"}}], "decrypted_buffers": []}},
{1: {"name": "blah.exe", "network_calls": [{"send": {"buffer": "blah"}}], "decrypted_buffers": [], 'loaded_modules': [], 'services_involved': []}},
),
(
[
Expand All @@ -32120,6 +32134,8 @@ def test_process_cape(input, expected_cape_artifacts, expected_result_section):
"name": "blah.exe",
"network_calls": [],
"decrypted_buffers": [{"CryptDecrypt": {"buffer": "blah"}}],
'loaded_modules': [],
'services_involved': []
}
},
),
Expand All @@ -32137,7 +32153,7 @@ def test_process_cape(input, expected_cape_artifacts, expected_result_section):
"process_id": 1,
}
],
{1: {"name": "blah.exe", "network_calls": [], "decrypted_buffers": []}},
{1: {"name": "blah.exe", "network_calls": [], "decrypted_buffers": [{'OutputDebugStringA': {'string': 'blah'}}], 'loaded_modules': [], 'services_involved': []}},
),
(
[
Expand All @@ -32158,6 +32174,8 @@ def test_process_cape(input, expected_cape_artifacts, expected_result_section):
"name": "blah.exe",
"network_calls": [],
"decrypted_buffers": [{"OutputDebugStringA": {"string": "cfg:blah"}}],
'loaded_modules': [],
'services_involved': []
}
},
),
Expand All @@ -32180,6 +32198,8 @@ def test_process_cape(input, expected_cape_artifacts, expected_result_section):
"name": "blah.exe",
"network_calls": [{"URLDownloadToFileW": {"url": "bad.evil"}}],
"decrypted_buffers": [],
'loaded_modules': [],
'services_involved': []
}
},
),
Expand All @@ -32202,6 +32222,8 @@ def test_process_cape(input, expected_cape_artifacts, expected_result_section):
"name": "blah.exe",
"network_calls": [{"WSASend": {"buffer": "blahblahblah bad.evil blahblahblah"}}],
"decrypted_buffers": [],
'loaded_modules': [],
'services_involved': []
}
},
),
Expand Down

0 comments on commit a11b2dd

Please sign in to comment.