Skip to content

Commit

Permalink
Merge branch 'kevoreilly:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
dsecuma authored Dec 18, 2024
2 parents 7e28221 + b28d42c commit 3c7bb25
Show file tree
Hide file tree
Showing 275 changed files with 3,090 additions and 20,276 deletions.
2 changes: 1 addition & 1 deletion .github/actions/python-setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ runs:
- name: Install poetry
shell: bash
run: PIP_BREAK_SYSTEM_PACKAGES=1 pip install poetry
run: PIP_BREAK_SYSTEM_PACKAGES=1 pip install poetry poetry-plugin-export

- name: Set up Python ${{ inputs.python-version }}
uses: actions/setup-python@v5
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/python-package-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
timeout-minutes: 20
strategy:
matrix:
python-version: ["3.10", "3.11"]
python-version: ["3.10"]

steps:
- name: Check out repository code
Expand Down
16 changes: 2 additions & 14 deletions .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
timeout-minutes: 20
strategy:
matrix:
python-version: ["3.10", "3.11"]
python-version: ["3.10"]
steps:
- name: Check out repository code
uses: actions/checkout@v4
Expand All @@ -37,23 +37,11 @@ jobs:
poetry run pip install pyattck==7.1.2 maco
- name: Run Ruff
run: poetry run ruff . --line-length 132 --ignore E501,E402
run: poetry run ruff check . --line-length 132 --ignore E501,E402

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

- name: See if any parser changed
uses: dorny/paths-filter@v3
id: changes
with:
filters: |
src:
- 'modules/processing/parsers/CAPE/*.py'
- name: Test parsers only if any parser changed
if: steps.changes.outputs.src == 'true'
run: poetry run python -m pytest tests_parsers -s --import-mode=append

format:
runs-on: ubuntu-latest
timeout-minutes: 20
Expand Down
12 changes: 0 additions & 12 deletions analyzer/windows/data/yara/Al-khaser.yar

This file was deleted.

15 changes: 14 additions & 1 deletion analyzer/windows/data/yara/NitrogenLoader.yar
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,17 @@ rule NitrogenLoaderBypass
$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}
condition:
all of them
}
}

rule NitrogenLoaderConfig
{
meta:
author = "enzok"
description = "NitrogenLoader Config Extraction"
cape_options = "bp0=$decrypt1*+6,hc0=1,count=0,action0=string:rcx,typestring=NitrogenLoader Config"
strings:
$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}
$decrypt2 = {8B ?? 24 [1-4] 33 C8 8B C1 48 63 4C 24 ?? 48 8B 94 24 [4] 88 04 0A}
condition:
all of them
}
14 changes: 0 additions & 14 deletions analyzer/windows/data/yara/Pafish.yar

This file was deleted.

2 changes: 2 additions & 0 deletions analyzer/windows/lib/core/packages.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,5 +147,7 @@ def choose_package(file_type, file_name, exports, target):
return "autoit"
elif file_name.endswith(("cmd", "bat")) or b"@echo off" in file_content:
return "batch"
elif file_name.endswith(".rdp"):
return "rdp"
else:
return "generic"
2 changes: 1 addition & 1 deletion analyzer/windows/modules/auxiliary/amsi.py
Original file line number Diff line number Diff line change
Expand Up @@ -1002,7 +1002,7 @@ def _unpackSimpleType(self, record, info, event_property):

data = formatted_data.value
# Convert the formatted data if necessary
if out_type in TDH_CONVERTER_LOOKUP and type(data) != TDH_CONVERTER_LOOKUP[out_type]:
if out_type in TDH_CONVERTER_LOOKUP and type(data) is TDH_CONVERTER_LOOKUP[out_type]:
data = TDH_CONVERTER_LOOKUP[out_type](data)

return {name_field: data}
Expand Down
13 changes: 4 additions & 9 deletions analyzer/windows/modules/auxiliary/disguise.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
from lib.common.rand import random_integer, random_string

