commit e4539ce9fa75f19bf02a2690c06d8c1dd76bfa8e Author: Dobin Date: Wed Jan 31 18:46:40 2024 +0000 initial version diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9733de9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.exe* +*.obj +*.lnk +*.bin +*.asm \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..fae34db --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +pefile diff --git a/source/main.c b/source/main.c new file mode 100644 index 0000000..6cad1e3 --- /dev/null +++ b/source/main.c @@ -0,0 +1,93 @@ +#include +#include "peb_lookup.h" + +/* + char load_lib_name1[] = { 'N','t','Q','u','e','r','y','S','y','s','t','e','m','E','n','v','i','r','o','n','m','e','n','t','V','a','l','u','e',0 }; + LPVOID load_lib = get_func_by_name((HMODULE)base1, (LPSTR)load_lib_name1); + if (!load_lib) { + return 2; + } + */ + + +int main() +{ + wchar_t kernel32_dll_name[] = { 'k','e','r','n','e','l','3','2','.','d','l','l', 0 }; + LPVOID base = get_module_by_name((const LPWSTR)kernel32_dll_name); + if (!base) { + return 1; + } + char load_lib_name[] = { 'L','o','a','d','L','i','b','r','a','r','y','A',0 }; + LPVOID load_lib = get_func_by_name((HMODULE)base, (LPSTR)load_lib_name); + if (!load_lib) { + return 2; + } + char get_proc_name[] = { 'G','e','t','P','r','o','c','A','d','d','r','e','s','s',0 }; + LPVOID get_proc = get_func_by_name((HMODULE)base, (LPSTR)get_proc_name); + if (!get_proc) { + return 3; + } + HMODULE(WINAPI * _LoadLibraryA)(LPCSTR lpLibFileName) = (HMODULE(WINAPI*)(LPCSTR))load_lib; + FARPROC(WINAPI * _GetProcAddress)(HMODULE hModule, LPCSTR lpProcName) + = (FARPROC(WINAPI*)(HMODULE, LPCSTR)) get_proc; + + + // ntdll.dll: GetEnvironmentVariableW() + char GetEnvironmentVariableW_str[] = { 'G','e','t','E','n','v','i','r','o','n','m','e','n','t','V','a','r','i','a','b','l','e','W', 0 }; + int (WINAPI * _GetEnvironmentVariableW)( + _In_opt_ LPCWSTR lpName, + _Out_opt_ LPWSTR lpBuffer, + _In_ DWORD nSize) = (int (WINAPI*)( + _In_opt_ LPCWSTR lpName, + _Out_opt_ LPWSTR lpBuffer, + _In_opt_ LPCWSTR, + _In_ DWORD nSize)) _GetProcAddress((HMODULE)base, GetEnvironmentVariableW_str); + if (_GetEnvironmentVariableW == NULL) return 4; + + + + wchar_t envVarName[] = {'U','S','E','R','P','R','O','F','I','L','E', 0}; + wchar_t tocheck[] = {'C',':','\\','U','s','e','r','s','\\','h','a','c','k','e','r', 0}; // L"C:\\Users\\hacker" + + //LPCWSTR envVarName = L"USERPROFILE"; + WCHAR buffer[1024]; // NOTE: Do not make it bigger, or we have a __chkstack() dependency! + DWORD result = ((DWORD(WINAPI*)(LPCWSTR, LPWSTR, DWORD))_GetEnvironmentVariableW)(envVarName, buffer, 1024); + if (result == 0) { + return 6; + } + if (mystrcmp(buffer, tocheck) != 0) { // escape backslash + return 6; + } + + // user32.dll: MessageBoxW() + char user32_dll_name[] = { 'u','s','e','r','3','2','.','d','l','l', 0 }; + LPVOID u32_dll = _LoadLibraryA(user32_dll_name); + char message_box_name[] = { 'M','e','s','s','a','g','e','B','o','x','W', 0 }; + int (WINAPI * _MessageBoxW)( + _In_opt_ HWND hWnd, + _In_opt_ LPCWSTR lpText, + _In_opt_ LPCWSTR lpCaption, + _In_ UINT uType) = (int (WINAPI*)( + _In_opt_ HWND, + _In_opt_ LPCWSTR, + _In_opt_ LPCWSTR, + _In_ UINT)) _GetProcAddress((HMODULE)u32_dll, message_box_name); + if (_MessageBoxW == NULL) return 4; + + wchar_t msg_content[] = { 'H','e','l','l','o', ' ', 'W','o','r','l','d','!', 0 }; + wchar_t msg_title[] = { 'D','e','m','o','!', 0 }; + _MessageBoxW(0, msg_title, msg_content, MB_OK); + + return 0; +} + +int mystrcmp(wchar_t* str1, wchar_t* str2) { + int i = 0; + while (str1[i] != L'\0' && str2[i] != L'\0') { + if (str1[i] != str2[i]) { + return 1; + } + i++; + } + return 0; +} \ No newline at end of file diff --git a/source/peb_lookup.h b/source/peb_lookup.h new file mode 100644 index 0000000..f018bdb --- /dev/null +++ b/source/peb_lookup.h @@ -0,0 +1,120 @@ +#pragma once +#pragma once +#include +#ifndef __NTDLL_H__ +#ifndef TO_LOWERCASE +#define TO_LOWERCASE(out, c1) (out = (c1 <= 'Z' && c1 >= 'A') ? c1 = (c1 - 'A') + 'a': c1) +#endif + +typedef struct _UNICODE_STRING +{ + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +} UNICODE_STRING, * PUNICODE_STRING; +typedef struct _PEB_LDR_DATA +{ + ULONG Length; + BOOLEAN Initialized; + HANDLE SsHandle; + LIST_ENTRY InLoadOrderModuleList; + LIST_ENTRY InMemoryOrderModuleList; + LIST_ENTRY InInitializationOrderModuleList; + PVOID EntryInProgress; +} PEB_LDR_DATA, * PPEB_LDR_DATA; +//here we don't want to use any functions imported form external modules +typedef struct _LDR_DATA_TABLE_ENTRY { + LIST_ENTRY InLoadOrderModuleList; + LIST_ENTRY InMemoryOrderModuleList; + LIST_ENTRY InInitializationOrderModuleList; + void* BaseAddress; + void* EntryPoint; + ULONG SizeOfImage; + UNICODE_STRING FullDllName; + UNICODE_STRING BaseDllName; + ULONG Flags; + SHORT LoadCount; + SHORT TlsIndex; + HANDLE SectionHandle; + ULONG CheckSum; + ULONG TimeDateStamp; +} LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY; +typedef struct _PEB +{ + BOOLEAN InheritedAddressSpace; + BOOLEAN ReadImageFileExecOptions; + BOOLEAN BeingDebugged; + BOOLEAN SpareBool; + HANDLE Mutant; + PVOID ImageBaseAddress; + PPEB_LDR_DATA Ldr; + // [...] this is a fragment, more elements follow here +} PEB, * PPEB; +#endif //__NTDLL_H__ + +inline LPVOID get_module_by_name(WCHAR * module_name) +{ + PPEB peb = NULL; +#if defined(_WIN64) + peb = (PPEB)__readgsqword(0x60); +#else + peb = (PPEB)__readfsdword(0x30); +#endif + PPEB_LDR_DATA ldr = peb->Ldr; + LIST_ENTRY list = ldr->InLoadOrderModuleList; + PLDR_DATA_TABLE_ENTRY Flink = *((PLDR_DATA_TABLE_ENTRY*)(&list)); + PLDR_DATA_TABLE_ENTRY curr_module = Flink; + while (curr_module != NULL && curr_module->BaseAddress != NULL) { + if (curr_module->BaseDllName.Buffer == NULL) continue; + WCHAR* curr_name = curr_module->BaseDllName.Buffer; + size_t i = 0; + for (i = 0; module_name[i] != 0 && curr_name[i] != 0; i++) { + WCHAR c1, c2; + TO_LOWERCASE(c1, module_name[i]); + TO_LOWERCASE(c2, curr_name[i]); + if (c1 != c2) break; + } + if (module_name[i] == 0 && curr_name[i] == 0) { + //found + return curr_module->BaseAddress; + } + // not found, try next: + curr_module = (PLDR_DATA_TABLE_ENTRY)curr_module->InLoadOrderModuleList.Flink; + } + return NULL; +} +inline LPVOID get_func_by_name(LPVOID module, char* func_name) +{ + IMAGE_DOS_HEADER* idh = (IMAGE_DOS_HEADER*)module; + if (idh->e_magic != IMAGE_DOS_SIGNATURE) { + return NULL; + } + IMAGE_NT_HEADERS* nt_headers = (IMAGE_NT_HEADERS*)((BYTE*)module + idh->e_lfanew); + IMAGE_DATA_DIRECTORY* exportsDir = &(nt_headers -> OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]); + if (exportsDir->VirtualAddress == NULL) { + return NULL; + } + DWORD expAddr = exportsDir->VirtualAddress; + IMAGE_EXPORT_DIRECTORY* exp = (IMAGE_EXPORT_DIRECTORY*)(expAddr + (ULONG_PTR)module); + SIZE_T namesCount = exp->NumberOfNames; + DWORD funcsListRVA = exp->AddressOfFunctions; + DWORD funcNamesListRVA = exp->AddressOfNames; + DWORD namesOrdsListRVA = exp->AddressOfNameOrdinals; + + //go through names: + for (SIZE_T i = 0; i < namesCount; i++) { + DWORD* nameRVA = (DWORD*)(funcNamesListRVA + (BYTE*)module + i * sizeof(DWORD)); + WORD* nameIndex = (WORD*)(namesOrdsListRVA + (BYTE*)module + i * sizeof(WORD)); + DWORD* funcRVA = (DWORD*)(funcsListRVA + (BYTE*)module + (*nameIndex) * sizeof(DWORD)); + LPSTR curr_name = (LPSTR)(*nameRVA + (BYTE*)module); + size_t k = 0; + for (k = 0; func_name[k] != 0 && curr_name[k] != 0; k++) { + if (func_name[k] != curr_name[k]) break; + } + if (func_name[k] == 0 && curr_name[k] == 0) { + //found + return (BYTE*)module + (*funcRVA); + } + } + return NULL; +} \ No newline at end of file diff --git a/supermega.py b/supermega.py new file mode 100644 index 0000000..a4b6334 --- /dev/null +++ b/supermega.py @@ -0,0 +1,120 @@ +import subprocess +import os +import pefile +import shutil + +print("Super Mega") + +use_sgn = False + + +def main(): + print("--[ Compile C source to ASM ]") + path_cl = r'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.37.32822\bin\Hostx64\x64\cl.exe' + subprocess.run([ + path_cl, + "/c", + "/FA", + "/GS-", + "source/main.c" + ]) + if not os.path.isfile("main.asm"): + print("Error") + return + else: + print(" Generated main.asm") + + print("--[ Cleanup ASM ]") + path_masmshc = r'C:\Users\hacker\Source\Repos\masm_shc\out\build\x64-Debug\masm_shc\masm_shc.exe' + subprocess.run([ + path_masmshc, + "main.asm", + "main-clean.asm", + ]) + if not os.path.isfile("main-clean.asm"): + print("Error") + return + else: + print(" Generated main-clean.asm") + + print("--[ Compile to exe ]") + path_ml64 = r'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.37.32822\bin\Hostx64\x64\ml64.exe' + subprocess.run([ + path_ml64, + "main-clean.asm", + "/link", + "/entry:AlignRSP" + ]) + if not os.path.isfile("main-clean.exe"): + print("Error") + return + else: + print(" Generated main-clean.exe") + + print("--[ Get code section from exe ]") + code = get_code_section("main-clean.exe") + with open("main-clean.bin", 'wb') as f: + f.write(code) + print("--[ Shellcode written to: main-clean.bin size: {} ]".format(len(code))) + + print("--[ Test it with runshc ]") + path_runshc = r'C:\Users\hacker\Source\Repos\masm_shc\out\build\x64-Debug\runshc\runshc.exe' + subprocess.run([ + path_runshc, + "main-clean.bin", + ]) + + if use_sgn: + print("--[ Convert with SGN ]") + path_sgn = r'C:\training\tools\sgn\sgn.exe' + subprocess.run([ + path_sgn, + "--arch=64", + "-i", "{}".format("main-clean.bin"), + "-o", "{}".format("main-clean-sgn.bin"), + ]) + if not os.path.isfile("main-clean-sgn.bin"): + print("Error") + return + else: + print(" Generated main-clean-sgn.bin") + + print("--[ Test SGN shellcode ]") + path_shexec = r'C:\Research\hasherezade\exec_fiber\sh-exec-fiber.exe' + subprocess.run([ + path_shexec, + "{}".format("main-clean-sgn.bin"), + ]) + else: + shutil.copyfile("main-clean.bin", "main-clean-sgn.bin") + + + + + +# $env:INCLUDE="C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.37.32822\include;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.37.32822\ATLMFC\include;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\VS\include;C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\ucrt;C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\um;C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\shared;C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\winrt;C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\cppwinrt;C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um" +# $env:LIB=C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.37.32822\ATLMFC\lib\x64;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.37.32822\lib\x64;C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\lib\um\x64;C:\Program Files (x86)\Windows Kits\10\lib\10.0.22621.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\\lib\10.0.22621.0\\um\x64 +# $env:LIBPATH=C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.37.32822\ATLMFC\lib\x64;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.37.32822\lib\x64;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.37.32822\lib\x86\store\references;C:\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.22621.0;C:\Program Files (x86)\Windows Kits\10\References\10.0.22621.0;C:\Windows\Microsoft.NET\Framework64\v4.0.30319 + +def get_code_section(pe_file): + try: + # Load the PE file + pe = pefile.PE(pe_file) + + # Iterate over the sections + for section in pe.sections: + # Check if this is the code section + if '.text' in section.Name.decode().rstrip('\x00'): + print("--> Size: {}".format(section.SizeOfRawData)) + return section.get_data() + else: + print("Code section not found.") + + except FileNotFoundError: + print(f"File not found: {pe_file}") + except pefile.PEFormatError: + print(f"Invalid PE file: {pe_file}") + + + +main() \ No newline at end of file