Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game. |
| Notices |
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
 |
GNU/Linux Basic Guide
This 255-page guide will provide you with the keys to understand the philosophy of free software, teach you how to use and handle it, and give you the tools required to move easily in the world of GNU/Linux. Many users and administrators will be taking their first steps with this GNU/Linux Basic guide and it will show you how to approach and solve the problems you encounter.
Click Here to receive this Complete Guide absolutely free. |
|
 |
08-19-2011, 12:33 PM
|
#1
|
|
LQ Newbie
Registered: Aug 2011
Posts: 3
Rep: 
|
Can't inject x00 value with bash-printf using string format vulnerability in x64
Hello! This is my first post here! So, here's the problem: I'm following a nice book called Hacking - The Art Of Exploitation. I'm at the point in wich the string format vulnerability is being explained. I've learned how to do it and on a x32 system of mine: it worked flawlessly. But on my x64 Ubuntu, I can't make it work.
This is the code of the program wich I need to exploit:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
char text[1024];
static int test_val = -72;
if(argc < 2) {
printf("Usage: %s <text to print>\n", argv[0]);
exit(0);
}
strcpy(text, argv[1]);
printf("The right way to print user-controlled input:\n");
printf("%s", text);
printf("\nThe wrong way to print user-controlled input:\n");
printf(text); // HERE IS THE VULNERABILITY
printf("\n");
// Debug output
printf("[*] test_val @ 0x%08x = %d 0x%08x\n", &test_val, test_val, test_val);
exit(0);
}
I have to input a string witch begins with the memory location of test_val, then some %08x. that reads the shit in the stack of main, then a %n parameter where I find the written address which on the inputed string to change the value of test_val to the number of writen bytes.
Normaly i would have to input this to make it work:
kaos@ubuntu$ ./a.out $(printf "\x40\x56\x5f\x6a")%08x.%08x.%08x.%08x.%08x%n
The problem in the x64 system is that test_val is located at 0x601080 (3 bytes) and when I input $(printf "\x80\x10\x60\x00"), it seems that \x00 doesn't input anything, because I think it's related to NULL as a string end.
Thus, I got a segmentation error all the times that I try because the address isn't valid.
How can I inject that 00? Or how can I write the address to make it readable to the %n parameter? It's just impossible? Hope I've made myself understood!
If there's anything unclear I can answer all the questions!
Thanks! 
Last edited by kaos_npc; 08-19-2011 at 12:35 PM.
|
|
|
|
08-19-2011, 01:45 PM
|
#2
|
|
Senior Member
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 2,967
Rep: 
|
Quote:
Originally Posted by kaos_npc
The problem in the x64 system is that test_val is located at 0x601080 (3 bytes) and when I input $(printf "\x80\x10\x60\x00"), it seems that \x00 doesn't input anything, because I think it's related to NULL as a string end.
Thus, I got a segmentation error all the times that I try because the address isn't valid.
|
Fortunately vulnerabilities aren't meant to be reliable. I'm also wondering how printing the address to standard output results in it being written to the stack right after printf's first argument, unless printf always has a stack-allocated output buffer at the beginning of the function.
Kevin Barry
PS It would be easier to just use an argument that's 1028 bytes long and overwrite test_val with strcpy, or if you're dead-set on %n use a string that writes past printf(text/*<--here*/); on the stack and write the address there (which could incidentally compromise the operation of strcpy, probably defeating your own effort).
Last edited by ta0kira; 08-19-2011 at 01:53 PM.
|
|
|
|
08-19-2011, 02:07 PM
|
#3
|
|
LQ Newbie
Registered: Aug 2011
Posts: 3
Original Poster
Rep: 
|
Quote:
Originally Posted by ta0kira
Fortunately vulnerabilities aren't meant to be reliable. I'm also wondering how printing the address to standard output results in it being written to the stack right after printf's first argument, unless printf always has a stack-allocated output buffer at the beginning of the function.
Kevin Barry
PS It would be easier to just use an argument that's 1028 bytes long and overwrite test_val with strcpy, or if you're dead-set on %n use a string that writes past printf(text/*<--here*/); on the stack and write the address there (which could incidentally compromise the operation of strcpy, probably defeating your own effort).
|
Yo thx for the answer!  I tought there was a method to print x00 with printf. No, I don't care about owning the program with the other overflows, because this was just an example. =) I'm just a little worried about all the times when I'll find adresses that start with 00.
|
|
|
|
08-19-2011, 05:35 PM
|
#4
|
|
Senior Member
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 2,967
Rep: 
|
Quote:
Originally Posted by kaos_npc
Yo thx for the answer!  I tought there was a method to print x00 with printf. No, I don't care about owning the program with the other overflows, because this was just an example. =) I'm just a little worried about all the times when I'll find adresses that start with 00.
|
You've got at least 3 things working against your attempt to pass 0x00 directly: - The shell (bash, anyway) will discard null characters:
Code:
$ value="$(printf '12\x0034')"
$ echo ${#value} "$value"
4 1234
- execve will only read argument characters up until a null character:
Code:
#include <stdio.h>
#include <unistd.h>
static void show(char *oOne, char *tTwo)
{
fprintf(stderr, "%p:\t'%s'\n", oOne, oOne);
fprintf(stderr, "%p:\t'%s'\n", tTwo, tTwo);
fprintf(stderr, "[offset %i]\n", (int) (tTwo - oOne));
}
int main(int argc, char *argv[], char *envp[])
{
if (argc == 3)
{
show(argv[1], argv[2]);
return 0;
}
char arg1[] = "12\00034\000hello";
char *arg2 = arg1 + 6;
show(arg1, arg2);
char *new_argv[] = { argv[0], arg1, arg2, NULL };
execve(argv[0], new_argv, envp);
return 1;
}
Code:
$ ./a.out
0x7fff23b85ae0: '12'
0x7fff23b85ae6: 'hello'
[offset 6] <-- 12\00034\000
0x7fffb7406146: '12'
0x7fffb7406149: 'hello'
[offset 3] <-- not far enough apart for \00034\000 to be present
- strcpy and printf will stop reading the string upon encountering a null character.
Kevin Barry
PS Ubuntu 64-bit uses 32-bit addresses, in case it wasn't obvious.
Last edited by ta0kira; 08-19-2011 at 05:59 PM.
Reason: made execve example more instructive, added comment
|
|
|
|
08-20-2011, 07:50 AM
|
#5
|
|
LQ Newbie
Registered: Aug 2011
Posts: 3
Original Poster
Rep: 
|
Quote:
Originally Posted by ta0kira
You've got at least 3 things working against your attempt to pass 0x00 directly: - The shell (bash, anyway) will discard null characters:
Code:
$ value="$(printf '12\x0034')"
$ echo ${#value} "$value"
4 1234
- execve will only read argument characters up until a null character:
Code:
#include <stdio.h>
#include <unistd.h>
static void show(char *oOne, char *tTwo)
{
fprintf(stderr, "%p:\t'%s'\n", oOne, oOne);
fprintf(stderr, "%p:\t'%s'\n", tTwo, tTwo);
fprintf(stderr, "[offset %i]\n", (int) (tTwo - oOne));
}
int main(int argc, char *argv[], char *envp[])
{
if (argc == 3)
{
show(argv[1], argv[2]);
return 0;
}
char arg1[] = "12\00034\000hello";
char *arg2 = arg1 + 6;
show(arg1, arg2);
char *new_argv[] = { argv[0], arg1, arg2, NULL };
execve(argv[0], new_argv, envp);
return 1;
}
Code:
$ ./a.out
0x7fff23b85ae0: '12'
0x7fff23b85ae6: 'hello'
[offset 6] <-- 12\00034\000
0x7fffb7406146: '12'
0x7fffb7406149: 'hello'
[offset 3] <-- not far enough apart for \00034\000 to be present
- strcpy and printf will stop reading the string upon encountering a null character.
Kevin Barry
PS Ubuntu 64-bit uses 32-bit addresses, in case it wasn't obvious.
|
Thanks a lot for the proof! ^^ I'm glad I've been clarified!
|
|
|
|
| Thread Tools |
Search this Thread |
|
|
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -5. The time now is 03:07 AM.
|
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|