Skip to content

Instantly share code, notes, and snippets.

@bahorn
Last active August 23, 2025 11:19
Show Gist options
  • Save bahorn/624596bbe235bffadb2b578d605f5cf5 to your computer and use it in GitHub Desktop.
Save bahorn/624596bbe235bffadb2b578d605f5cf5 to your computer and use it in GitHub Desktop.
file2cmdline.py - store an arbitary file in /proc/self/cmdline and expose it to the rest of the system
"""
file2cmdline.py - bah / august 2025 - MIT license
a very stupid trick to create a tmpfile without memfd or the other usual
approaches.
essentially just storing it in the /proc/PID/cmdline of a sacrificial process.
cat works well for this as it doesn't die instantly if it hits an non existant
file, and you can stall it if it sees a blocking file like /dev/stdout
abusing the filename to store code is a pretty well known trick, see all 9000
BGGP5 entries using it, but i've not seen anything about using it as a method of
getting an in-mem tempfile on systems without any writable filesystems.
what you might want this for is a undecided, maybe not bad for hitting more bugs
in userspace tools if you wanna get native code exec that way.
but you should just use python / perl to make a memfd, and load a shared object
from the memfd with a lolbin.
its way easier, and if you unmap() it and do a sleep mask you'll have no obvious
artifacts left in /proc/PID/maps.
sadly can't be mmap()'d, like most things in /proc/PID, so not possible to load
shared objects via this.
can fully write nullbytes via empty arguments and $'\n' lets you do whatever you
want with newlines.
"""
import argparse
import base64
def convert(b):
if b == b'':
return "''"
return f'${repr(bytes(b))[1:]}'
def main():
parser = argparse.ArgumentParser()
parser.add_argument('filename')
parser.add_argument('--shell', default='bash')
args = parser.parse_args()
shell = args.shell
blocks = []
b = b''
with open(args.filename, 'rb') as f:
b = f.read()
curr = bytearray()
last = False
for c in b:
last = False
if int(c) != 0:
curr.append(c)
else:
blocks.append(curr)
curr = bytearray()
last = True
if not last:
blocks.append(curr)
argv0 = convert(blocks[0])
args = ' '.join([convert(block) for block in blocks[1:]])
print(f'#!/usr/bin/{shell}')
print(f'exec -a {argv0} -- cat {args}')
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment