Land #3600 - GPP Junk Padding Fix

bug/bundler_fix
sinn3r 2014-08-04 16:21:57 -05:00
commit 7044dabea1
No known key found for this signature in database
GPG Key ID: 2384DB4EF06F730B
2 changed files with 106 additions and 65 deletions

View File

@ -129,14 +129,40 @@ class GPP
# Decrypts passwords using Microsoft's published key: # Decrypts passwords using Microsoft's published key:
# http://msdn.microsoft.com/en-us/library/cc422924.aspx # http://msdn.microsoft.com/en-us/library/cc422924.aspx
def self.decrypt(encrypted_data) def self.decrypt(encrypted_data)
unless encrypted_data password = ""
return "" return password unless encrypted_data
end
password = "" password = ""
padding = "=" * (4 - (encrypted_data.length % 4)) retries = 0
epassword = "#{encrypted_data}#{padding}" original_data = encrypted_data.dup
decoded = Rex::Text.decode_base64(epassword)
begin
mod = encrypted_data.length % 4
# PowerSploit code strips the last character, unsure why...
case mod
when 1
encrypted_data = encrypted_data[0..-2]
when 2, 3
padding = '=' * (4 - mod)
encrypted_data = "#{encrypted_data}#{padding}"
end
# Strict base64 decoding used here
decoded = encrypted_data.unpack('m0').first
rescue ::ArgumentError => e
# Appears to be some junk UTF-8 Padding appended at times in
# Win2k8 (not in Win2k8R2)
# Lets try stripping junk and see if we can decrypt
if retries < 8
retries += 1
original_data = original_data[0..-2]
encrypted_data = original_data
retry
else
return password
end
end
key = "\x4e\x99\x06\xe8\xfc\xb6\x6c\xc9\xfa\xf4\x93\x10\x62\x0f\xfe\xe8\xf4\x96\xe8\x06\xcc\x05\x79\x90\x20\x9b\x09\xa4\x33\xb6\x6c\x1b" key = "\x4e\x99\x06\xe8\xfc\xb6\x6c\xc9\xfa\xf4\x93\x10\x62\x0f\xfe\xe8\xf4\x96\xe8\x06\xcc\x05\x79\x90\x20\x9b\x09\xa4\x33\xb6\x6c\x1b"
aes = OpenSSL::Cipher::Cipher.new("AES-256-CBC") aes = OpenSSL::Cipher::Cipher.new("AES-256-CBC")

View File

@ -1,3 +1,4 @@
# encoding: binary
require 'rex/parser/group_policy_preferences' require 'rex/parser/group_policy_preferences'
xml_group = ' xml_group = '
@ -76,75 +77,89 @@ xml_ms = '
</Groups> </Groups>
' '
# Win2k8 appears to append some junk padding in some cases
cpassword_win2k8 = []
# Win2k8R2 - EqWFlA4kn2T6PHvGi09M7seHuqCYK/slkJWIl7mK+wEMON8tIIslS6707RU1F7Bh
cpassword_win2k8 << ['EqWFlA4kn2T6PHvGi09M7seHuqCYK/slkJWIl7mK+wEMON8tIIslS6707RU1F7BhTµkp', 'N3v3rGunnaG!veYo']
cpassword_win2k8 << ['EqWFlA4kn2T6PHvGi09M7seHuqCYK/slkJWIl7mK+wGSwOI7Be//GJdxd5YYXUQHTµkp', 'N3v3rGunnaG!veYou']
# Win2k8R2 - EqWFlA4kn2T6PHvGi09M7seHuqCYK/slkJWIl7mK+wFSuDccBEp/4l5EuKnwF0WS
cpassword_win2k8 << ['EqWFlA4kn2T6PHvGi09M7seHuqCYK/slkJWIl7mK+wFSuDccBEp/4l5EuKnwF0WS»YÂVAA', 'N3v3rGunnaG!veYouUp']
cpassword_normal = "j1Uyj3Vx8TY9LtLZil2uAuZkFQA/4latT76ZwgdHdhw" cpassword_normal = "j1Uyj3Vx8TY9LtLZil2uAuZkFQA/4latT76ZwgdHdhw"
cpassword_bad = "blah" cpassword_bad = "blah"
describe Rex::Parser::GPP do describe Rex::Parser::GPP do
GPP = Rex::Parser::GPP GPP = Rex::Parser::GPP
## ##
# Decrypt # Decrypt
## ##
it "Decrypt returns Local*P4ssword! for normal cpassword" do it "Decrypt returns Local*P4ssword! for normal cpassword" do
result = GPP.decrypt(cpassword_normal) result = GPP.decrypt(cpassword_normal)
result.should eq("Local*P4ssword!") result.should eq("Local*P4ssword!")
end end
it "Decrypt returns blank for bad cpassword" do it "Decrypt returns blank for bad cpassword" do
result = GPP.decrypt(cpassword_bad) result = GPP.decrypt(cpassword_bad)
result.should eq("") result.should eq("")
end end
it "Decrypt returns blank for nil cpassword" do it "Decrypt returns blank for nil cpassword" do
result = GPP.decrypt(nil) result = GPP.decrypt(nil)
result.should eq("") result.should eq("")
end end
## it 'Decrypts a cpassword containing junk padding' do
# Parse cpassword_win2k8.each do |encrypted, expected|
## result = GPP.decrypt(encrypted)
result.should eq(expected)
end
end
it "Parse returns empty [] for nil" do ##
GPP.parse(nil).should be_empty # Parse
end ##
it "Parse returns results for xml_ms and password is empty" do it "Parse returns empty [] for nil" do
results = GPP.parse(xml_ms) GPP.parse(nil).should be_empty
results.should_not be_empty end
results[0][:PASS].should be_empty
end
it "Parse returns results for xml_datasrc, and attributes, and password is test1" do it "Parse returns results for xml_ms and password is empty" do
results = GPP.parse(xml_datasrc) results = GPP.parse(xml_ms)
results.should_not be_empty results.should_not be_empty
results[0].include?(:ATTRIBUTES).should be_true results[0][:PASS].should be_empty
results[0][:ATTRIBUTES].should_not be_empty end
results[0][:PASS].should eq("test")
end
xmls = [] it "Parse returns results for xml_datasrc, and attributes, and password is test1" do
xmls << xml_group results = GPP.parse(xml_datasrc)
xmls << xml_drive results.should_not be_empty
xmls << xml_schd results[0].include?(:ATTRIBUTES).should be_true
xmls << xml_serv results[0][:ATTRIBUTES].should_not be_empty
xmls << xml_datasrc results[0][:PASS].should eq("test")
end
it "Parse returns results for all good xmls and passwords" do xmls = []
xmls.each do |xml| xmls << xml_group
results = GPP.parse(xml) xmls << xml_drive
results.should_not be_empty xmls << xml_schd
results[0][:PASS].should_not be_empty xmls << xml_serv
end xmls << xml_datasrc
end
## it "Parse returns results for all good xmls and passwords" do
# Create_Tables xmls.each do |xml|
## results = GPP.parse(xml)
it "Create_tables returns tables for all good xmls" do results.should_not be_empty
xmls.each do |xml| results[0][:PASS].should_not be_empty
results = GPP.parse(xml) end
tables = GPP.create_tables(results, "test") end
tables.should_not be_empty
end ##
end # Create_Tables
##
it "Create_tables returns tables for all good xmls" do
xmls.each do |xml|
results = GPP.parse(xml)
tables = GPP.create_tables(results, "test")
tables.should_not be_empty
end
end
end end