A little puzzle

About me

I came across this puzzle while looking for interesting work. I have not had the opportunity to use red teams skills outside of a lab and have been concerned with IT operations for so long that the thought of “hacking” has come and gone a few times. Every now and then I search for pen testing jobs on indeed, in this case I was specifically looking at the job offerings at a company that a friend of mine works for. With that being said, I had a great time completing this puzzle between work meetings and family time. I have never completed a CTF or Red team exercise before, so this was both very fun and very educational. I’ve included a summary below and a slightly edited version of my notes taken as I completed the puzzle , edited only to remove identifying information.

I have a very eclectic background but each team that I’ve worked with over the years will agree that I learn quickly, strive for improvement, and just generally do a good job. I’ve spent the last 12 or so months deciding whether to go back Cybersecurity (Security Analyst for 1 year and an AAS in CyberSecurity) or Software Engineering (Programmer Apprentice and freelance Web stuff) because I need a challenge and a change. I’ve been working in government for quite some time now and I’ve landed myself on a spectacular team that I would most definitely consider friends, but unfortunately I can’t base my career goals on my personal relationships and instead need to continue on my journey to something more interesting, with more responsibility, or that pays more money.

Puzzle Summary

I have made every effort to strip any details from my notes that might identify this puzzle to other’s who might attempt to solve it. I’d like to keep the puzzle on this blog to bring it to a whopping 2 articles, but I will remove it upon request.

The puzzle starts with a mention of an executable, but the page also includes two nearly identical images. The images turned out to be a distraction (or maybe not and I missed a different solution). The first step in solving the puzzle involved reverse engineering an ELF file, or Executable and Linkable Format file. Static analysis revealed no data. Dynamic analysis revealed a URL written to memory.

The URL redirected to a simple web application. The application relied on a function to populate a list of image names to the browser and another function that would return “combined” images. At the onset it was unclear if these images were being combined on the fly, served from local storage, or fetched from an external service. Based on some research, it was likely done on the fly with a Python library. Through trial and error and the modification of the client side code it was possible to browse directories, or at least see strings representing file and directory names, on the server outside of areas that were otherwise forbidden from browsing.

By trying a combination of inputs to the blending function, specifically those that should cause an error, it was found that the content of a given file could be retrieved. More specifically, the server side blend function accepted two arguments, but when one of the arguments was repeated the contents of the second argument was displayed, i.e. ?img1=something&img1=somethingelse, the contents of somethingelse from the server filesystem is shown. An important distinction is that ?img1=valid.jpg&img2=valid.jpg returned a “non-combined” image, but did not have the same behavior has described above.

Lessons Learned

Never forget Occam’s Razor, but there’s no harm in exhausting possibilities. The puzzle description implies that the solution is in the ELF file, but never says so explicitly. The presence of a distorted file led me to believe hidden data existed within said file, but in hindsight I wonder what hidden data might cause a consistent visual artifact across an entire image. Nothing is out of the realm of possibility, but I should have spent less time trying the same tactics on so many source files. What I mean is that I assumed steganography was the solution so on the images from the URL and also on the images from the puzzle description I tried the same tactics over and over again, which wasted time. If this were to happen again, I would script my attempts so as to be more efficient.

Regarding the final solution at the webserver, I don’t know if there are any tools that might have made my find any easier, but I felt it was important to use the clues I had and not simply use the shotgun method. At some point I was tempted to click lots of buttons in Burpsuite, but I decided against it as I didn’t want to bombard the server or get cheap win. More accurately, I didn’t want to use any tools I didn’t understand. I did use the intercept tab, but there’s nothing in Burpsuite that I used that I couldn’t also find in Firefox or Chrome’s dev tools. Overall, I’m happy with my results, and if I become a Security Professional again in the near future I look forward to learning how to more effectively use a much wider set of tools.

Note Dump

Getting started and initial thoughts. 
	1. Learn about elf
	2. Deploy a linux vm

