Understanding the Basics of Computer Malware
September 23, 2024
Any recent examples of zero-day exploits? Let’s explore further!
Self-replicating and self-propagating software
Worms can spread without user interaction
Primary goal: infect as many devices as possible
Worms can be spread via:
Modifies a program and inserts their own code
Viruses often require user interaction to spread
Primary goal: cause damage or steal information
Viruses can be spread via:
Disguises itself as a normal file or program
Trojan horses often require user interaction to spread
Primary goal: create a backdoor in your system for malicious activities
Trojan horses can be spread via:
Access and then encrypts a victim’s files
Demands access to payment to decrypt the files
Primary goal: extort money by denying file access
Ransomware can be spread via:
Secretly monitors and collects user activity
Often installed without the user’s knowledge
Primary goal: gather information on person or organization
Spyware can be spread via:
curl
and bash
! We do this?!?curl -L https://install.pivpn.io | bash
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/install.sh)"
strings
commandstrings /path/to/malware
strings
on nvim
:export NVIM_SYSTEM_RPLUGIN_MANIFEST='/nix/store/0mifqx8ab7nm7xf3h6jw55fgs109hlz2-neovim-0.10.1/rplugin.vim'
export GEM_HOME='/nix/store/08bjh6z0xj5cdw86fibbbqabrj8ss6f2-neovim-ruby-env/lib/ruby/gems/3.3.0'
PATH=${PATH:+':'$PATH':'}
if [[ $PATH != *':''/nix/store/08bjh6z0xj5cdw86fibbbqabrj8ss6f2-neovim-ruby-env/bin'':'* ]]; then
PATH=$PATH'/nix/store/08bjh6z0xj5cdw86fibbbqabrj8ss6f2-neovim-ruby-env/bin'
PATH=${PATH#':'}
PATH=${PATH%':'}
export PATH
LUA_PATH=${LUA_PATH:+';'$LUA_PATH';'}
Obscure a malware’s source code or binary
Makes it harder to detect and analyze
Common obfuscation techniques:
What can we obfuscate in a program?
Remember, the program must still work correctly
Deobfuscation is the process of reversing obfuscation
Let’s explore some obfuscation techniques!
151M ┌── 592d5e7d-99f2-40dc-a83f-06f87c9894c8 │██▓▓▓░░ │ 4%
157M ├── cd131393-d367-4d5b-aae9-8bcd2e853819 │███▓▓░░ │ 4%
308M ┌─┴ 4c237d5e33167c88df3e45d9c8b59fdd4d727472 │████▓░░ │ 7%
341M ┌─┴ CacheStorage │█████░░ │ 8%
347M ┌─┴ Service Worker │█████░░ │ 8%
381M ┌─┴ Default │█████░░ │ 9%
476M ┌─┴ chromium │███████ │ 12%
171M │ ┌── modules │███░░░░░░░░ │ 4%
171M │ ┌─┴ 0.0.67 │███░░░░░░░░ │ 4%
296M │ │ ┌── js │████░░░░░░░ │ 7%
296M │ ├─┴ Code Cache │████░░░░░░░ │ 7%
338M │ │ ┌── Cache_Data │█████░░░░░░ │ 8%
338M │ ├─┴ Cache │█████░░░░░░ │ 8%
853M ├─┴ discord │███████████ │ 21%
148M │ ┌── 004 │██▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒ │ 4%
149M │ ┌─┴ File System │██▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒ │ 4%
337M │ ├── IndexedDB │█████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒ │ 8%
319M │ │ ┌── 8cbb992fe0cd9ef960e69a214646bd270516a23e│█████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒ │ 8%
153M │ │ │ ┌── efae9b38-28ca-46be-9a0a-7e9a7d6f80e0 │██▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒ │ 4%
159M │ │ │ ├── 7e999286-e8e9-4508-b39a-2b49d8761bb5 │███▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒ │ 4%
160M │ │ │ ├── 13b2d983-8a6b-4e6e-a887-401635b378ac │███▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒ │ 4%
581M │ │ ├─┴ 4c237d5e33167c88df3e45d9c8b59fdd4d727472│████████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒ │ 14%
1.8G │ │ ┌─┴ CacheStorage │████████████████████████▓▓▓▓▓▓▓▓▒▒▒ │ 44%
1.8G │ ├─┴ Service Worker │█████████████████████████▓▓▓▓▓▓▓▒▒▒ │ 46%
2.4G │ ┌─┴ Default │████████████████████████████████▒▒▒ │ 60%
2.6G │ ┌─┴ Brave-Browser │███████████████████████████████████ │ 65%
2.6G ├─┴ BraveSoftware │███████████████████████████████████ │ 65%
4.0G ┌─┴ . │█████████████████████████████████████████████████████ │ 100%
System configuration data may be sensitive:
import os
def get_dir_size_and_file_count(start_path = '.'):
total_size = 0
file_count = 0
for dirpath, dirnames, filenames in os.walk(start_path):
for f in filenames:
fp = os.path.join(dirpath, f)
if not os.path.islink(fp):
total_size += os.path.getsize(fp)
file_count += 1
return total_size / 1024, file_count
config_dir = os.path.expanduser("~/.config")
for root, dirs, files in os.walk(config_dir):
size, count = get_dir_size_and_file_count(root)
print(f"Directory: {root}")
print(f"Total size: {size} KB")
print(f"Total files: {count}")
Directory: /home/gkapfham/.config/io.datasette.llm
Total size: 132.48 KB
Total files: 3
Directory: /home/gkapfham/.config/io.datasette.llm/replicate
Total size: 0.24 KB
Total files: 1
Directory: /home/gkapfham/.config/atuin
Total size: 0.00 KB
Total files: 0
Directory: /home/gkapfham/.config/croc
Total size: 0.00 KB
Total files: 0
Directory: /home/gkapfham/.config/chromium
Total size: 487834.33 KB
Total files: 2802
import os as o
def a(b = '.'):
c = 0
d = 0
for e, f, g in o.walk(b):
for h in g:
i = o.path.join(e, h)
if not o.path.islink(i):
c += o.path.getsize(i)
d += 1
return c / 1024, d
j = o.path.expanduser(o.path.join("~", "." + chr(99) + chr(111) + chr(110) + chr(102) + chr(105) + chr(103)))
for k, l, m in o.walk(j):
n, p = a(k)
print(f"{chr(68) + chr(105) + chr(114) + chr(101) + chr(99) + chr(116) + chr(111) + chr(114) + chr(121)}: {k}")
print(f"{chr(84) + chr(111) + chr(116) + chr(97) + chr(108) + chr(32) + chr(115) + chr(105) + chr(122) + chr(101)}: {n:.2f} KB")
print(f"{chr(84) + chr(111) + chr(116) + chr(97) + chr(108) + chr(32) + chr(102) + chr(105) + chr(108) + chr(101) + chr(115)}: {p}")
from pyarmor_runtime_000000 import __pyarmor__
__pyarmor__(__name__, __file__, b'PY000000\x00\x03\x0c\x00\xcb\r\r\n\x80\x00\x01\x00\x08\x00\x00\x00\x04\x00\x00\x00@\x00\x00\x00\x18\x07\x00\x00\x12\t\x04\x00\x99\x9dm\xe4\rV\x9f\r\xa0mg%\x15E\x91C\x00\x00\x00\x00\x00\x00\x00\x00]U\xae\xdd>\x9c5\xe3\xa8\xf7\xe1\xa2\x8eCP\xbeu\xf9\xe2\x18\x07\xfb\xddd\xf2ot\xd7P\x98w\xa3\xcf?\xc1\xfdc\xc3\xf7qE\xdc \x84M\x8f\xde\xaa\x8d\x14x\xb1\xe9\xa1^W[{q>\x109\x94P\x16^=p\x9fD\xbf\xb1\xe8H\xaf\xe3J\xf4\xb3\xbeA\x8b\xad@!Q\x8ePD\xe6?\x9d\x11}\x18\xa2iq\xca\x1cT\xd7-\x88}\x05EviD\x00\xd7?S\x112k\r\xeeB\xeb\xdbod9\x158\x93\xf7G\x8a\xda(A\xc6nd\x11\x81\xe5\x04\x9cH\xccA%\x13\xd3U\xdeq,Q\r\xf0\x8d?\x80\xe769\xbd:\xceb\xdb\xd0\x9b\x81\xe7V\x05X\xa8\xfa\x97\x10\x89\xa2\x91\x89\xe5\xb50*4\xe7\x12\xe9\xc3Ts\x9c\xa8\\f\xbe\xff6\x12P\xb9\x88\xabJP\xee:h\xeb\x9e\x07\xae\x13\x92;V\xff\x88d5\xaa\xc9}.\x97\xedc\xaa&\xa0\xdc!\xd2\x953\xf8\x05\xa2\x807\x87\xfe\xf4\xa1n3\x9a\x8e\x99\xc9J\xd6\xca\xaf\x12Y\x85G[\x1a\xf1%\xdb\xf4=\x8c\xe0/\\&\xd5\xe3\xbfn\xf7 \x1c|\xe8\x8a\xb7\x1b\xc0\xc0\xfa\xb1[\xf6M\x03\xf6D\xee\xab\x94Z\x8b\xc0\x8c\xce\x9b\x9eO\x922Z"8\x89[\xcda\xa2(\x11\x98\x0bil\x94f"\xe7\x01h\xae\xa6\x1d\x03IX\xa2\xda\x89\x9d\xd9\xae\x9ew\xaeCK_\x99\xa3\xc0\xc1\x96j\x87jOW\xa9\xecwfQ&\x82\x07;I91gSr\x19\x1c\xe4\xe6\x7f5[\xb3\xba\xfa\x0c\xb6\xbf\xbd\x01\x8d\xb2\x1a\x1c\xe0\n\x94\xb9H\x1f\x8cj\x7fd\xe4\xdc\x15e \xf0\x90\xe7*\x9f4\x98\x80{\x91A\xb7\xb21P\x1d\xadC\xee,\xfb\x1d\'\xad71\xbck\xcd\nI|g3\x1a\x13#\x082Ca$\x99r\xfc\xf1u\x83\xbb\x94o\x1dP\xc5\x88\xc8\xa3\x7fS\xde\xdf\xaf\x84Rx\xfb\xc4)\xd1\x14\x04$\xb1\x178\xd0\\X>\xf3\xca@\t\xf1"\xfd\x9b\x18\xb5\x18/\x03\x1c\x0bP-*\x08\x86\x0c\xd9\x17\x1b\xbb\x8b\xfaTV\xeb\xe7C\'$+\x1f\x86\x8e\xdf\x01\xd7\xf8u\xbd\xfa8\x12\xa3RQ\xdf\x19p\xf1\xa1Ob\xb2\xa2\x81D\xba8\xaf\x83\xc3\x8d\xe0#.*\xa9\xd2@\x1cO\xf9\xb8\\\xda\xa8\x1d&\xc7Xs\x90\xe8\xad\x9d\n\\q\x19 \x83\xac\xc9S\x0c\xdd\x13\xaf\xf7\x16\x1bnP\x99\xb9\x18\x95\x19\xb1G1\xe8R\x1f\xe0\xbf\x8e\xfb\x8e\x8dR\x84\x0bY\xe9\x9d\xcf\xfc9)\x02-\\\xc6\xe9\x0c\xdbrbp\xad\x18q\xeb\xf6\x82cSW\x89\xb6\x8c;\xf5\xc2\xb8\xdfq\xd7Vv\xd2\xcc\t\x8f\xb3.\xd7s\x0f\xe5\xfaw\x16_x\xcbL\xfd\xc9\xbd\xf8\xdf\x1b\x1d\xf8\xc5\n\xadW\xa8)\xd1-\xfd/%\x8f;\x97\x96y\x0b\xee\x86\xe7%\x8f\x1e\x01\xc7J\x92\xb1\x99&\x9d\xa6\xc8\xd4`E\'\x82\x1d\xa1\x187Y\x81\x05\xa9\xf4\xfb\x1c\xf5\x8eb\xf8\x0c2\xceo\xdbD\xe8\x12\xfcU\x81\xc0\x07\xfc*\x91u\xf7J\xfd\x8d\xc7\x97?U\x0e\x8f\xe8\xf7M\xffIK\xf7?`r\xaf\x91L\xf4\x0bg\xa4\x8bn%\'v\x90^\xe6\xcc\x14\xb1A1\x16\xff~\x1d4z\x92\x8eS\x92n\xac\xf5\xcf\xf3\xec\xf4Z\xb0\xf1\x87WK\x14\x10\xb8@`OQ\x83\xdb\xaaA\x11\x12e_$\x81\x86\x81\xdc\xcfE\xd1W\xca\x08\x8c\x7f\xc7~rZ\xb7HS\xa9=/\xba7B\xfc\xb5\xda\xb3\xb8\x81\x06a\xd1\x95\'t3d\xdd\xdc\xe1\xad\xdd/\x92\xd8\xd2j\xb6j&_\xc9\xec\xfd\xfe\x02\xc7\x02\xbb\xf5\xeeVm\xc1\x9b\x96\xca\x88,#\xb3]\x08\x1a\xc8\x01\xee\x9ec\xe6\xe6H\xf9\x0b\xf5\xf7Z\xca)\xc1\x99\xa6E\n[eV\x87\x9c\xa9>\xb7\x13\xff\xe1W\x8a8\x82\xb0C\xf3$8\xf4\xa5\x8a\xe8q\x07]H?\xb5\'T\xf0\xeb\xe1\x8b*\x86\x9b!\x124\xc4Nb\xf3\xc37\xcc;\xbbaw\xf0p3s4+\xc2\xb5\xd32\xa8r\x05 \xf8\x8cIxv`\x8d\x12\x12Y\x92<K\x18\x8f\x1cGn\xff\x7fQ\xb7\xbeW;\x95\xa1\xc4\xcc\xfdx\x03\xfb:q\xb8\xa3\x14\xd3\xb9=\xf1\xbb\x1e<8\x8aru\x84d\xa5wm\xc4-\xa5t\xb6cWH\xa8\xa6\xefP`\xa0m\x17\xe6NT\xd5\'B\xb1\x1e\xe2\x92\x14\x9eS\xf1=\r\xa4\xbd\xccJ\xaf\x1c\xe9J\xae\xdc\xab\xc0\x9ap\x1c\x8c\x0c"k\x8f\x1ab)\xb1\xa9\xba\xb2\x99\xe4\\\xa8\xcda\xe7\xd0\x02Y-\xab\xe40\x1d\x0c:@\xdc\x1b7\x0e\xb0\x87"9\x06E\xed\xbaW\xb8\xe9\xf7\xfbl,G\x8a\xefc\x99\xcd\xb61cT\x12,\xd6\xec\xcf\xc5U\xd9\xb0\x1c\xf5\xfdi\xc6\xa8~Q\xa4\xbaF\x102\xc8&\'S\xfa\xbf\xa8L\xa57\x80\x8fq]\xd1\xc4\x94\xab? M\x04\xfe\xd0\xe6\xbcs\xb9Y\xe1\xcc\x9e\xd8\x8dx\xa4\x08\x85"\xcc\x91Cc\xac\xb4\t\x9b\xc0\x12[\xd6)/\xb8\xad\xc0\x8cE\xe3\x92\xeb\x8334f\xa62\xcc\xfc\x8f\xdb\'\xe3\x12Q\xae#Z\xe4.K\xdaG\xbc>\x00?\xe9\xbd\xb1\xf39Lv>\x84\x11\xcb\xb1I\xca\x1b\xcb\x00\xc0\xef\xdfWA\xc2\xf0\xa6\xf5\x13\xdd\x82X\xec_\x80?5\xd8\xd6\x8a\x9d\xdf\xa9\x16D\x9fe\xef\x0e6\x92a\xc2\x12V=A9+)b\x8d\xe0o\xc66\xe5\xfd\xf1;z\xb2\xf9\xbe\xb8\xf2\xa9\xd5>z\x96 \x8fp=\xa4\x1ep\xb4k\x88s\x0c\x01m\xa71\xec\x92Q\xbb\xd5pF\x80\xd2\x9cN\x895\xb7\xcf\xbbY\x7f|\x91\xcbUO\xfa\xeb\x17\xb2D\xc8\xa9_\x84\x8el)\xd7h\xa3_\r\xf7\x87U\xfe\xc3\xee\x81\xa1N\xe8fq\x9b\x06\xae\xd3\xb2\xfe\xcd\xe4\xd4y\xd6\x00c\r\x87\xc6V\xcb\xfc\xc9\x0b\xdc$\xbf28\xb9\x99\x90%\xa9.V-~\xe1\x8fn\xbc\x87\xd3\xc9\xa6\xe0\xdf+;\xa5\xdc\xc8\r\x97\x1b\xa9\x83+\x00$\xab}\x08\xcd\r\xa2r\xcf\xcfQN\xc5\xe4\xadv\x97j{\xc5b3\xa3\x08\xc6\xc1L\x12\xa5\x99\xb5e\xbb\x1b\xb7\xe9!h\xa0\xe9|4`\x9eL\x07\xb6Q\x1a\x96\xc9\xac\xa5\xd0j"\xe2\xeb<\x90\x0f\xe0G\xb8r\x15\xef\xfa\xd9\xe9\xa1\x88\x16\xbf\xa5\x8f\xeew\x84\xe5\xfa\x92\xed\x02\xa8\r\x07\xa3\xed8\x1a\xa8\xd9\xf2\xa3$\x86\x8b\xa8\xfd\xe4#"\xc1P\xa8\x911vx_\xebJ\xe2-\xb9\xba\x90\xa3\xf24\x03\x975?l\x18\xa4_\xc1\xb4\x1c`\xbdk\x90\xb9\xed\xc0P\x93\xddz\x97\xb7b\x06\xc3\xc0~S\xe3E\rE\xb7bug\xf4\x0f\xddWE\xae\xab\xcab\x10n\xedk\xc7K\xf7\x8e\xaf\xcd\x19\xbc\'\x16\x06\x15\x174\xe0\x9byI\xb8\xd5B\xbd\x11-A\xdd\xe7\x05\x9b\xda\xb4\x90#0\x96\xea\xeb{\xdaN\xae{4\xd7\xbc\x88W!\x11K,yb`\xb79\xedJ\x1d\xb2f*\xdb=\xd3\x18\xbe\x87\x8cH\xd4:6\xd0\xf6nT\xd9\xfb\xc0\xfbk\x06\xb3\x05\xdc\xec\xbb\xa4!O\xdb\xffm[\xfa\xdc\xb9\x8b\xc6\xbbZv\x97\x0e\xad\xe7\xff\xab\x88\xa3\xd5\xf3\xcc\xc8K\x1dF\x97\x1c\xe6&\x8e\x0f\x0bA\x1cU\x16\x18\xbd\x8fr\x18\x0cs\xf6?\xab{\xbe\xe3\x01k\x19Z\xb9\x1eh;L\xd6\\\xee\xe1B\x06\x9bSwZ\x96\xdd\xf0T\xff\xd8.\xcb\xfdh\x16\xb8\xba\xc8\x9ey\xe2\xc9Xt\xc0\xfc\x9dWh')
pyarmor
on Linux:
pipx install pyarmor
pyarmor gen collect_system_data.py
cd dist
python collect_system_data.py
pyarmor_runtime_000000/
from .pyarmor_runtime import __pyarmor__
pyarmor_runtime.so
strings
is clearly no longer possible!One noteworthy Emotet attack on the City of Allentown, PA required direct help from Microsoft’s incident response team to clean up and reportedly cost the city upwards of $1M to fix. Reference: MalwareBytes Analysis of Emotet
Security Synapse