Where's mah Gibson, punk?
Hi y'all!
As mentioned here, I played around with some steganography. The idea was simple and unfancy: just a .ppm
file and some Python.
Why .ppm
? Because it’s stupidly simple: uncompressed RGB values, no PNG compression, or arcane metadata. Just bytes (although .ppm headers can have comments, so keep that in mind).
The Method
A .ppm header
Looking at the image above, the header is simply to get:
(0x50 0x36) → P6: binary PPM file
(0x0a) → newline
(0x36 0x34 0x30
) → 640: image width
(0x20) → space
(0x34 0x32 0x36
) → 426: image height
And bam—our header info.
And then we get 3 bytes at a time, for each pixel (RGB: Red, Green, Blue), defining the color of that precise byte.
After that, pixel data: 3 bytes per pixel (RGB). Nothing else.
To hide data, I zeroed the least significant bit (LSB) of each byte, which doesn’t really alter the image in a visible way. This gives you 3 bits per pixel to encode data. Stack those bits together and slice them in blocks of 8—now you have bytes. Bytes mean ASCII. ASCII means text.
That’s the gist. You can write an entire hidden message (or image, or audio) inside another image by tampering with just the LSBs.
To make this practical, I wrote a couple of Python scripts. You can find them here. Mess with that as you see fit.
Limitations?
Sure. Quite a few:
.ppm
headers with comments will throw things off. But you can easily code around that. Heck, have that as a homework if you'd like.- No encryption. Anyone with a hex editor and some free time can sniff it out.
- No error detection or correction. More homework.
- Every LSB is predictably overwritten—pattern detection is trivial.
- Any kind of compression or encryption on the container image kills the message.
OpSec Level: Meh
You’d probably want to:
-
Only use one LSB per pixel (maybe just Blue).
-
Randomize altered pixels with a PRNG.
-
Encrypt the payload beforehand.
...
But let’s be real—Chi-squared tests, histograms, stego‑detectors—if someone’s looking for it, they’ll find it.
Still, security through obscurity has its place (despite all the hate). Think authoritarian regimes where strong crypto might be illegal or where you might simply be forced to decrypt everything you own.
Just saying... it can be part of your 'onion'.
Malware Analysis Lab - The Barebones Setup
I’ve said before I’d blog about my lab setup. Never got around to it because I kept tweaking things or getting distracted by something shinier.
Goal here: no fancy stuff, just a focus on working securely with malware.
My current setup:
- a dedicated Mini-PC.
- a managed switch which has a port isolated for the Mini-PC
- a VLAN dedicated to that host
- a Raspery Pi as Gateway/firewall/logger for that VLAN
A true minimal setup:
- Your laptop
- Two VMs:
Flare VM (Windows + analysis tools)
REMnux (Linux + reverse engineering toolkit)
Essentials:
Keep malware VM networks disabled unless strictly needed
Take frequent snapshots
Log and document everything
Don’t aim for perfect—just safe and functional
That's it. I won't go further into this for now. If I find the need, I'll do it later. What you want is something that will let you experiment with some safe malware samples, learn the basic tools and avoid having your home invaded by your baddies.
🧙♂️ Back to Narnia (OverTheWire)
Yup, I’m back at it. I paused these CTFs months ago—wasn’t getting much out of them. Realized I needed to read more about shellcode and memory handling before diving deeper.
So now I’m back. And yeah, I’m also changing my mind about avoiding walkthroughs. Everyone does them, so I might as well add my spin: fewer spoilers, more insights. You’ll find the step-by-step mess here on GitHub (don’t expect polish).
narnia0
What’s this one about? Buffer overflows and UTF-8 stuffsesses. Simple code:
There's the Gibson <3
Buffer overflow by 4 bytes. The goal is to insert \xde\xad\xbe\xef
in little-endian form.
First instinct was to strings
, gdb
, and objdump
my way through. But you don’t need that. Just feed the program 20 garbage bytes (aaaaaaaa...
) followed by those 4 crafted bytes.
Small snag: input is treated as UTF-8. So outputting raw 0xde
didn’t work nicely.
Long story short, I learned that I couldn't easily output xde, and I did try, by looking at UTF-8/HEX lists, but it was a no go. I then decided to build a binary with printf:
printf "aaaaaaaaaaaaaaaaaaaa\xef\xbe\xad\xde" > /tmp/key
This solved the problem, but didn't elevate me to narnia1. A picture can explain more than a thousand words, and so a picture filled to the brim with words might be a wonder. So, here:
See at the top? the redirection is not returning an error message, but I am still user narnia0, and thus haven't really solved the issue. But why?
The issue is Linux related, to be fair. As we run the script with our payload, we're spawning a shell, but it is dying instantly since it's not connected to a tty. I needed to keep the shell opened, so I got the cat out of the bag. It forces the shell session to remain open and thus granting us permanence.
The shell is ugly, but we get elevated privileges (you can always load a nicer shell, if you really want to), and now we can search for the password. That's easy enough, so we can leave it out of this explanation.
That’s it for now. These blogposts are mostly memory aids and curiosity igniters. Narnia stuff goes to GitHub as I solve them, and I’ll post here only when there’s something worth rambling about.
Get your tools ready and keep exploring!
No comments:
Post a Comment