Tasks in order
	1. Download 32bit (recommended) file. Open with  notepad++. Yep, looks like a binary.
	2. Start kali image download
	3. Research elf and find https://linux-audit.com/elf-binaries-on-linux-understanding-and-analysis/#what-is-elf
	4. Found Radare2 in from article above. Linked website is a bit broken and the domains feel sketchy. Give up on that for now.
	5. Kali download done. Deploy vm.
	6. Detonate. Ran the binary to see what it does (this is dangerous). Hedging my bets. Whatever it did, it did it in the background. If I wrote it, I'd phone home because that would be neat.
	7. Redeployed vm.
	8. "readelf -all file.32" - Yep it's an ELF file.
	9. Let's look for an email address "strings -a address.32|grep @ " Found something that looks like an email address
	10. Search the domain https://www.talosintelligence.com/ there's a mail server.
	11. Search the email address. String found in some github repos. Found a name.
	12. Search the name. Found of danish unix group dkuug. Probably not it. 
	13. virus total says 'The string "[email protected]" and various others are in the source of the glibc standard library' not it.
	14. Low hanging fruit all picked. Radare2 included in kali. Search for usage guide. Find https://www.megabeets.net/a-journey-into-radare-2-part-1/
	15. "r2 file.32"
	16. "aaa" to analyze all
	17. "s main" to get to main
	18. "pdf" to see the assembly
	19. Refresh my memory on assembly
	20. break
	
Back to it. Decide to try dynamic analysis instead
	1. start remnux download and deploy
	2. "VVV" for visual mode
	3. Found what looked like a for-loop. Looks like "do this math 20 times" 
	4. remnux ready
	5. Searched for remnux documents. Discovered edb. Opened elf file in edb
	6. Find entry point: plugins binaryinfo.
	7. Ran to what I expected was a loop I found earlier. Toggled a break point.
	8. Stepped through the remainder of the program and watched the stack. Found a goo.gl link related to the company
	9. Exit code 41
	10. Visited site. Inspected index and main.js. Attempted to query individual images but could not. Cloudfront stopped some requests. Could not browse directories
	11. Checked variations of filenames as ascii characters. No message.
	12. Downloaded the top two cat photos in the list, used a hex viewer to check for messages.
	13. Checked metadata with metadata2go and found "[minor] Skipped unknown 16 bytes after JPEG DQT segment" nothing found by just looking at the hex 
	14. Cyberchef extract EXIF, nothing interesting
	15. Cyberchef extract LSB, search string @, nothing obvious
	16. Break

I really want to get to the non-combined images
	1. Duplicated html elements to allow selecting the same image twice. Saved each to file. Now what? These aren't un-modified files, just combined with themselves.
	2. Break

Back to the elf files
	1. Started ghidra. Ghidra crashed on run. Give up.
	2. Started cutter. The prettiest so far and easy to use. Watched the loop build the url then return. Same URL and nothing else is obvious.
	3. Unsure how to proceed. Thoughts: Probe the server to look for vulns or look for more things in the images themselves? What am I allowed to scan, and how hard am I allowed to try? This is an amazon hosted app.
	4. Break. 

Fresh start. What have I learned? 
	• Refresher on assembly
	• randar2 and readelf static analysis techniques
	• edb and cutter in remnux for dynamic analysis
	• Confident there's nothing left in the binary to find.
	• Based on error messages verbatim, the web app is probably flask
	• The app hosted on amazon with some cloudfront protections
	• The images have no obvious signs of steganography
	• I can trick app into giving me non-blended images, though that doesn't mean they're "original"
	• No similarities between files besides type and header, no data gained by comparing differences between non-blended and blended. Unsure what method is being used for blending, but if flask, then maybe opencv? It's not being done on the client side since the response is a base64 of the blended image 
	• No obvious sign where the original files are hosted. Obvious paths are not-found or forbidden
	• instructions state that the files are the same but compiled differently...that should be verified
	• The persons on the puzzle instruction page looks modified or just lower quality?
	1. Downloaded both persons. The 32 bit, lower quality image is bigger in filesize
	2. Cyberchef to extract a message. Nothing found by clicking and guessing.
	3. The files are the same dimensional size but the "32bit" image has red dots, is that something? Seems like a plant because they're in a perfect grid.
	4. One more attempt with LSB. Nothing.
	5. cyberchef extract embedded files. Nothing definitive. Handful of zlib files. (png uses zlib I think, probably nothing)
	6. "binwalk file.png" found zlib
	7. "binwalk -e file.png" extracted ##.zlib
	8. installed zlib-flated. 
	9. zlib-flated -uncompress < ##.zlib > ##.flated
	10. ##.flated unknown filetype, no ELF header, not ascii.
	11. While binwalk only found the one at ##, cyberchef found many
	12. Use cyberchef to inflate zlibs, still nothing obvious.
	13. Back to kali tools. "zsteg -a file.png" nothing.
	14. Hit the google for some ideas. Nothing I haven't tried yet. Internet says look for more magic bytes and don't skip the simple stuff.
	15. break

