第八周培训笔记(pwn)

本文介绍了黑客术语PWN的概念,详细解释了CTF中的Pwn技巧,涉及函数调用栈的工作原理,展示了不同架构下寄存器的作用,并指导如何在Ubuntu环境中搭建PWN开发环境,包括使用Pwntools工具。此外,还涵盖了gcc编译保护机制和GDB调试基础,以及栈溢出和ret2text技术的简要概述。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

0x01 PWN是做什么的

“Pwn” 是一个黑客语法的俚语词,是指攻破设备或者系统。 发音类似 ,对黑客而言,这就是成功实施黑客攻击的声音—— 砰的一声,被 的电脑或手机就被你操纵了。
CTF 中的 pwn 指的是通过程序本身的漏洞,编写利用脚本破解程序拿到主机的权限

0x02 C函数调用栈(Stack)过程

了解主调函数调用被调函数时, call 指令开辟栈的过程和函数调用结束后, leave ret 指令恢复现场的过程, EIP , EBP, ESP 分别是如何变化的。

0x03 不同寄存器(Register)的作用

https://blog.youkuaiyun.com/rankun1/article/details/70880239
传参的时候需要用到寄存器,在 64 x86 架构中,传参寄存器的顺序如下:
1. RDI (Destination Index): 用于传递第一个整数参数。
2. RSI (Source Index): 用于传递第二个整数参数。
3. RDX (Data Register): 用于传递第三个整数参数。
4. RCX (Counter Register): 用于传递第四个整数参数。
5. R8: 用于传递第五个整数参数。
6. R9: 用于传递第六个整数参数。

0x04 VMwareUbuntuPWN环境搭建:

检查环境升级

sudo apt-get update: 升级安装包相关的命令,刷新可安装的软件列表(但不做任何实际的安装动作)

sudo apt-get upgrade: 进行安装包的更新(软件版本的升级)

sudo apt-get dist-upgrade: 除了拥有 upgrade 的全部功能外, dist-upgrade 会比 upgrade 更智能地处理需要更新的软件 包的依赖关系。
sudo do-release-upgrade: 进行系统版本的升级 (Ubuntu 版本的升级 ) Ubuntu 官方推荐的系统升级方式 , 若加参数 -d
还可以升级到开发版本 , 但会不稳定
sudo apt-get autoclean: 清理旧版本的软件缓存
sudo apt-get clean: 清理所有软件缓存
sudo apt-get autoremove: 删除系统不再使用的孤立软件

0x05 pwntools介绍

from pwn import *导入模块
设置全局变量 context 一般就用context(os='linux',arch='i386',log_level='debug') 来设置
创建对象
process 是指运行本地的程序, remote 是指连接远程的服务器
数据接收
*recv(numb= 字节大小 , timeout=default) : 接收指定字节数。
recvall() : 一直接收直到达到文件 EOF
recvline(keepends=True) : 接收一行, keepends 为是否保留行尾的 \n
*recvuntil(delims, drop=False) : 一直读到 delims pattern 出现为止。
recvrepeat(timeout=default) : 持续接收直到 EOF timeout
数据发送
*send(data) : 发送数据。
*sendline(data) : 发送一行数据,相当于在数据末尾加 \n
*sendafter() :在接收到某数据后发送。
交互
interactive()
链接到 gdb 中进行本地程序调试
gdb.attach()

0x06 gcc编译演示保护机制问题

0x07 GDB调试基础功能演示(pwndbg)

log_level='debug'
# 设置日志输出的等级为 debug ,这句话在调试的时候一般会设置,这样 pwntools 会将完整的 io 过程都打印下来,使 得调试更加方便
arch='ARM64'
# 设置架构类型
os='linux'
# 设置 os 类型

基本指令

help //帮助
i //info,查看一些信息,只输入info可以看可以接什么参数,
i b //info break 查看所有断点信息(编号、断点位置)
i r //info registers 查看各个寄存器当前的值
i f //info function 查看所有函数名,需保留符号
show //和info类似,但是查看调试器的基本信息,如:show args //查看参数
rdi //+寄存器名代表一个寄存器内的值,用在地址上直接相当与一个十六进制变量
backtrace //查看调用栈
q //quit 退出,常用

执行指令

s //s单步步入,遇到调用跟进函数中,相当于step into,源码层面的一步
si //同s,汇编层面的一步
n //next,单步步过,遇到调用不跟进,相当于step over,源码层面的一步
ni //nexti,同n,汇编层面的一步
c //continue,继续执行到断点,没断点就一直执行下去
r //run,重新开始执行

断点指令

下普通断点指令b(break):
b *(0x123456) //,给0x123456地址处的指令下断点
b *$ rebase(0x123456) //$rebase 在调试开PIE的程序的时候可以直接加上程序的随机地址
b function_name //给函数fun_name下断点,目标文件要保留符号才行
b file_name:fun_name
b file_name:15 //给file_name的15行下断点,要有源码才行
b 15//单个文件的第15行
b +0x10 //在程序当前停住的位置下0x10的位置下断点,同样可以-0x10,就是前0x10
break fun if \$rdi==5 //条件断点,rdi值为5的时候才断

删除、禁用断点:
使用info break(简写: i b)来查看断点编号

delete 5 //删除5号断点,直接delete不接数字删除所有
disable 5 //禁用5号断点
enable 5 //启用5号断点
clear //不加参数默认清除当前函数所在行的所有断点
clear function//删除该函数内的所有断点
clear line//删除该行的所有断点

内存断点指令watch:
watch 0x123456 //0x123456地址的数据改变的时候会断
watch a //变量a改变的时候会断
info watchpoints //查看watch断点信息

捕获断点catch:
catch syscall //syscall系统调用的时候断住
tcatch syscall //syscall系统调用的时候断住,只断一次
info break //catch的断点可以通过i b查看

除syscall外还可以使用的有:

1)throw: 抛出异常

2)catch: 捕获异常

3)exec: exec被调用

4)fork: fork被调用

5)vfork: vfork被调用

6)load: 加载动态库

7)load libname: 加载名为libname的动态库

8)unload: 卸载动态库

9)unload libname: 卸载名为libname的动态库

10)syscall [args]: 调用系统调用,args可以指定系统调用号,或者系统名称

打印指令

查看内存指令x:x /nuf 0x123456 //常用,x指令的格式是:x空格/nfu,nfu代表三个参数

n代表显示几个单元(而不是显示几个字节,后面的u表示一个单元多少个字节),放在’/'后面
u代表一个单元几个字节,b(一个字节),h(二个字节),w(四字节),g(八字节)
f代表显示数据的格式,f和u的顺序可以互换,也可以只有一个或者不带n,用的时候很灵活

x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十六进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
c 按字符格式显示变量。
f 按浮点数格式显示变量。
s 按字符串显示。
b 按字符显示。
i 显示汇编指令。

x /10gx 0x123456 //常用,从0x123456开始每个单元八个字节,十六进制显示是个单元的数据

x /10xd \$rdi //从rdi指向的地址向后打印10个单元,每个单元4字节的十进制数

x /10i 0x123456 //常用,从0x123456处向后显示十条汇编指令

打印指令

p(print):
p fun_name //打印fun_name的地址,需要保留符号
p 0x10-0x08 //计算0x10-0x08的结果
p &a //查看变量a的地址
p *(0x123456) //查看0x123456地址的值,注意和x指令的区别,x指令查看地址的值不用星号
p \$rdi //显示rdi寄存器的值,注意和x的区别,这只是显示rdi的值,而不是rdi指向的值
p *($rdi) //显示rdi指向的值

打印汇编指令disass:(disassemble的缩写)

disass 0x123456 //显示0x123456前后的汇编指令

打印源代码指令list:
list //查看当前附近10行代码,要有源码,list指令pwn题中几乎不用,但为了完整性还是简单举几个例子
list 38 //查看38行附近10行代码
list 1,10 //查看1-10行
list main //查看main函数开始10行

修改和查找指令

修改数据指令set:
set $​rdi=0x10 //把rdi寄存器的值变为0x10
set *(0x123456)=0x10 //0x123456地址的值变为0x10,注意带星号
set args “abc” “def” “gh“//给参数123赋值
set args “python -c ‘print “1234\x7f\xde”’” //使用python给参数赋值不可见字符

查找数据:
search rdi //从当前位置向后查包含rdi的指令,返回若干
search -h //查看search帮助
find “hello” //查找hello字符串,pwndbg独有
ropgadget //查找ropgadget,pwndbg独有,

堆操作指令(pwndbg插件独有)

arena //显示arena的详细信息
arenas //显示所有arena的基本信息
arenainfo //好看的显示所有arena的信息
bins //常用,查看所有种类的堆块的链表情况
fastbins //单独查看fastbins的链表情况
largebins //同上,单独查看largebins的链表情况
smallbins //同上,单独查看smallbins的链表情况
unsortedbin //同上,单独查看unsortedbin链表情况
tcachebins //同上,单独查看tcachebins的链表情况
tcache //查看tcache详细信息
heap //数据结构的形式显示所有堆块,会显示一大堆
heapbase //查看堆起始地址
heapinfo、heapinfoall //显示堆得信息,和bins的挺像的,没bins好用
parseheap //显示堆结构,很好用
tracemalloc //好用,会跟提示所有操作堆的地方
其他pwndbg插件独有指令
cyclc 50 //生成50个用来溢出的字符,如:aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaama

$reabse //开启PIE的情况的地址偏移

b *$reabse(0x123456) //断住PIE状态下的二进制文件中0x123456的地方

codebase //打印PIE偏移,与rebase不同,这是打印,rebase是使用

stack //查看栈

retaddr //打印包含返回地址的栈地址

canary //直接看canary的值

plt //查看plt表

got //查看got表

hexdump //想IDA那样显示数据,带字符串

参考 pwndbg的安装和gdb使用-优快云博客

0x08 栈溢出及ret2text

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值