Reputation: 21
what happens if a program receives as an argv[1] argument a string with a null terminator in the middle? for example:
./program test'\0'example
what is the value of argv[1]? is it test? is it test\0example? I have these lines of code
max = sizeof(filename);
len = strlen(argv[1]);
if (len > max) goto error;
strcpy(filename, argv[1]);
I need to build an exploit for this program and what I wanted to do, is making argv[1] worth test'\0'example so strlen(argv[1])=strlen("test")=4 and strcpy(filename, argv[1])=strcpy(filename, "test") so I can use the rest of the string (the example part) to put my exploit. is it possible? thank you very much?
Upvotes: 1
Views: 5300
Reputation: 263197
argv[1]
is a pointer object of type char*
. Its value is an address, not a string. Specifically, its value is the address of a char
object whose value is 't'
.
The C standard (in section 7.1.1) has the following definitions:
A string is a contiguous sequence of characters terminated by and including the first null character.
[...]
A pointer to a string is a pointer to its initial (lowest addressed) character. The length of a string is the number of bytes preceding the null character and the value of a string is the sequence of the values of the contained characters, in order.
Since argv[1]
points to the first of a contiguous sequence of characters, one of which is a null character, it's a pointer to a string. The value of that string is "test" (which includes the terminating '\0'
), and the length of the string is 4.
It's common to say, as a kind of verbal shorthand, that the value of argv[1]
is "test"
, but that's imprecise -- especially in a case like this where the distinction between the value of a string and the value of the array containing that string is significant.
argv[1]
also points to the first character of an array of characters. The first 5 bytes of that array contain the string "test"
. The entire array contains the character values:
{ 't', 'e', 's', 't',
'\0',
'e', 'x', 'a', 'm', 'p', 'l', 'e',
'\0' }
If you pass the value of argv[1]
to a string function, that function will only see "test"
, and will not access anything past the terminating '\0'
. The rest of the contents of the array are still perfectly valid, and can be accessed using functions (like memcpy
) that don't just operate on strings.
Whether it's possible to invoke your main program in such a way that argv[1]
will point to the first element of an array with those particular contents is another matter, one that depends on your operating system.
Upvotes: 2
Reputation: 108968
Your idea works when main()
is called from within main()
#include <stdio.h>
int main(int argc, char **argv) {
if (argc == 1) {
char *data[] = {"", "5one\0two", "7three\0four", "6five\0six"};
main(4, data); // call main again, with exploitable data
} else {
if (!argv[0][0]) { // test for empty argv[0]
for (int i = 1; i < 4; i++) {
printf("%s ==> %s\n", argv[i] + 1, argv[i] + argv[i][0] - '0');
}
}
}
return 0;
}
I'm not sure if it will work when main()
is called from the C library initialization code ... or even if you can make your shell accept a NUL character as part of an argument.
Upvotes: 0
Reputation: 75545
The value of argv[1]
will be "test"
, assuming you actually manage to get a real NULL character on the terminal and not just the literal characters \
and 0
.
As RedAlert's comment mentioned, strlen
and strcpy
both stop on a null character, so getting a null character will not help for most exploits.
You most likely need to find a way to do the exploit without using the character \0
.
Upvotes: 0