merge chao-mu's patches for railgun testing, fixes #4015, thanks!
git-svn-id: file:///home/svn/framework3/trunk@12697 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
f4b8b56883
commit
ad2880ce67
|
@ -43,6 +43,7 @@ class DLL
|
|||
include DLLHelper
|
||||
|
||||
attr_accessor :functions
|
||||
attr_reader :dll_path
|
||||
|
||||
def initialize(dll_path, client, win_consts) #
|
||||
@dll_path = dll_path
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
$:.unshift(File.join(File.dirname(__FILE__), '..', '..', '..','..','..','..','..', 'lib'))
|
||||
|
||||
require 'rex/post/meterpreter/extensions/stdapi/railgun/dll'
|
||||
require 'rex/post/meterpreter/extensions/stdapi/railgun/mock_magic'
|
||||
require 'test/unit'
|
||||
|
||||
module Rex
|
||||
|
@ -13,51 +14,10 @@ module Stdapi
|
|||
module Railgun
|
||||
class DLL::UnitTest < Test::Unit::TestCase
|
||||
|
||||
TLV_TYPE_NAMES = {
|
||||
TLV_TYPE_RAILGUN_SIZE_OUT => "TLV_TYPE_RAILGUN_SIZE_OUT",
|
||||
TLV_TYPE_RAILGUN_STACKBLOB => "TLV_TYPE_RAILGUN_STACKBLOB",
|
||||
TLV_TYPE_RAILGUN_BUFFERBLOB_IN => "TLV_TYPE_RAILGUN_BUFFERBLOB_IN",
|
||||
TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT => "TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT",
|
||||
TLV_TYPE_RAILGUN_DLLNAME => "TLV_TYPE_RAILGUN_DLLNAME",
|
||||
TLV_TYPE_RAILGUN_FUNCNAME => "TLV_TYPE_RAILGUN_FUNCNAME",
|
||||
}
|
||||
|
||||
class MockRailgunClient
|
||||
attr_reader :platform, :check_request, :response_tlvs
|
||||
|
||||
def initialize(platform, response_tlvs, check_request)
|
||||
@check_request = check_request
|
||||
@response_tlvs = response_tlvs
|
||||
@platform = platform
|
||||
end
|
||||
|
||||
def send_request(request)
|
||||
check_request.call(request)
|
||||
|
||||
(Class.new do
|
||||
def initialize(response_tlvs)
|
||||
@response_tlvs = response_tlvs
|
||||
end
|
||||
def get_tlv_value(type)
|
||||
return @response_tlvs[type]
|
||||
end
|
||||
end).new(@response_tlvs)
|
||||
end
|
||||
end
|
||||
|
||||
def make_mock_client(platform = "x86/win32", target_request_tlvs = [], response_tlvs = [])
|
||||
check_request = lambda do |request|
|
||||
target_request_tlvs.each_pair do |type, target_value|
|
||||
assert_equal(target_value, request.get_tlv_value(type),
|
||||
"process_function_call should send to client appropriate #{TLV_TYPE_NAMES[type]}")
|
||||
end
|
||||
end
|
||||
|
||||
return MockRailgunClient.new(platform, response_tlvs, check_request)
|
||||
end
|
||||
include MockMagic
|
||||
|
||||
def test_add_function
|
||||
function_descriptions.each do |func|
|
||||
mock_function_descriptions.each do |func|
|
||||
dll = DLL.new(func[:dll_name], make_mock_client(func[:platform]), nil)
|
||||
dll.add_function(func[:name], func[:return_type], func[:params])
|
||||
|
||||
|
@ -67,7 +27,7 @@ class DLL::UnitTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_method_missing
|
||||
function_descriptions.each do |func|
|
||||
mock_function_descriptions.each do |func|
|
||||
client = make_mock_client(func[:platform], func[:request_to_client], func[:response_from_client])
|
||||
dll = DLL.new(func[:dll_name], client, nil)
|
||||
|
||||
|
@ -82,90 +42,6 @@ class DLL::UnitTest < Test::Unit::TestCase
|
|||
"process_function_call convert function result to a ruby hash")
|
||||
end
|
||||
end
|
||||
|
||||
# These are sample descriptions of functions to use for testing.
|
||||
def function_descriptions
|
||||
[
|
||||
{
|
||||
:platform => "x86/win32",
|
||||
:name => "LookupAccountSidA",
|
||||
:params => [
|
||||
["PCHAR","lpSystemName","in"],
|
||||
["LPVOID","Sid","in"],
|
||||
["PCHAR","Name","out"],
|
||||
["PDWORD","cchName","inout"],
|
||||
["PCHAR","ReferencedDomainName","out"],
|
||||
["PDWORD","cchReferencedDomainName","inout"],
|
||||
["PBLOB","peUse","out"],
|
||||
],
|
||||
:return_type => "BOOL",
|
||||
:dll_name => "advapi32",
|
||||
:ruby_args => [nil, 1371864, 100, 100, 100, 100, 1],
|
||||
:request_to_client => {
|
||||
TLV_TYPE_RAILGUN_SIZE_OUT => 201,
|
||||
TLV_TYPE_RAILGUN_STACKBLOB => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xD8\xEE\x14\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00d\x00\x00\x00\x03\x00\x00\x00\b\x00\x00\x00\x02\x00\x00\x00\xC8\x00\x00\x00",
|
||||
TLV_TYPE_RAILGUN_BUFFERBLOB_IN => "",
|
||||
TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT => "d\x00\x00\x00\x00\x00\x00\x00d\x00\x00\x00\x00\x00\x00\x00",
|
||||
TLV_TYPE_RAILGUN_DLLNAME => "advapi32",
|
||||
TLV_TYPE_RAILGUN_FUNCNAME => "LookupAccountSidA"
|
||||
},
|
||||
:response_from_client => {
|
||||
TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_INOUT => "\x06\x00\x00\x00\x00\x00\x00\x00\f\x00\x00\x00\x00\x00\x00\x00",
|
||||
TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_OUT => "SYSTEM\x00AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANT AUTHORITY\x00AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x05",
|
||||
TLV_TYPE_RAILGUN_BACK_RET => 1,
|
||||
TLV_TYPE_RAILGUN_BACK_ERR => 997
|
||||
},
|
||||
:returned_hash => {
|
||||
"GetLastError" => 997,
|
||||
"return" => true,
|
||||
"Name" => "SYSTEM",
|
||||
"ReferencedDomainName" => "NT AUTHORITY",
|
||||
"peUse" => "\x05",
|
||||
"cchName" => 6,
|
||||
"cchReferencedDomainName" => 12
|
||||
},
|
||||
},
|
||||
{
|
||||
:platform => 'x64/win64',
|
||||
:name => 'LookupAccountSidA',
|
||||
:params => [
|
||||
["PCHAR", "lpSystemName", "in"],
|
||||
["LPVOID", "Sid", "in"],
|
||||
["PCHAR", "Name", "out"],
|
||||
["PDWORD", "cchName", "inout"],
|
||||
["PCHAR", "ReferencedDomainName", "out"],
|
||||
["PDWORD", "cchReferencedDomainName", "inout"],
|
||||
["PBLOB", "peUse", "out"]
|
||||
],
|
||||
:return_type => 'BOOL',
|
||||
:dll_name => 'advapi32',
|
||||
:ruby_args => [nil, 1631552, 100, 100, 100, 100, 1],
|
||||
:request_to_client => {
|
||||
TLV_TYPE_RAILGUN_SIZE_OUT => 201,
|
||||
TLV_TYPE_RAILGUN_STACKBLOB => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\xE5\x18\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00d\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\b\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\xC8\x00\x00\x00\x00\x00\x00\x00",
|
||||
TLV_TYPE_RAILGUN_BUFFERBLOB_IN => "",
|
||||
TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT => "d\x00\x00\x00\x00\x00\x00\x00d\x00\x00\x00\x00\x00\x00\x00",
|
||||
TLV_TYPE_RAILGUN_DLLNAME => 'advapi32',
|
||||
TLV_TYPE_RAILGUN_FUNCNAME => 'LookupAccountSidA',
|
||||
},
|
||||
:response_from_client => {
|
||||
TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_INOUT => "\x06\x00\x00\x00\x00\x00\x00\x00\f\x00\x00\x00\x00\x00\x00\x00",
|
||||
TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_OUT => "SYSTEM\x00AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANT AUTHORITY\x00AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x05",
|
||||
TLV_TYPE_RAILGUN_BACK_RET => 1,
|
||||
TLV_TYPE_RAILGUN_BACK_ERR => 0,
|
||||
},
|
||||
:returned_hash => {
|
||||
"GetLastError"=>0,
|
||||
"return"=>true,
|
||||
"Name"=>"SYSTEM",
|
||||
"ReferencedDomainName"=>"NT AUTHORITY",
|
||||
"peUse"=>"\x05",
|
||||
"cchName"=>6,
|
||||
"cchReferencedDomainName"=>12
|
||||
},
|
||||
},
|
||||
]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,146 @@
|
|||
module Rex
|
||||
module Post
|
||||
module Meterpreter
|
||||
module Extensions
|
||||
module Stdapi
|
||||
module Railgun
|
||||
|
||||
require 'rex/post/meterpreter/extensions/stdapi/railgun/tlv'
|
||||
|
||||
#
|
||||
# This mixin serves as a means of providing common mock objects and utilities
|
||||
# relevant to railgun until a better home is decided upon
|
||||
#
|
||||
module MockMagic
|
||||
|
||||
TLV_TYPE_NAMES = {
|
||||
TLV_TYPE_RAILGUN_SIZE_OUT => "TLV_TYPE_RAILGUN_SIZE_OUT",
|
||||
TLV_TYPE_RAILGUN_STACKBLOB => "TLV_TYPE_RAILGUN_STACKBLOB",
|
||||
TLV_TYPE_RAILGUN_BUFFERBLOB_IN => "TLV_TYPE_RAILGUN_BUFFERBLOB_IN",
|
||||
TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT => "TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT",
|
||||
TLV_TYPE_RAILGUN_DLLNAME => "TLV_TYPE_RAILGUN_DLLNAME",
|
||||
TLV_TYPE_RAILGUN_FUNCNAME => "TLV_TYPE_RAILGUN_FUNCNAME",
|
||||
}
|
||||
|
||||
class MockRailgunClient
|
||||
attr_reader :platform, :check_request, :response_tlvs
|
||||
|
||||
def initialize(platform, response_tlvs, check_request)
|
||||
@check_request = check_request
|
||||
@response_tlvs = response_tlvs
|
||||
@platform = platform
|
||||
end
|
||||
|
||||
def send_request(request)
|
||||
check_request.call(request)
|
||||
|
||||
(Class.new do
|
||||
def initialize(response_tlvs)
|
||||
@response_tlvs = response_tlvs
|
||||
end
|
||||
def get_tlv_value(type)
|
||||
return @response_tlvs[type]
|
||||
end
|
||||
end).new(@response_tlvs)
|
||||
end
|
||||
end
|
||||
|
||||
def make_mock_client(platform = "x86/win32", target_request_tlvs = [], response_tlvs = [])
|
||||
check_request = lambda do |request|
|
||||
target_request_tlvs.each_pair do |type, target_value|
|
||||
assert_equal(target_value, request.get_tlv_value(type),
|
||||
"process_function_call should send to client appropriate #{TLV_TYPE_NAMES[type]}")
|
||||
end
|
||||
end
|
||||
|
||||
return MockRailgunClient.new(platform, response_tlvs, check_request)
|
||||
end
|
||||
|
||||
# These are sample descriptions of functions to use for testing.
|
||||
# the definitions include everything needed to mock and end to end test
|
||||
def mock_function_descriptions
|
||||
[
|
||||
{
|
||||
:platform => "x86/win32",
|
||||
:name => "LookupAccountSidA",
|
||||
:params => [
|
||||
["PCHAR","lpSystemName","in"],
|
||||
["LPVOID","Sid","in"],
|
||||
["PCHAR","Name","out"],
|
||||
["PDWORD","cchName","inout"],
|
||||
["PCHAR","ReferencedDomainName","out"],
|
||||
["PDWORD","cchReferencedDomainName","inout"],
|
||||
["PBLOB","peUse","out"],
|
||||
],
|
||||
:return_type => "BOOL",
|
||||
:dll_name => "advapi32",
|
||||
:ruby_args => [nil, 1371864, 100, 100, 100, 100, 1],
|
||||
:request_to_client => {
|
||||
TLV_TYPE_RAILGUN_SIZE_OUT => 201,
|
||||
TLV_TYPE_RAILGUN_STACKBLOB => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xD8\xEE\x14\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00d\x00\x00\x00\x03\x00\x00\x00\b\x00\x00\x00\x02\x00\x00\x00\xC8\x00\x00\x00",
|
||||
TLV_TYPE_RAILGUN_BUFFERBLOB_IN => "",
|
||||
TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT => "d\x00\x00\x00\x00\x00\x00\x00d\x00\x00\x00\x00\x00\x00\x00",
|
||||
TLV_TYPE_RAILGUN_DLLNAME => "advapi32",
|
||||
TLV_TYPE_RAILGUN_FUNCNAME => "LookupAccountSidA"
|
||||
},
|
||||
:response_from_client => {
|
||||
TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_INOUT => "\x06\x00\x00\x00\x00\x00\x00\x00\f\x00\x00\x00\x00\x00\x00\x00",
|
||||
TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_OUT => "SYSTEM\x00AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANT AUTHORITY\x00AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x05",
|
||||
TLV_TYPE_RAILGUN_BACK_RET => 1,
|
||||
TLV_TYPE_RAILGUN_BACK_ERR => 997
|
||||
},
|
||||
:returned_hash => {
|
||||
"GetLastError" => 997,
|
||||
"return" => true,
|
||||
"Name" => "SYSTEM",
|
||||
"ReferencedDomainName" => "NT AUTHORITY",
|
||||
"peUse" => "\x05",
|
||||
"cchName" => 6,
|
||||
"cchReferencedDomainName" => 12
|
||||
},
|
||||
},
|
||||
{
|
||||
:platform => 'x64/win64',
|
||||
:name => 'LookupAccountSidA',
|
||||
:params => [
|
||||
["PCHAR", "lpSystemName", "in"],
|
||||
["LPVOID", "Sid", "in"],
|
||||
["PCHAR", "Name", "out"],
|
||||
["PDWORD", "cchName", "inout"],
|
||||
["PCHAR", "ReferencedDomainName", "out"],
|
||||
["PDWORD", "cchReferencedDomainName", "inout"],
|
||||
["PBLOB", "peUse", "out"]
|
||||
],
|
||||
:return_type => 'BOOL',
|
||||
:dll_name => 'advapi32',
|
||||
:ruby_args => [nil, 1631552, 100, 100, 100, 100, 1],
|
||||
:request_to_client => {
|
||||
TLV_TYPE_RAILGUN_SIZE_OUT => 201,
|
||||
TLV_TYPE_RAILGUN_STACKBLOB => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\xE5\x18\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00d\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\b\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\xC8\x00\x00\x00\x00\x00\x00\x00",
|
||||
TLV_TYPE_RAILGUN_BUFFERBLOB_IN => "",
|
||||
TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT => "d\x00\x00\x00\x00\x00\x00\x00d\x00\x00\x00\x00\x00\x00\x00",
|
||||
TLV_TYPE_RAILGUN_DLLNAME => 'advapi32',
|
||||
TLV_TYPE_RAILGUN_FUNCNAME => 'LookupAccountSidA',
|
||||
},
|
||||
:response_from_client => {
|
||||
TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_INOUT => "\x06\x00\x00\x00\x00\x00\x00\x00\f\x00\x00\x00\x00\x00\x00\x00",
|
||||
TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_OUT => "SYSTEM\x00AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANT AUTHORITY\x00AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x05",
|
||||
TLV_TYPE_RAILGUN_BACK_RET => 1,
|
||||
TLV_TYPE_RAILGUN_BACK_ERR => 0,
|
||||
},
|
||||
:returned_hash => {
|
||||
"GetLastError"=>0,
|
||||
"return"=>true,
|
||||
"Name"=>"SYSTEM",
|
||||
"ReferencedDomainName"=>"NT AUTHORITY",
|
||||
"peUse"=>"\x05",
|
||||
"cchName"=>6,
|
||||
"cchReferencedDomainName"=>12
|
||||
},
|
||||
},
|
||||
]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end; end; end; end; end; end;
|
|
@ -0,0 +1,63 @@
|
|||
#!/usr/bin/env rubyj
|
||||
|
||||
$:.unshift(File.join(File.dirname(__FILE__), '..', '..', '..','..','..','..','..', 'lib'))
|
||||
|
||||
require 'rex/post/meterpreter/extensions/stdapi/railgun/railgun'
|
||||
require 'rex/post/meterpreter/extensions/stdapi/railgun/mock_magic'
|
||||
require 'test/unit'
|
||||
require 'benchmark'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
module Meterpreter
|
||||
module Extensions
|
||||
module Stdapi
|
||||
module Railgun
|
||||
class Railgun::UnitTest < Test::Unit::TestCase
|
||||
|
||||
include MockMagic
|
||||
|
||||
def test_add_dll
|
||||
railgun = Railgun.new(make_mock_client())
|
||||
|
||||
target_dll_name = 'discordia'
|
||||
target_windows_name = 'C:\look\behind\you'
|
||||
|
||||
railgun.add_dll(target_dll_name, target_windows_name)
|
||||
|
||||
actual_dll = railgun.get_dll(target_dll_name);
|
||||
|
||||
assert_not_nil(actual_dll,
|
||||
"add_dll should make a DLL accessible via get_dll")
|
||||
|
||||
assert_equal(actual_dll.dll_path, target_windows_name,
|
||||
"add_dll should set a dll path when specified")
|
||||
|
||||
#
|
||||
# wrapper = railgun.send(target_dll_name.to_sym)
|
||||
#
|
||||
# assert_same(wrapper._dll, actual_dll,
|
||||
# "railgun instance responds with dll wrapper as expected")
|
||||
end
|
||||
|
||||
def test_add_function
|
||||
mock_function_descriptions.each do |func|
|
||||
railgun = Railgun.new(make_mock_client(func[:platform]))
|
||||
|
||||
dll_name = func[:dll_name]
|
||||
function_name = func[:name]
|
||||
|
||||
railgun.add_dll(dll_name)
|
||||
railgun.add_function(dll_name, function_name, func[:return_type], func[:params])
|
||||
|
||||
assert(railgun.get_dll(dll_name).functions.has_key?(function_name),
|
||||
"add_function should add a function to the DLL specified")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue