Skip to content

Commit 3c7bb25

Browse files
authored
Merge branch 'kevoreilly:master' into master
2 parents 7e28221 + b28d42c commit 3c7bb25

File tree

275 files changed

+3090
-20276
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

275 files changed

+3090
-20276
lines changed

.github/actions/python-setup/action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ runs:
1616
1717
- name: Install poetry
1818
shell: bash
19-
run: PIP_BREAK_SYSTEM_PACKAGES=1 pip install poetry
19+
run: PIP_BREAK_SYSTEM_PACKAGES=1 pip install poetry poetry-plugin-export
2020

2121
- name: Set up Python ${{ inputs.python-version }}
2222
uses: actions/setup-python@v5

.github/workflows/python-package-windows.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
timeout-minutes: 20
1616
strategy:
1717
matrix:
18-
python-version: ["3.10", "3.11"]
18+
python-version: ["3.10"]
1919

2020
steps:
2121
- name: Check out repository code

.github/workflows/python-package.yml

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
timeout-minutes: 20
1616
strategy:
1717
matrix:
18-
python-version: ["3.10", "3.11"]
18+
python-version: ["3.10"]
1919
steps:
2020
- name: Check out repository code
2121
uses: actions/checkout@v4
@@ -37,23 +37,11 @@ jobs:
3737
poetry run pip install pyattck==7.1.2 maco
3838
3939
- name: Run Ruff
40-
run: poetry run ruff . --line-length 132 --ignore E501,E402
40+
run: poetry run ruff check . --line-length 132 --ignore E501,E402
4141

4242
- name: Run unit tests
4343
run: poetry run python -m pytest --import-mode=append
4444

45-
- name: See if any parser changed
46-
uses: dorny/paths-filter@v3
47-
id: changes
48-
with:
49-
filters: |
50-
src:
51-
- 'modules/processing/parsers/CAPE/*.py'
52-
53-
- name: Test parsers only if any parser changed
54-
if: steps.changes.outputs.src == 'true'
55-
run: poetry run python -m pytest tests_parsers -s --import-mode=append
56-
5745
format:
5846
runs-on: ubuntu-latest
5947
timeout-minutes: 20

analyzer/windows/data/yara/Al-khaser.yar

Lines changed: 0 additions & 12 deletions
This file was deleted.

analyzer/windows/data/yara/NitrogenLoader.yar

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,17 @@ rule NitrogenLoaderBypass
3838
$exit = {33 C9 E8 [4] E8 [4] 48 8D 84 24 [4] 48 89 44 24 ?? 4? B? E4 00 00 00 4? 8B 05 [4] B? 03 00 00 00 48 8D}
3939
condition:
4040
all of them
41-
}
41+
}
42+
43+
rule NitrogenLoaderConfig
44+
{
45+
meta:
46+
author = "enzok"
47+
description = "NitrogenLoader Config Extraction"
48+
cape_options = "bp0=$decrypt1*+6,hc0=1,count=0,action0=string:rcx,typestring=NitrogenLoader Config"
49+
strings:
50+
$decrypt1 = {48 8B 8C 24 [4] 0F B6 04 01 89 ?? 24 [1-4] 48 63 4C 24 ?? 33 D2 48 8B C1 48 F7 B4 24 [4] 48 8B C2 48 8B 8C}
51+
$decrypt2 = {8B ?? 24 [1-4] 33 C8 8B C1 48 63 4C 24 ?? 48 8B 94 24 [4] 88 04 0A}
52+
condition:
53+
all of them
54+
}

analyzer/windows/data/yara/Pafish.yar

Lines changed: 0 additions & 14 deletions
This file was deleted.

analyzer/windows/lib/core/packages.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,5 +147,7 @@ def choose_package(file_type, file_name, exports, target):
147147
return "autoit"
148148
elif file_name.endswith(("cmd", "bat")) or b"@echo off" in file_content:
149149
return "batch"
150+
elif file_name.endswith(".rdp"):
151+
return "rdp"
150152
else:
151153
return "generic"

analyzer/windows/modules/auxiliary/amsi.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1002,7 +1002,7 @@ def _unpackSimpleType(self, record, info, event_property):
10021002

10031003
data = formatted_data.value
10041004
# Convert the formatted data if necessary
1005-
if out_type in TDH_CONVERTER_LOOKUP and type(data) != TDH_CONVERTER_LOOKUP[out_type]:
1005+
if out_type in TDH_CONVERTER_LOOKUP and type(data) is TDH_CONVERTER_LOOKUP[out_type]:
10061006
data = TDH_CONVERTER_LOOKUP[out_type](data)
10071007

10081008
return {name_field: data}

analyzer/windows/modules/auxiliary/disguise.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
from lib.common.rand import random_integer, random_string
3131

3232
log = logging.getLogger(__name__)
33-
PERSISTENT_ROUTE_GATEWAY = "192.168.1.1"
3433
si = subprocess.STARTUPINFO()
3534
si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
3635

@@ -243,18 +242,14 @@ def randomizeUUID(self):
243242
# Replace the UUID with the new UUID
244243
SetValueEx(key, "MachineGuid", 0, REG_SZ, createdUUID)
245244

246-
def add_persistent_route(self):
247-
self.run_as_system(
248-
["C:\\Windows\\System32\\ROUTE.exe", "-p", "add", "0.0.0.0", "mask", "0.0.0.0", PERSISTENT_ROUTE_GATEWAY]
249-
)
250-
self.run_as_system(
251-
["C:\\Windows\\System32\\ROUTE.exe", "-p", "change", "0.0.0.0", "mask", "0.0.0.0", PERSISTENT_ROUTE_GATEWAY]
252-
)
245+
def add_persistent_route(self, gateway: str):
246+
self.run_as_system(["C:\\Windows\\System32\\ROUTE.exe", "-p", "add", "0.0.0.0", "mask", "0.0.0.0", gateway])
247+
self.run_as_system(["C:\\Windows\\System32\\ROUTE.exe", "-p", "change", "0.0.0.0", "mask", "0.0.0.0", gateway])
253248

254249
def start(self):
255250
if self.config.windows_static_route:
256251
log.info(f"Config for route is: {str(self.config.windows_static_route)}")
257-
self.add_persistent_route()
252+
self.add_persistent_route(self.config.windows_static_route_gateway)
258253
self.change_productid()
259254
self.set_office_mrus()
260255
self.ramnit()

analyzer/windows/modules/auxiliary/human.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
"don't send",
7272
"don't save",
7373
"continue",
74+
"connect",
7475
"unzip",
7576
"open",
7677
"close the program",
@@ -115,6 +116,7 @@
115116
DONT_CLICK_BUTTONS = (
116117
# english
117118
"check online for a solution",
119+
"don't ask me again for remote connections from this publisher",
118120
"don't run",
119121
"do not ask again until the next update is available",
120122
"cancel",

analyzer/windows/modules/packages/rdp.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from lib.common.common import check_file_extension
33

44

5-
class Exe(Package):
5+
class RDP(Package):
66
"""RDP analysis package."""
77

88
PATHS = [

changelog.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
### [01.11.2024] Parsers
2+
* Malware config parsers aka parsers are moved out of core of CAPE.
3+
* Now they are at their own [repository](https://github.com/CAPESandbox/CAPE-parsers).
4+
* Feature added. `load=X`, where `X` is one of those: all/core/community
5+
* All = core and community
6+
* Exclude parsers. Allows to not load some particular parsers. `exclude_parsers=["name1", "name2"]`
7+
* Your custom parsers from `custom/parsers/` will still load and overwrite cape carser if name matches.
8+
* __Action required!__ `cd /opt/CAPEv2 && poetry install`
9+
110
### [04.10.2024]
211
* Monitor update: Add GetClassObject hook to handle UAC bypass technique using CMSTPLUA COM object
312
* PrivateLoader direct syscall capture

conf/default/auxiliary.conf.default

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ browser = yes
2222
curtain = no
2323
digisig = yes
2424
disguise = yes
25+
# This is only useful in case you use KVM's dnsmasq. You need to set windows_static_route_gateway. Disguise must be enabled
26+
windows_static_route = no
27+
windows_static_route_gateway = 192.168.1.1
2528
evtx = no
2629
human_windows = yes
2730
human_linux = no
@@ -38,8 +41,6 @@ permissions = no
3841
pre_script = no
3942
during_script = no
4043
filecollector = yes
41-
# This is only useful in case you use KVM's dnsmasq. You need to change your range inside of analyzer/windows/modules/auxiliary/disguise.py. Disguise must be enabled
42-
windows_static_route = no
4344
tracee_linux = no
4445
sslkeylogfile = no
4546
# Requires setting up browser extension, check extra/browser_extension
@@ -80,6 +81,6 @@ enabled = no
8081

8182
[Mitmdump]
8283
# Enable or disable the use of mitmdump (mitmproxy) to get dump.har [yes/no].
83-
# This module requires installed mitmproxy see install_mitmproxy
84+
# This module requires installed mitmproxy see install_mitmproxy
8485
# (https://github.com/kevoreilly/CAPEv2/blob/master/installer/cape2.sh#L1320)
8586
enabled = no

conf/default/cuckoo.conf.default

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ scaling_semaphore = off
3333
# A configurable wait time between updating the limit value of the scaling bounded semaphore
3434
scaling_semaphore_update_timer = 10
3535

36+
# Specify a timeout for tasks, useful if you are bound to timely reports awaited by users
37+
task_timeout = off
38+
task_pending_timeout = 0
39+
task_timeout_scan_interval = 30
40+
3641
# Enable creation of memory dump of the analysis machine before shutting
3742
# down. Even if turned off, this functionality can also be enabled at
3843
# submission. Currently available for: VirtualBox and libvirt modules (KVM).

conf/default/processing.conf.default

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ platform = linux
8181
[debug]
8282
enabled = yes
8383
# Amount of text (bytes)
84-
buffer = 8192
84+
buffer = 0
8585

8686
[detections]
8787
enabled = yes
@@ -310,6 +310,10 @@ modules_path = modules/processing/parsers/malduck/
310310
enabled = yes
311311
# Must ends with /
312312
modules_path = modules/processing/parsers/CAPE/
313+
# Config parsers all/core/community
314+
parsers = all
315+
# list of comma separated parsers. Ex: stealc,lumma
316+
exclude=
313317

314318
# Community
315319
[reversinglabs]

conf/default/selfextract.conf.default

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,10 @@ timeout = 60
5656
enabled = yes
5757
timeout = 60
5858

59-
# sudo apt install innoextract
59+
# Use https://github.com/gdesmar/innoextract
6060
[Inno_extract]
6161
enabled = yes
62-
binary = /usr/bin/innoextract
62+
binary = data/innoextract
6363
timeout = 60
6464

6565
# https://github.com/mstrobel/procyon/releases

conf/default/web.conf.default

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ guest_width = 1280
194194
guest_height = 1024
195195
# rdp settings
196196
guest_rdp_port = 3389
197+
ignore_rdp_cert = false
197198

198199
[packages]
199200
# VM tags may be used to specify on which guest machines a sample should be run

data/yara/CAPE/CobaltStrikeBeacon.yar

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ rule CobaltStrikeBeacon
1717
$pwsh1 = "IEX (New-Object Net.Webclient).DownloadString('http" ascii
1818
$pwsh2 = "powershell -nop -exec bypass -EncodedCommand \"%s\"" fullword ascii
1919
$ver3a = {69 68 69 68 69 6b ?? ?? 69}
20-
$ver3b = {69 69 69 69}
20+
$ver3b = {69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69}
2121
$ver4a = {2e 2f 2e 2f 2e 2c ?? ?? 2e}
22-
$ver4b = {2e 2e 2e 2e}
22+
$ver4b = {2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e}
2323
$a1 = "%02d/%02d/%02d %02d:%02d:%02d" xor(0x00-0xff)
2424
$a2 = "Started service %s on %s" xor(0x00-0xff)
2525
$a3 = "%s as %s\\%s: %d" xor(0x00-0xff)

data/yara/CAPE/NitrogenLoader.yar

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,20 @@ rule NitrogenLoader
44
author = "enzok"
55
description = "Nitrogen Loader"
66
cape_type = "NitrogenLoader Loader"
7-
hash = "7b603d63a23201ff0b6ffa9acdd650df9caa1731837d559d93b3d8ce1d82a962"
7+
hash1 = "7b603d63a23201ff0b6ffa9acdd650df9caa1731837d559d93b3d8ce1d82a962"
8+
hash2 = "50c2afd792bfe2966133ee385054eaae1f73b04e013ef3434ef2407f99d7f037"
89
strings:
9-
$aes1 = {63 7c 77 7b f2 6b 6f c5 30 01 67 2b fe d7 ab 76 ca 82 c9 7d fa}
10-
$aes2 = {52 09 6a d5 30 36 a5 38 bf 40 a3 9e 81 f3 d7 fb 7c e3 39 82 9b}
10+
$stringaes1 = {63 7c 77 7b f2 6b 6f c5 30 01 67 2b fe d7 ab 76 ca 82 c9 7d fa}
11+
$stringaes2 = {52 09 6a d5 30 36 a5 38 bf 40 a3 9e 81 f3 d7 fb 7c e3 39 82 9b}
1112
$string1 = "BASS_GetEAXParameters"
1213
$string2 = "LoadResource"
1314
$syscallmakehashes = {48 89 4C 24 ?? 48 89 54 24 ?? 4? 89 44 24 ?? 4? 89 4C 24 ?? 4? 83 EC ?? B? [4] E8 [3] 00}
1415
$syscallnumber = {49 89 C3 B? [4] E8 [3] 00}
1516
$syscall = {48 83 C4 ?? 4? 8B 4C 24 ?? 4? 8B 54 24 ?? 4? 8B 44 24 ?? 4? 8B 4C 24 ?? 4? 89 CA 4? FF E3}
16-
condition:
17-
all of ($aes*) and all of ($string*) and any of ($syscall*)
17+
$decryptstr1 = {33 D2 48 8B 04 24 B? 0C 00 00 00 48 F7 F1 48 8B C2 48 C1 E0 02 0F B6 C8 48 8B 44 24 ?? 48 D3 E8 48 25 AB 00 00 00}
18+
$decryptstr2 = {0F BE C0 48 8B 0C 24 48 8B 54 24 ?? 48 03 D1 48 8B CA 0F BE 09 33 C8 8B C1 48 8B 0C 24 48 8B 54 24 ?? 48 03 D1}
19+
$decryptrsc1 = {48 8B 8C 24 [4] 0F B6 04 01 89 ?? 24 [1-4] 48 63 4C 24 ?? 33 D2 48 8B C1 48 F7 B4 24 [4] 48 8B C2 48 8B 8C}
20+
$decryptrsc2 = {8B ?? 24 [1-4] 33 C8 8B C1 48 63 4C 24 ?? 48 8B 94 24 [4] 88 04 0A}
21+
condition:
22+
(all of ($string*) or all of ($decrypt*)) and any of ($syscall*)
1823
}

data/yara/CAPE/Quickbind.yar

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@ rule Quickbind
55
description = "Quickbind"
66
cape_type = "Quickbind Payload"
77
strings:
8-
$anti_appdirs = {E8 [4] 83 F8 0? 7? ?? E8}
9-
$anti_procs_ram = {E8 [4] 83 F8 0? 7? ?? E8 [4] 3D (FF 0E | 00 0F | FF 16) 00 00}
10-
$anti_ram = {E8 [4] 3D (FF 1F | 00 20 | 00 17 | FF 0E | FF 16 | FF 2F) 00 00}
11-
$mutex_1 = {FF [1-5] 3D B7 00 00 00 74 [7-10] 25 89 00 00 00}
12-
$mutex_2 = {FF 15 [4] 4? 89 C? 4? 85 C? 74 ?? FF 15 [4] 3D B7 00 00 00}
13-
$mutex_3 = {FF 15 [4] 4? 89 44 24 ?? 4? 83 7C 24 ?? 00 74 ?? FF 15 [4] 3D B7 00 00 00}
14-
$sleep = {B9 64 00 00 00 [0-7] FF}
8+
$anti_appdirs = {E8 [4] 83 F8 0? 7? ?? E8}
9+
$anti_procs_ram = {E8 [4] 83 F8 0? 7? ?? E8 [4] 3D (FF 0E | 00 0F | FF 16) 00 00}
10+
$anti_procs = {4C 89 F1 [0-9] FF D3 83 7C 24 ?? (03 | 07)}
11+
$anti_ram = {E8 [4] 3D (FF 1F | 00 20 | 00 17 | FF 0E | FF 16 | FF 2F) 00 00}
12+
$sleep = {B9 64 00 00 00 [0-7] FF}
13+
$mutex_api = "CreateMutexW"
14+
$mutex_error = {FF [1-5] 3D B7 00 00 00}
1515
condition:
16-
all of ($anti_*) and 1 of ($mutex_*) and $sleep
16+
//any of them
17+
3 of ($anti_*) and all of ($mutex_*) and $sleep
1718
}

data/yara/CAPE/SmokeLoader.yar

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ rule SmokeLoader
77
strings:
88
$rc4_decrypt64 = {41 8D 41 01 44 0F B6 C8 42 0F B6 [2] 41 8D 04 12 44 0F B6 D0 42 8A [2] 42 88 [2] 42 88 [2] 42 0F B6 [2] 03 CA 0F B6 C1 8A [2] 30 0F 48 FF C7 49 FF CB 75}
99
$rc4_decrypt32 = {47 B9 FF 00 00 00 23 F9 8A 54 [2] 0F B6 C2 03 F0 23 F1 8A 44 [2] 88 44 [2] 88 54 [2] 0F B6 4C [2] 0F B6 C2 03 C8 81 E1 FF 00 00 00 8A 44 [2] 30 04 2B 43 3B 9C 24 [4] 72 C0}
10-
$fetch_c2_64 = {00 48 8D 05 [3] FF 48 8B CB 48 8B 14 D0 48 8B 5C 24 ?? 48 83 C4 20 5F E9}
10+
$fetch_c2_64 = {74 ?? B? E8 03 00 00 B9 58 02 00 00 FF [5] 48 FF C? 75 F0 [6-10] 48 8D 05}
1111
$fetch_c2_32 = {8B 96 [2] (00|01) 00 8B CE 5E 8B 14 95 [4] E9}
1212
condition:
13-
2 of them
13+
2 of them
1414
}

docs/book/src/installation/guest/cloning.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,7 @@ There is a `Python command-line utility`_ available that can automate this proce
1414
The new virtual machine will also contain all of the settings of the original one,
1515
which is not good. Now you need to proceed by repeating the steps explained in
1616
:doc:`network`, :doc:`agent`, and :doc:`saving` for this new machine.
17+
18+
One alternative to manually make the clones unique is to enable the disguise auxiliary module, windows_static_route and windows_static_route_gateway in conf/auxiliary.conf.
19+
The auxiliary option is applicable to dnsmasq user which can't set the default gateway there because of the usage of an isolated routing in kvm.
20+
One could run it once and snapshot to apply the modification or running the auxiliary module at every analysis.

extra/libvirt_installer.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
set -ex
33

44
# run this via...
5-
# cd /opt/CAPEv2/ ; sudo -u cape poetry run extra/libvirt_installer.sh
5+
# cd /opt/CAPEv2/ ; sudo -u cape /etc/poetry/bin/poetry run extra/libvirt_installer.sh
66

77
LIB_VERSION=10.7.0
88
cd /tmp || return

extra/yara_installer.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@
22
set -ex
33

44
# run this via...
5-
# cd /opt/CAPEv2/ ; sudo -u cape poetry run extra/yara_installer.sh
5+
# cd /opt/CAPEv2/ ; sudo -u cape /etc/poetry/bin/poetry run extra/yara_installer.sh
66

77
if [ ! -d /tmp/yara-python ]; then
88
git clone --recursive https://github.com/VirusTotal/yara-python /tmp/yara-python
99
fi
1010

1111
cd /tmp/yara-python
1212

13-
poetry --directory /opt/CAPEv2 run python setup.py build --enable-cuckoo --enable-magic --enable-profiling
14-
poetry --directory /opt/CAPEv2 run pip install .
13+
/etc/poetry/bin/poetry --directory /opt/CAPEv2 run python setup.py build --enable-cuckoo --enable-magic --enable-profiling
14+
/etc/poetry/bin/poetry --directory /opt/CAPEv2 run pip install .
1515

1616
cd ..
1717

0 commit comments

Comments
 (0)