# -*- coding: binary -*-
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/windows", 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/windows",
        :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/windows',
        :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
        },
      },
      {
        :platform => 'x86/windows',
        :name => 'CryptAcquireContextW',
        :params => [["PDWORD", "phProv", "out"], ["PWCHAR", "pszContainer", "in"], ["PWCHAR", "pszProvider", "in"], ["DWORD", "dwProvType", "in"], ["DWORD", "dwflags", "in"]],
        :return_type => 'BOOL',
        :dll_name => 'advapi32',
        :ruby_args => [4, nil, "Microsoft Enhanced Cryptographic Provider v1.0", 1, 4026531840],
        :request_to_client => {
          TLV_TYPE_RAILGUN_SIZE_OUT => 4,
          TLV_TYPE_RAILGUN_STACKBLOB => "\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xF0",
          TLV_TYPE_RAILGUN_BUFFERBLOB_IN => "M\x00i\x00c\x00r\x00o\x00s\x00o\x00f\x00t\x00 \x00E\x00n\x00h\x00a\x00n\x00c\x00e\x00d\x00 \x00C\x00r\x00y\x00p\x00t\x00o\x00g\x00r\x00a\x00p\x00h\x00i\x00c\x00 \x00P\x00r\x00o\x00v\x00i\x00d\x00e\x00r\x00 \x00v\x001\x00.\x000\x00\x00\x00\x00\x00",
          TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT => "",
          TLV_TYPE_RAILGUN_DLLNAME => 'advapi32',
          TLV_TYPE_RAILGUN_FUNCNAME => 'CryptAcquireContextW',
        },
        :response_from_client => {
          TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_INOUT => "",
          TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_OUT => "\xC8\xEB\x14\x00",
          TLV_TYPE_RAILGUN_BACK_RET => 1,
          TLV_TYPE_RAILGUN_BACK_ERR => 0,
        },
        :returned_hash => {"GetLastError"=>0, "return"=>true, "phProv"=>1371080},
      },
      {
        :platform => 'x86/windows',
        :name => 'CryptCreateHash',
        :params => [["LPVOID", "hProv", "in"], ["DWORD", "Algid", "in"], ["LPVOID", "hKey", "in"], ["DWORD", "dwFlags", "in"], ["PDWORD", "phHash", "out"]],
        :return_type => 'BOOL',
        :dll_name => 'advapi32',
        :ruby_args => [1371080, 32771, 0, 0, 4],
        :request_to_client => {
          TLV_TYPE_RAILGUN_SIZE_OUT => 4,
          TLV_TYPE_RAILGUN_STACKBLOB => "\x00\x00\x00\x00\xC8\xEB\x14\x00\x00\x00\x00\x00\x03\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00",
          TLV_TYPE_RAILGUN_BUFFERBLOB_IN => "",
          TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT => "",
          TLV_TYPE_RAILGUN_DLLNAME => 'advapi32',
          TLV_TYPE_RAILGUN_FUNCNAME => 'CryptCreateHash',
        },
        :response_from_client => {
          TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_INOUT => "",
          TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_OUT => "p\xEA\x14\x00",
          TLV_TYPE_RAILGUN_BACK_RET => 1,
          TLV_TYPE_RAILGUN_BACK_ERR => 0,
        },
        :returned_hash => {"GetLastError"=>0, "return"=>true, "phHash"=>1370736},
      },
      {
        :platform => 'x86/windows',
        :name => 'CryptHashData',
        :params => [["LPVOID", "hHash", "in"], ["PWCHAR", "pbData", "in"], ["DWORD", "dwDataLen", "in"], ["DWORD", "dwFlags", "in"]],
        :return_type => 'BOOL',
        :dll_name => 'advapi32',
        :ruby_args => [1370736, "SmartFTP", 16, 0],
        :request_to_client => {
          TLV_TYPE_RAILGUN_SIZE_OUT => 0,
          TLV_TYPE_RAILGUN_STACKBLOB => "\x00\x00\x00\x00p\xEA\x14\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
          TLV_TYPE_RAILGUN_BUFFERBLOB_IN => "S\x00m\x00a\x00r\x00t\x00F\x00T\x00P\x00\x00\x00\x00\x00\x00\x00\x00\x00",
          TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT => "",
          TLV_TYPE_RAILGUN_DLLNAME => 'advapi32',
          TLV_TYPE_RAILGUN_FUNCNAME => 'CryptHashData',
        },
        :response_from_client => {
          TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_INOUT => "",
          TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_OUT => "",
          TLV_TYPE_RAILGUN_BACK_RET => 1,
          TLV_TYPE_RAILGUN_BACK_ERR => 0,
        },
        :returned_hash => {"GetLastError"=>0, "return"=>true},
      },
      {
        :platform => 'x86/windows',
        :name => 'CryptDeriveKey',
        :params => [["LPVOID", "hProv", "in"], ["DWORD", "Algid", "in"], ["LPVOID", "hBaseData", "in"], ["DWORD", "dwFlags", "in"], ["PDWORD", "phKey", "inout"]],
        :return_type => 'BOOL',
        :dll_name => 'advapi32',
        :ruby_args => [1371080, 26625, 1370736, 8388608, 4],
        :request_to_client => {
          TLV_TYPE_RAILGUN_SIZE_OUT => 0,
          TLV_TYPE_RAILGUN_STACKBLOB => "\x00\x00\x00\x00\xC8\xEB\x14\x00\x00\x00\x00\x00\x01h\x00\x00\x00\x00\x00\x00p\xEA\x14\x00\x00\x00\x00\x00\x00\x00\x80\x00\x03\x00\x00\x00\x00\x00\x00\x00",
          TLV_TYPE_RAILGUN_BUFFERBLOB_IN => "",
          TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT => "\x04\x00\x00\x00\x00\x00\x00\x00",
          TLV_TYPE_RAILGUN_DLLNAME => 'advapi32',
          TLV_TYPE_RAILGUN_FUNCNAME => 'CryptDeriveKey',
        },
        :response_from_client => {
          TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_INOUT => "\xA0\x9C\x15\x00\x00\x00\x00\x00",
          TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_OUT => "",
          TLV_TYPE_RAILGUN_BACK_RET => 1,
          TLV_TYPE_RAILGUN_BACK_ERR => 0,
        },
        :returned_hash => {"GetLastError"=>0, "return"=>true, "phKey"=>1416352},
      },
      {
        :platform => 'x86/windows',
        :name => 'CryptDecrypt',
        :params => [["LPVOID", "hKey", "in"], ["LPVOID", "hHash", "in"], ["BOOL", "Final", "in"], ["DWORD", "dwFlags", "in"], ["PBLOB", "pbData", "inout"], ["PDWORD", "pdwDataLen", "inout"]],
        :return_type => 'BOOL',
        :dll_name => 'advapi32',
        :ruby_args => [1416352, 0, true, 0, "\x96\"\x83/\xCE|", 6],
        :request_to_client => {
          TLV_TYPE_RAILGUN_SIZE_OUT => 0,
          TLV_TYPE_RAILGUN_STACKBLOB => "\x00\x00\x00\x00\xA0\x9C\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\b\x00\x00\x00",
          TLV_TYPE_RAILGUN_BUFFERBLOB_IN => "",
          TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT => "\x96\"\x83/\xCE|\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00",
          TLV_TYPE_RAILGUN_DLLNAME => 'advapi32',
          TLV_TYPE_RAILGUN_FUNCNAME => 'CryptDecrypt',
        },
        :response_from_client => {
          TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_INOUT => "q\x00u\x00x\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00",
          TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_OUT => "",
          TLV_TYPE_RAILGUN_BACK_RET => 1,
          TLV_TYPE_RAILGUN_BACK_ERR => 0,
        },
        :returned_hash => {"GetLastError"=>0, "return"=>true, "pbData"=>"q\x00u\x00x\x00", "pdwDataLen"=>6},
      },
      {
        :platform => 'x86/windows',
        :name => 'CryptDestroyHash',
        :params => [["LPVOID", "hHash", "in"]],
        :return_type => 'BOOL',
        :dll_name => 'advapi32',
        :ruby_args => [1370736],
        :request_to_client => {
          TLV_TYPE_RAILGUN_SIZE_OUT => 0,
          TLV_TYPE_RAILGUN_STACKBLOB => "\x00\x00\x00\x00p\xEA\x14\x00",
          TLV_TYPE_RAILGUN_BUFFERBLOB_IN => "",
          TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT => "",
          TLV_TYPE_RAILGUN_DLLNAME => 'advapi32',
          TLV_TYPE_RAILGUN_FUNCNAME => 'CryptDestroyHash',
        },
        :response_from_client => {
          TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_INOUT => "",
          TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_OUT => "",
          TLV_TYPE_RAILGUN_BACK_RET => 1,
          TLV_TYPE_RAILGUN_BACK_ERR => 0,
        },
        :returned_hash => {"GetLastError"=>0, "return"=>true},
      },
      {
        :platform => 'x86/windows',
        :name => 'CryptDestroyKey',
        :params => [["LPVOID", "hKey", "in"]],
        :return_type => 'BOOL',
        :dll_name => 'advapi32',
        :ruby_args => [1416352],
        :request_to_client => {
          TLV_TYPE_RAILGUN_SIZE_OUT => 0,
          TLV_TYPE_RAILGUN_STACKBLOB => "\x00\x00\x00\x00\xA0\x9C\x15\x00",
          TLV_TYPE_RAILGUN_BUFFERBLOB_IN => "",
          TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT => "",
          TLV_TYPE_RAILGUN_DLLNAME => 'advapi32',
          TLV_TYPE_RAILGUN_FUNCNAME => 'CryptDestroyKey',
        },
        :response_from_client => {
          TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_INOUT => "",
          TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_OUT => "",
          TLV_TYPE_RAILGUN_BACK_RET => 1,
          TLV_TYPE_RAILGUN_BACK_ERR => 0,
        },
        :returned_hash => {"GetLastError"=>0, "return"=>true},
      },
      {
        :platform => 'x86/windows',
        :name => 'CryptReleaseContext',
        :params => [["LPVOID", "hProv", "in"], ["DWORD", "dwFlags", "in"]],
        :return_type => 'BOOL',
        :dll_name => 'advapi32',
        :ruby_args => [1371080, 0],
        :request_to_client => {
          TLV_TYPE_RAILGUN_SIZE_OUT => 0,
          TLV_TYPE_RAILGUN_STACKBLOB => "\x00\x00\x00\x00\xC8\xEB\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00",
          TLV_TYPE_RAILGUN_BUFFERBLOB_IN => "",
          TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT => "",
          TLV_TYPE_RAILGUN_DLLNAME => 'advapi32',
          TLV_TYPE_RAILGUN_FUNCNAME => 'CryptReleaseContext',
        },
        :response_from_client => {
          TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_INOUT => "",
          TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_OUT => "",
          TLV_TYPE_RAILGUN_BACK_RET => 1,
          TLV_TYPE_RAILGUN_BACK_ERR => 0,
        },
        :returned_hash => {"GetLastError"=>0, "return"=>true},
      },
      {
        :platform => 'x64/windows',
        :name => 'CryptAcquireContextW',
        :params => [["PDWORD", "phProv", "out"], ["PWCHAR", "pszContainer", "in"], ["PWCHAR", "pszProvider", "in"], ["DWORD", "dwProvType", "in"], ["DWORD", "dwflags", "in"]],
        :return_type => 'BOOL',
        :dll_name => 'advapi32',
        :ruby_args => [8, nil, "Microsoft Enhanced Cryptographic Provider v1.0", 1, 4026531840],
        :request_to_client => {
          TLV_TYPE_RAILGUN_SIZE_OUT => 8,
          TLV_TYPE_RAILGUN_STACKBLOB => "\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xF0\x00\x00\x00\x00",
          TLV_TYPE_RAILGUN_BUFFERBLOB_IN => "M\x00i\x00c\x00r\x00o\x00s\x00o\x00f\x00t\x00 \x00E\x00n\x00h\x00a\x00n\x00c\x00e\x00d\x00 \x00C\x00r\x00y\x00p\x00t\x00o\x00g\x00r\x00a\x00p\x00h\x00i\x00c\x00 \x00P\x00r\x00o\x00v\x00i\x00d\x00e\x00r\x00 \x00v\x001\x00.\x000\x00\x00\x00\x00\x00",
          TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT => "",
          TLV_TYPE_RAILGUN_DLLNAME => 'advapi32',
          TLV_TYPE_RAILGUN_FUNCNAME => 'CryptAcquireContextW',
        },
        :response_from_client => {
          TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_INOUT => "",
          TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_OUT => "\x80\xCE\x1A\x00\x00\x00\x00\x00",
          TLV_TYPE_RAILGUN_BACK_RET => 1,
          TLV_TYPE_RAILGUN_BACK_ERR => 0,
        },
        :returned_hash => {"GetLastError"=>0, "return"=>true, "phProv"=>1756800},
      },
      {
        :platform => 'x64/windows',
        :name => 'CryptCreateHash',
        :params => [["LPVOID", "hProv", "in"], ["DWORD", "Algid", "in"], ["LPVOID", "hKey", "in"], ["DWORD", "dwFlags", "in"], ["PDWORD", "phHash", "out"]],
        :return_type => 'BOOL',
        :dll_name => 'advapi32',
        :ruby_args => [1756800, 32771, 0, 0, 8],
        :request_to_client => {
          TLV_TYPE_RAILGUN_SIZE_OUT => 8,
          TLV_TYPE_RAILGUN_STACKBLOB => "\x00\x00\x00\x00\x00\x00\x00\x00\x80\xCE\x1A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
          TLV_TYPE_RAILGUN_BUFFERBLOB_IN => "",
          TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT => "",
          TLV_TYPE_RAILGUN_DLLNAME => 'advapi32',
          TLV_TYPE_RAILGUN_FUNCNAME => 'CryptCreateHash',
        },
        :response_from_client => {
          TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_INOUT => "",
          TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_OUT => "\x00\xA3\x19\x00\x00\x00\x00\x00",
          TLV_TYPE_RAILGUN_BACK_RET => 1,
          TLV_TYPE_RAILGUN_BACK_ERR => 0,
        },
        :returned_hash => {"GetLastError"=>0, "return"=>true, "phHash"=>1680128},
      },
      {
        :platform => 'x64/windows',
        :name => 'CryptHashData',
        :params => [["LPVOID", "hHash", "in"], ["PWCHAR", "pbData", "in"], ["DWORD", "dwDataLen", "in"], ["DWORD", "dwFlags", "in"]],
        :return_type => 'BOOL',
        :dll_name => 'advapi32',
        :ruby_args => [1680128, "SmartFTP", 16, 0],
        :request_to_client => {
          TLV_TYPE_RAILGUN_SIZE_OUT => 0,
          TLV_TYPE_RAILGUN_STACKBLOB => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\xA3\x19\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
          TLV_TYPE_RAILGUN_BUFFERBLOB_IN => "S\x00m\x00a\x00r\x00t\x00F\x00T\x00P\x00\x00\x00\x00\x00\x00\x00\x00\x00",
          TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT => "",
          TLV_TYPE_RAILGUN_DLLNAME => 'advapi32',
          TLV_TYPE_RAILGUN_FUNCNAME => 'CryptHashData',
        },
        :response_from_client => {
          TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_INOUT => "",
          TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_OUT => "",
          TLV_TYPE_RAILGUN_BACK_RET => 1,
          TLV_TYPE_RAILGUN_BACK_ERR => 0,
        },
        :returned_hash => {"GetLastError"=>0, "return"=>true},
      },
      {
        :platform => 'x64/windows',
        :name => 'CryptDeriveKey',
        :params => [["LPVOID", "hProv", "in"], ["DWORD", "Algid", "in"], ["LPVOID", "hBaseData", "in"], ["DWORD", "dwFlags", "in"], ["PDWORD", "phKey", "inout"]],
        :return_type => 'BOOL',
        :dll_name => 'advapi32',
        :ruby_args => [1756800, 26625, 1680128, 8388608, 4],
        :request_to_client => {
          TLV_TYPE_RAILGUN_SIZE_OUT => 0,
          TLV_TYPE_RAILGUN_STACKBLOB => "\x00\x00\x00\x00\x00\x00\x00\x00\x80\xCE\x1A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01h\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xA3\x19\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
          TLV_TYPE_RAILGUN_BUFFERBLOB_IN => "",
          TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT => "\x04\x00\x00\x00\x00\x00\x00\x00",
          TLV_TYPE_RAILGUN_DLLNAME => 'advapi32',
          TLV_TYPE_RAILGUN_FUNCNAME => 'CryptDeriveKey',
        },
        :response_from_client => {
          TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_INOUT => "p\xA3\x19\x00\x00\x00\x00\x00",
          TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_OUT => "",
          TLV_TYPE_RAILGUN_BACK_RET => 1,
          TLV_TYPE_RAILGUN_BACK_ERR => 0,
        },
        :returned_hash => {"GetLastError"=>0, "return"=>true, "phKey"=>1680240},
      },
      {
        :platform => 'x64/windows',
        :name => 'CryptDecrypt',
        :params => [["LPVOID", "hKey", "in"], ["LPVOID", "hHash", "in"], ["BOOL", "Final", "in"], ["DWORD", "dwFlags", "in"], ["PBLOB", "pbData", "inout"], ["PDWORD", "pdwDataLen", "inout"]],
        :return_type => 'BOOL',
        :dll_name => 'advapi32',
        :ruby_args => [1680240, 0, true, 0, "\x85\"\x97/\xCC|", 6],
        :request_to_client => {
          TLV_TYPE_RAILGUN_SIZE_OUT => 0,
          TLV_TYPE_RAILGUN_STACKBLOB => "\x00\x00\x00\x00\x00\x00\x00\x00p\xA3\x19\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\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\x03\x00\x00\x00\x00\x00\x00\x00\b\x00\x00\x00\x00\x00\x00\x00",
          TLV_TYPE_RAILGUN_BUFFERBLOB_IN => "",
          TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT => "\x85\"\x97/\xCC|\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00",
          TLV_TYPE_RAILGUN_DLLNAME => 'advapi32',
          TLV_TYPE_RAILGUN_FUNCNAME => 'CryptDecrypt',
        },
        :response_from_client => {
          TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_INOUT => "b\x00a\x00z\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00",
          TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_OUT => "",
          TLV_TYPE_RAILGUN_BACK_RET => 1,
          TLV_TYPE_RAILGUN_BACK_ERR => 0,
        },
        :returned_hash => {"GetLastError"=>0, "return"=>true, "pbData"=>"b\x00a\x00z\x00", "pdwDataLen"=>6},
      },
      {
        :platform => 'x64/windows',
        :name => 'CryptDestroyHash',
        :params => [["LPVOID", "hHash", "in"]],
        :return_type => 'BOOL',
        :dll_name => 'advapi32',
        :ruby_args => [1680128],
        :request_to_client => {
          TLV_TYPE_RAILGUN_SIZE_OUT => 0,
          TLV_TYPE_RAILGUN_STACKBLOB => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\xA3\x19\x00\x00\x00\x00\x00",
          TLV_TYPE_RAILGUN_BUFFERBLOB_IN => "",
          TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT => "",
          TLV_TYPE_RAILGUN_DLLNAME => 'advapi32',
          TLV_TYPE_RAILGUN_FUNCNAME => 'CryptDestroyHash',
        },
        :response_from_client => {
          TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_INOUT => "",
          TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_OUT => "",
          TLV_TYPE_RAILGUN_BACK_RET => 1,
          TLV_TYPE_RAILGUN_BACK_ERR => 0,
        },
        :returned_hash => {"GetLastError"=>0, "return"=>true},
      },
      {
        :platform => 'x64/windows',
        :name => 'CryptDestroyKey',
        :params => [["LPVOID", "hKey", "in"]],
        :return_type => 'BOOL',
        :dll_name => 'advapi32',
        :ruby_args => [1680240],
        :request_to_client => {
          TLV_TYPE_RAILGUN_SIZE_OUT => 0,
          TLV_TYPE_RAILGUN_STACKBLOB => "\x00\x00\x00\x00\x00\x00\x00\x00p\xA3\x19\x00\x00\x00\x00\x00",
          TLV_TYPE_RAILGUN_BUFFERBLOB_IN => "",
          TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT => "",
          TLV_TYPE_RAILGUN_DLLNAME => 'advapi32',
          TLV_TYPE_RAILGUN_FUNCNAME => 'CryptDestroyKey',
        },
        :response_from_client => {
          TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_INOUT => "",
          TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_OUT => "",
          TLV_TYPE_RAILGUN_BACK_RET => 1,
          TLV_TYPE_RAILGUN_BACK_ERR => 0,
        },
        :returned_hash => {"GetLastError"=>0, "return"=>true},
      },
      {
        :platform => 'x64/windows',
        :name => 'CryptReleaseContext',
        :params => [["LPVOID", "hProv", "in"], ["DWORD", "dwFlags", "in"]],
        :return_type => 'BOOL',
        :dll_name => 'advapi32',
        :ruby_args => [1756800, 0],
        :request_to_client => {
          TLV_TYPE_RAILGUN_SIZE_OUT => 0,
          TLV_TYPE_RAILGUN_STACKBLOB => "\x00\x00\x00\x00\x00\x00\x00\x00\x80\xCE\x1A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
          TLV_TYPE_RAILGUN_BUFFERBLOB_IN => "",
          TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT => "",
          TLV_TYPE_RAILGUN_DLLNAME => 'advapi32',
          TLV_TYPE_RAILGUN_FUNCNAME => 'CryptReleaseContext',
        },
        :response_from_client => {
          TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_INOUT => "",
          TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_OUT => "",
          TLV_TYPE_RAILGUN_BACK_RET => 1,
          TLV_TYPE_RAILGUN_BACK_ERR => 0,
        },
        :returned_hash => {"GetLastError"=>0, "return"=>true},
      },
    ]
  end

end

end; end; end; end; end; end;