log = logging.getLogger(__name__)
PERSISTENT_ROUTE_GATEWAY = "192.168.1.1"
si = subprocess.STARTUPINFO()
si.dwFlags |= subprocess.STARTF_USESHOWWINDOW

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

def add_persistent_route(self):
self.run_as_system(
["C:\\Windows\\System32\\ROUTE.exe", "-p", "add", "0.0.0.0", "mask", "0.0.0.0", PERSISTENT_ROUTE_GATEWAY]
)
self.run_as_system(
["C:\\Windows\\System32\\ROUTE.exe", "-p", "change", "0.0.0.0", "mask", "0.0.0.0", PERSISTENT_ROUTE_GATEWAY]
)
def add_persistent_route(self, gateway: str):
self.run_as_system(["C:\\Windows\\System32\\ROUTE.exe", "-p", "add", "0.0.0.0", "mask", "0.0.0.0", gateway])
self.run_as_system(["C:\\Windows\\System32\\ROUTE.exe", "-p", "change", "0.0.0.0", "mask", "0.0.0.0", gateway])

def start(self):
if self.config.windows_static_route:
log.info(f"Config for route is: {str(self.config.windows_static_route)}")
self.add_persistent_route()
self.add_persistent_route(self.config.windows_static_route_gateway)
self.change_productid()
self.set_office_mrus()
self.ramnit()
Expand Down
2 changes: 2 additions & 0 deletions analyzer/windows/modules/auxiliary/human.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
"don't send",
"don't save",
"continue",
"connect",
"unzip",
"open",
"close the program",
Expand Down Expand Up @@ -115,6 +116,7 @@
DONT_CLICK_BUTTONS = (
# english
"check online for a solution",
"don't ask me again for remote connections from this publisher",
"don't run",
"do not ask again until the next update is available",
"cancel",
Expand Down
2 changes: 1 addition & 1 deletion analyzer/windows/modules/packages/rdp.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from lib.common.common import check_file_extension


class Exe(Package):
class RDP(Package):
"""RDP analysis package."""

PATHS = [
Expand Down
9 changes: 9 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
### [01.11.2024] Parsers
* Malware config parsers aka parsers are moved out of core of CAPE.
* Now they are at their own [repository](https://github.com/CAPESandbox/CAPE-parsers).
* Feature added. `load=X`, where `X` is one of those: all/core/community
* All = core and community
* Exclude parsers. Allows to not load some particular parsers. `exclude_parsers=["name1", "name2"]`
* Your custom parsers from `custom/parsers/` will still load and overwrite cape carser if name matches.
* __Action required!__ `cd /opt/CAPEv2 && poetry install`

### [04.10.2024]
* Monitor update: Add GetClassObject hook to handle UAC bypass technique using CMSTPLUA COM object
* PrivateLoader direct syscall capture
Expand Down
7 changes: 4 additions & 3 deletions conf/default/auxiliary.conf.default
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ browser = yes
curtain = no
digisig = yes
disguise = yes
# This is only useful in case you use KVM's dnsmasq. You need to set windows_static_route_gateway. Disguise must be enabled
windows_static_route = no
windows_static_route_gateway = 192.168.1.1
evtx = no
human_windows = yes
human_linux = no
Expand All @@ -38,8 +41,6 @@ permissions = no
pre_script = no
during_script = no
filecollector = yes
# 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
windows_static_route = no
tracee_linux = no
sslkeylogfile = no
# Requires setting up browser extension, check extra/browser_extension
Expand Down Expand Up @@ -80,6 +81,6 @@ enabled = no

[Mitmdump]
# Enable or disable the use of mitmdump (mitmproxy) to get dump.har [yes/no].
# This module requires installed mitmproxy see install_mitmproxy
# This module requires installed mitmproxy see install_mitmproxy
# (https://github.com/kevoreilly/CAPEv2/blob/master/installer/cape2.sh#L1320)
enabled = no
5 changes: 5 additions & 0 deletions conf/default/cuckoo.conf.default
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ scaling_semaphore = off
# A configurable wait time between updating the limit value of the scaling bounded semaphore
scaling_semaphore_update_timer = 10

# Specify a timeout for tasks, useful if you are bound to timely reports awaited by users
task_timeout = off
task_pending_timeout = 0
task_timeout_scan_interval = 30

# Enable creation of memory dump of the analysis machine before shutting
# down. Even if turned off, this functionality can also be enabled at
# submission. Currently available for: VirtualBox and libvirt modules (KVM).
Expand Down
6 changes: 5 additions & 1 deletion conf/default/processing.conf.default
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ platform = linux
[debug]
enabled = yes
# Amount of text (bytes)
buffer = 8192
buffer = 0

[detections]
enabled = yes
Expand Down Expand Up @@ -310,6 +310,10 @@ modules_path = modules/processing/parsers/malduck/
enabled = yes
# Must ends with /
modules_path = modules/processing/parsers/CAPE/
# Config parsers all/core/community
parsers = all
# list of comma separated parsers. Ex: stealc,lumma
exclude=

# Community
[reversinglabs]
Expand Down
4 changes: 2 additions & 2 deletions conf/default/selfextract.conf.default
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ timeout = 60
enabled = yes
timeout = 60

# sudo apt install innoextract
# Use https://github.com/gdesmar/innoextract
[Inno_extract]
enabled = yes
binary = /usr/bin/innoextract
binary = data/innoextract
timeout = 60

# https://github.com/mstrobel/procyon/releases
Expand Down
1 change: 1 addition & 0 deletions conf/default/web.conf.default
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ guest_width = 1280
guest_height = 1024
# rdp settings
guest_rdp_port = 3389
ignore_rdp_cert = false

[packages]
# VM tags may be used to specify on which guest machines a sample should be run
Expand Down
4 changes: 2 additions & 2 deletions data/yara/CAPE/CobaltStrikeBeacon.yar
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ rule CobaltStrikeBeacon
$pwsh1 = "IEX (New-Object Net.Webclient).DownloadString('http" ascii
$pwsh2 = "powershell -nop -exec bypass -EncodedCommand \"%s\"" fullword ascii
$ver3a = {69 68 69 68 69 6b ?? ?? 69}
$ver3b = {69 69 69 69}
$ver3b = {69 69 69 69 69 69 69 69 69 69 69 69 69 69 69 69}
$ver4a = {2e 2f 2e 2f 2e 2c ?? ?? 2e}
$ver4b = {2e 2e 2e 2e}
$ver4b = {2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e 2e}
$a1 = "%02d/%02d/%02d %02d:%02d:%02d" xor(0x00-0xff)
$a2 = "Started service %s on %s" xor(0x00-0xff)
$a3 = "%s as %s\\%s: %d" xor(0x00-0xff)
Expand Down
15 changes: 10 additions & 5 deletions data/yara/CAPE/NitrogenLoader.yar
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,20 @@ rule NitrogenLoader
author = "enzok"
description = "Nitrogen Loader"
cape_type = "NitrogenLoader Loader"
hash = "7b603d63a23201ff0b6ffa9acdd650df9caa1731837d559d93b3d8ce1d82a962"
hash1 = "7b603d63a23201ff0b6ffa9acdd650df9caa1731837d559d93b3d8ce1d82a962"
hash2 = "50c2afd792bfe2966133ee385054eaae1f73b04e013ef3434ef2407f99d7f037"
strings:
$aes1 = {63 7c 77 7b f2 6b 6f c5 30 01 67 2b fe d7 ab 76 ca 82 c9 7d fa}
$aes2 = {52 09 6a d5 30 36 a5 38 bf 40 a3 9e 81 f3 d7 fb 7c e3 39 82 9b}
$stringaes1 = {63 7c 77 7b f2 6b 6f c5 30 01 67 2b fe d7 ab 76 ca 82 c9 7d fa}
$stringaes2 = {52 09 6a d5 30 36 a5 38 bf 40 a3 9e 81 f3 d7 fb 7c e3 39 82 9b}
$string1 = "BASS_GetEAXParameters"
$string2 = "LoadResource"
$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}
$syscallnumber = {49 89 C3 B? [4] E8 [3] 00}
$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}
condition:
all of ($aes*) and all of ($string*) and any of ($syscall*)
$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}
$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}
$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}
$decryptrsc2 = {8B ?? 24 [1-4] 33 C8 8B C1 48 63 4C 24 ?? 48 8B 94 24 [4] 88 04 0A}
condition:
(all of ($string*) or all of ($decrypt*)) and any of ($syscall*)
}
17 changes: 9 additions & 8 deletions data/yara/CAPE/Quickbind.yar
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ rule Quickbind
description = "Quickbind"
cape_type = "Quickbind Payload"
strings:
$anti_appdirs = {E8 [4] 83 F8 0? 7? ?? E8}
$anti_procs_ram = {E8 [4] 83 F8 0? 7? ?? E8 [4] 3D (FF 0E | 00 0F | FF 16) 00 00}
$anti_ram = {E8 [4] 3D (FF 1F | 00 20 | 00 17 | FF 0E | FF 16 | FF 2F) 00 00}
$mutex_1 = {FF [1-5] 3D B7 00 00 00 74 [7-10] 25 89 00 00 00}
$mutex_2 = {FF 15 [4] 4? 89 C? 4? 85 C? 74 ?? FF 15 [4] 3D B7 00 00 00}
$mutex_3 = {FF 15 [4] 4? 89 44 24 ?? 4? 83 7C 24 ?? 00 74 ?? FF 15 [4] 3D B7 00 00 00}
$sleep = {B9 64 00 00 00 [0-7] FF}
$anti_appdirs = {E8 [4] 83 F8 0? 7? ?? E8}
$anti_procs_ram = {E8 [4] 83 F8 0? 7? ?? E8 [4] 3D (FF 0E | 00 0F | FF 16) 00 00}
$anti_procs = {4C 89 F1 [0-9] FF D3 83 7C 24 ?? (03 | 07)}
$anti_ram = {E8 [4] 3D (FF 1F | 00 20 | 00 17 | FF 0E | FF 16 | FF 2F) 00 00}
$sleep = {B9 64 00 00 00 [0-7] FF}
$mutex_api = "CreateMutexW"
$mutex_error = {FF [1-5] 3D B7 00 00 00}
condition:
all of ($anti_*) and 1 of ($mutex_*) and $sleep
//any of them
3 of ($anti_*) and all of ($mutex_*) and $sleep
}
4 changes: 2 additions & 2 deletions data/yara/CAPE/SmokeLoader.yar
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ rule SmokeLoader
strings:
$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}
$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}
$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}
$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}
$fetch_c2_32 = {8B 96 [2] (00|01) 00 8B CE 5E 8B 14 95 [4] E9}
condition:
2 of them
2 of them
}
4 changes: 4 additions & 0 deletions docs/book/src/installation/guest/cloning.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,7 @@ There is a `Python command-line utility`_ available that can automate this proce
The new virtual machine will also contain all of the settings of the original one,
which is not good. Now you need to proceed by repeating the steps explained in
:doc:`network`, :doc:`agent`, and :doc:`saving` for this new machine.

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.
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.
One could run it once and snapshot to apply the modification or running the auxiliary module at every analysis.
2 changes: 1 addition & 1 deletion extra/libvirt_installer.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
set -ex

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

LIB_VERSION=10.7.0
cd /tmp || return
Expand Down
6 changes: 3 additions & 3 deletions extra/yara_installer.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@
set -ex

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

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

cd /tmp/yara-python

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

cd ..

Expand Down
Loading

0 comments on commit 3c7bb25

Please sign in to comment.