Hacker News new | past | comments | ask | show | jobs | submit login
Implementing a web server in a single printf() call (tinyhack.com)
181 points by pdq on Mar 13, 2014 | hide | past | favorite | 39 comments

It's called Shellcode. These kids these days with their exclusive Ruby on Rails knowledge. "Shell what? Oh you mean that new band that you probably never heard of?"

I don't see ruby mentioned anywhere and the article mentions shellcode. I thought it was informative and interesting and I am well aware of shellcode. Your comment is unnecessarily condescending and may discourage posts like this.

>may discourage posts like this.

That may be goldenkey's goal, and shouldn't be discouraged either. Someone's opinion that something is awful and doesn't belong here is just as legitimate as your opinion that something is informative and interesting.

Your comment is unnecessarily condescending and may discourage comments like this.

I disagree. Most opinions that state "I already knew this, and you should too" are banal and do not lead to interesting discussion. And the moderation system of this site is set up to promote interesting discussion.

True but my comment was more directed at the disenfranchising nature of 'using printf.' Printf has nothing to do with shellcode, and is just a silent mockdrop of BS to entice those who would probably click onto the next article of a real explanation of shellcode were had. I prefer frankness to BS even if the frank explanation intimidates most.

"Machine code? What's that?"

"Javascript is assembly". ROFL!

If you want to read more about shellcode/C vulnerabilities you can check out the Phrack and other links at Stanford's CS155 web site: https://courseware.stanford.edu/pg/assignments/view/280907/b...

The Buffer Overflow #1 and #2 projects might also be worth checking out. You can download the project description, starter code, and VM image, and see if you can write code to get the root shell.

  The requested URL /cs155/hw_and_proj/pp1/boxes-2.3.tar.bz2 was not found on this server.
From https://crypto.stanford.edu/cs155/hw_and_proj/pp1/boxes-2.3.... which is the VM image link.

Anyone got any contacts at Stanford?

If you change https to http, it works for me (and I'm not logged in or privileged in any way).

Thanks for the course info!

Quick link for those that missed how to use printf to call arbitrary functions: http://stackoverflow.com/a/7459758/113507

Along the same lines, I would also recommend "Hacking" by Jon Erickson.

I did something like this in Haskell a few years ago, largely as an entertaining practical joke:


I admire that feat at the same time as I have an overwhelming urge to take a cheap shot about which Haskell projects are entertaining practical jokes.

Minor lacerations detected.

When I read the title I thought it was going to be a printf("HTTP/1.1 200 OK..."); sort of thing, but I was pleasantly surprised.

if you're going to insert a shell code into printf, then well... you can implement anything in printf... or in memcpy.. or in strcat.. or whatever really.

Heck, why not just title it "a web server with no library function calls" and call an array of bytes as a function? Then everybody would be able to see what it really is, which is an unremarkable shellcode embedded directly in a C program. I feel like the "printf" was only included so that people would have something to recognize in the title.

By that logic you could just execve httpd with shellcode. Or ruby. Or a ruby program that generates a perl script that compiles a Prolog program to shellcode that looks like it prints hello world, but actually does execve httpd.

Yes, he mentions that.

I got segmentation fault trying out his hello world example (after changing VMA address). Then again, isn't that the supposed behavior? Not every memory page can be written to, if I remember correctly.

Yes, segfault for me too after i changed ADDR preprocessor directive to the VMA address from objdump, as the instruction says. I'm on Ubuntu Linux 13.10 x64.

Ubuntu adds a security feature that provides a read-only relocation table area in the final ELF. To be able to run the examples in ubuntu, add this in the command line when compiling



gcc -Wl,-z,norelro test.c

ok, now it compiles, thanks for that. However, I'm getting an incomplete response "<h1>hello world</h1" without the trailing closing angled bracket. And when I try to run final.c after setting the FUNCTION_ADDR and ADDR as per your tutorial, I get some stray HTTP/1.0 200 and Content-type text/html being displayed on stdout as I start the program final.c (compiled to a.out by default)

Ah, you have found a bug in my code (I made an error in computing the string length, and didn't notice it because it displayed fine on Chrome). I have fixed my code in git and the blog post.

As for the stray output displayed on the stdout: it is to be expected. The %n format outputs the numbers of character that is written by printf, so it must have written something to the stdout.

Ah! that explains so much (and also why i've wasted a whole hour figuring out why what I observed was happening) I'm a CLI curl guy, rather than relying on these browsers which randomly would add a 0x0d 0x0a to my form submissions, for example. I also noticed that compiling (assembling-linking) the .S to execute it would not print anything (just hang there like a normal webserver), but I was getting stuff written to stdout with the final.c/webserver.c version using its shellcode.

Did you also post this reply using curl?

Really nice, it's so weird that format strings support %n, it's such a massive security vulnerability that I don't really know what was going on in the mind of the guy that decided to implement this.

But alas, it's always fun to see. Here's an excellent article on format string vulnerabilities, an amazing read: http://crypto.stanford.edu/cs155/papers/formatstring-1.2.pdf

It's only a vulnerability if the user can control the format string. Otherwise it's a useful way of getting the lengths of things; but ironically it's not paying attention to lengths that also causes buffer overflow vulnerabilities...

C was designed way before security was a concern. If somebody exploited your program, you could just slap them because they'd be sitting at a terminal in the same room with you - no need for fancy ASLR or controlling how many characters you write to a buffer when physical violence was a viable option :)

Except security was already a concern in other operating systems that had Lisp, Cedar, Modula-2, Algol as system languages among others.

C designers just decided to ignored it.

This isn't even remotely true. Computer security was a concern and an area of study long before C/Unix showed up. Unix (and by extension C) descended directly from the Multics project, which from its start in 1964 made security a central priority. Kernighan and Ritche were important members of the Multics project. Further, the idea that everyone who used the computers of that era were "in the same room" is also patently absurd.

I like my fantasy about how things were back then better, thankyouverymuch. At least this way I can believe they didn't unleash the flood of pwnage on the world while knowing better.

I wish for a forum/site with links only like these! Pure code hacking.

Seems to be available: purecodehacking.com. Do it!

maintenance nightmare

Understatement of the year!

it doesn't need maintenance - it works as advertised! If a client asks for a change, write a new program!

Applications are open for YC Winter 2021

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact