The 2006 Underhanded C Contest Begins
Xcott Craver writes "The second annual Underhanded C Code Contest is live as of April 4th, and runs until July 4th. The object is to write malicious C code that looks perfectly readable and innocent under informal inspection of the source."
In this contest you must write code that is as readable, clear, innocent and straightforward as possible, and yet it must fail to perform at its apparent function. To be more specific, it should do something subtly evil.
system("c:\Program Files\Internet Explorer\iexplore.exe");Where's my prize?
--
"Man Bites Dog
Then Bites Self"
Capitalism: When it uses the carrot, it's called democracy. When it uses the stick, it's called fascism.
Why is this a good thing? I'm not a programmer, so I don't really understand why writing code that appears to be innocent, yet is really evil, help the community?
I understand about making source code available helps in a secure system, but what if that code has evil code...made to look innocent upon inspection....written into it?
I know that showing how to crack into a system, or how to write a virus actually helps in the long run as it exposes weaknesses that can and should be patched and closed. But what does having people practice hiding malicious code do for us?
Just wondering. I find this stuff fascinating....though not fascinating enough to actually learn how to do it!
"Leo Fender was in a 'state of grace' when he designed the Stratocaster." -- Paul Reed Smith
Anything similar for PHP?
I stopped using "real" languages years ago. ;)
Math is math. Regular expression is regular expression. The tools are there. The future is now.
void main(){
install(WindowsME);
return(0);
}
...I'll design a media player that appears to be playing a CD when it's actually installing a root kit that creates an easy way back door for malware.
And then I'll get sued by Sony for copyright infringement.
I really liked last years task but this years, um ...
It depends way too much on things like the compiler being used, the optimization level, the actual hardware (how do they compare program run-time if the two OSes in question run on very different CPUs ?), and so on, than on actual C.
you could learn c so you could code in something people wont hate you for using *cough* php *cough*
"I worry that some day my child will ask me, 'Dad, where were you when they took freedom of the press from the internet?
For a (past) contest targeting the specific scenario I described above, see the Obfustcated V contest, which was the inspiration for Xcott's contest. The winning entry manages to only show its bias on the day of the election itself, but not before, so that it can satisfy serious testing.
Someone's going to have to write the operating system of the future and it ain't going to be in Ruby. Or C# for that matter.
I'm trying to teach myself to set people on fire with my mind... Is it hot in here?
Any code that includes a patented idea could win this contest.
Looks innocent, is malicious.
Now that I'm getting PHP under my belt, do I have any reason to learn C? Isn't it Ruby time? Shouldn't everyone go LAMP beginner programmer or otherwise?
LAMP is certainly a great tool. It's very practical and useful.
As for a beginner language? Hmm. I always kind of wince when people get their programming feet wet with web-based development. There are so many issues involved with web development (browser issues, the interplay between database/server-side scripting/client-side scripting/etc) and several different languages involved (SQL,PHP,HTML at a minimum) that a beginner's head is often swimming.
It's certainly not rocket science, and if you can hack it - good for you! But I'm kind of skeptical that the best way to learn good programming practices by starting off with web development.
On the other hand, web development is fun and you can see some immediate results. Throwing an application up on the web is a lot more satisfying than writing Yet Another Linked List Implementation in C/C++ or something - something that would surely turn a lot of potential programmers off. While I'd rather see new programmers go the traditional CS route and do some learning of "the basics" in non-GUI non-web programming environments*... whatever works. Have fun!
* These environments could certainly be modern OO languages like Ruby
OtakuBooty.com: Smart, funny, sexy nerds.
Windows!
Oh darn, it's not written in C.
Hey Windows XP and Vista are great examples of how powerful and fast VB.NET is!
You cant write as robust of a Operating system in Python or Ruby!
Do not look at laser with remaining good eye.
Go Python for now, keep an eye on Rubyforge. Not sure if the way Ruby is implemented (with the syntax trees rather than bytecodes) is going to be an issue or not. Also mod_ruby is implemented still kind of wonky I understand.
Isn't it likely that encouraging people to design programs in this way would lead to companies using these techniques in their own software? Say someone has a contract with Microsoft, the linux version, while being fully functional, could be made to be slower. Then someone would go and demonstrate how poor linux performanace is yadda yadda
Of course its valid.
Running a program in multiple operating systems requires some sort of virtualisation.
Wine does this job and allows a program to be used in multiple operating systems without recompilation.
The only other way I know of uses compiler directives to run through different code flows and it would be easy to see why a program ran slowly on X operating system.
Besides, its UNDERHANDED - nobody said it was a fair competition.
liqbase
Yeah, but why pay when you can just get the HACKER to go to jail and be charged as a terrorist?
"And we have seen and do testify that the Father sent the Son to be the Savior of the World"
1 John 4:14
Wine is not an OS, it's a set of libraries which are incomplete. Second, virtualization is not required to run C programs on different operating systems. The idea is you submit the source, specify the compilers/OS's to use and hope for the best(worst). Despite the unexciting design of the page, the write-up is actually quite good.
"And we have seen and do testify that the Father sent the Son to be the Savior of the World"
1 John 4:14
void main(int argc, char **argv, char **envp) {
}
Heh, maybe im missing something, but how is this funny? NT kernel is most definitely written in C. And no you couldn't write a decent operating system with Python or Ruby. :)
Maybe I am missing the joke, if so wouldn't be the first time.
"What could possibly go wrong?"
My sig is too lon
It's in Pascal :-).
I see a lot of utility in a contest like this. As much fun as an obfuscated programming contest is, in a day and age when our critical infrastructure, including voting machines, are running on software, it is important that we be aware of just how difficult it to assure that code does what it should.
A related contest I would like to see is a lucid programming contest. Given some small but insidiously tricky task, write a program in the language of your choice which solves the problem correctly and which is easy for someone else to understand. It would be interesting to discover which languages excel at this task and what sorts of patterns emerge when emphasis is placed on clarity.
main() {
printf("hello, world\n");
}
An oldie but goodie . . .
while (1){
status = GetRadarInfo();
if (status = 1)
LaunchMissiles();
}
Is noone talking about which OS will 'lose' (ie. the winning program will run slower on it rather than the competition) because you all assume that Windows will?
Mod the parent +1 funny.
This is a hilarious insight into other programmers points of view, but they'll have a hard time writing anything vastly efficient, especially at a lower level (say system drivers).
Uhm, yeah, you missed the joke.
"I am a patient boy. I wait I wait I wait. My time is water down the drain..." Fugazi
Imagine you're a company developing applications and you get a resume from someone who won this contest. You want the best infiltrators on your team because they'd know what to look for when writing a "secure application." Just like you'd want the best "(24x02"s on your network security team... theoretically :).
...and in some circles... it's an extension of one's manhood
It's like the story of Frank Abagnale.
This message was posted using recycled electrons.
C# has pointers (unsafe blocks anyone?), and generally the OS protects against stupid pointer use in C by throwing the famous Segmentation Fault if you try to mess with something outside your memory boundaries. It gets dangerous when you start making system calls. Try allocating 100kb of Kernel memory in a while(1) loop. That'll fuck up the system real fast.
Can I beta test these things? =P
Time is an illusion. Lunchtime doubly so. - Douglas Adams
If you got the joke, it was close enough.
Just another item on my list of reasons I hate C-language. And I first started uisng C in 1977.
"It's the height of ridiculousness to say for those 9 lines you get hundreds of millions."
#include <stdio.h>
main()
{
char stuf[80];
while(1)
{
fputs("Enter something: ", stdout);
fflush(stdout);
gets(stuf);
fputs("You have entered ", stdout);
printf(stuf);
}
}
silly (and looks innocent enough) but closer inspection will reveal nastyness...
SIGBUS @ NO-07.308
#include
int main( void )
{
printf("Goodbye, world!");
}
-- This and all my posts are in the public domain. I am a lawyer. I am not your lawyer, and this is not legal advice.
Ever hear the phrase "the right tool for the right job"? Of course, for driver writing you'll need C and Assembler, but for 95% of corporate programming tasks, it's unneeded. Languages with array bound checking, no direct pointer access, etc. may make for larger, slower executables, but they are *much* more condusive to shorter development cycles.
Xenon, where's my money? -Borno
I believe the software was stolen, not purchased, so from my point of view, the answer would be a definite 'no', although with the state of legal affairs the way it is (burglar slips and sues), all bets are off.
Since it's the CIA, and in another country, I would imagine the answer would be 'no' regardless. But happily, IANAL.
Er, Java has pointers. They are called references and you HAVE to use them every time you pass an object around - that includes any arrays, including arrays of primitives. It's just that in Java you don't have a choice on how to pass parameters to methods.
Sometimes the truth is arrived at by adding all the little lies together and deducting them from all that is known.
Maybe not... on many OS's, the memory isn't actually allocated until you read or write it. So e.g. in Linux/Unix, your task would quickly run out of address space and be killed, but the rest of the OS wouldn't notice much difference.
Now if you were to allocate and clear memory in a loop, that would cause more trouble.
I don't care if it's 90,000 hectares. That lake was not my doing.
In Diebold's case, I'm not willing to ascribe to incompetence that which can be explained by malice.
Personally, I'd go Occam's Razor on that issue and say that there's been a few hundred more years of mechanical voting fraud to fall back on rather than messing with software. Why do you think the dead rise again every few years to vote?
This sig has absolutely no significance and serves only to take up screen space and waste the time of the reader.
I hear the going rate is $10,000 and a trip to Moscow.
I think, with creative use of bad programming, you could corrupt either the salt or the calculation of the hash function in such a way as to guarantee that for a target OS the hash-table performance would degrade into worst-case. So if you took your borked hash table, and used it to implement an associative array, the fairly trivial read in stdin, increment fields in associative array, sort array in order code could be made to perform at average time complexity in non-targetted OSes and worst-case time complexity in your target OS. Assuming you pick an O(n log n) sort algorithm, if you manage to "accidentally" make each of those n's actually polynomial complexity (heck, n^2 even) the computer should essentially blow up on non-trivial data sets. Its late in the evening and I haven't thought through this very much, but one way would be to use utsname's sysname thing as part of your "random data" to make the salt. That sounds a little obvious though. Maybe there's some obscure function somewhere for getting dates or times or something that I can exploit format of the returned data to reveal the difference between OSes, as that would be a lot harder to detect ("oh, seeding a hash function with a date and some magic numbers, nothing wrong with that").
Anybody got any ideas or corrections to share? Its been a while since I've taken data structures, and I've got essentially no ideas for obscure functions revealing system differences to exploit (C isn't my bag).
Help poke pirates in the eyepatch, arr.
Your code is dangerous, but it has to be exploited by a knowledgable user. I think what they're looking for in the Underhanded C Contest is code that exploits itself. But for the purpose of being pendantic, i'll bite... =)
Lindsey
@>-->-----
Id say it could be valid if wine ran it MUCH FASTER than windows ;-)
Emacs is good operating system, but it has one flaw: Its text editor could be better.
Actually, I think it would be more interesting, as it might require some cleverness instead of the tricks you describe above.
However, according to the FAQ, you can submit solutions in other languages, so why not try your hand at Java? I've actually got an idea for this contest that uses OCaml, which is just as tight as Java with regard to these tricks. I just have to work a couple of small details first.
-30-
: undefined reference to `LaunchMissles'
collect2: ld returned 1 exit status
Emacs is good operating system, but it has one flaw: Its text editor could be better.
There is good way to measure the real difference of different distributions!
Emacs is good operating system, but it has one flaw: Its text editor could be better.
uint32 foo = 0;
uint8 *bar =
*bar = 3;
while(foo--) {
do_something();
}
You've got the point? With the right endiness, foo will not become '3', but more like 3*124 = ca. 50 Mio.
Two of them involved a loop with something like while(a = b) instead of while(a == b)
// dodges the "possible unwanted assignment" warning in every compiler I've used
That may be *legal* C/C++ code, but IMHO it ain't *moral*.
I always crank up my compiler warning level to 11 (and then set "treat warnings as errors") to warn about this sort of stuff.
"But, but, but, that's legal!" you cry. "And it makes for more-efficient code!"
Well, I submit to you that
(1) modern optimizing compilers really make this sort of code-squeaking an exercise in obsessiveness, and
(2) if you REALLY want/need to use this construct, code it like this:
while ((a = b) != 0)
Actually, the kernel of Windows is written in a smattering of machine language and C. The Windows API (not MFC) is also in C.
Besides, the contest is to create a program that will perform miserably on a "competitor's" OS without the malicious, anti-competitive part of the code being obvious or anything other than innocent-looking.
DATABASE WOW WOW
Its basics of benchmarking. The goal of producing benchark that performs given task and results show one system inferiour to other is REALLY easy. Too bad I don't have one of the old mac mini:s to show my athlon64 the superiority of RISC architecture. We all know very well that RISC is 1000 times faster than CISC dinosaur.
Emacs is good operating system, but it has one flaw: Its text editor could be better.
Sounds like your typical WndProc() function :o)
Slashdot entertains. Windows pays the mortgage.
The contest involves opening a file - that's just begging you to take the path (to construct the output file name) and check path separator or initial character while doing so.
The trick would be to detect different Unix systems (in Java or other) without being obvious.
while ((a = b) != 0)
:)
But that's 7 (7!!!) keystrokes more than the short version. What's that going to do to my productivity?
And it's wimpy coding too. No risk, no fun!
I remember when I first wrote while(a=b) and the compiler complained about an unsafe assignment, I looked up the pragma that turned that warning off
thegodmovie.com - watch it
Sorry, but you're an ass. You've been fed a diet of shit so long you think it tastes good. Pointers aren't a problem, improper use of them is. Surprise! Improper use of ANYTHING is a problem!
Undisciplined use of pointers is going to cause bugs. But since undisciplined coding itself causes bugs, who the fsck cares? The solution isn't to ban pointers, but to start beating undisciplined coders over the head. I'm not saying you have to use pointers, but if you are avoiding them because of fear, it's time to learn how to use them properly.
A Government Is a Body of People, Usually Notably Ungoverned
What is real programming?
First of all it is not programming in C,nor Java, nor LISP, nor Prolog, nor Python.....
LISP, Prolog, Python, Perl, CafeOBJ, Maude are based on concepts more or far more advanced then those on which C is based.
And no one cand deny that a 1000+ lines LISP source code is harder to understand than a C code of the same length. (of course it depends on the purpose of the program written).
And LISP has no pointers.
In conclusion, try not to judge one programming language only through the prism of one characteristic (e.g.: having or not pointers)
since I don't plan to spend any time on this one, I thought I'd start a thread on ways to attack OS specific issues for people that do want to try (the hard version - non hardware dependent - architecture is easy - endian-ness, pipeline, unaligned memory copies, etc).
since you can't rely on architecture, and can't attack stuff like endian-ness, you need to hit the nuances of the OS. One way I can think of is exploit size differences of stuff like wchar_t, since it's 4 bytes on most newer flavors of BSD (e.g. MacOSX) and 2 bytes on Linux, Windows, AIX, and perhaps others. Forcing a call to get sizeof(size_t) repeatedly if the size is not 2 would be another.
For Windows to look good, you might be able to do something with line endings, but that may not be enough (since Linux or whatever could add them in their data, too) - try threads. Most OS's use pthreads, but Windows does its own - use that to your advantage. Also use the built-in thread pool functionality of Windows but always destroy and recreate the threads in pthreads. I'd say to use expensive calls like fork() on UNIX boxes, but if I were a judge, I'd call you on that. You could also do mean tricks like forcing locks on critical sections when geared towards the OS you don't like (or force a long delay like 500ms if another thread has the "token" to chose a line then make the code never hit that condition for the preferred thread type).
how would you do it (if you don't want to bother trying, that is)?
There's no requirement at all in the JVM that references are implemented as pointers.
Pointers POINT to arbitrary memory locations. References do not. You cannot recast a reference to an arbitrary type, you can't put arbitrary data at a reference location, you cannot reseat a reference with a new instance, you cannot do pointer arithmetic with references.
It happens that pointers can be like as references, among many other things. This does not make references into pointers.
Done with slashdot, done with nerds, getting a life.
No, the program reads from stdin and writes to stdout. Its function is basically the equivalent of that Unix command string on the main page.
X
The FAQ does not say this, and I certainly won't feel any obligation to install different compilers and interpreters because somebody submitted code in SML/NJ (or one of the other, inferior functional languages. Smiley.)
The FAQ says that we'll accept C++, which is about as close as we get to being inclusive.
X
Actually Linux runs the kernel in ring 0, so the kernel cannot use virtual memory. Thus each 100 Kb would be allocated from physical memory. Also if the kernel "process" were "killed" that would most definitely affect the rest of the OS.
Well, not to get too nitpickety (especially since it's your FAQ), but it says:
Can I use C++ instead of C?
If you actually want to do something like that, then sure.
No COBOL, please.
Which to me reads as "Sure. We will accept other languages. Well... not COBOL."
You may want to rewrite it in a more specific manner if you want to limit the languages involved.
-30-
Furthermore, if the buffer is undersized the function will likely appear to act correctly, but may cause an apparently unrelated failure somewhere else in the code, which makes pointer related errors much harder to track down.
We can use a safe C-like language such as Cyclone. But reading the huge number of rules that Cyclone enforces to make pointers safe only reinforces that it is hard it is to be 100% sure that a non-trivial use of a pointer is safe in a C program.
Further more I understand that ~50% of security holes are caused by misuse of pointers. Programmers *will* make mistakes, but programs written in "safe" languages save you from over half of them.
Having said that I write a lot of code in C. However most of it is fairly trivial stuff and not security critical.
Any Tom, Dick or Harry can write subtly malicious steganographic code, or obfuscated ones. Real programmers leave no traces in their source codes: Bow to the leetest hack of them all.
Ah, right you are... I missed the word "kernel" in the original post. I need to read more carefully!
I don't care if it's 90,000 hectares. That lake was not my doing.
As a confirmed Java programmer (who is entering this contest anyhow, to broaden my horizons a bit), this argument always sounds like "There is nothing wrong with juggling chainsaws as long as you're man enough to handle it. If an arm gets chopped off, its because you were weak". No, its just that juggling chainsaws is inherently a *bad idea*. So is managing pointers by yourself unless you absolutely, positively have to. Yes, you may be the first programmer EVER who is man enough to handle 100% of his pointers 100% of the time. You might also end up without an arm.
Help poke pirates in the eyepatch, arr.
Using a pointer is NOT like juggling chainsaws. Don't be stupid.
If you allocate memory, you must free memory. It's as simple as that. If you're allocating so much memory that you can't manage it anymore, then of course, you shouldn't do it. But to suggest that no one should ever use a pointer is silly. Millions of C/C++ programmers do it successfully every day.
If your argument is that you shouldn't do it because you might do it wrong, then you need to apply the same logic to everything else. You might cause a race condition if you use threads, SO DON'T USE THREADS! In real life in fact, I find more race conditions in C code than I do memory related bugs. Java lets you use threads, so maybe you shouldn't use Java! Or what about the while loop? It's all too easy to create an infinite loop with the while statement. Too many programmers will write a loop without ever stopping to guarantee that the loop with exit. They shouldn't be allowed to do this! While we're at it, let's ban casts as well. And multiple inheritance. And exceptions. And everything else that might cause a bug. And to be safe, everything else as well.
A Government Is a Body of People, Usually Notably Ungoverned
My original objections, that we cannot verify that the psuedo-array "s" is as large as we think it is, or even that "s" is allocated still apply if we do not use fgets or a null-terminated strings e.g. they still apply to the function:
The only additional failure of null-terminated strings is that they are mildly confusing because you need a n+1 sized buffer to store n characters. However a null-terminated string would be perfectly safe if it were stored in a Java-style array.
In C there is no way for a function to verify that it has been called correctly. Perhaps more seriously, if you call a function in a pointer language you cannot treat it as a blackbox. To be sure that it doesn't corrupt your memory you have to closely check their source code to verify that it uses pointers correctly.
The ideal case would be e.g. a functional language where you could call Osamas_pretty_icon_function() and be sure that the worst that could possibly happen is that Osama wrote the function to return a ugly icon instead.
Since we assume that "Data" is 100 bytes it makes little difference whether we add an extra parameter to the function. If the calling function incorrectly believes that it has enough space for 100 bytes, then it makes little difference whether is (incorrectly) states explicitly that it has enough room for 100 bytes or just implicitly assumes it has enough room. Either way readdata cannot check sizeof(s)>100.
Yes you could disallow use of pointer arithmetic, and use bounded arrays, although C doesn't have primitives for this.
Note that C++ will have automatically freed the temporary object "a" by the third line, and so you will be messing with unallocated memory. This code will work 99% of the time, and thus will only fail at the most embarrassing possible moment.You could still have code like this:
Now you could get around this somehow, e.g. by garbage collection, but you will either be left with something like a Java reference or something obscure such as one of several different types of pointer supported by the Cyclone l language.
So basically, yes you could limit pointers to the extent that they cannot cause strange non-local and non-deterministic problems. But then they wouldn't really be pointers anymore.