Add support to encode PAC-TYPE
parent
1721641138
commit
a5f8b4319f
|
@ -7,6 +7,13 @@ module Rex
|
|||
module RsaMd5
|
||||
# Checksum identifier
|
||||
RSA_MD5 = 7
|
||||
|
||||
def checksum_rsa_md5(data)
|
||||
md5 = OpenSSL::Digest::MD5.new
|
||||
md5 << data
|
||||
|
||||
md5.digest
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -10,6 +10,11 @@ module Rex
|
|||
SE_GROUP_ALL = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED
|
||||
USER_NORMAL_ACCOUNT = 0x00000010
|
||||
USER_DONT_EXPIRE_PASSWORD = 0x00000200
|
||||
|
||||
PAC_LOGON_INFO = 1
|
||||
PAC_SERVER_CHECKSUM = 6
|
||||
PAC_PRIVSVR_CHECKSUM = 7
|
||||
PAC_CLIENT_INFO = 10
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -20,3 +25,4 @@ require 'rex/proto/kerberos/pac/priv_svr_checksum'
|
|||
require 'rex/proto/kerberos/pac/server_checksum'
|
||||
require 'rex/proto/kerberos/pac/client_info'
|
||||
require 'rex/proto/kerberos/pac/logon_info'
|
||||
require 'rex/proto/kerberos/pac/type'
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
module Rex
|
||||
module Proto
|
||||
module Kerberos
|
||||
module Pac
|
||||
class Type < Element
|
||||
|
||||
include Rex::Proto::Kerberos::Crypto::RsaMd5
|
||||
|
||||
# @!attribute buffers
|
||||
# @return [Array<Rex::Text::Proto::Kerberos::Pac::Element>] An array of PAC_INFO_BUFFER structures
|
||||
attr_accessor :buffers
|
||||
# @!attribute checksum
|
||||
# @return [Fixnum] The type of checksum to use when encoding PAC-TYPE
|
||||
attr_accessor :checksum
|
||||
|
||||
# Encodes the Rex::Proto::Kerberos::Pac::Type
|
||||
#
|
||||
# @return [String]
|
||||
def encode
|
||||
offset_one = 0
|
||||
offset_two = 0
|
||||
|
||||
draft = ''
|
||||
draft << encode_buffers_length
|
||||
draft << encode_version
|
||||
draft << encode_pac_info_buffers
|
||||
|
||||
# Encode buffers
|
||||
buffers.each do |buffer|
|
||||
if buffer.class == ServerChecksum
|
||||
offset_one = draft.length + 4
|
||||
elsif buffer.class == PrivSvrChecksum
|
||||
offset_two = draft.length + 4
|
||||
end
|
||||
|
||||
buffer_encoded = buffer.encode
|
||||
draft << buffer_encoded
|
||||
draft << "\x00" * ((buffer_encoded.length + 7) / 8 * 8 - buffer_encoded.length)
|
||||
end
|
||||
|
||||
checksum_draft = make_checksum(draft)
|
||||
double_checksum = make_checksum(checksum_draft)
|
||||
|
||||
encoded = ''
|
||||
encoded << draft[0..(offset_one - 1)]
|
||||
encoded << checksum_draft
|
||||
encoded << draft[(offset_one + checksum_draft.length)..(offset_two - 1)]
|
||||
encoded << double_checksum
|
||||
encoded << draft[(offset_two + double_checksum.length)..(draft.length - 1)]
|
||||
|
||||
encoded
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def encode_buffers_length
|
||||
[buffers.length].pack('V')
|
||||
end
|
||||
|
||||
def encode_version
|
||||
[0].pack('V')
|
||||
end
|
||||
|
||||
def encode_pac_info_buffers
|
||||
offset = 8 + buffers.length * 16
|
||||
encoded = ''
|
||||
buffers.each do |buffer|
|
||||
case buffer
|
||||
when ClientInfo
|
||||
encoded << [PAC_CLIENT_INFO].pack('V')
|
||||
when LogonInfo
|
||||
encoded << [PAC_LOGON_INFO].pack('V')
|
||||
when PrivSvrChecksum
|
||||
encoded << [PAC_PRIVSVR_CHECKSUM].pack('V')
|
||||
when ServerChecksum
|
||||
encoded << [PAC_SERVER_CHECKSUM].pack('V')
|
||||
end
|
||||
|
||||
buffer_length = buffer.encode.length
|
||||
|
||||
encoded << [buffer_length].pack('V')
|
||||
encoded << [offset].pack('Q<')
|
||||
|
||||
offset = (offset + buffer_length + 7) / 8 * 8
|
||||
end
|
||||
|
||||
encoded
|
||||
end
|
||||
|
||||
def make_checksum(data)
|
||||
res = ''
|
||||
case checksum
|
||||
when RSA_MD5
|
||||
res = checksum_rsa_md5(data)
|
||||
else
|
||||
raise ::RuntimeError, 'PAC-TYPE checksum not supported'
|
||||
end
|
||||
|
||||
res
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,93 @@
|
|||
# -*- coding:binary -*-
|
||||
require 'spec_helper'
|
||||
|
||||
require 'rex/proto/kerberos'
|
||||
|
||||
describe Rex::Proto::Kerberos::Pac::Type do
|
||||
|
||||
subject(:pac_type) do
|
||||
described_class.new
|
||||
end
|
||||
|
||||
let(:sample) do
|
||||
"\x04\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\xb0\x01\x00\x00" +
|
||||
"\x48\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00\x12\x00\x00\x00" +
|
||||
"\xf8\x01\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x14\x00\x00\x00" +
|
||||
"\x10\x02\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x14\x00\x00\x00" +
|
||||
"\x28\x02\x00\x00\x00\x00\x00\x00\x01\x10\x08\x00\xcc\xcc\xcc\xcc" +
|
||||
"\xa0\x01\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x1e\x7c\x42" +
|
||||
"\xfc\x18\xd0\x01\xff\xff\xff\xff\xff\xff\xff\x7f\xff\xff\xff\xff" +
|
||||
"\xff\xff\xff\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
|
||||
"\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\x7f\x08\x00\x08\x00" +
|
||||
"\x04\x00\x02\x00\x00\x00\x00\x00\x08\x00\x02\x00\x00\x00\x00\x00" +
|
||||
"\x0c\x00\x02\x00\x00\x00\x00\x00\x10\x00\x02\x00\x00\x00\x00\x00" +
|
||||
"\x14\x00\x02\x00\x00\x00\x00\x00\x18\x00\x02\x00\x00\x00\x00\x00" +
|
||||
"\xe8\x03\x00\x00\x01\x02\x00\x00\x05\x00\x00\x00\x1c\x00\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\x20\x00\x02\x00\x14\x00\x14\x00" +
|
||||
"\x24\x00\x02\x00\x28\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
|
||||
"\x10\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\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
|
||||
"\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00" +
|
||||
"\x6a\x00\x75\x00\x61\x00\x6e\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\x00\x00\x00" +
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
|
||||
"\x00\x00\x00\x00\x05\x00\x00\x00\x01\x02\x00\x00\x07\x00\x00\x00" +
|
||||
"\x00\x02\x00\x00\x07\x00\x00\x00\x08\x02\x00\x00\x07\x00\x00\x00" +
|
||||
"\x06\x02\x00\x00\x07\x00\x00\x00\x07\x02\x00\x00\x07\x00\x00\x00" +
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x00" +
|
||||
"\x00\x00\x00\x00\x0a\x00\x00\x00\x44\x00\x45\x00\x4d\x00\x4f\x00" +
|
||||
"\x2e\x00\x4c\x00\x4f\x00\x43\x00\x41\x00\x4c\x00\x04\x00\x00\x00" +
|
||||
"\x01\x04\x00\x00\x00\x00\x00\x05\x15\x00\x00\x00\x03\x99\xa8\x68" +
|
||||
"\xe0\x0e\x0e\xd9\x9a\x18\xcf\xcf\x00\x1e\x7c\x42\xfc\x18\xd0\x01" +
|
||||
"\x08\x00\x6a\x00\x75\x00\x61\x00\x6e\x00\x00\x00\x00\x00\x00\x00" +
|
||||
"\x07\x00\x00\x00\x48\x0b\x02\xf8\xfe\x54\x02\x96\x7d\x7e\xee\x24" +
|
||||
"\x12\x73\x67\x4e\x00\x00\x00\x00\x07\x00\x00\x00\x91\x35\x2a\xc2" +
|
||||
"\x7c\x08\x1c\xa7\x88\xd9\x63\xbb\x23\x71\xb8\x64\x00\x00\x00\x00"
|
||||
end
|
||||
|
||||
let(:rsa_md5) { 7 }
|
||||
|
||||
describe "#encode" do
|
||||
context "when RSA-MD5 checksums" do
|
||||
it "encodes the PAC-TYPE correctly" do
|
||||
logon_info = Rex::Proto::Kerberos::Pac::LogonInfo.new(
|
||||
logon_time: Time.at(1418712492),
|
||||
effective_name: 'juan',
|
||||
user_id: 1000,
|
||||
primary_group_id: 513,
|
||||
group_ids: [513, 512, 520, 518, 519],
|
||||
logon_domain_name: 'DEMO.LOCAL',
|
||||
logon_domain_id: 'S-1-5-21-1755879683-3641577184-3486455962',
|
||||
)
|
||||
|
||||
client_info = Rex::Proto::Kerberos::Pac::ClientInfo.new(
|
||||
client_id: Time.at(1418712492),
|
||||
name: 'juan'
|
||||
)
|
||||
|
||||
server_checksum = Rex::Proto::Kerberos::Pac::ServerChecksum.new(
|
||||
checksum: rsa_md5
|
||||
)
|
||||
|
||||
priv_srv_checksum = Rex::Proto::Kerberos::Pac::PrivSvrChecksum.new(
|
||||
checksum: rsa_md5
|
||||
)
|
||||
|
||||
pac_type.buffers = [
|
||||
logon_info,
|
||||
client_info,
|
||||
server_checksum,
|
||||
priv_srv_checksum
|
||||
]
|
||||
|
||||
pac_type.checksum = rsa_md5
|
||||
|
||||
expect(pac_type.encode).to eq(sample)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue