metasploit-framework/lib/rex/compat.rb

157 lines
2.8 KiB
Ruby
Raw Normal View History

require 'dl'
module Rex
###
#
# This class provides os-specific functionality
#
###
module Compat
STD_INPUT_HANDLE = -10
ENABLE_LINE_INPUT = 2
ENABLE_ECHO_INPUT = 4
ENABLE_PROCESSED_INPUT = 1
def self.win32_stdin_unblock
begin
@@k32 ||= DL.dlopen("kernel32.dll")
gsh = @@k32['GetStdHandle', 'LL']
gcm = @@k32['GetConsoleMode', 'LLP']
scm = @@k32['SetConsoleMode', 'LLL']
inp = gsh.call(STD_INPUT_HANDLE)[0]
inf = DL.malloc(DL.sizeof('L'))
gcm.call(inp, inf)
old_mode = inf.to_a('L', 1)[0]
new_mode = old_mode & ~(ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT|ENABLE_PROCESSED_INPUT)
scm.call(inp, new_mode)
rescue ::Exception
raise $!
end
end
def self.win32_stdin_block
begin
@@k32 ||= DL.dlopen("kernel32.dll")
gsh = @@k32['GetStdHandle', 'LL']
gcm = @@k32['GetConsoleMode', 'LLP']
scm = @@k32['SetConsoleMode', 'LLL']
inp = gsh.call(STD_INPUT_HANDLE)[0]
inf = DL.malloc(DL.sizeof('L'))
gcm.call(inp, inf)
old_mode = inf.to_a('L', 1)[0]
new_mode = old_mode | ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT
scm.call(inp, new_mode)
rescue ::Exception
raise $!
end
end
def self.win32_ruby_path
begin
@@k32 ||= DL.dlopen("kernel32.dll")
gmh = @@k32['GetModuleHandle', 'LP']
gmf = @@k32['GetModuleFileName', 'LLPL']
mod = gmh.call(nil)[0]
inf = DL.malloc(1024)
gmf.call(mod, inf, 1024)
return inf.to_s
rescue ::Exception
raise $!
end
end
def self.win32_winexec(cmd)
begin
@@k32 ||= DL.dlopen("kernel32.dll")
win = @@k32['WinExec', 'LPL']
win.call(cmd.to_ptr, 0)
rescue ::Exception
raise $!
end
end
=begin
BOOL WINAPI ReadConsole(
HANDLE hConsoleInput,
LPVOID lpBuffer,
DWORD nNumberOfCharsToRead,
LPDWORD lpNumberOfCharsRead,
LPVOID lpReserved
);
=end
def self.win32_stdin_read
begin
@@k32 ||= DL.dlopen("kernel32.dll")
gsh = @@k32['GetStdHandle', 'LL']
rco = @@k32['ReadConsole', 'LLPLPL']
inp = gsh.call(STD_INPUT_HANDLE)[0]
buf = DL.malloc(512)
num = DL.malloc(DL.sizeof('L'))
rco.call(inp, buf, 512, num, 0)
buf.to_s
rescue ::Exception
raise $!
end
end
def self.win32_readline_daemon
serv = nil
port = 1024
while (! serv and port < 65535)
begin
serv = TCPServer.new('127.0.0.1', (port += 1))
rescue ::Exception
end
end
path = win32_ruby_path()
rubyw = File.join(File.dirname(path.to_s), "ruby.exe")
helpr = File.join(File.dirname(__FILE__), 'win32_stdio.rb')
win32_winexec( [rubyw, helpr, port.to_s].join(" ") )
# Accept the forked child
clnt = serv.accept
# Shutdown the server
serv.close
# Replace stdin with the socket
$stdin.reopen(clnt)
# Thread monitor
Thread.new do
cnt = 0
lst = Time.now.to_i
while(true)
select(nil,nil,nil,3)
cnt +=1
now = Time.now.to_i
if (now - lst > 3)
$stderr.puts "---= monitor lost #{ (now-lst).to_s } seconds"
end
lst = now
end
end
end
end
end