pwnable中的passcode题目以及GOT表和PLT表初识

首先解释一下GOT表和PLT表

GOT表是全局函数表(动态函数表,全局函数偏移量表)而PLT表则是局部函数表,GOT表中具有这个程序或者进程引用的所有的数据(包括函数和全局变量),PLT表中则是局部函数的表目,PLT表与GOT表是一一对应的,即PLT表中存储的是GOT表中的相对位置,而GOT表中存储的是函数的真正地址。在程序加载的时候,动态链接器会重定位GOT表中函数得到地址,即达到动态加载的过程。

PLT表与GOT表通过延时绑定,即将过程地址的绑定推迟到第一次调用该函数的时候,为了实现延时绑定,GOT表中的三个位置是特殊的:GOT[0]包含.dynamic段的地址,.dynamic段包含了动态链接器用来绑定过程地址的信息,比如符号的位置和重定位信息;GOT[1]包含动态链接器的标识;GOT[2]包含动态链接器的延迟绑定代码的入口点。GOT的其他表目为本模块要引用的一个全局变量或函数的地址。同样PLT表中有一个位置是特殊的,PLT[0]中保存的是相当于一个函数的一串代码,他跳到动态链接库中执行。每一个数据的PLT表目中的数据是由三部分组成的:第一条指令是跳转到相应的GOT存储的地址值中.第二条指令把函数相应的ID压入栈中,第三条指令跳转到PLT[O]中调用动态链接器解析函数地址,并把函数真正地址存入相应的GOT表目中。GOT表的初始化函数地址是PLT表中的第二条指令的地址,在函数被调用一次之后,GOT表中的函数地址的值就会变为真正的函数地址的值,在下一次调用函数的时候,只会花费一条指令和一个间接的存储器引用。

下面是具体的函数第一次调用的过程

首先是跳转到相应的PLT表中,此时该PLT表中的指令为

0x000001 jmp GOT
0x000002 push id
0x000003 jmp PLT[0]

GOT表中的内容

id:
0x000002

首先是程序执行到jmp GOT  进入GOT表中之后又跳转到0x000002位置即push id处将函数的id压入栈中,接着跳转到jmp PLT[0]的位置执行相应的动态链接库中查找该函数的真实地址的操作,并且把真实地址写入到GOT表中,在下一次调用函数的时候直接就进入GOT表中的相应位置,这是跳转的地址就直接到了真是函数地址的入口处,开始执行相应的代码

 

在执行完6之后GOT表中的id为3的函数的地址就变为函数的真实入口地址

 

再看这个题目

 

查看源代码发现漏洞很明显,scanf函数后面没有加 &所产生的漏洞原理

输入scanf(“%d”,&passcode)时读取的是passcode的地址0x70707070

当输入scanf(“%d”,passcode)时读取的是passcode这个地址的存储内容即0x80808080

如果我们可以控制0x80808080这个内容,那我们就可以利用这个漏洞进行GOT表的覆写

首先是检查一下有没有加壳,发现没有加壳
然后查看是32位的程序

用gdb调试一下程序在各个函数入口处下一个断点运行

我们写入数据存储的地方是0xffffd268   地址为edp-0x70  此时ebp的地址为

其中红色标识的部分是启用了栈溢出保护措施,再继续向下执行

进入到login函数中,发现两者的ebp相同

继续向下看,反编译一下login函数

发现scanf要读取的地址就是ebp-0x10(前面的两个参数从右向左依次压栈),两者ebp地址又相同,也就是scanf要写入的地址会从输入的name变量中读取,这就给了我们控制写入地址的机会

在IDA反编译中也可以看到passcode1的地址

 

 

两者的距离为0x60 即96个字节,最后的四个字节恰好是要写入的地址,那么我们怎么知道哪些地址可以写入呢,答案就是GOT表可以写入,我们可以将scanf后面的函数在GOT表中的真实函数地址写为我们想要执行的函数地址如(system)就可以获得相应的权限或者直接拿到flag

看到后面运行了fflush函数  puts函数  exit函数

这三个函数都可以,我们的目的是通过覆写GOT表在执行完scanf后直接执行system函数

我们看一下函数的地址

选这三个函数都可以,因为都在login中调用,我们选择最近的fflush函数,他的地址为0x0804a004

也就是说我们输入的name字段的最后四位是这个地址

我们再来查找system函数的地址,我们的目的是获取flag,因此要执行的是验证成功之后的system('/bin/bash cat flag')而不是单纯的system函数,他是有参数的于是我们选择地址0x80485e3,参数地址0x80487af

这样playload就出来了
由于scanf输入passcode1时是\d因此我们要先把地址转换为十进制

'a'*96 + '\x00\xa0\x04\x08'+ '\n'+'134514147\n'

连上服务器

python -c print('a'*96 + '\x00\xa0\x04\x08'+ '\n'+'134514147\n') | ./passcode

成功拿到flag

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值