How to pass \x00 as argument to program?
Asked Answered
M

6

7

I have a small program where I wish to pass shellcode as argument. In the shellcode, there is a necessity to pass \x00. I tried the following command:

./program `python -c 'print "\x01\x00\x00\x00\x9c\xd8\xff\xbf"'`

But the \x00 doesn't get registered at all! The arguments passed to the program are "\x01\x9c\xff\xbf".

I don't think it's a problem with python, but rather with the shell which passes the argument. I am using the bash shell.

Now, how do I force the shell to pass the argument '\x00'?

Thanks and Regards,
Hrishikesh Murali

Menorca answered 6/9, 2011 at 7:17 Comment(0)
S
2

Not at all. Unix uses C-style strings for the arguments a command is invoked with, and they are NUL-terminated character sequences.

What you can do is to rewrite your program (or find an invocation variant) to accept the parameter in its standard input. NUL bytes work just fine there and are, in fact, widely used, typically as separators for file names, since they are pretty much the only thing a file name can never contain. See find's -print0 switch and xarg's switch -0 for the arguably most popular examples.

Swords answered 6/9, 2011 at 7:35 Comment(2)
Thanks! But I have no control over the program, hence I cannot change it. Is it possible to do it without changing the program?Menorca
No. You'd need to change the OS in a fairly fundamental detail.Cherlycherlyn
A
2

If you check with wc, you'll find that the NUL character is indeed passed:

$ python -c 'print "\x00"' | wc -c
2

To get rid of the newline at the end:

$ python -c 'import sys; sys.stdout.write("\x00")' | wc -c
1

This data is passed to the script, but the problem is that NUL can not be part of a variable value.

To see how, try to pass this to a script:

$ cat test.sh 
#!/usr/bin/env bash
echo ${#1}
$ ./test.sh "$(python -c 'import sys; sys.stdout.write("\x00")')"
0

Gone. But there's a way to save the day - Read from standard input, using either redirection or a pipe:

$ cat test2.sh 
#!/usr/bin/env bash
wc -c
$ ./test2.sh < <(python -c 'import sys; sys.stdout.write("\x00")')
1
$ python -c 'import sys; sys.stdout.write("\x00")' | ./test2.sh
1
Aerograph answered 21/3, 2012 at 11:6 Comment(0)
P
1

the xargs command with --null option can help:

python -c 'print "\x30\x00\x31"' | xargs --null ./program

I tried that, and it worked.

Preference answered 31/7, 2015 at 6:43 Comment(0)
H
0

I believe this is because Bash discards null characters.

To test this I used the od command to dump out the parameters in octal format, using the following script:

$ cat script.sh

#!/bin/bash
echo "$@" | od -c

and ran it using:

$ script.sh `python -c 'print "\x01\x00\x00\x00\x9c\xd8\xff\xbf"'`
0000000 001 234 330 377 277  \n
0000006

The null characters are not printed.

To get around this issue pass in a hexdump and then reverse it in your program. Example:

$ cat script.sh

#!/bin/bash
echo "$@" | xxd -r -p | od -c

$ script.sh `python -c 'print "\x01\x00\x00\x00\x9c\xd8\xff\xbf"' | xxd -p`
0000000 001  \0  \0  \0 234 330 377 277  \n
0000011                                    

Now you see that the null characters are printed.

Hawkweed answered 6/9, 2011 at 7:43 Comment(3)
The above program (xxd) doesn't pass the shellcode as it is, but it passes the ascii representation of the shellcode as argument. This is as good as typing 'print "10009cd8ffbf"'.Menorca
yes, that's what I said. You can't pass in a null character, so you have to encode it into hex first, using xxd.Hawkweed
Bash can't do anything about it (else, we could just create a wrapper program to invoke the target without involving a shell), it's tied to the standard execvp suite of calls, and they simply take a char** for the argument list. There's just no way to get 0 bytes through there.Swords
E
0

You can try putting the shellcode in a file and then read it back and pass it to the executable.

something like:

$ cat shellcode.txt
\xb5\x06\x40\x00\x00\x00\x00\x00

$ perl -e ' $a = `cat shellcode.txt`; chomp($a); print $a x 10; '
\xb5\x06\x40\x00\x00\x00\x00\x00\xb5\x06\x40\x00\x00\x00\x00\x00\xb5\x06\x40\x00
\x00\x00\x00\x00\xb5\x06\x40\x00\x00\x00\x00\x00\xb5\x06\x40\x00\x00\x00\x00\x00
\xb5\x06\x40\x00\x00\x00\x00\x00\xb5\x06\x40\x00\x00\x00\x00\x00\xb5\x06\x40\x00
\x00\x00\x00\x00\xb5\x06\x40\x00\x00\x00\x00\x00\xb5\x06\x40\x00\x00\x00\x00\x00

use the above perl cmdline as argument to the program

$ ./program $(perl -e ' $a = `cat shellcode.txt`; chomp($a); print $a x 10; ')
Edmiston answered 8/9, 2011 at 17:5 Comment(0)
R
0

You can try this,

main.out `perl -e 'print "xxxxssssdd\x23\x00\xaf"'`

and

perl -e 'print "xxxxssssdd\x23\x00\xaf"' | wc -c
13

It proves \x00 is passed.

By the way, I find c program surely stip \00 in argv in my test. You can examine the argv such as,

 x /8sb 0x7fffffffe46a
0x7fffffffe46a: "/home/victor/Documents/CDemo/overflow/shellcode2/shellcode_host.out"
0x7fffffffe4ae: '\220' <repeats 21 times>, "\353#YUH\211\345@\200\354\200H\211M\220H1\300H\211E\230H\211\302H\215u\220H\213}\220\260;\017\005\350\330\377\377\377/bin/sh\200\337\377\377\377\177"
0x7fffffffe4fb: "LC_PAPER=zh_CN.UTF-8"

So I guess shell or c program can stip \x00 chararcter automatically.Maybe someone can explain why it happens.

But we have other technique to avoid \x00 in shellcode.

mov     $59, %al # not %rax 
sub    $0x80, %spl  # not %rsp
xorq    %rax,  %rax # construct 0 value with rax

You can refer to the article. https://www.exploit-db.com/docs/english/13019-shell-code-for-beginners.pdf

Raimondo answered 4/10, 2018 at 13:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.