pwn小知识
pwn-gdb操作
在PWN中使用GDB (GNU Debugger) 进行调试是一个常见的方法。以下是使用GDB调试二进制文件的一般步骤和一些有用的技巧:
启动GDB:
gdb ./binary_name
设置断点:
使用b
(或break
) 命令设置断点。例如,为主函数设置断点:b main
运行程序:
使用r
(或run
) 命令:r [program arguments]
查看寄存器状态:
使用info registers
或简写i r
:i r
单步执行:
s
或step
: 执行一行源代码。如果该行是函数调用,则进入该函数。n
或next
: 执行一行源代码。不会进入函数。
查看内存:
x
命令: 使用这个命令可以查看某个地址的内容。x/10x $rsp # 查看堆栈顶部的10个十六进制值
继续执行:
使用c
(或continue
) 命令。退出GDB:
使用q
(或quit
) 命令。使用GDB插件:
为了方便PWN调试,社区有很多有用的GDB插件,例如pwndbg
,PEDA
和GEF
。这些插件为GDB提供了额外的功能和视觉增强,使其更容易用于漏洞分析和利用。调试远程程序:
如果你正在尝试利用远程服务,可以使用gdbserver
在远程端启动程序,并从本地使用GDB连接它进行调试。其他有用的命令:
info proc mappings
: 显示进程的内存映射。set follow-fork-mode child
: 当程序进行fork时,GDB会跟踪子进程。set disassembly-flavor intel
: 将反汇编格式设置为Intel格式,这通常比默认的AT&T格式更易于阅读。
这只是使用GDB进行PWN调试的基础。为了成功地找到并利用漏洞,可能还需要掌握更多高级的调试和逆向技巧。
栈的小知识
栈(Stack)是啥?
栈是一种特殊的线性数据结构,它只允许在一端(称为“顶”)进行插入和删除操作。由于它的特点,我们经常用“后进先出”(LIFO)来描述它。就像一叠盘子,我们只能放在最顶端或从最顶端拿走。🍽️
但是栈在实际结构里是“倒着的”,也就是高位地址才是底部,低位地址才是顶部,值得注意。
栈的主要操作
- 压栈(Push): 向栈中添加元素。
- 弹栈(Pop): 从栈中取出元素。
为啥要用栈呢?🤔
- 函数调用:当函数A调用函数B时,函数A的状态(例如局部变量)被“压入”栈中,等待函数B完成后再继续执行。
- 括号匹配:你知道编程中的括号是否配对正确吗?用栈就能轻松搞定!
- 撤销操作:例如在文字处理软件中,撤销功能就靠栈实现。
栈的美中不足:🌹与🌪️
- 🌹优点:结构简单,操作灵活。
- 🌪️缺点:存储空间受限,容易造成溢出。
举个例子
有一段ROP链被发送到32位linux,它其中的内容是:
payload = cyclic(0x38) |
则栈的结构变成:
+--------------+ |
每次从最低位POP一个方块,并执行其中的要求,比如是一个函数地址read_addr的话,就要再连续POP它所要求的参数,read有三个参数,所以POP三个参数。然后read是要读取用户输入的内容的,因此还要等用户输入内容。输入完之后,函数一般都会有一个return,这里就是回到start_addr。而原题shellcode在read过程中写入了此地址,因此可直接进入shell。
原题是pwn刷题记录2中的get_started_3dsctf_2016(*)