Starting to wonder if these images of persons are the distraction.
	1. Not sure what to look for really. "java -jar stegsolver.jar" run through the basics. Nothing obvious.
	2. "pip3 install stegoveritas; stegoveritas_install_deps" (had to add .local/bin to $PATH)
	3. "stegoveritas file.png" found something interesting.
	4. Handfull of 7z that won't extract. More false positives?
	5. stegsolver again. Compare the 32 and 64 image. Image combiner shows the persons himself is the same size. That means it's being rendered on the website differently, not that it's been zoomed or cropped at the png level.
	6. Styles are identical. Bad choice chasing the website rendering I think. The files are different filesizes but identical dimensions, there has to be something in there.
	7. back in stegsolver found extra chunk data, and CRCs don't match. I knew this. Now what?
	8. break

Another reset. What else do we know
	• The 32 and 64 images have the same file info, but 32 is larger in filesize
	• 32 has hidden pixles per fotoforensics
	• cyberchef and stegovertias found possible embedded files. Could not open easily/nothing obvious.
	• lsb and strings checked with cyberchef and zsteg. Nothing found.
	• Stegsolver produced nothing obvious. The files are completely different with the 32bit having more chunks as well.
	• Probably nothing on the advertising website worth finding. Checked css and html
	• Both ELF files linked below the persons images writes a url to memory.
	• Probably nothing at URL. A distraction?: the webapp is simple and I hesitate to attack the server directly. Nothing obvious about the jpgs on the site or the client side js/html.
	• Googled some more advanced steg techniques. I like the idea that the reverse-engineering aspect was a decoy but I'm feeling more like it was actually the first step. I'm stuck on "there's something in the persons png..."
	1. Google for png steg writeups, what am I missing? No assumptions. Let's check both persons from the beginning
		a. "exiftool" both files show the same info except that 32 has a larger filesize
		b. "strings" nothing obvious
		c. "strings -n 10" nothing obvious
		d. "zsteg -a" nothing
		e. stegsolver channels reveal nothing
		f. stegsolver file format. The chunks are all different (different crc) and there's more chunks in the 32
		g. Image combiner (the blending website is hint?) nothing visually obvious found (They're different from each other....) Let's remove the extra chunks later then try this again.
		h. binwalk produced zlibs
		i. uncompress the zlibs
		j. binwalk the zlibs, both the compressed and uncompressed. nothing
		k. Cyberchef extract zlib at x##, uncompress, search for strings. Still nothing.
	2. Removed the extra IDAT sections with a hex editor for the 32 image. The bottom half of the image got removed(don't know what I expected)
	3. I want to generate a file that consists of the difference of 64.png uncompressed binary subtracted from 32.png uncompressed binary (Don't know how to do that yet, nor do I know if that would be fruitful).
	4. break

Back to the found url
	1. Look at main.js again. The ls function takes a path with '.', implying a relative path. Send a .. instead.
	2. Found secret folder with .txt files
	3. Forbidden from browsing the actual directories.
	4. Blend function errors when called with a non jpeg
	5. Blend function also accepts relative paths, but only jpeg. Retrieved gun.jpeg as above. Check for steg.
		a. strings nothing obvious
		b. zsteg does not support filetype
		c. exiftool 
		d. stegsolver guns.jpeg nothing obvious in the channels
		e. stegoveritas found nothing good. 
	6. Various combinations of get and blend to see what happens. Tried blending txt with jpeg, internal error
	7. lookup javascript xmlhttprequest - Same as address bar probably, not going to get more access.
	8. lookup 'REDACTED' and find documentation about PIL
	9. PIL exists on the server. PIL is a python image library. I'm going to send some python through the blend function
	10. string.replace() python sent through blend function. still returned an error. blend might check the filetype.
	11. Tried sending a request the didn't include filetypes, maybe they are ignored. Internal error
	12. Tried a different string.replace() that used two jpegs to check if the error was caused by the python or the file type. Probably the python.
	13. Try sending python in the address bar. still nothing.
	14. Try putting a valid blend request in the address bar. I must have tried this earlier because it was in my address bar history. Returned no data, but did get a valid non-error response. Let's do more testing from here instead of the dev console.
	15. tried putting file.txt instead of jpeg. Internal error.
	16. sent img2 parameter twice instead of img1 and img2. Got a valid response with data and no error (a little dev snark, though). I was trying to break it... (luck?)
	17. sent img2=../folder/file.txt&img2=../some.jpeg. Received snark and some.jpeg
	18. sent img2=../folder/file.txt&img2=../folder/file.txt. Received snark and the contents of file.txt
        19. cyberchef convert from base64
Done.


Leave a Reply