Files
naksyn-PythonMemoryModule/pythonmemorymodule/windows/native_exec/nativeutils.py
T
naksyn db1893910c command line support (partial) via PEB stomping
This update include support to passing command line parameters to unmanaged exe via PEB stomping.
This technique is not working with every executable since it depends on which functions are used to pass arguments.
Generally, to get a universally working technique would be required to hook GetCommandlineA GetCommandlineW __getmainargs and __wgetmainargs since PEB stomping won't cover all cases, more details here:
https://blog-30cm-tw.translate.goog/2020/08/windows-c-mainargc-argv.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=it&_x_tr_pto=wapp

However, during my testing I found that mimikatz and several go binaries are working just by doing PEB stomping.
On the other hand, cmdline passing via PEB stomping alone to mingw and VS compiled binaries won't likely work.
2023-07-27 06:44:29 -07:00

280 lines
12 KiB
Python

import windows
import windows.native_exec.simple_x64 as x64
import windows.native_exec.simple_x86 as x86
from windows.generated_def.winstructs import *
StrlenW64 = x64.MultipleInstr()
StrlenW64 += x64.Label(":FUNC_STRLENW64")
StrlenW64 += x64.Push("RCX")
StrlenW64 += x64.Push("RDI")
StrlenW64 += x64.Mov("RDI", "RCX")
StrlenW64 += x64.Xor("RAX", "RAX")
StrlenW64 += x64.Xor("RCX", "RCX")
StrlenW64 += x64.Dec("RCX")
StrlenW64 += x64.Repne + x64.ScasW()
StrlenW64 += x64.Not("RCX")
StrlenW64 += x64.Dec("RCX")
StrlenW64 += x64.Mov("RAX", "RCX")
StrlenW64 += x64.Pop("RDI")
StrlenW64 += x64.Pop("RCX")
StrlenW64 += x64.Ret()
StrlenA64 = x64.MultipleInstr()
StrlenA64 += x64.Label(":FUNC_STRLENA64")
StrlenA64 += x64.Push("RCX")
StrlenA64 += x64.Push("RDI")
StrlenA64 += x64.Mov("RDI", "RCX")
StrlenA64 += x64.Xor("RAX", "RAX")
StrlenA64 += x64.Xor("RCX", "RCX")
StrlenA64 += x64.Dec("RCX")
StrlenA64 += x64.Repne + x64.ScasB()
StrlenA64 += x64.Not("RCX")
StrlenA64 += x64.Dec("RCX")
StrlenA64 += x64.Mov("RAX", "RCX")
StrlenA64 += x64.Pop("RDI")
StrlenA64 += x64.Pop("RCX")
StrlenA64 += x64.Ret()
GetProcAddress64 = x64.MultipleInstr()
GetProcAddress64 += x64.Label(":FUNC_GETPROCADDRESS64")
GetProcAddress64 += x64.Push("RBX")
GetProcAddress64 += x64.Push("RCX")
GetProcAddress64 += x64.Push("RDX")
GetProcAddress64 += x64.Push("RSI")
GetProcAddress64 += x64.Push("RDI")
GetProcAddress64 += x64.Push("R8")
GetProcAddress64 += x64.Push("R9")
GetProcAddress64 += x64.Push("R10")
GetProcAddress64 += x64.Push("R11")
GetProcAddress64 += x64.Push("R12")
GetProcAddress64 += x64.Push("R13")
# Params : RCX -> libname
# Params : RDX -> API Name
GetProcAddress64 += x64.Mov("R11", "RCX")
GetProcAddress64 += x64.Mov("R12", "RDX")
GetProcAddress64 += x64.Mov("RAX", x64.mem("GS:[0x60]")) #PEB !
GetProcAddress64 += x64.Mov("RAX", x64.mem("[RAX + 24] ")) # ; RAX = ldr (+ 6 for 64 cause of 2 ptr)
GetProcAddress64 += x64.Mov("RAX", x64.mem("[RAX + 32]")) # ; RAX on the first elt of the list (first module)
GetProcAddress64 += x64.Mov("RDX", "RAX")
GetProcAddress64 += x64.Label(":a_dest")
GetProcAddress64 += x64.Mov("RAX", "RDX")
GetProcAddress64 += x64.Mov("RBX", x64.mem("[RAX + 32]")) # RBX : first base ! (base of current module)
#GetProcAddress64 += x64.Mov("RBX ", x64.mem("[RAX + 32]")) # RBX : first base ! (base of current module)
GetProcAddress64 += x64.Cmp("RBX", 0)
GetProcAddress64 += x64.Jz(":DLL_NOT_FOUND")
GetProcAddress64 += x64.Mov("RCX", x64.mem("[RAX + 80]")) # RCX = NAME (UNICODE_STRING.Buffer)
GetProcAddress64 += x64.Call(":FUNC_STRLENW64")
GetProcAddress64 += x64.Mov("RDI", "RCX")
GetProcAddress64 += x64.Mov("RCX", "RAX")
GetProcAddress64 += x64.Mov("RSI", "R11")
GetProcAddress64 += x64.Rep + x64.CmpsW() #;cmp with current dll name (unicode)
GetProcAddress64 += x64.Test("RCX", "RCX")
GetProcAddress64 += x64.Jz(":DLL_FOUND")
GetProcAddress64 += x64.Mov("RDX", x64.mem("[RDX]"))
GetProcAddress64 += x64.Jmp(":a_dest")
GetProcAddress64 += x64.Label(":DLL_FOUND") # here rbx = base
GetProcAddress64 += x64.Mov("EAX", x64.mem("[RBX + 60]")) # rax = PEBASE RVA
GetProcAddress64 += x64.Add("RAX", "RBX") # RAX = PEBASE
GetProcAddress64 += x64.Add("RAX", 24) # ;OPTIONAL HEADER
GetProcAddress64 += x64.Mov("ECX", x64.mem("[rax + 112]")) # ;rcx = RVA export dir
GetProcAddress64 += x64.Add("RCX", "RBX") # ;rcx = export_dir
GetProcAddress64 += x64.Mov("RAX", "RCX") # ;RAX = export_dir
GetProcAddress64 += x64.Push("RAX") # ;Save it for after function search
# ; EBX = BASE | EAX = EXPORT DIR
GetProcAddress64 += x64.Mov("ECX", x64.mem("[RAX + 24] "))
GetProcAddress64 += x64.Mov("R13", "RCX") # ;r13 = NB names
GetProcAddress64 += x64.Mov("EDX", x64.mem("[RAX + 32] ")) # EDX = names array RVA
GetProcAddress64 += x64.Add("RDX", "RBX") # RDX = names array
GetProcAddress64 += x64.Xor("RCX", "RCX")
GetProcAddress64 += x64.Label(":SEARCH_LOOP")
GetProcAddress64 += x64.Cmp("RCX", "R13")
GetProcAddress64 += x64.Jz(":API_NOT_FOUND")
GetProcAddress64 += x64.Mov("ESI", x64.mem("[RDX + RCX * 4]")) # ;Get function name RVA
GetProcAddress64 += x64.Add("RSI", "RBX") # ;Get name addr
GetProcAddress64 += x64.Push("RCX") # ;Save current index (could use x64 register)
GetProcAddress64 += x64.Mov("RCX", "R12")
GetProcAddress64 += x64.Call(":FUNC_STRLENA64") # TODO: mov outside the loop :D
GetProcAddress64 += x64.Mov("RCX", "RAX")
GetProcAddress64 += x64.Mov("RDI", "R12")
GetProcAddress64 += x64.Inc("RCX")
GetProcAddress64 += x64.Rep + x64.CmpsB()
GetProcAddress64 += x64.Mov("EAX", "ECX")
GetProcAddress64 += x64.Pop("RCX")
GetProcAddress64 += x64.Inc("RCX")
GetProcAddress64 += x64.Test("RAX", "RAX")
GetProcAddress64 += x64.Jnz(":SEARCH_LOOP")
# Func FOUND !
GetProcAddress64 += x64.Dec("RCX")
GetProcAddress64 += x64.Pop("RAX") # ;Restore export_dir addr
GetProcAddress64 += x64.Mov("EDX", x64.mem("[RAX + 36]")) # ;EDX = AddressOfNameOrdinals RVX
GetProcAddress64 += x64.Add("RDX", "RBX")
GetProcAddress64 += x64.OperandSizeOverride + x64.Mov("ECX", x64.mem("[rdx + rcx * 2]")) # ; ecx = Ieme ordinal (short array)
GetProcAddress64 += x64.And('RCX', 0xffff)
GetProcAddress64 += x64.Mov("EDX", x64.mem("[RAX + 28]")) # ; AddressOfFunctions RVA
GetProcAddress64 += x64.Add("RDX", "RBX")
GetProcAddress64 += x64.Mov("EDX", x64.mem("[RDX + RCX * 4]"))
GetProcAddress64 += x64.Add("RDX", "RBX")
GetProcAddress64 += x64.Mov("RAX", "RDX")
GetProcAddress64 += x64.Label(":RETURN")
GetProcAddress64 += x64.Pop("R13")
GetProcAddress64 += x64.Pop("R12")
GetProcAddress64 += x64.Pop("R11")
GetProcAddress64 += x64.Pop("R10")
GetProcAddress64 += x64.Pop("R9")
GetProcAddress64 += x64.Pop("R8")
GetProcAddress64 += x64.Pop("RDI")
GetProcAddress64 += x64.Pop("RSI")
GetProcAddress64 += x64.Pop("RDX")
GetProcAddress64 += x64.Pop("RCX")
GetProcAddress64 += x64.Pop("RBX")
GetProcAddress64 += x64.Ret()
GetProcAddress64 += x64.Label(":DLL_NOT_FOUND")
GetProcAddress64 += x64.Mov("RAX", 0xfffffffffffffffe)
GetProcAddress64 += x64.Jmp(":RETURN")
GetProcAddress64 += x64.Label(":API_NOT_FOUND")
GetProcAddress64 += x64.Pop("RAX")
GetProcAddress64 += x64.Mov("RAX", 0xffffffffffffffff)
GetProcAddress64 += x64.Jmp(":RETURN")
# Ajout des dependances
GetProcAddress64 += StrlenW64
GetProcAddress64 += StrlenA64
###### 32 bits #######
StrlenW32 = x86.MultipleInstr()
StrlenW32 += x86.Label(":FUNC_STRLENW32")
StrlenW32 += x86.Push("EDI")
StrlenW32 += x86.Mov("EDI", x86.mem("[ESP + 8]"))
StrlenW32 += x86.Push("ECX")
StrlenW32 += x86.Xor("EAX", "EAX")
StrlenW32 += x86.Xor("ECX", "ECX")
StrlenW32 += x86.Dec("ECX")
StrlenW32 += x86.Repne + x86.ScasW()
StrlenW32 += x86.Not("ECX")
StrlenW32 += x86.Dec("ECX")
StrlenW32 += x86.Mov("EAX", "ECX")
StrlenW32 += x86.Pop("ECX")
StrlenW32 += x86.Pop("EDI")
StrlenW32 += x86.Ret()
StrlenA32 = x86.MultipleInstr()
StrlenA32 += x86.Label(":FUNC_STRLENA32")
StrlenA32 += x86.Push("EDI")
StrlenA32 += x86.Mov("EDI", x86.mem("[ESP + 8]"))
StrlenA32 += x86.Push("ECX")
StrlenA32 += x86.Xor("EAX", "EAX")
StrlenA32 += x86.Xor("ECX", "ECX")
StrlenA32 += x86.Dec("ECX")
StrlenA32 += x86.Repne + x86.ScasB()
StrlenA32 += x86.Not("ECX")
StrlenA32 += x86.Dec("ECX")
StrlenA32 += x86.Mov("EAX", "ECX")
StrlenA32 += x86.Pop("ECX")
StrlenA32 += x86.Pop("EDI")
StrlenA32 += x86.Ret()
GetProcAddress32 = x86.MultipleInstr()
GetProcAddress32 += x86.Label(":FUNC_GETPROCADDRESS32")
GetProcAddress32 += x86.Push("EBX")
GetProcAddress32 += x86.Push("ECX")
GetProcAddress32 += x86.Push("EDI")
GetProcAddress32 += x86.Push("ESI")
GetProcAddress32 += x86.Push("EBP")
GetProcAddress32 += x86.Mov("EAX", x86.mem("FS:[0x30]"))
GetProcAddress32 += x86.Mov("EAX", x86.mem("[EAX + 0xC]"))
GetProcAddress32 += x86.Mov("EAX", x86.mem("[EAX + 0xC]")) # ; RAX on the first elt of the list (first module)
GetProcAddress32 += x86.Mov("EDX", "EAX")
GetProcAddress32 += x86.Label(":a_dest")
GetProcAddress32 += x86.Mov("EAX", "EDX")
GetProcAddress32 += x86.Mov("EBX", x86.mem("[EAX + 0x18]")) # EBX : first base ! (base of current module)
GetProcAddress32 += x86.Cmp("EBX", 0)
GetProcAddress32 += x86.Jz(":DLL_NOT_FOUND")
GetProcAddress32 += x86.Mov("ECX", x86.mem("[EAX + 0x30]")) # RCX = NAME (UNICODE_STRING.Buffer)
GetProcAddress32 += x86.Push("ECX")
GetProcAddress32 += x86.Call(":FUNC_STRLENW32")
GetProcAddress32 += x86.Pop("EDI") # Current name
GetProcAddress32 += x86.Mov("ECX", "EAX")
GetProcAddress32 += x86.Mov("ESI", x86.mem("[ESP + 0x18]"))
GetProcAddress32 += x86.Rep + x86.CmpsW()
GetProcAddress32 += x86.Test("ECX", "ECX")
GetProcAddress32 += x86.Jz(":DLL_FOUND")
GetProcAddress32 += x86.Mov("EDX", x86.mem("[EDX]"))
GetProcAddress32 += x86.Jmp(":a_dest")
GetProcAddress32 += x86.Label(":DLL_FOUND")
GetProcAddress32 += x86.Mov("EAX", x86.mem("[EBX + 0x3c]")) # rax = PEBASE RVA
GetProcAddress32 += x86.Add("EAX", "EBX") # RAX = PEBASE
GetProcAddress32 += x86.Add("EAX", 0x18) # ;OPTIONAL HEADER
GetProcAddress32 += x86.Mov("ECX", x86.mem("[EAX + 0x60]")) # ;ecx = RVA export dir
GetProcAddress32 += x86.Add("ECX", "EBX") # ;ecx = export_dir
GetProcAddress32 += x86.Mov("EAX", "ECX")
GetProcAddress32 += x86.Push("EAX") # Save it
# ; EBX = BASE | EAX = EXPORT DIR
GetProcAddress32 += x86.Mov("ECX", x86.mem("[EAX + 24] "))
GetProcAddress32 += x86.Mov("EBP", "ECX") # ;EBP = NB names
GetProcAddress32 += x86.Mov("EDX", x86.mem("[EAX + 32] ")) # EDX = names array RVA
GetProcAddress32 += x86.Add("EDX", "EBX") # RDX = names array
GetProcAddress32 += x86.Xor("ECX", "ECX")
GetProcAddress32 += x86.Mov("ESI", x86.mem("[ESP + 0x20]"))
GetProcAddress32 += x86.Label(":SEARCH_LOOP")
GetProcAddress32 += x86.Cmp("ECX", "EBP")
GetProcAddress32 += x86.Jz(":API_NOT_FOUND")
GetProcAddress32 += x86.Mov("EDI", x86.mem("[EDX + ECX * 4]")) # ;Get function name RVA
GetProcAddress32 += x86.Add("EDI", "EBX") # ;Get name addr
GetProcAddress32 += x86.Push("ECX") # Save current index
GetProcAddress32 += x86.Push("ESI")
GetProcAddress32 += x86.Call(":FUNC_STRLENA32")
GetProcAddress32 += x86.Mov("ECX", "EAX")
GetProcAddress32 += x86.Push("EDI")
GetProcAddress32 += x86.Call(":FUNC_STRLENA32")
GetProcAddress32 += x86.Pop("EDI")
GetProcAddress32 += x86.Cmp("EAX", "ECX")
GetProcAddress32 += x86.Jnz(":ABORT_STRCMP")
GetProcAddress32 += x86.Inc("ECX")
GetProcAddress32 += x86.Rep + x86.CmpsB()
GetProcAddress32 += x86.Label(":ABORT_STRCMP")
GetProcAddress32 += x86.Pop("ESI")
GetProcAddress32 += x86.Mov("EAX", "ECX")
GetProcAddress32 += x86.Pop("ECX")
GetProcAddress32 += x86.Inc("ECX")
GetProcAddress32 += x86.Test("EAX", "EAX")
GetProcAddress32 += x86.Jnz(":SEARCH_LOOP")
GetProcAddress32 += x86.Dec("ECX")
#GetProcAddress32 += x86.Int3() # da poi(edx + (ecx * 4)) + ebx; da esi
GetProcAddress32 += x86.Pop("EAX") # ;Restore export_dir addr
GetProcAddress32 += x86.Mov("EDX", x86.mem("[EAX + 36]")) # ;EDX = AddressOfNameOrdinals RVX
GetProcAddress32 += x86.Add("EDX", "EBX")
#GetProcAddress32 += x86.Mov("ECX", x86.mem("[EDX + ECX * 2]"))
GetProcAddress32 += x86.OperandSizeOverride + x86.Mov("ECX", x86.mem("[EDX + ECX * 2]"))
# ; ecx = Ieme ordinal (short array)
GetProcAddress32 += x86.And('ECX', 0xffff)
GetProcAddress32 += x86.Mov("EDX", x86.mem("[EAX + 28]")) # ; AddressOfFunctions RVA
GetProcAddress32 += x86.Add("EDX", "EBX")
GetProcAddress32 += x86.Mov("EDX", x86.mem("[EDX + ECX * 4]"))
GetProcAddress32 += x86.Add("EDX", "EBX")
GetProcAddress32 += x86.Mov("EAX", "EDX")
GetProcAddress32 += x86.Label(":RETURN")
GetProcAddress32 += x86.Pop("EBP")
GetProcAddress32 += x86.Pop("ESI")
GetProcAddress32 += x86.Pop("EDI")
GetProcAddress32 += x86.Pop("ECX")
GetProcAddress32 += x86.Pop("EBX")
GetProcAddress32 += x86.Ret()
GetProcAddress32 += x86.Label(":DLL_NOT_FOUND")
GetProcAddress32 += x86.Mov("EAX", 0xfffffffe)
GetProcAddress32 += x86.Jmp(":RETURN")
GetProcAddress32 += x86.Label(":API_NOT_FOUND")
GetProcAddress32 += x86.Pop("EAX")
GetProcAddress32 += x86.Mov("EAX", 0xffffffff)
GetProcAddress32 += x86.Jmp(":RETURN")
GetProcAddress32 += StrlenW32
GetProcAddress32 += StrlenA32