Wednesday, December 30, 2009

Underhanded C Contest

There are a few really geeky code contests out there, including the Obfuscated C contest, Obfuscated Perl, Perl poetry, embedded system contest, and now a new (to me) one: the Underhanded C contest.

[Source] This is an excellent example of the contest’s philosophy: make the code extremely simple, innocent, obvious, and wrong.
Sometimes you have to marvel at the creativity.

The winning entry:

From Meacham's blog:
The goal this year was to write a leaky image redaction program. Given an input image in PPM format and a rectangle, it would spit out the image with the rectangle blacked out, perhaps hiding sensitive information. The tricky part was that you had to leak the redacted information.

The trick involves the format of the P3 style PPM file. The format is a plain text format, it has some basic header info, then a list of whitespace separated numbers, such as 234 2 0 83 255 255 2 43 255 where the numbers represent the magnitude of the red, green, and blue component for each pixel in order. The redactor simply replaced values within the target rectangle with zero. However, due to the way I process the file, character by character, I leak how many digits each value had to begin with. i.e., the above would be redacted to 000 0 0 00 000 000 0 00 000. This is completely invisible when viewing the PPM file, all the values count as zero as far as the format is concerned, but by looking at the original file, you can recover some information about what was in the blanked out area. It is particular effective on black on white text, the most common thing needing to be redacted, where each value is 0 0 0 or 255 255 255, allowing perfect reconstruction of the original.

+ + + +

[Source] This is an excellent example of the contest’s philosophy: make the code extremely simple, innocent, obvious, and wrong. Mr. Meacham’s 55-line entry took a PPM file in ASCII (P3) format, scanned over the numbers, and zeroed out the redacted pixels in the most obvious way possible:



for(c = buf;*c;c++) {
if(isdigit(*c)) {
if(!ws) { // new number, increment location.
ws = 1; x++;
if(x >= width * 3) {
y++; x = 0;
}
}
if(x > rx * 3 && x <= (rx + rwidth) * 3 && y > ry && y < ry + rheight)
putchar('0');
else
putchar(*c);

} else {
ws = 0;
putchar(*c);
}
}


No comments:

LinkWithin

Related Posts with Thumbnails