merge chao-mu's patches for railgun testing, fixes #4015, thanks!

git-svn-id: file:///home/svn/framework3/trunk@12697 4d416f70-5f16-0410-b530-b9f4589650da
unstable
James Lee 2011-05-23 22:20:45 +00:00
parent f4b8b56883
commit ad2880ce67
4 changed files with 214 additions and 128 deletions

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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