If you change your process startup to
p = process(["strace", "-o", "strace.out", "./bof"])
and check the resulting strace.out file, you will see:
close(0) = 0
open("/dev/tty", O_RDWR|O_NOCTTY|O_TRUNC|O_APPEND|FASYNC) = 0
execve("/bin/sh", NULL, NULL) = 0
...
read(0, 0x55ae7a6d5aa0, 8192) = -1 EIO (Input/output error)
So this has to do with shellcode reopening stdin as /dev/tty.
Let's check the doc:
stdin (int) – File object or file descriptor number to use for stdin.
By default, a pipe is used. A pty can be used instead by setting this
to PTY. This will cause programs to behave in an interactive manner
(e.g.., python will show a >>> prompt). If the application reads from
/dev/tty directly, use a pty.
and do as it says:
p = process("./bof", stdin=PTY)
Voila!
[*] Switching to interactive mode
Type in your name:
$ id -u
1000
Answer from mephi42 on Stack ExchangeThis is a relatively old question, but I recently stumbled across the same problem myself. In the interest of the greater good, I will explain what is going on.
It is likely that the structure of your payload (the entire sequence of bytes you send to the process) is something like this:
PADDING + SHELLCODE + RETURN_ADDRESS
Sadly, this does not work well with pwntools' shellcode. The reason is that the push instructions modify the stack, where your shellcode is. This means that the shellcode is (unintentionally) mutated to something else, and of course shenanigans ensue.
The solution is to add some padding after the shellcode. Because the stack grows to lesser addresses, push instructions will first overwrite the data in the greater address locations.
PADDING + SHELLCODE + **MORE_PADDING** + RETURN_ADDRESS
For me, MORE_PADDING of 32 bytes worked nicely. Do not forget to reduce the size of the original PADDING appropriately so that the return address is correctly overwritten.
When encountering such issue, you should keep debugging. After breaking on the payload you can notice GDB is showing these instructions (as Intel flavor disassembly):
push 0x68
push 0x732f2f2f
push 0x6e69622f
mov ebx,esp
push 0x1010101
xor DWORD PTR [ecx+eax*1],0x51c93101
push 0x4
This XOR instruction is suspicious since it is using eax and ecx while they've not been initiliazed by our shellcode. I checked against what pwnlib instructions suggest for this shellcode:
shellcraft.i386.linux.sh()
/* ... */
xor dword ptr [esp], 0x1016972
/* ... */
Then, you're still getting a SEGFAULT because the instruction is wrong, and dereferencing some incorrect values.
Also the second shellcode you're providing can be retrieved with shellcraft.execve('/bin/sh').
EDIT
The issue is not from pwntools but must be linked to the way the payload is used. The bad instruction identified above contains a '$' character which is then (if you still use your $(python -c '...') input) interpreted by the subshell invoked as the variable name '$ri'.
This variable is likely not defined in your shell which in turn makes these 3 characters to be deleted from the input given to the program, hence, modifying operands of this instruction and the instruction following it.
In order to make it right, you may sanitize the input by bringing whatever is required. For example :
asm(shellcraft.i386.linux.sh()).replace('
')
I suppose it is the issue you got, but can't be sure without more information.