Pranks with Base64
Recently, I saw an encoded string on Twitter with a request to have people run the following in their terminals:
printf 'aW1wb3J0IHN1YnByb2Nlc3MKCnN1YnByb2Nlc3MuUG9wZW4oWyJzYXkiLCAibXkgYXNzIG5lZWRzIHRvIHBvb3AhIGhleSBldmVyeW9uZSwgbXkgYXNzIGZyZWFraW4gc3RpbmtzIGJlY2F1c2Ugb2YgYSBiaWcgY3JhcCBpbiBteSBhc3MiXSk=' | base64 -D | python
Of course I didn't run it - it's piping an encoded string to Python (meaning it will execute something) and that's dangerous. But what is it trying to run? I was curious, so I removed the final pipe to investigate. The script turned out to be:
import subprocess
subprocess.Popen(["say", "my ass needs to poop! hey everyone, my ass freakin stinks because of a big crap in my ass"])
Interesting...
It's been a while since I've done anything with Python, but I had a good idea of what this would do. I reattached the pipe to Python step so it would execute, and I turned out to be right: it generates speech that says "my ass needs to poop! hey everyone, my ass freakin stinks because of a big crap in my ass" and plays it through your speakers. Amazing.
April Fools Day is coming up, and what better way to celebrate than writing a script to embarrass people? I'm better known for bathroom jokes than a highbrow sense of humor, and I'm okay with that. But I also love writing about tech, so I want to try and make this accessible to everyone.
What's going on?
To understand what this command does, let's work backwards, starting with the Python script.
First, we import the built-in subprocess module, then we call Popen
, a constructor that creates a new subprocess with the arguments "say"
and "my ass needs to poop! hey everyone, my ass freakin stinks because of a big crap in my ass"
.
You can do a lot of complex stuff with subprocesses, but in this case, we're just running the Mac tool "say," followed by the second string. Translated to plain English, it's more or less equivalent to running this in your terminal:
say "my ass needs to poop! hey everyone, my ass freakin stinks because of a big crap in my ass"
You'd probably have a difficult time getting someone to run that, however (at least if you wanted to surprise them).
Here's where base64 comes in. Base64 is an encoding method that uses a base of...you guessed it, 64. If this sounds unfamiliar, Vaidehi Joshi did a really good intro to encoding here, but to simplify, base64 is just one way of representing text and other characters. Here's why it's important: the reason you can't get somebody to run the above command is that it includes words like "ass" and "crap." That's just no good - we want people's computers to start talking unexpectedly. So we use base64 to encode the message. Try this:
printf "my ass needs to poop! hey everyone, my ass freakin stinks because of a big crap in my ass" | openssl base64
It should output:
bXkgYXNzIG5lZWRzIHRvIHBvb3AhIGhleSBldmVyeW9uZSwgbXkgYXNzIGZyZWFraW4gc3RpbmtzIGJlY2F1c2Ugb2YgYSBiaWcgY3JhcCBpbiBteSBhc3M=
If we look even more closely, we'll see that this output contains a substring of the base64 in the original command that was tweeted. This encoded version, however, makes no obvious mention of asses or poop.
We're making progress, so now let's look at the command in its entirety.
First, the string we want our target to play through their speakers is placed in a say
call, and the Python script that is meant to make that call gets encoded. Next, we use printf
to input that encoded string into stdin. Then, we pipe it to base64 -D
(the -D stands for decode), and pipe that to the Python interpreter. The script is run, the message plays, and everyone thinks the person who ran it is moments away from pooping their pants.
How to construct your own command
Now that it's clear how the command works, you can create your own message. Start by creating a Python script similar to the one above, but substitute whatever message you like. Here's an example:
import subprocess
subprocess.Popen(["say", "Hey everyone, I have diarrhea! Listen up! Hey! I have diarrhea!"])
Save that file - I called mine lol.py
as an example. From the directory where you saved it, run this:
openssl base64 -in lol.py -out encodedlol.txt
This will use the OpenSSL library to encode your script and output it to encodedlol.txt
, or whatever filename you choose. To construct your command, just substitute the encoded string into the original format. In my case, it would be:
printf "aW1wb3J0IHN1YnByb2Nlc3MKCnN1YnByb2Nlc3MuUG9wZW4oWyJzYXkiLCAiSGV5IGV2ZXJ5b25lLCBJIGhhdmUgZGlhcnJoZWEhIExpc3RlbiB1cCEgSGV5ISBJIGhh
dmUgZGlhcnJoZWEhIl0p" | base64 -D | python
One final note - some of these command line tools are specific to the Mac (although the Python is not). Similar things exist for Windows and Linux, so if you want to use this on a different platform, you may need to dig a little.
Getting people to run it
I guess this counts as social engineering, which I don't have any real experience with. Sounds pretty impressive, but don't overthink it - getting people to execute arbitrary code is way easier than I thought. What worked for me was something like this:
"Hey, I'm having trouble with this encoded string, I think the output is kinda weird. Would you mind running this and telling me what you get?"
I got a few people with that, believe it or not. Obviously I don't want to throw anyone under the bus for lax security practices - I doubt that they'd have run it if I were a total stranger, but asking as an earnest coworker changed up the context entirely.
Anyway, this is probably the least technically helpful post I've ever written, but I thought it was fun. This silly project got me looking into OpenSSL command options and Python modules I'd probably never have looked at otherwise. Will I apply this knowledge in the future? Doubtful. But a big part of my technical curiosity comes from the ability to make your computer do things - I think this is the case for most other people too.
And if the thing you're making your computer do is tell a poop joke? Well, I'll be the last one to judge you for that.
Credit for the inspiring code: Jon Hendren