feature: createfile shellcode verification

This commit is contained in:
Dobin
2024-02-03 14:43:21 +00:00
parent c37e4a577b
commit 508799cdc9
7 changed files with 160 additions and 22 deletions
+1
View File
@@ -4,3 +4,4 @@
/*.bin /*.bin
*.asm *.asm
__pycache__ __pycache__
bak/
+51 -17
View File
@@ -1,20 +1,31 @@
import subprocess import subprocess
import os import os
import pefile import pefile
import time
SHC_VERIFY_SLEEP = 0.1
path_cl = r'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.37.32822\bin\Hostx64\x64\cl.exe'
path_masmshc = r'C:\Users\hacker\Source\Repos\masm_shc\out\build\x64-Debug\masm_shc\masm_shc.exe'
path_ml64 = r'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.37.32822\bin\Hostx64\x64\ml64.exe'
path_runshc = r'C:\Users\hacker\Source\Repos\masm_shc\out\build\x64-Debug\runshc\runshc.exe'
path_shexec = r'C:\Research\hasherezade\exec_fiber\sh-exec-fiber.exe'
verify_filename = r'C:\Temp\a'
def clean_files(): def clean_files():
try:
os.remove("main.asm") # generated from compiling source/main.c os.remove("main.asm") # generated from compiling source/main.c
os.remove("main-clean.asm") # cleaned for being a shellcode os.remove("main-clean.asm") # cleaned for being a shellcode
os.remove("main-clean.exe") # assembled os.remove("main-clean.exe") # assembled
os.remove("main-clean.bin") os.remove("main-clean.bin")
os.remove("main-clean-append.bin") os.remove("main-clean-append.bin")
os.remove(verify_filename)
path_cl = r'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.37.32822\bin\Hostx64\x64\cl.exe' except OSError:
path_masmshc = r'C:\Users\hacker\Source\Repos\masm_shc\out\build\x64-Debug\masm_shc\masm_shc.exe' pass
path_runshc = r'C:\Users\hacker\Source\Repos\masm_shc\out\build\x64-Debug\runshc\runshc.exe'
path_shexec = r'C:\Research\hasherezade\exec_fiber\sh-exec-fiber.exe'
def make_c_to_asm(c_file, asm_file, asm_clean_file): def make_c_to_asm(c_file, asm_file, asm_clean_file):
@@ -25,24 +36,24 @@ def make_c_to_asm(c_file, asm_file, asm_clean_file):
"/FA", "/FA",
"/GS-", "/GS-",
c_file, c_file,
], check=True) ], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
if not os.path.isfile(asm_file): if not os.path.isfile(asm_file):
print("Error") print("Error")
return return
else: else:
print(" Generated {}".format(asm_file)) print(" > Generated {}".format(asm_file))
print("--[ Cleanup ASM: {} -> {} ]".format(asm_file, asm_clean_file)) print("--[ Cleanup ASM: {} -> {} ]".format(asm_file, asm_clean_file))
subprocess.run([ subprocess.run([
path_masmshc, path_masmshc,
asm_file, asm_file,
asm_clean_file, asm_clean_file,
], check=True) ], check=True, stdout=subprocess.DEVNULL)
if not os.path.isfile(asm_clean_file): if not os.path.isfile(asm_clean_file):
print("Error") print("Error")
return return
else: else:
print(" Generated {}".format(asm_clean_file)) print(" > Generated {}".format(asm_clean_file))
print("--[ Fixup ASM: {} ]".format(asm_clean_file)) print("--[ Fixup ASM: {} ]".format(asm_clean_file))
fixup_asm_file(asm_clean_file) fixup_asm_file(asm_clean_file)
@@ -55,7 +66,7 @@ def fixup_asm_file(filename):
# replace external reference with shellcode reference # replace external reference with shellcode reference
for idx, line in enumerate(lines): for idx, line in enumerate(lines):
if "dobin" in lines[idx]: if "dobin" in lines[idx]:
print("--( Replace external reference at: {})".format(idx)) print(" > Replace external reference at: {})".format(idx))
lines[idx] = lines[idx].replace( lines[idx] = lines[idx].replace(
"mov r8, QWORD PTR dobin", "mov r8, QWORD PTR dobin",
"lea r8, [shcstart]" "lea r8, [shcstart]"
@@ -64,7 +75,7 @@ def fixup_asm_file(filename):
# add label at end of code # add label at end of code
for idx, line in enumerate(lines): for idx, line in enumerate(lines):
if lines[idx].startswith("END"): if lines[idx].startswith("END"):
print("--( Add end of code label at: {})".format(idx)) print(" > Add end of code label at: {})".format(idx))
lines.insert(idx-1, "shcstart:\r\n") lines.insert(idx-1, "shcstart:\r\n")
lines.insert(idx, "\tnop\r\n") lines.insert(idx, "\tnop\r\n")
break break
@@ -75,18 +86,17 @@ def fixup_asm_file(filename):
def make_shc_from_asm(asm_clean_file, exe_file, shc_file): def make_shc_from_asm(asm_clean_file, exe_file, shc_file):
print("--[ Assemble to exe ]") print("--[ Assemble 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([ subprocess.run([
path_ml64, path_ml64,
asm_clean_file, asm_clean_file,
"/link", "/link",
"/entry:AlignRSP" "/entry:AlignRSP"
], check=True) ], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
if not os.path.isfile(exe_file): if not os.path.isfile(exe_file):
print("Error") print("Error")
return return
else: else:
print(" Generated {}".format(exe_file)) print(" > Generated {}".format(exe_file))
print("--[ Get code section from exe ]") print("--[ Get code section from exe ]")
code = get_code_section(exe_file) code = get_code_section(exe_file)
@@ -104,9 +114,10 @@ def get_code_section(pe_file):
for section in pe.sections: for section in pe.sections:
# Check if this is the code section # Check if this is the code section
if '.text' in section.Name.decode().rstrip('\x00'): if '.text' in section.Name.decode().rstrip('\x00'):
print("--> Size: {}".format(section.SizeOfRawData))
data = section.get_data() data = section.get_data()
data = remove_trailing_null_bytes(data) data = remove_trailing_null_bytes(data)
print(" > Code Size Raw: {} Size me: {}".format(
section.SizeOfRawData, len(data)))
return data return data
else: else:
print("Code section not found.") print("Code section not found.")
@@ -145,7 +156,7 @@ def obfuscate_shc_loader(file_shc_in, file_shc_out):
print("Error") print("Error")
return return
else: else:
print(" Generated main-clean-sgn.bin") print(" > Generated main-clean-sgn.bin")
def test_shellcode(shc_name): def test_shellcode(shc_name):
@@ -155,3 +166,26 @@ def test_shellcode(shc_name):
"{}".format(shc_name), "{}".format(shc_name),
]) # , check=True ]) # , check=True
def verify_shellcode(shc_name):
print("--[ Test shellcode: {} ]".format(shc_name))
# check if directory exists
if not os.path.exists(os.path.dirname(verify_filename)):
print("Error, directory does not exist for: {}".format(verify_filename))
return
# path_runshc
# path_shexec
subprocess.run([
path_runshc,
"{}".format(shc_name),
]) # , check=True
time.sleep(SHC_VERIFY_SLEEP)
if os.path.isfile(verify_filename):
print("--> OK. File creation test shellcode payload verified")
# better to remove it immediately. If cleanup on start is not performed,
# there may be false positives
os.remove(verify_filename)
else:
print("--> FAIL. Payload did not create file.")
+3
View File
@@ -0,0 +1,3 @@
+40
View File
@@ -0,0 +1,40 @@
# createfile shellcode
```
> use payload/windows/x64/exec
msf6 payload(windows/x64/exec) > set cmd "cmd.exe /c echo a > a"
cmd => cmd.exe /c echo a > a
msf6 payload(windows/x64/exec) > generate -b "\x00"
# windows/x64/exec - 339 bytes
# https://metasploit.com/
# Encoder: x64/xor_dynamic
# VERBOSE=false, PrependMigrate=false, EXITFUNC=process,
# CMD=cmd.exe /c echo a > a
buf =
"\xeb\x27\x5b\x53\x5f\xb0\x3f\xfc\xae\x75\xfd\x57\x59\x53" +
"\x5e\x8a\x06\x30\x07\x48\xff\xc7\x48\xff\xc6\x66\x81\x3f" +
"\x04\x74\x74\x07\x80\x3e\x3f\x75\xea\xeb\xe6\xff\xe1\xe8" +
"\xd4\xff\xff\xff\x07\x3f\xfb\x4f\x84\xe3\xf7\xef\xc7\x07" +
"\x07\x07\x46\x56\x46\x57\x55\x56\x51\x4f\x36\xd5\x62\x4f" +
"\x8c\x55\x67\x4f\x8c\x55\x1f\x4f\x8c\x55\x27\x4f\x8c\x75" +
"\x57\x4f\x08\xb0\x4d\x4d\x4a\x36\xce\x4f\x36\xc7\xab\x3b" +
"\x66\x7b\x05\x2b\x27\x46\xc6\xce\x0a\x46\x06\xc6\xe5\xea" +
"\x55\x46\x56\x4f\x8c\x55\x27\x8c\x45\x3b\x4f\x06\xd7\x8c" +
"\x87\x8f\x07\x07\x07\x4f\x82\xc7\x73\x60\x4f\x06\xd7\x57" +
"\x8c\x4f\x1f\x43\x8c\x47\x27\x4e\x06\xd7\xe4\x51\x4f\xf8" +
"\xce\x46\x8c\x33\x8f\x4f\x06\xd1\x4a\x36\xce\x4f\x36\xc7" +
"\xab\x46\xc6\xce\x0a\x46\x06\xc6\x3f\xe7\x72\xf6\x4b\x04" +
"\x4b\x23\x0f\x42\x3e\xd6\x72\xdf\x5f\x43\x8c\x47\x23\x4e" +
"\x06\xd7\x61\x46\x8c\x0b\x4f\x43\x8c\x47\x1b\x4e\x06\xd7" +
"\x46\x8c\x03\x8f\x4f\x06\xd7\x46\x5f\x46\x5f\x59\x5e\x5d" +
"\x46\x5f\x46\x5e\x46\x5d\x4f\x84\xeb\x27\x46\x55\xf8\xe7" +
"\x5f\x46\x5e\x5d\x4f\x8c\x15\xee\x50\xf8\xf8\xf8\x5a\x4f" +
"\xbd\x06\x07\x07\x07\x07\x07\x07\x07\x4f\x8a\x8a\x06\x06" +
"\x07\x07\x46\xbd\x36\x8c\x68\x80\xf8\xd2\xbc\xf7\xb2\xa5" +
"\x51\x46\xbd\xa1\x92\xba\x9a\xf8\xd2\x4f\x84\xc3\x2f\x3b" +
"\x01\x7b\x0d\x87\xfc\xe7\x72\x02\xbc\x40\x14\x75\x68\x6d" +
"\x07\x5e\x46\x8e\xdd\xf8\xd2\x64\x6a\x63\x29\x62\x7f\x62" +
"\x27\x28\x64\x27\x62\x64\x6f\x68\x27\x66\x27\x39\x27\x66" +
"\x07\x04\x74"
```
+25
View File
@@ -0,0 +1,25 @@
\xeb\x27\x5b\x53\x5f\xb0\xa8\xfc\xae\x75\xfd\x57\x59\x53
\x5e\x8a\x06\x30\x07\x48\xff\xc7\x48\xff\xc6\x66\x81\x3f
\xb5\x35\x74\x07\x80\x3e\xa8\x75\xea\xeb\xe6\xff\xe1\xe8
\xd4\xff\xff\xff\x07\xa8\xfb\x4f\x84\xe3\xf7\xef\xc7\x07
\x07\x07\x46\x56\x46\x57\x55\x56\x51\x4f\x36\xd5\x62\x4f
\x8c\x55\x67\x4f\x8c\x55\x1f\x4f\x8c\x55\x27\x4f\x8c\x75
\x57\x4f\x08\xb0\x4d\x4d\x4a\x36\xce\x4f\x36\xc7\xab\x3b
\x66\x7b\x05\x2b\x27\x46\xc6\xce\x0a\x46\x06\xc6\xe5\xea
\x55\x46\x56\x4f\x8c\x55\x27\x8c\x45\x3b\x4f\x06\xd7\x8c
\x87\x8f\x07\x07\x07\x4f\x82\xc7\x73\x60\x4f\x06\xd7\x57
\x8c\x4f\x1f\x43\x8c\x47\x27\x4e\x06\xd7\xe4\x51\x4f\xf8
\xce\x46\x8c\x33\x8f\x4f\x06\xd1\x4a\x36\xce\x4f\x36\xc7
\xab\x46\xc6\xce\x0a\x46\x06\xc6\x3f\xe7\x72\xf6\x4b\x04
\x4b\x23\x0f\x42\x3e\xd6\x72\xdf\x5f\x43\x8c\x47\x23\x4e
\x06\xd7\x61\x46\x8c\x0b\x4f\x43\x8c\x47\x1b\x4e\x06\xd7
\x46\x8c\x03\x8f\x4f\x06\xd7\x46\x5f\x46\x5f\x59\x5e\x5d
\x46\x5f\x46\x5e\x46\x5d\x4f\x84\xeb\x27\x46\x55\xf8\xe7
\x5f\x46\x5e\x5d\x4f\x8c\x15\xee\x50\xf8\xf8\xf8\x5a\x4f
\xbd\x06\x07\x07\x07\x07\x07\x07\x07\x4f\x8a\x8a\x06\x06
\x07\x07\x46\xbd\x36\x8c\x68\x80\xf8\xd2\xbc\xf7\xb2\xa5
\x51\x46\xbd\xa1\x92\xba\x9a\xf8\xd2\x4f\x84\xc3\x2f\x3b
\x01\x7b\x0d\x87\xfc\xe7\x72\x02\xbc\x40\x14\x75\x68\x6d
\x07\x5e\x46\x8e\xdd\xf8\xd2\x64\x6a\x63\x29\x62\x7f\x62
\x27\x28\x64\x27\x62\x64\x6f\x68\x27\x66\x27\x39\x27\x64
\x3d\x5b\x73\x62\x6a\x77\x5b\x66\x07\xb5\x35
+3 -1
View File
@@ -51,6 +51,7 @@ int main()
} }
// user32.dll: MessageBoxW() // user32.dll: MessageBoxW()
/*
char user32_dll_name[] = { 'u','s','e','r','3','2','.','d','l','l', 0 }; char user32_dll_name[] = { 'u','s','e','r','3','2','.','d','l','l', 0 };
LPVOID u32_dll = _LoadLibraryA(user32_dll_name); LPVOID u32_dll = _LoadLibraryA(user32_dll_name);
char message_box_name[] = { 'M','e','s','s','a','g','e','B','o','x','W', 0 }; char message_box_name[] = { 'M','e','s','s','a','g','e','B','o','x','W', 0 };
@@ -68,6 +69,7 @@ int main()
wchar_t msg_content[] = { 'H','e','l','l','o', ' ', 'W','o','r','l','d','!', 0 }; wchar_t msg_content[] = { 'H','e','l','l','o', ' ', 'W','o','r','l','d','!', 0 };
wchar_t msg_title[] = { 'D','e','m','o','!', 0 }; wchar_t msg_title[] = { 'D','e','m','o','!', 0 };
_MessageBoxW(0, msg_title, msg_content, MB_OK); _MessageBoxW(0, msg_title, msg_content, MB_OK);
*/
// Copy shellcode // Copy shellcode
// ntdll.dll: VirtualAlloc() // ntdll.dll: VirtualAlloc()
@@ -83,7 +85,7 @@ int main()
_In_ DWORD flProtect)) _GetProcAddress((HMODULE)base, VirtualAlloc_str); _In_ DWORD flProtect)) _GetProcAddress((HMODULE)base, VirtualAlloc_str);
if (_VirtualAlloc == NULL) return 4; if (_VirtualAlloc == NULL) return 4;
char *dest = _VirtualAlloc(NULL, 4096, 0x3000, 0x40); char *dest = _VirtualAlloc(NULL, 4096, 0x3000, 0x40);
for(int n=0; n<272; n++) { for(int n=0; n<347+1; n++) {
dest[n] = dobin[n]; dest[n] = dobin[n];
} }
+35 -2
View File
@@ -20,8 +20,9 @@ class DataRefStyle(Enum):
APPEND = 1 APPEND = 1
options = { options_default = {
"payload": "shellcodes/calc64.bin", "payload": "shellcodes/calc64.bin",
"verify": False,
"cleanup_files_on_start": True, "cleanup_files_on_start": True,
"generate_asm_from_c": True, "generate_asm_from_c": True,
@@ -29,6 +30,7 @@ options = {
"test_loader_shellcode": False, "test_loader_shellcode": False,
"obfuscate_shc_loader": False, "obfuscate_shc_loader": False,
"test_obfuscated_shc": False, "test_obfuscated_shc": False,
"exec_final_shellcode": True,
"alloc_style": AllocStyle.RWX, "alloc_style": AllocStyle.RWX,
"exec_style": ExecStyle.CALL, "exec_style": ExecStyle.CALL,
@@ -37,6 +39,31 @@ options = {
} }
# This will verify if our loader works
# - Use it on a "target" machine
# - payload shellcode will create a file c:\temp\a
# - set: verify=True
options_test = {
"payload": "shellcodes/createfile.bin",
"verify": True,
"cleanup_files_on_start": True,
"generate_asm_from_c": True,
"generate_shc_from_asm": True,
"test_loader_shellcode": False,
"obfuscate_shc_loader": False,
"test_obfuscated_shc": False,
"exec_final_shellcode": False,
"alloc_style": AllocStyle.RWX,
"exec_style": ExecStyle.CALL,
"copy_style": CopyStyle.SIMPLE,
"dataref_style": DataRefStyle.APPEND
}
options = options_test
def main(): def main():
print("Super Mega") print("Super Mega")
@@ -67,12 +94,18 @@ def main():
with open(options["payload"], 'rb') as input2: with open(options["payload"], 'rb') as input2:
data_payload = input2.read() data_payload = input2.read()
print("---[ Stager: {} Shellcode: {} ]".format(len(data_stager), len(data_payload))) print("--[ Stager: {} Shellcode: {} (both: {})]".format(
len(data_stager), len(data_payload), len(data_stager)+len(data_payload)))
with open("main-clean-append.bin", 'wb') as output: with open("main-clean-append.bin", 'wb') as output:
output.write(data_stager) output.write(data_stager)
output.write(data_payload) output.write(data_payload)
if options["verify"]:
print("--[ Verify final shellcode ]")
verify_shellcode("main-clean-append.bin")
if options["exec_final_shellcode"]:
print("--[ Test Append shellcode ]") print("--[ Test Append shellcode ]")
test_shellcode("main-clean-append.bin") test_shellcode("main-clean-append.bin")