Add preview of 1984-2019
The 2020 winners are hinted it, but the source code is not there,
nor are the hints. Someone could look into the HTML and
see what was commented out, but that is not a problem because
WHO won is known and the name of their AWARD is known already.
Moreover a number of the winners have talked about what their
entirs do, so the commented out spoiler text is not a bit problem.
One will find HTML commented out with:
<!-- XXX remove when 2020 is ready
2020 links here
XXX remove when 2020 is ready -->
The "XXX remove when 2020 is ready" string is found at the
start and end comment blocks. Again, soneone could read
what was commented out, but that is OK since most of that
information is known or can be known. The following files
have such HTML comment blocks in them.
./winners.html
./years-spoiler.html
./years.html
In addition, ./all/summary.txt was modified to not
include the 2020 entries for the momemt.
The 2020 winner code AND write-ups are NOT part of this set.
p.s. The all/all.tar.bz2 does not contain the 2020 source code (yet?).
This commit is contained in:
1 parent
28efc67f5d
commit
c0663537cb
1683 files changed
+220064
No files matched your search
@@ -0,0 +1,207 @@
|
||||
#!/usr/bin/env make
|
||||
#
|
||||
# 2014 makefile
|
||||
#
|
||||
# This work by Landon Curt Noll, Simon Cooper, and Leonid A. Broukhis
|
||||
# is licensed under:
|
||||
#
|
||||
# Creative Commons Attribution-ShareAlike 3.0 Unported License.
|
||||
#
|
||||
# See: http://creativecommons.org/licenses/by-sa/3.0/
|
||||
|
||||
|
||||
################
|
||||
# tool locations
|
||||
################
|
||||
#
|
||||
SHELL= /bin/bash
|
||||
CP= cp
|
||||
CPP= cpp
|
||||
GUNZIP= gunzip
|
||||
LD= ld
|
||||
MAKE= make
|
||||
RM= rm
|
||||
SED= sed
|
||||
TAR= tar
|
||||
TRUE= true
|
||||
|
||||
# Set X11_LIBDIR to the directory where the X11 library resides
|
||||
#
|
||||
X11_LIBDIR= /usr/X11R6/lib
|
||||
|
||||
# Set X11_INCLUDEDIR to the directory where the X11 include files reside
|
||||
#
|
||||
X11_INCDIR= /usr/X11R6/include
|
||||
|
||||
# Compiler warnings
|
||||
#
|
||||
#CWARN=
|
||||
#CWARN= -Wall
|
||||
#CWARN= -Wall -pedantic
|
||||
CWARN= -Wall -Wno-format-extra-args -Wno-parentheses -Wno-return-type
|
||||
|
||||
# compiler standard
|
||||
#
|
||||
#CSTD=
|
||||
#CSTD= -ansi
|
||||
CSTD= -std=c11
|
||||
|
||||
# compiler bit architecture
|
||||
#
|
||||
# Some entries require 32-bitness:
|
||||
# ARCH= -m32
|
||||
#
|
||||
# Some entries require 64-bitess:
|
||||
# ARCH= -m64
|
||||
#
|
||||
# By default we assume nothing:
|
||||
#
|
||||
ARCH=
|
||||
|
||||
# optimization
|
||||
#
|
||||
# Most compiles will safely use -O2. Some can use only -O1 or -O.
|
||||
# A few compilers have broken optimizers or this entry make break
|
||||
# under those buggy optimizers and thus you may not want anything.
|
||||
#
|
||||
#OPT=
|
||||
#OPT= -O
|
||||
#OPT= -O1
|
||||
OPT= -O2
|
||||
#OPT= -O3
|
||||
|
||||
# Libraries needed to build
|
||||
#
|
||||
LIBS= -ldl
|
||||
|
||||
# default flags for ANSI C compilation
|
||||
#
|
||||
CFLAGS= ${CWARN} ${CSTD} ${ARCH} ${OPT} '-DCC="${CC} -fPIC"'
|
||||
|
||||
# ANSI compiler
|
||||
#
|
||||
# Set CC to the name of your ANSI compiler.
|
||||
#
|
||||
# Some entries seem to need gcc. If you have gcc, set
|
||||
# both CC and MAY_NEED_GCC to gcc.
|
||||
#
|
||||
# If you do not have gcc, set CC to the name of your ANSI compiler, and
|
||||
# set MAY_NEED_GCC to either ${CC} (and hope for the best) or to just :
|
||||
# to disable such programs.
|
||||
#
|
||||
CC= cc
|
||||
#CC=clang
|
||||
MAY_NEED_GCC= gcc
|
||||
|
||||
|
||||
##############################
|
||||
# Special flags for this entry
|
||||
##############################
|
||||
#
|
||||
ENTRY= prog
|
||||
DATA=
|
||||
ALT_OBJ= prog.orig.o
|
||||
ALT_ENTRY= prog.orig
|
||||
|
||||
|
||||
#################
|
||||
# build the entry
|
||||
#################
|
||||
#
|
||||
all: ${ENTRY} ${DATA}
|
||||
@${TRUE}
|
||||
|
||||
${ENTRY}: ${ENTRY}.c
|
||||
${CC} ${CFLAGS} $< -o $@ ${LIBS}
|
||||
|
||||
# alternative executable
|
||||
#
|
||||
alt: ${ALT_ENTRY}
|
||||
@${TRUE}
|
||||
|
||||
${ALT_ENTRY}: ${ALT_ENTRY}.c
|
||||
${CC} ${CFLAGS} $< -o $@ ${LIBS}
|
||||
|
||||
# data files
|
||||
#
|
||||
data: ${DATA}
|
||||
@${TRUE}
|
||||
|
||||
|
||||
###############
|
||||
# utility rules
|
||||
###############
|
||||
#
|
||||
everything: all alt
|
||||
|
||||
clean:
|
||||
${RM} -f ${ENTRY}.o ${ALT_OBJ} t.o
|
||||
|
||||
clobber: clean
|
||||
${RM} -f ${ENTRY} ${ALT_ENTRY}
|
||||
${RM} -f err static_assert t.c thread_local volatile
|
||||
|
||||
nuke: clobber
|
||||
@${TRUE}
|
||||
|
||||
dist_clean: nuke
|
||||
@${TRUE}
|
||||
|
||||
install:
|
||||
@echo "Surely we are joking Dr. Science!"
|
||||
@${TRUE}
|
||||
|
||||
# backwards compatibility
|
||||
#
|
||||
build: all
|
||||
@${TRUE}
|
||||
|
||||
|
||||
##################
|
||||
# 133t hacker rulz
|
||||
##################
|
||||
#
|
||||
love:
|
||||
@echo 'not war?'
|
||||
@${TRUE}
|
||||
|
||||
haste:
|
||||
$(MAKE) waste
|
||||
@${TRUE}
|
||||
|
||||
waste:
|
||||
@echo 'haste'
|
||||
@${TRUE}
|
||||
|
||||
easter_egg:
|
||||
@echo you expected to sometimes mis-understand this $${RANDOM} magic
|
||||
@echo chongo '<was here>' "/\\oo/\\"
|
||||
@echo Readers shall not be disallowed from failong to be unable to not partly misunderstand this partocular final echo.
|
||||
|
||||
# Understand the history of the Homebrew Computer Club
|
||||
# as well as the West Coast Computer Faire and
|
||||
# you might be confused different. :-)
|
||||
#
|
||||
supernova: nuke
|
||||
@-if [ -r .code_anal ]; then \
|
||||
${RM} -f .code_anal_v4; \
|
||||
else \
|
||||
echo "We are not expected to understand that"; \
|
||||
fi
|
||||
@${TRUE}
|
||||
|
||||
deep_magic:
|
||||
@-if [ -r .code_anal ]; then \
|
||||
ccode_analysis --deep_magic 2ed3582ec5c094a093fea2a6bcb9f19439892873c9cc45ed1ceaafe08b7d52e1b2c7cd524be3b0b2 --FNV1a_hash 512-bit "${ENTRY}"; \
|
||||
else \
|
||||
echo "You are holding it wrong!"; \
|
||||
fi
|
||||
@${TRUE}
|
||||
|
||||
magic: deep_magic
|
||||
@-if [ -r .code_anal ]; then \
|
||||
ccode_analysis --mode 391581 --level 216193 --FNV1a_hash 512-bit "${ENTRY}"; \
|
||||
else \
|
||||
echo "These aren't the primes you're looking for Pauline!"; \
|
||||
fi
|
||||
@${TRUE}
|
||||
@@ -0,0 +1,266 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="GENERATOR" content="mkd2html 2.1.5a DL=DISCOUNT">
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
|
||||
<link rel="stylesheet"
|
||||
type="text/css"
|
||||
href="../hint.css">
|
||||
<title>Most dynamic</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Most dynamic</h1>
|
||||
|
||||
<p>Cel Skeggs<br>
|
||||
<a href="mailto:ioccc@celskeggs.com">ioccc@celskeggs.com</a><br>
|
||||
<a href="http://www.celskeggs.com">http://www.celskeggs.com</a></p>
|
||||
|
||||
<h2>Judges' comments:</h2>
|
||||
|
||||
<h3>To build:</h3>
|
||||
|
||||
<pre><code>make
|
||||
</code></pre>
|
||||
|
||||
<h3>To run:</h3>
|
||||
|
||||
<pre><code>./prog
|
||||
</code></pre>
|
||||
|
||||
<h3>Try:</h3>
|
||||
|
||||
<pre><code>./prog
|
||||
</code></pre>
|
||||
|
||||
<p>HINT: Try pressing the left and right arrow keys as needed.
|
||||
Also try pressing space/enter to select options.
|
||||
Pressing Q or Escape may end the fun before you are ready. :-)</p>
|
||||
|
||||
<h3>Selected Judges Remarks:</h3>
|
||||
|
||||
<p>When the code looks like lemons, it is probably because the LEMONPEOPLE,
|
||||
or at least the LEMONLORD was involved. :-)</p>
|
||||
|
||||
<p>Look at some of the C pre-processor macros in the source code.
|
||||
Ask yourself why C source is being passed as arguments to some
|
||||
of those macros.</p>
|
||||
|
||||
<p>Now you may observe, while it is running, that some C source code
|
||||
is being written to a file and then compiled. And yet that compiled
|
||||
code is somehow executed from main. But how? How is main able to
|
||||
call code that was written and compiled just in time for execution?</p>
|
||||
|
||||
<h2>Author’s comments:</h2>
|
||||
|
||||
<h3>TABLE OF CONTENTS</h3>
|
||||
|
||||
<ul>
|
||||
<li>Backstory</li>
|
||||
<li>Known compiler warnings</li>
|
||||
<li>Obfuscation</li>
|
||||
<li>Troubleshooting guide (IMPORTANT!)</li>
|
||||
<li>Q&A</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h3>BACKSTORY</h3>
|
||||
|
||||
<p>It was ten yours ago when THE LEMONPEOPLE invaded, juicing all in their path.</p>
|
||||
|
||||
<p>Attempting to free the Earth from their tyranny, you have endured pulpy and
|
||||
sour battles.</p>
|
||||
|
||||
<p>This has now culminated in you reaching the throne room of THE LEMONLORD.</p>
|
||||
|
||||
<p>Armed with your right-facing curly brace, you charge into battle.</p>
|
||||
|
||||
<p>(Use left and right arrow keys and space/enter to select options. Press Q or
|
||||
Escape to quit.)</p>
|
||||
|
||||
<h3>KNOWN COMPILER WARNINGS</h3>
|
||||
|
||||
<p>Unfortunately, it became very difficult to get this entry to fit within the
|
||||
size requirements. It’s currently at 2052 according to iocccsize, and 3994
|
||||
according to wc -c.</p>
|
||||
|
||||
<p>The current size is a third to a half of the original size before compression.</p>
|
||||
|
||||
<p>Due to this, it does LOTS of things that subtly annoy compilers!</p>
|
||||
|
||||
<ul>
|
||||
<li><p>(10) data argument not used by format string</p>
|
||||
|
||||
<p>This occurs because some of the fprintf invocations don’t use all their
|
||||
parameters. The program should still work fine!</p></li>
|
||||
<li><p>(1) using the result of an assignment as a condition without parentheses</p>
|
||||
|
||||
<p>Somewhere, I needed to set a variable and then branch on the result. The
|
||||
shortest way was to combine them. Some self-proclaimed “EXPERTS” think this
|
||||
is a bad programming practice, but what do they know? :P</p></li>
|
||||
<li><p>(1) implicit declaration of function ‘time’ is invalid in C99</p>
|
||||
|
||||
<p>An <code>#include</code> statement is expensive, and I’m broke.</p></li>
|
||||
<li><p>(1) control may reach end of non-void function</p>
|
||||
|
||||
<p>Turns out that sometimes, a return statement is too much. This will never
|
||||
actually occur, but some C compilers think they know more about my program
|
||||
than I do! :P</p></li>
|
||||
<li><p>(?) Under some systems, <code>-fPIC</code> is irrelevant for shared libraries. If so,
|
||||
you should remove it from the Makefile.</p></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2>OBFUSCATION? WHAT OBFUSCATION? THIS IS A PERFECTLY NORMAL C PROGRAM!</h2>
|
||||
|
||||
<h1>THE COOL PART</h1>
|
||||
|
||||
<p>Take a close look at how it works. Notice that it’s passing C code to certain
|
||||
macros…</p>
|
||||
|
||||
<p>Guess what? It’s a very simple kind of JIT compiler, though not used as deeply
|
||||
as would be cool.</p>
|
||||
|
||||
<p>Essentially, it generates C code at runtime, dumps it to a file, and then runs
|
||||
a C compiler on that file, telling the C compiler to generate a shared library.
|
||||
Then it loads the shared library with dlopen, and…</p>
|
||||
|
||||
<p>Ignores the result?</p>
|
||||
|
||||
<p>That can’t be right.</p>
|
||||
|
||||
<p>Well, it is. Instead of using dlsym like a normal programmer, I mark one of the
|
||||
generated functions with <code>__attribute__((constructor))</code>. This means that it
|
||||
gets called immediately on load, so it can make its functions available.</p>
|
||||
|
||||
<p>But wait - how can it link into the main program, either? It has no way to
|
||||
reference anything in the main executable!</p>
|
||||
|
||||
<p>But it does: I’m injecting certain addresses into the generated code, which it
|
||||
then casts to pointers and accesses! It uses this to make certain functions
|
||||
available to the main program, so the main program’s generated code will then
|
||||
enter itself where it’s needed.</p>
|
||||
|
||||
<h1>THE NOT-SO-COOL PART</h1>
|
||||
|
||||
<p>There are also lots of <code>#defines</code>.</p>
|
||||
|
||||
<p>No, these are not obfuscation. These are compression.</p>
|
||||
|
||||
<p>There is a little bit of obfuscation gained from using the stringification
|
||||
operator. (I can never remember what it’s actually called, but it’s the #
|
||||
operator in a preprocessor macro) - this allows me to pass C code in arguments
|
||||
to the macros, meaning that it gets interpreted as C code instead of a string
|
||||
by the iocccsize tool, so it gets counted as smaller! :D</p>
|
||||
|
||||
<h1>A SLIGHTLY COOL PART</h1>
|
||||
|
||||
<p>As part of the JIT compiling, the program hides the fact that it needs ncurses:
|
||||
it just links ncurses with one of the generated shared libraries, and then can
|
||||
access the contents of the ncurses library!</p>
|
||||
|
||||
<h1>WAIT WHAT</h1>
|
||||
|
||||
<p>Also, note where functions start and end…</p>
|
||||
|
||||
<p>I’ve messed with the syntax so that it’s not actually formatted properly. It
|
||||
almost looks like it is, but it isn’t.</p>
|
||||
|
||||
<p>This isn’t significant obfuscation as long as you run it through a C source
|
||||
code beautifier.</p>
|
||||
|
||||
<p>But wait… if you aren’t careful, running it through a C source code
|
||||
beautifier won’t work. Remember how I’m interlacing generated C code with
|
||||
actual C code? Note that this WRECKS some beautifiers. I hope you have a good
|
||||
one!</p>
|
||||
|
||||
<p>(There’s an obvious way around this but I’m not going to spell it out for you.
|
||||
That’d be too easy!)</p>
|
||||
|
||||
<h3>MISCELLANEOUS STUFF</h3>
|
||||
|
||||
<p>Do note that there are some other miscellaneous obfuscations, but they should
|
||||
be easy to understand once you figure out the ones above.</p>
|
||||
|
||||
<h3>TROUBLESHOOTING GUIDE</h3>
|
||||
|
||||
<p>This program is a very easy program to cause to fail!</p>
|
||||
|
||||
<p>Some things to check</p>
|
||||
|
||||
<ul>
|
||||
<li>On line 16, where it says <code>%cinclude "prog.c"</code>, is <code>prog.c</code> the name of the
|
||||
original source code file?</li>
|
||||
<li>Do you have ncurses installed?</li>
|
||||
<li><p>Does your system have <code>ncurses.h</code> (like a nice system) or
|
||||
<code>ncurses/ncurses.h</code> (like a rude system) ?</p>
|
||||
|
||||
<p>If it’s the latter (or some other path), you’ll need to update line 97.</p>
|
||||
|
||||
<p>(I had to do this under Cygwin.)</p></li>
|
||||
<li>Does your system need <code>-fPIC</code> (or other arcane invocations) to compile a
|
||||
shared library? If so, make sure that you include it in the -DCC argument in
|
||||
the build script.</li>
|
||||
<li>Does your system have a vague dislike for <code>-fPIC</code>? (Like Cygwin.) You might
|
||||
need to remove it from the build script.</li>
|
||||
<li>Does your system support <code>__attribute__((constructor))</code>? It needs to.</li>
|
||||
<li>Check the file <code>err</code>. Maybe it will help you figure out why a runtime-
|
||||
generated program failed. The failing program should be found in <code>t.c</code>.</li>
|
||||
<li>Can’t run a beautifier on the source code? I’m not going to help you there.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>I’ve tested it on the following platforms, in case you need to try it on one:</p>
|
||||
|
||||
<ul>
|
||||
<li>64-bit Windows 7 32-bit Cygwin with gcc 4.8.2 and standards c89, c90, c99,
|
||||
and c11. Note that the program ran as 32-bit due to the version of cygwin.</li>
|
||||
<li>64-bit Arch Linux with gcc 4.9.1 and standards c89, c90, c99, c11.</li>
|
||||
<li>64-bit Arch Linux with clang 3.5.0 and standards c89 and c11.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>I ran out of time to test it on more systems.</p>
|
||||
|
||||
<h3>Q&A</h3>
|
||||
|
||||
<ul>
|
||||
<li><p>Who am I?</p>
|
||||
|
||||
<p>Yes.</p></li>
|
||||
<li><p>Why doesn’t your program require a pet fish license?</p>
|
||||
|
||||
<p>THE LEMONLORD’s pet LEMONFISH was not rendered in the game, and so does not
|
||||
require a pet fish license.</p></li>
|
||||
<li><p>Was this inspired by anything?</p>
|
||||
|
||||
<p>Yes, this was inspired by a minigame from an open-source codebase of Space
|
||||
Station 13. I didn’t, however, look at the minigame at all during the
|
||||
development of this entry.</p></li>
|
||||
<li><p>What’s the length of this REMARKS file according to the iocccsize tool?</p>
|
||||
|
||||
<p><code>$ ./iocccsize -i <REMARKS.MD</code></p>
|
||||
|
||||
<p><code>5092</code></p></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<hr />
|
||||
|
||||
<!--
|
||||
(c) Copyright 1984-2015, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved
|
||||
This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License][cc].
|
||||
|
||||
[judges]: http://www.ioccc.org/judges.html
|
||||
[cc]: http://creativecommons.org/licenses/by-sa/3.0/
|
||||
-->
|
||||
|
||||
<TABLE><TR>
|
||||
<TD><a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-sa/3.0/88x31.png" /></a></TD>
|
||||
<TD><P>© Copyright 1984-2015,
|
||||
<A HREF="/judges.html">Leo Broukhis, Simon Cooper, Landon Curt Noll</A>
|
||||
- All rights reserved<BR>
|
||||
This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
|
||||
<TD> <!--<a href="http://validator.w3.org/check?uri=referer"><img src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
|
||||
</TR></TABLE>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,231 @@
|
||||
# Most dynamic
|
||||
|
||||
Cel Skeggs
|
||||
<ioccc@celskeggs.com>
|
||||
<http://www.celskeggs.com>
|
||||
|
||||
|
||||
## Judges' comments:
|
||||
### To build:
|
||||
|
||||
make
|
||||
|
||||
### To run:
|
||||
|
||||
./prog
|
||||
|
||||
### Try:
|
||||
|
||||
./prog
|
||||
|
||||
HINT: Try pressing the left and right arrow keys as needed.
|
||||
Also try pressing space/enter to select options.
|
||||
Pressing Q or Escape may end the fun before you are ready. :-)
|
||||
|
||||
### Selected Judges Remarks:
|
||||
|
||||
When the code looks like lemons, it is probably because the LEMONPEOPLE,
|
||||
or at least the LEMONLORD was involved. :-)
|
||||
|
||||
Look at some of the C pre-processor macros in the source code.
|
||||
Ask yourself why C source is being passed as arguments to some
|
||||
of those macros.
|
||||
|
||||
Now you may observe, while it is running, that some C source code
|
||||
is being written to a file and then compiled. And yet that compiled
|
||||
code is somehow executed from main. But how? How is main able to
|
||||
call code that was written and compiled just in time for execution?
|
||||
|
||||
## Author's comments:
|
||||
### TABLE OF CONTENTS
|
||||
|
||||
* Backstory
|
||||
* Known compiler warnings
|
||||
* Obfuscation
|
||||
* Troubleshooting guide (IMPORTANT!)
|
||||
* Q&A
|
||||
|
||||
### BACKSTORY
|
||||
|
||||
It was ten yours ago when THE LEMONPEOPLE invaded, juicing all in their path.
|
||||
|
||||
Attempting to free the Earth from their tyranny, you have endured pulpy and
|
||||
sour battles.
|
||||
|
||||
This has now culminated in you reaching the throne room of THE LEMONLORD.
|
||||
|
||||
Armed with your right-facing curly brace, you charge into battle.
|
||||
|
||||
(Use left and right arrow keys and space/enter to select options. Press Q or
|
||||
Escape to quit.)
|
||||
|
||||
### KNOWN COMPILER WARNINGS
|
||||
|
||||
Unfortunately, it became very difficult to get this entry to fit within the
|
||||
size requirements. It's currently at 2052 according to iocccsize, and 3994
|
||||
according to wc -c.
|
||||
|
||||
The current size is a third to a half of the original size before compression.
|
||||
|
||||
Due to this, it does LOTS of things that subtly annoy compilers!
|
||||
|
||||
* (10) data argument not used by format string
|
||||
|
||||
This occurs because some of the fprintf invocations don't use all their
|
||||
parameters. The program should still work fine!
|
||||
|
||||
* (1) using the result of an assignment as a condition without parentheses
|
||||
|
||||
Somewhere, I needed to set a variable and then branch on the result. The
|
||||
shortest way was to combine them. Some self-proclaimed "EXPERTS" think this
|
||||
is a bad programming practice, but what do they know? :P
|
||||
|
||||
* (1) implicit declaration of function 'time' is invalid in C99
|
||||
|
||||
An `#include` statement is expensive, and I'm broke.
|
||||
|
||||
* (1) control may reach end of non-void function
|
||||
|
||||
Turns out that sometimes, a return statement is too much. This will never
|
||||
actually occur, but some C compilers think they know more about my program
|
||||
than I do! :P
|
||||
|
||||
* (?) Under some systems, `-fPIC` is irrelevant for shared libraries. If so,
|
||||
you should remove it from the Makefile.
|
||||
|
||||
## OBFUSCATION? WHAT OBFUSCATION? THIS IS A PERFECTLY NORMAL C PROGRAM!
|
||||
|
||||
# THE COOL PART
|
||||
|
||||
Take a close look at how it works. Notice that it's passing C code to certain
|
||||
macros...
|
||||
|
||||
Guess what? It's a very simple kind of JIT compiler, though not used as deeply
|
||||
as would be cool.
|
||||
|
||||
Essentially, it generates C code at runtime, dumps it to a file, and then runs
|
||||
a C compiler on that file, telling the C compiler to generate a shared library.
|
||||
Then it loads the shared library with dlopen, and...
|
||||
|
||||
Ignores the result?
|
||||
|
||||
That can't be right.
|
||||
|
||||
Well, it is. Instead of using dlsym like a normal programmer, I mark one of the
|
||||
generated functions with `__attribute__((constructor))`. This means that it
|
||||
gets called immediately on load, so it can make its functions available.
|
||||
|
||||
But wait - how can it link into the main program, either? It has no way to
|
||||
reference anything in the main executable!
|
||||
|
||||
But it does: I'm injecting certain addresses into the generated code, which it
|
||||
then casts to pointers and accesses! It uses this to make certain functions
|
||||
available to the main program, so the main program's generated code will then
|
||||
enter itself where it's needed.
|
||||
|
||||
# THE NOT-SO-COOL PART
|
||||
|
||||
There are also lots of `#defines`.
|
||||
|
||||
No, these are not obfuscation. These are compression.
|
||||
|
||||
There is a little bit of obfuscation gained from using the stringification
|
||||
operator. (I can never remember what it's actually called, but it's the #
|
||||
operator in a preprocessor macro) - this allows me to pass C code in arguments
|
||||
to the macros, meaning that it gets interpreted as C code instead of a string
|
||||
by the iocccsize tool, so it gets counted as smaller! :D
|
||||
|
||||
# A SLIGHTLY COOL PART
|
||||
|
||||
As part of the JIT compiling, the program hides the fact that it needs ncurses:
|
||||
it just links ncurses with one of the generated shared libraries, and then can
|
||||
access the contents of the ncurses library!
|
||||
|
||||
# WAIT WHAT
|
||||
|
||||
Also, note where functions start and end...
|
||||
|
||||
I've messed with the syntax so that it's not actually formatted properly. It
|
||||
almost looks like it is, but it isn't.
|
||||
|
||||
This isn't significant obfuscation as long as you run it through a C source
|
||||
code beautifier.
|
||||
|
||||
But wait... if you aren't careful, running it through a C source code
|
||||
beautifier won't work. Remember how I'm interlacing generated C code with
|
||||
actual C code? Note that this WRECKS some beautifiers. I hope you have a good
|
||||
one!
|
||||
|
||||
(There's an obvious way around this but I'm not going to spell it out for you.
|
||||
That'd be too easy!)
|
||||
|
||||
### MISCELLANEOUS STUFF
|
||||
|
||||
Do note that there are some other miscellaneous obfuscations, but they should
|
||||
be easy to understand once you figure out the ones above.
|
||||
|
||||
### TROUBLESHOOTING GUIDE
|
||||
|
||||
This program is a very easy program to cause to fail!
|
||||
|
||||
Some things to check
|
||||
|
||||
* On line 16, where it says `%cinclude "prog.c"`, is `prog.c` the name of the
|
||||
original source code file?
|
||||
* Do you have ncurses installed?
|
||||
* Does your system have `ncurses.h` (like a nice system) or
|
||||
`ncurses/ncurses.h` (like a rude system) ?
|
||||
|
||||
If it's the latter (or some other path), you'll need to update line 97.
|
||||
|
||||
(I had to do this under Cygwin.)
|
||||
* Does your system need `-fPIC` (or other arcane invocations) to compile a
|
||||
shared library? If so, make sure that you include it in the -DCC argument in
|
||||
the build script.
|
||||
* Does your system have a vague dislike for `-fPIC`? (Like Cygwin.) You might
|
||||
need to remove it from the build script.
|
||||
* Does your system support `__attribute__((constructor))`? It needs to.
|
||||
* Check the file `err`. Maybe it will help you figure out why a runtime-
|
||||
generated program failed. The failing program should be found in `t.c`.
|
||||
* Can't run a beautifier on the source code? I'm not going to help you there.
|
||||
|
||||
I've tested it on the following platforms, in case you need to try it on one:
|
||||
|
||||
* 64-bit Windows 7 32-bit Cygwin with gcc 4.8.2 and standards c89, c90, c99,
|
||||
and c11. Note that the program ran as 32-bit due to the version of cygwin.
|
||||
* 64-bit Arch Linux with gcc 4.9.1 and standards c89, c90, c99, c11.
|
||||
* 64-bit Arch Linux with clang 3.5.0 and standards c89 and c11.
|
||||
|
||||
I ran out of time to test it on more systems.
|
||||
|
||||
### Q&A
|
||||
|
||||
* Who am I?
|
||||
|
||||
Yes.
|
||||
|
||||
* Why doesn't your program require a pet fish license?
|
||||
|
||||
THE LEMONLORD's pet LEMONFISH was not rendered in the game, and so does not
|
||||
require a pet fish license.
|
||||
|
||||
* Was this inspired by anything?
|
||||
|
||||
Yes, this was inspired by a minigame from an open-source codebase of Space
|
||||
Station 13. I didn't, however, look at the minigame at all during the
|
||||
development of this entry.
|
||||
|
||||
* What's the length of this REMARKS file according to the iocccsize tool?
|
||||
|
||||
`$ ./iocccsize -i <REMARKS.MD`
|
||||
|
||||
`5092`
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
<!--
|
||||
(c) Copyright 1984-2015, [Leo Broukhis, Simon Cooper, Landon Curt Noll][judges] - All rights reserved
|
||||
This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License][cc].
|
||||
|
||||
[judges]: http://www.ioccc.org/judges.html
|
||||
[cc]: http://creativecommons.org/licenses/by-sa/3.0/
|
||||
-->
|
||||
@@ -0,0 +1,126 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <dlfcn.h>
|
||||
#include <time.h>
|
||||
|
||||
typedef int (*and_eq)();
|
||||
|
||||
typedef struct {
|
||||
and_eq T[15];
|
||||
int U[6];
|
||||
void *V;
|
||||
} W;
|
||||
|
||||
#define struct(z, x, y) FILE*q = fopen("t.c", "w"); E(%cinclude "prog.c"\n extern void bitand() __attribute__((constructor)); \n, 35, 9); z fclose(q); if (system(CC " -DCC= -shared t.c -o " #x " " #y " 2>err")) exit(3); { dlopen("./" #x, RTLD_LAZY); }
|
||||
#define E(x, v, w) fprintf(q, #x, v, w);
|
||||
#define H "THE LEMONLORD"
|
||||
#define Q (intptr_t)&
|
||||
#define O(x) = (J(x)(V.V) - 32 / x) / 2,
|
||||
#define R(x, y) E(J(3)(%d, %d, B(0) == x ? "{" #y "} " : " " #y); , o + 12, a += (3 + 5*x) | 1 )
|
||||
#define A(x) ((W *)x)->
|
||||
#define Z "%5d"
|
||||
#define B(x) V.U[x]
|
||||
#define J(x) V.T[x]
|
||||
#define restrict sprintf
|
||||
|
||||
char M[99] = " { { DEFEAT "H" } } ";
|
||||
|
||||
W V;
|
||||
|
||||
void xor_eq() {
|
||||
int a O(1) b O(2) o = b;
|
||||
if (J(14)) { J(14)();
|
||||
return;
|
||||
}
|
||||
|
||||
struct(E(
|
||||
|
||||
int k() {
|
||||
V = *(W *)%td;
|
||||
char *y = (char*) %td; , Q V, Q M)
|
||||
E(int x = %d; , a, a)
|
||||
char *x = "\0; ; ; ; ; ; ; ; ;; ; ; ; ; ; ; ; ; \0{ } \0{ } \0{ } \0{ } \0{ {HP} {MP} {HP} {MP} } \0{ } \0{ O O } \0{ /|-} {-|\\\\ } \0{ | | } \0{ / \\\\ / \\\\ } \0{ } \0{ } \0{ } \0; ; ; ; ; ; ; ; ;; ; ; ; ; ; ; ; ; \0";
|
||||
while (*++x) for (E(J(3)(%d, x, "%s"); , b++, x)*++x; ); {
|
||||
R(0, ATTACK)
|
||||
R(1, REGENERATE)
|
||||
R(2, HEAL)
|
||||
}
|
||||
E(J(3)(%d, %d - strlen(y) / 2, y); char d[99]; , o+2, a - 8)
|
||||
E(restrict(d, Z Z " " Z Z, B(1), B(3), B(2), B(4)); J(3)(%d, %d, d); , o + 4, a - 24)
|
||||
E(J(4)();
|
||||
}
|
||||
|
||||
void bitand() {
|
||||
A(%td)T[14] = k; } , Q V, V)
|
||||
, volatile, )
|
||||
xor_eq();
|
||||
}
|
||||
|
||||
#define S(x) 1 + rand() % (x)
|
||||
#define Y(x) restrict(M,#x,D)
|
||||
|
||||
void N() {
|
||||
int c = 0;
|
||||
xor_eq();
|
||||
if (B(5) = (B(1) * B(2) < 1)) {
|
||||
for (; !sleep(++c) && c < 3; xor_eq()) {
|
||||
char *D = ((B(1) < 1) + c) & 1 ? H " has" : "You have";
|
||||
c & 1 ? Y(%s died!) : Y(%s won!);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define X(a, n, b, g, f) switch (B(n) a) { case 0: D = S(16 - 4*n); B(2-n) -= D; Y(b hit for %d!); break; case 1: D = S(10-6*n); g; B(3+n) += D; Y(b f %d MP!); break; case 2: D = 33; if (B(3+n) > 1) { B(3+n) -= S(2); B(1+n) += D = S(18 + 6*n); Y(b heal %d!); } else { Y(b need more MP%c); u = 1; } break; } N(); if (B(5) | u | n) { return 2; }
|
||||
|
||||
int x() {
|
||||
int u = 0, D;
|
||||
X(, 0, You, , gain)
|
||||
sleep(1);
|
||||
X(< 9 ? 0 : B(2) < 20 ? B(4) < 2 ? B(3) >= 1 : 2 : B(4) < 5 && S(3) != 1 && !(B(3) < 1) ? 1 : S(8) > 6 && (B(3) || B(4) > 1) ? 1 + (B(4) > 9 || B(3) < 1) : 0, 1, They, if (B(3) < D) { D = B(3); } B(3) -= D, steal) } int w(int *p, and_eq *P) {
|
||||
int r = 9;
|
||||
struct(
|
||||
E(int f(int x) { switch(x) { , 0, 0)
|
||||
while (*p) {
|
||||
E(case %d: return ((and_eq) %td)(); , r += *(p++), Q **(P++)); }
|
||||
E(} return 1; } void bitand() { A(%td) T[13] = f; } , Q V, 1)
|
||||
, thread_local, )
|
||||
return p[-2];
|
||||
} int u() {
|
||||
return B(5) = 1;
|
||||
}
|
||||
|
||||
int main(int j, char **v) {
|
||||
srand(time(0));
|
||||
struct(
|
||||
E(#include <ncurses.h>\n void F() { endwin(); puts("Play again?"); } int g() { int o = getch(); return o == KEY_LEFT ? -1 : o == KEY_RIGHT ? -2 : o;
|
||||
}
|
||||
|
||||
void bitand() {
|
||||
and_eq *G = A(%td) T - 1; , Q V, 8);
|
||||
char *i = "\0keypad\0getmaxx\0getmaxy\0mvaddstr\0refresh\0g\0cbreak\0noecho\0nonl\0";
|
||||
memcpy(V.U, ((int[6]) { 0, 30, 50, 5, 10, 0}) , 6 * sizeof(int));
|
||||
while (*++i) {
|
||||
E(*++G = (and_eq) %s; , i, i);
|
||||
while (*++i);
|
||||
}
|
||||
E(initscr(); A(%td)V = stdscr; atexit(F); } , Q V, i)
|
||||
, static_assert, -lncurses)
|
||||
for (j = 6; j < 9; ) {
|
||||
J(j++)();
|
||||
}
|
||||
J(0)(V.V, 1);
|
||||
for (; !B(5); ) {
|
||||
xor_eq();
|
||||
j = J(5)();
|
||||
if (j & (~((1+~1U) >> 1))) {
|
||||
B(0) = (B(0) + j + 3) % 3;
|
||||
} else {
|
||||
J(13) || w((int[]) { 1, 3, 14, 5, 49, 32, 0} , (and_eq[]) { x, x, u, x, u, u} );
|
||||
J(13)(j);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
typedef int (*and_eq)();
|
||||
|
||||
typedef struct {
|
||||
and_eq T[15];
|
||||
int U[6];
|
||||
void *V;
|
||||
} W;
|
||||
|
||||
#define struct(z, x, y) FILE*q = fopen("t.c", "w"); E(%cinclude "prog.c"\n extern void bitand() __attribute__((constructor)); \n, 35, 9); z fclose(q); if (system(CC " -DCC= -shared t.c -o " #x " " #y " 2>err")) exit(3); { dlopen("./" #x, RTLD_LAZY); }
|
||||
#define E(x, v, w) fprintf(q, #x, v, w);
|
||||
#define H "THE LEMONLORD"
|
||||
#define Q (intptr_t)&
|
||||
#define O(x) = (J(x)(V.V) - 32 / x) / 2,
|
||||
#define R(x, y) E(J(3)(%d, %d, B(0) == x ? "{" #y "} " : " " #y); , o + 12, a += (3 + 5*x) | 1 )
|
||||
#define A(x) ((W *)x)->
|
||||
#define Z "%5d"
|
||||
#define B(x) V.U[x]
|
||||
#define J(x) V.T[x]
|
||||
#define restrict sprintf
|
||||
|
||||
char M[99] = " { { DEFEAT "H" } } ";
|
||||
|
||||
W V;
|
||||
|
||||
void xor_eq() {
|
||||
int a O(1) b O(2) o = b;
|
||||
if (J(14)) { J(14)();
|
||||
return;
|
||||
}
|
||||
|
||||
struct(E(
|
||||
|
||||
int k() {
|
||||
V = *(W *)%td;
|
||||
char *y = (char*) %td; , Q V, Q M)
|
||||
E(int x = %d; , a, a)
|
||||
char *x = "\0; ; ; ; ; ; ; ; ;; ; ; ; ; ; ; ; ; \0{ } \0{ } \0{ } \0{ } \0{ {HP} {MP} {HP} {MP} } \0{ } \0{ O O } \0{ /|-} {-|\\\\ } \0{ | | } \0{ / \\\\ / \\\\ } \0{ } \0{ } \0{ } \0; ; ; ; ; ; ; ; ;; ; ; ; ; ; ; ; ; \0";
|
||||
while (*++x) for (E(J(3)(%d, x, "%s"); , b++, x)*++x; ); {
|
||||
R(0, ATTACK)
|
||||
R(1, REGENERATE)
|
||||
R(2, HEAL)
|
||||
}
|
||||
E(J(3)(%d, %d - strlen(y) / 2, y); char d[99]; , o+2, a - 8)
|
||||
E(restrict(d, Z Z " " Z Z, B(1), B(3), B(2), B(4)); J(3)(%d, %d, d); , o + 4, a - 24)
|
||||
E(J(4)();
|
||||
}
|
||||
|
||||
void bitand() {
|
||||
A(%td)T[14] = k; } , Q V, V)
|
||||
, volatile, )
|
||||
xor_eq();
|
||||
}
|
||||
|
||||
#define S(x) 1 + rand() % (x)
|
||||
#define Y(x) restrict(M,#x,D)
|
||||
|
||||
void N() {
|
||||
int c = 0;
|
||||
xor_eq();
|
||||
if (B(5) = (B(1) * B(2) < 1)) {
|
||||
for (; !sleep(++c) && c < 3; xor_eq()) {
|
||||
char *D = ((B(1) < 1) + c) & 1 ? H " has" : "You have";
|
||||
c & 1 ? Y(%s died!) : Y(%s won!);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define X(a, n, b, g, f) switch (B(n) a) { case 0: D = S(16 - 4*n); B(2-n) -= D; Y(b hit for %d!); break; case 1: D = S(10-6*n); g; B(3+n) += D; Y(b f %d MP!); break; case 2: D = 33; if (B(3+n) > 1) { B(3+n) -= S(2); B(1+n) += D = S(18 + 6*n); Y(b heal %d!); } else { Y(b need more MP%c); u = 1; } break; } N(); if (B(5) | u | n) { return 2; }
|
||||
|
||||
int x() {
|
||||
int u = 0, D;
|
||||
X(, 0, You, , gain)
|
||||
sleep(1);
|
||||
X(< 9 ? 0 : B(2) < 20 ? B(4) < 2 ? B(3) >= 1 : 2 : B(4) < 5 && S(3) != 1 && !(B(3) < 1) ? 1 : S(8) > 6 && (B(3) || B(4) > 1) ? 1 + (B(4) > 9 || B(3) < 1) : 0, 1, They, if (B(3) < D) { D = B(3); } B(3) -= D, steal) } int w(int *p, and_eq *P) {
|
||||
int r = 9;
|
||||
struct(
|
||||
E(int f(int x) { switch(x) { , 0, 0)
|
||||
while (*p) {
|
||||
E(case %d: return ((and_eq) %td)(); , r += *(p++), Q **(P++)); }
|
||||
E(} return 1; } void bitand() { A(%td) T[13] = f; } , Q V, 1)
|
||||
, thread_local, )
|
||||
return p[-2];
|
||||
} int u() {
|
||||
return B(5) = 1;
|
||||
}
|
||||
|
||||
int main(int j, char **v) {
|
||||
srand(time(0));
|
||||
struct(
|
||||
E(#include <ncurses.h>\n void F() { endwin(); puts("Play again?"); } int g() { int o = getch(); return o == KEY_LEFT ? -1 : o == KEY_RIGHT ? -2 : o;
|
||||
}
|
||||
|
||||
void bitand() {
|
||||
and_eq *G = A(%td) T - 1; , Q V, 8);
|
||||
char *i = "\0keypad\0getmaxx\0getmaxy\0mvaddstr\0refresh\0g\0cbreak\0noecho\0nonl\0";
|
||||
memcpy(V.U, (int[6]) { 0, 30, 50, 5, 10, 0} , 6 * sizeof(int));
|
||||
while (*++i) {
|
||||
E(*++G = (and_eq) %s; , i, i);
|
||||
while (*++i);
|
||||
}
|
||||
E(initscr(); A(%td)V = stdscr; atexit(F); } , Q V, i)
|
||||
, static_assert, -lncurses)
|
||||
for (j = 6; j < 9; ) {
|
||||
J(j++)();
|
||||
}
|
||||
J(0)(V.V, 1);
|
||||
for (; !B(5); ) {
|
||||
xor_eq();
|
||||
j = J(5)();
|
||||
if (j & (~((1+~1U) >> 1))) {
|
||||
B(0) = (B(0) + j + 3) % 3;
|
||||
} else {
|
||||
J(13) || w((int[]) { 1, 3, 14, 5, 49, 32, 0} , (and_eq[]) { x, x, u, x, u, u} );
|
||||
J(13)(j);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user