前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【技术创作101训练营】CTF-PWN方向入门

【技术创作101训练营】CTF-PWN方向入门

原创
作者头像
yichen
修改2021-01-18 11:13:12
1.3K0
修改2021-01-18 11:13:12
举报

PPT:

训练营.pptx

演讲文稿:

大家好,我是yichen,今天跟大家分享一些CTF中PWN这个方向的知识。

PWN 是一个黑客语法的俚语词,是指攻破设备或者系统。发音类似"砰"。对黑客而言,这就是成功实施黑客攻击的声音”砰”的一声,被"黑"的电脑或手机就被你操纵了。

在CTF中PWN题目则主要是分析所给的可执行程序,找到并分析漏洞然后编写EXP,使用EXP对运行着这个程序的服务器进行攻击并获得权限从而找到flag,提交得到分数。

这是本次分享的目录,首先会介绍一下PWN的环境配置及常用的工具,然后我们来了解一下当调用一个函数的时候到底发生了什么,这有助于理解栈溢出这类漏洞的原理,一定要认真理解!理解了原理之后我们就开始上手操作啦,我们自己编译一个简单的例子,然后PWN掉它,获得系统管理权来感受一下PWN的魅力。最后我们来了解一下安全工程师们针对栈溢出漏洞发明的保护机制,这很大程度上限制了缓冲区漏洞的利用,然而道高一尺魔高一丈,我们将学到如何突破重重保护来利用栈溢出漏洞。

下面是第一部分,PWN的环境配置及常用的工具,这里我列举了几个必须要有的,因为我们在下面的演示中会用到,需要自己安装ubuntu 16.04的虚拟机,然后在里面安装pwntools这个python库,他会帮助我们构造EXP来攻击存在漏洞的程序。LibcSearcher也是一个python的库,在后面的例子中它可以帮助我们找到libc的版本,从而绕过相关的保护。gdb-peda插件可以在调试的时候显示更多信息来帮助我们理解程序在干什么。最后这两个是反编译的,帮助我们通过反编译出来的代码来分析程序的漏洞。

好,介绍完环境我们来看一下当调用一个函数时发生了什么。

我通过OllyDbg打开一个软件,call指令就是去调用一个函数的意思,大家注意call指令下面那条指令的地址,当call指令执行完成他应该要返回到这里的,那程序是怎么实现的那呐?在这个界面的右下角是栈窗口,他会显示程序此时的栈布局,我们把此时的栈窗口截个图,保留一下,然后摁下快捷键f7单步进入call的那个函数内部,注意此时栈窗口已经变化了,在call指令执行的同时他把执行完函数应该要返回的地址放到了栈顶。继续f8单步步过(意思是遇到call不进去执行,而是直接执行完这个函数)一直到retn这条指令,retn指令是返回的意思(return),相当于pop eip,即到目前栈顶的那个地址继续执行代码。

这里我放了一个小总结,大家可以根据这个自己调试着理解一下。

我们看下面这个图示,上面演示的是正常的情况,那如果我们调用的函数正好是往栈空间里面读入文本的呐?如果它没有对输入的长度进行限制是不是我们可以覆盖掉返回地址。那如果我们可以精心构造输入到栈空间的数据为可以执行的代码,同时把返回地址改为shellcode的地址就可以正常的执行shellcode啦!这就是传说中的栈溢出漏洞。

接下来我们自己编译一个简单的例子,然后PWN掉它,获得系统管理权。代码已经在ppt中附上了,大家将代码保存为level1.c,使用这条命令进行编译:gcc -m32 -fno-stack-protector -z execstack -o level1 level1.c。其中-m32意思是编译为32位的程序-fno-stack-protector和-z execstack这两个参数会分别关掉程序的Stack Protector和DEP,然后使用这条命令关掉ASLR。

代码中我故意存放了一个函数,它的功能是调用了system(‘/bin/sh’),也就是说如果能执行这个函数就能拿到系统的管理权。

使用cyclic 200生成200个有规律的字符,然后再gdb调试的时候输入进去,因为超出了缓冲区的长度而且不是正常的地址程序会报错,我们用得到的地址再次使用cyclic算一下偏移是多少。算出偏移然后只要找到后门函数的地址就可以啦

我们可以使用objdump -d level1来查看反汇编代码,找到后门函数的地址(也可以用IDA查看)。到此为止占空间的大小与后门函数的地址我们就得到了,只需要利用pwntools这个库来写EXP就可以啦

(演示EXP运行及拿到权限的操作)

最后我们来看一下重重保护下的栈溢出漏洞利用。先来看一下针对栈溢出的保护机制,首先是NX即No-eXecute(不可执行)的意思,NX(DEP)的基本原理是将数据所在内存页标识为不可执行,当程序溢出成功转入shellcode时,程序会尝试在数据页面上执行指令,此时CPU就会抛出异常,而不是去执行恶意指令。

CANARY(栈保护)栈溢出保护是一种缓冲区溢出攻击缓解手段,当启用栈保护后,函数开始执行的时候会先往栈里插入cookie信息,当函数真正返回的时候会验证cookie信息是否合法,如果不合法就停止程序运行。攻击者在覆盖返回地址的时候往往也会将cookie信息给覆盖掉,导致栈保护检查失败而阻止shellcode的执行。在Linux中我们将cookie信息称为canary。

PIE(ASLR)内存地址随机化机制(address space layout randomization),有以下三种情况:

0 - 表示关闭进程地址空间随机化

1 - 表示将mmap的基址,stack和vdso页面随机化

2 - 表示在1的基础上增加堆(heap)的随机化

了解了这些以后我们把右边的代码保存为level2.c使用gcc -m32 -fno-stack-protector -o level2 level2.c编译,这次我们打开了栈不可执行,再使用echo 2 > /proc/sys/kernel/randomize_va_space关掉ASLR。现在因为没有后门函数能让我们直接返回到它从而获取shell,所以需要自己去构造,而开启ASLR之后每次地址是随机的,所以没法通过调试后记录system等的地址下次直接用,所以我们也要学会用LibcSearcher动态的获取libc

我已经给出了EXP,我们来通过分析EXP学习一下用到的技术,这里还要在额外介绍一下延迟绑定技术与PLT&GOT表,这里简单说一下就是:当你去调用一个函数的时候,如果这个函数执行过了就会把它的真实地址放在got表项,也就说去执行这个函数的got表中的地址的代码就行了。

好,我们回到EXP的代码,这里我摘抄出来一部分关键的代码,我们来一点一点分析一下。

payload1 = 'a'*108+ p32(write_plt) + p32(vulfun_addr) + p32(1) + p32(write_got) + p32(4)

p.sendline(payload1)

这一句首先填充了108个’a’,然后把返回地址改为了write_plt(即write函数的plt表项的内容,可以直接调用write函数),而后面的vulfun_addr则是调用玩write函数的返回地址,在后面就是write函数的参数了,这里相当于模拟了一个函数调用的过程(push参数进栈,push返回地址,调用函数)。那这里利用write函数将write函数的got表项中的内容即write函数本次加载的真实地址

write_addr = u32(p.recv(4))

通过p.recv(4)接收write函数的输出,然后使用libc = LibcSearcher('write',write_addr)计算libc,之后libc_base = write_addr - libc.dump("write")使用write函数的地址减去write函数的偏移得到libc的基址,这样用libc基址加上其他函数的偏移就能找到其他函数了。

Ok,我的分享到这里就结束了,之后会把ppt分享给大家,大家如果复现出了任何问题可以联系我,我们一起探讨解决。谢谢大家!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • PPT:
  • 演讲文稿:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档