I'm working on an online CTF challenge and I need to somehow give raw bytes to this compiled C program. I've tried the following using python:
./program `python -c 'print "\x00\x00"'`
... but for some reason that doesn't seem to be giving me what I'm expecting. Is there some conversion/formatting that's happening that I'm not aware of? I would expect this to give raw bytes as an argument.
Command line args in C are an array of 0 terminated strings. There is no way to pass "raw bytes" (any 0 byte won't behave as expected).
I'd suggest passing either reading the bytes from stdin or from a file specified on the command line.
Related
import subprocess
result = subprocess.run(['pkexec', 'apt', 'update'], stdout=subprocess.PIPE)
print(result.stdout)
print(result.stdout) returned a very long string. See below.
pprint.pprint(result.stdout) returned the same content as a block of sentences. See below.
I would like the print out of result.stdout to be similar to the terminal print out when executing sudo apt update. How can I achieve it with python 3.6 found in Ubuntu 18.04?
The reason you get a block of "text" is that the output is not an actual string (which is utf-8 encoded in Python 3) but a bytes object. This is seen from the b being written in front of the text. In order to turn a bytes object into a string it needs to be "decoded."
To decode the bytes object the text.decode() method is used, for the particular string in this question that turns into
print(result.stdout.decode())
The bytes object can be of any coding, therefore the .decode() call accepts a parameter which tells which coding that is supposed to be decoded. The most common one is utf-8 so if no parameter is given, this is assumed. However, specifically on Windows systems, also other codings exists (e.g. "latin1"). To decode a "latin1" bytesobject the call would thus look like
print(text.decode("latin1"))
The opposite operation, which encodes a string to a bytes object is also available. Logically enough it is called .encode() and is typically used in protocols that stream the data to another destination (e.g. over the Internet or to disc). Also this call accepts code argument, that allows the text to be encoded as e.g. "latin1" even though the default is "utf-8".
I'm working on a problem which involves performing a buffer overflow on a C program. The program asks for a command line input from the user, and I need to use this input to enter in my byte string including nops, shellcode, ret address, etc. The problem is the c program interprets everything I enter as a literal string, so if I enter in something like "\xff\xab\x12..." the program will interpret each separate character as a different byte. I can enter in separate bytes by creating a string of the corresponding ASCII characters for each byte, but this limits me to hex values 00-7F for my byte values. I'm wondering if there's some way I can use python to enter in the byte string, or possibly format the user input so that the C program interprets it the way I need it to. Please note that I don't know what the return address of the byte string will be until after I start running the program, so I can't make the byte string prior to running the C program I'm working on a Linux x86 shell, and I do not have the source code for the C program.
I've tried calling python to print the string I need into the input using commands like,
$(python -c 'print "\x41" * 205 + "\x34\x86")
but the C program just interprets all these characters literally. I've also tried using extended ASCII characters but the C program doesn't seem to interpret them correctly, associating them all with an unknown character symbol and 0xc3 hex value. Is it possible there is some other character/hex mapping that the C program may be using?
If anyone knows a way I can enter the input the way I need to, your help would be very much appreciated.
thanks
You were missing a semicolon (') in your shell call to python. Additionally:
If your executable takes its input in the form of a CLI argument:
$ ./yourprog $(python -c 'print "\x41" * 205 + "\x34\x86"')
If it takes its input in the form of STDIN:
$ python -c 'print "\x41" * 205 + "\x34\x86"' | ./yourprog
Replace "./yourprog" with the name of your executable.
I have a quick question. I got the following bash script from my friend, but I don't know what /inline/b64/ is, and how the following code segment works.
I have some experience with bash, and Python, but I cannot understand the following code fragment at all. Could anyone please give me some enlightenment?
More specifically,
1) What does /inline/b64 mean? I did some search on the web, but I couldn't find any clues.
2) What does the following command mean?
ENCODED_COMMAND=$(python <<EOF
3) What's the purpose of these kinds of encoding?
#!/bin/bash
COMMAND="FILTER file utterance_id /tmp/my_utt_list"
ENCODED_COMMAND=$(python <<EOF
import base64
print base64.urlsafe_b64encode('$COMMAND')
EOF
)
$BIN --edit_commands="/inline/b64/$ENCODED_COMMAND"
This depends on what the value of $BIN is. Presumably this is some other script which supports an --edit_commands flag. You would need to what that other script is expecting for this value to be able to interpret it.
This is combining a couple of bits of bash syntax. First, $(...) means "execute the enclosed command and capture its output as a string". Second, the <<EOF means that the following lines until the second EOF should be passed to the standard input of the command. So taken together, this is executing the Python script between the two EOFs, capturing its output, and assigning it to the ENCODED_COMMAND variable.
The script is taking some string, $COMMAND, and using the Python base64.urlsafe_b64encode function to encode it with Base64. The encoded string is then being passed to some unknown command, $BIN, which will presumably do something with it — perhaps decode and execute it in some way.
I was looking for a way to run an external process from python script and print its stdout messages during the execution.
The code below works, but prints no stdout output during runtime. When it exits I am getting the following error:
sys.stdout.write(nextline) TypeError:must be str,not bytes
p = subprocess.Popen(["demo.exe"],stdout = subprocess.PIPE, stderr= subprocess.PIPE)
# Poll process for new output until finished
while True:
nextline = p.stdout.readline()
if nextline == '' and p.poll() != None:
break
sys.stdout.write(nextline)
sys.stdout.flush()
output = p.communicate()[0]
exitCode = p.returncode
I am using python 3.3.2
Python 3 handles strings a bit different. Originally there was just one type for
strings: str. When unicode gained traction in the '90s the new unicode type
was added to handle Unicode without breaking pre-existing code1. This is
effectively the same as str but with multibyte support.
In Python 3 there are two different types:
The bytes type. This is just a sequence of bytes, Python doesn't know
anything about how to interpret this as characters.
The str type. This is also a sequence of bytes, but Python knows how to
interpret those bytes as characters.
The separate unicode type was dropped. str now supports unicode.
In Python 2 implicitly assuming an encoding could cause a lot of problems; you
could end up using the wrong encoding, or the data may not have an encoding at
all (e.g. it’s a PNG image).
Explicitly telling Python which encoding to use (or explicitly telling it to
guess) is often a lot better and much more in line with the "Python philosophy"
of "explicit is better than implicit".
This change is incompatible with Python 2 as many return values have changed,
leading to subtle problems like this one; it's probably the main reason why
Python 3 adoption has been so slow. Since Python doesn't have static typing2
it's impossible to change this automatically with a script (such as the bundled
2to3).
You can convert str to bytes with bytes('h€llo', 'utf-8'); this should
produce b'H\xe2\x82\xacllo'. Note how one character was converted to three
bytes.
You can convert bytes to str with b'H\xe2\x82\xacllo'.decode('utf-8').
Of course, UTF-8 may not be the correct character set in your case, so be sure
to use the correct one.
In your specific piece of code, nextline is of type bytes, not str,
reading stdout and stdin from subprocess changed in Python 3 from str to
bytes. This is because Python can't be sure which encoding this uses. It
probably uses the same as sys.stdin.encoding (the encoding of your system),
but it can't be sure.
You need to replace:
sys.stdout.write(nextline)
with:
sys.stdout.write(nextline.decode('utf-8'))
or maybe:
sys.stdout.write(nextline.decode(sys.stdout.encoding))
You will also need to modify if nextline == '' to if nextline == b'' since:
>>> '' == b''
False
Also see the Python 3 ChangeLog, PEP 358, and PEP 3112.
1 There are some neat tricks you can do with ASCII that you can't do with multibyte character sets; the most famous example is the "xor with space to switch case" (e.g. chr(ord('a') ^ ord(' ')) == 'A') and "set 6th bit to make a control character" (e.g. ord('\t') + ord('#') == ord('I')). ASCII was designed in a time when manipulating individual bits was an operation with a non-negligible performance impact.
2 Yes, you can use function annotations, but it's a comparatively new feature and little used.
While the accepted answer will work fine if the bytes you have from your subprocess are encoded using sys.stdout.encoding (or a compatible encoding, like reading from a tool that outputs ASCII and your stdout uses UTF-8), the correct way to write arbitrary bytes to stdout is:
sys.stdout.buffer.write(some_bytes_object)
This will just output the bytes as-is, without trying to treat them as text-in-some-encoding.
I need to call an executable in a python script and also pass binary data (generated in the same script) to this executable.
I have it working like so:
bin = make_config(data)
open('binaryInfo.bin', 'wb+').write(bin)
os.system("something.exe " + "binaryInfo.bin")
I thought I could avoid creating the binaryInfo.bin file altogether by passing 'bin' straight to the os.system call:
bin = make_config(data)
os.system("something.exe " + bin)
But in this case I get an error:
"Can't convert 'bytes' object to str implicitly"
Does anyone know the correct syntax here? Is this even possible?
Does anyone know the correct syntax here? Is this even possible?
Not like you're doing it. You can't pass arbitrary binary data on the UNIX command line, as each argument is inherently treated as null-terminated, and there's a maximum total length limit which is typically 64KB or less.
With some applications which recognize this convention, you may be able to pipe data on stdin using something like:
pipe = os.popen("something.exe -", "w")
pipe.write(bin)
pipe.close()
If the application doesn't recognize "-" for stdin, though, you will probably have to use a temporary file like you're already doing.
os.system(b"something.exe " + bin)
Should do it.. However, I'm not sure you should be sending binary data through the command line. There might be some sort of limit on character count. Also, does this something.exe actually accept binary data through the command line even?
how bout base64encoding it before sending and decoding on the other end... afaik command line arguments must be ascii range values (although this maynot be true... but I think it is..) ...
another option would be to do it the way you currently are and passing the file ...
or maybe see this Passing binary data as arguments in bash