- UID
- 1324609
- 在线时间
- 0 小时
- 最后登录
- 1970-1-1
- 注册时间
- 2016-6-15
- 宅魂
- 295 点
- 贡献
- 83 点
- 宅币
- 2230 枚
- 灵石
- 0 块
- 元气(技能点)
- 2 点
- 活跃
- 6 ℃
- 听众
- 5
- 收听
- 0
签到天数: 1 天 连续签到: 1 天 [LV.1]初来乍到
序章
- 积分
- 3464
|
pwn是二进制安全的一个分方向,其主要目的是挖掘软件中的缓冲区溢出;格式化字符串等漏洞,来达到控制程序流程,甚至任意命令执行的结果
作为开始的一篇,首先还是复习一下binary的一些基础知识,以下是需要用到的资料。
[灰帽攻击安全手册].(美)哈里斯&哈珀
《汇编语言》王爽
Exploit编写系列教程1-10篇
Linux_Interactive_Exploit_Development_with_GDB_and_PEDA_Slides
http://shell-storm.org/shellcode/ 在线的shellcode库
这里首先以简单的栈溢出作为开始吧。
栈溢出的形式多种多样,其中最主要的方式是通过覆盖函数的返回地址,来使程序执行任意地址的指令的方法。
同时,由于现代计算机不区分代码和数据,于是我们还可以构造一段shellcode,直接跳转执行,来实现在程序中植入代码的效果。
由于笔者之前有一定的基础,所以这里比较简略,由于程序运行时每次初始化后的地址都有所不同,覆盖的返回地址不能是某段代码的一个静态的地址(硬编码)。
而最好是一条程序中地址相对固定的,类似于jmp rsp的指令。
这里如果是为了方便快速的寻找,大可不用gdb,直接使用objdump命令
objdump -d test 反汇编test中的需要执行指令的那些section
objdump -D test 与-d类似,但反汇编test中的所有section
对于objdump指令,可以使用|grep xxx管道符来过滤出我们想要的的指令。
对于python来说,我们要方便的生成填充用的buffer和之后的payload,可以直接用python -c "print '$\backslash$x11'*1" 之类的指令来实现
在python中要集成在pwning中的网络通信功能,需要用到zio库,这个库可以在Linux下通过pip来进行pip install zio,如果没有pip,则需要sudo apt-get install pip
参考网页:https://pypi.python.org/pypi/zio
在这其中,zio主要起到的是简化socket编程的作用。
大概的使用方法如下
from zio import * 来导入zio库。
如果你需要在本地进行调试
io = zio('./buggy-server') \# used for local pwning development
如果需要连接到远程服务器
io = zio(('1.2.3.4', 1337)) \# used to exploit remote service
Bigtang给出了更详细的用法
io = zio(target,timeout=5,print_read=COLORED(REPR,’yellow’),print_write=COLORED(REPR,’red’))
这里target就是ip,port. 也就是说后面还可以指定超时的时间和读写的字体颜色。
io.read_until(“input name:\x00″) 可以指定读取的终止部分。
io.write()方法,用于向服务器端传输指定的数据(字符串)
另外,zio内部带有很方便的转换函数l32,l64.可以把你的给的形似0x01020202的内存地址转化为hex编码,并且反序后的地址,这样就可以直接用write()方法了。
如果你通过write方法获取了一个交互shell,使用io.interact()来进入这个shell。
GDB:在linux下,唯一真正可靠的动态调试工具,大概就是gdb了,自带了disassemble的功能,可以查看到汇编源码,美中不足是没有GUI,而且指令较为复杂。
BT命令,可以查看当前使用的栈和其地址。另外,如果需要下断点,使用break 函数名,如break main,来对main()函数下断
如果要对某个内存地址下断点,使用break *内存地址来下断点,同时,后面还可以跟上条件语句,如 break *01010101 if x==1,这里如果有一个局部变量x,就可以进行判断
gdb查看指定地址的内存地址的值:examine 简写 x 用法:x/(n,f,u为可选参数) 内存地址(或者\$寄存器名称)
其中n是整数,表示从x开始到后面取几个内存单元的内容加以显示,每个内存单元的大小由u决定,u=b:1 byte h:2 bytes w:4 bytes g:8 bytes (均以字节为单位,1byte=2bits
f是显示的字符格式,x是16进制,c是字符串(char),d是10进制,i可以显示出反编译的汇编代码。
查看寄存器的指令,使用i r \$寄存器名称,或者是i r a来查看所有寄存器。
用r运行该程序 同时后面可以跟上参数python -c ' '来把输出的内容应用到程序的输入流上。
使用set disassembly-flavor intel可以把反汇编的结构显示为intel风格
set variable 变量名= 或者*(地址)= 可以修改内存的数值
使用metasploit的pattern_create.rb来精确计算缓冲区的大小,其原理是生成一个有序字符串,根据最终EIP被冲刷后的结果,来确定缓冲区的大小。
该工具位于framework\tools目录下,使用方法是 ./pattern_create.rb 字符串大小(例如5000)
最终通过./pattern_offset.rb (EIP地址)0x356b4234 5000 来计算出最终的buffer大小。
如果buffer过大,其实可以先大致的确定其大体部分,再把这个模型附加在后面,会更省时间和计算量。
//在gdb下,由于无法像od那样每步跟踪,所以对于rip来说无法直接观测到被覆盖后的结果。因此我们需要直接对rbp进行观察,计算出了rbp之前的buffer后,就可以加上rbp的长度,然后继续溢出
peda可以方便的让你查看寄存器的信息和其他数据,它也是用python编写的,而且直接附加到gdb。
可以用jmpcall来搜寻一些跳板指令,如jmpcall rsp
|
评分
-
查看全部评分
|