I'm trying to use ruby Fiddle standard library to Windows APIs to run a shellcode
The idea of the code is to
- having a hexdicemial shellcode raw that executes anything (eg. MessageBoxA)
- call
kernel32.dll
- allocate a memory for this shellcode.
VirtualAlloc
- create a buffer for this shellcode
- move the shellcode to that allocation.
RtlMoveMemory
- create a new thread to execute that shellcode.
CreateThread
- wait for the execution/thread to end.
WaitForSingleObject
here is the code:
require 'fiddle'
require 'fiddle/import'
require 'fiddle/types'
shellcode = # MessageBoxA
"\x31\xd2\xb2\x30\x64\x8b\x12\x8b\x52\x0c\x8b\x52\x1c\x8b\x42" +
"\x08\x8b\x72\x20\x8b\x12\x80\x7e\x0c\x33\x75\xf2\x89\xc7\x03" +
"\x78\x3c\x8b\x57\x78\x01\xc2\x8b\x7a\x20\x01\xc7\x31\xed\x8b" +
"\x34\xaf\x01\xc6\x45\x81\x3e\x46\x61\x74\x61\x75\xf2\x81\x7e" +
"\x08\x45\x78\x69\x74\x75\xe9\x8b\x7a\x24\x01\xc7\x66\x8b\x2c" +
"\x6f\x8b\x7a\x1c\x01\xc7\x8b\x7c\xaf\xfc\x01\xc7\x68\x79\x74" +
"\x65\x01\x68\x6b\x65\x6e\x42\x68\x20\x42\x72\x6f\x89\xe1\xfe" +
"\x49\x0b\x31\xc0\x51\x50\xff\xd7"
include Fiddle
kernel32 = Fiddle.dlopen('kernel32')
puts "[-] VirtualAlloc"
ptr = Function.new(kernel32['VirtualAlloc'], [4,4,4,4], 4).call(0, (shellcode.size), 0x3000, 0x40)
Function.new(kernel32['VirtualProtect'], [4,4,4,4], 4).call(ptr, shellcode.size, 0, 0)
puts "[-] Create buffer"
buf = Fiddle::Pointer[shellcode]
puts "[-] RtlMoveMemory"
Function.new(kernel32['RtlMoveMemory'], [4, 4, 4], 4).call(ptr, buf, shellcode.size)
puts "[-] CreateThread"
# thread = Function.new(kernel32['CreateThread'], [4, 4, 4, 4, 4, -4], 4).call(0, 0, ptr, 0, 0, 0)
thread = Function.new(kernel32['CreateThread'], [4,4,4,4,4,4], 4).call(Fiddle::NULL, 0, ptr, 0, 0, 0)
pp Function.new(kernel32['WaitForSingleObject'], [4,4], 4).call(thread, -1)
The problem is the MessageBoxA never get executed, when I try to something like a bind shell, the TCP connection starts successfully when I connect but I can't execute commands and it ends once I send anything twice like pressing enter twice.
I checked the buffer buf
size and contents buf.size
, buf.to_str
and it's accurate.
Am I missing something here?
Thanks!
Note: I don't want to call the MessageBoxA API directly I need to execute it from the shellcode.