Add support to encode PAC-TYPE

bug/bundler_fix
jvazquez-r7 2014-12-16 11:31:27 -06:00
parent 1721641138
commit a5f8b4319f
4 changed files with 213 additions and 0 deletions

View File

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

View File

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

View File

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

View File

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