From: elton@sybase.com (Elton Wildermuth)
To: cypherpunks@toad.com
Message Hash: 86271023cf25d72089aa99fdfc2d499a7a23c3b3994974bbb5b10ef28ef6bfa6
Message ID: <9412200231.AA04630@fnord.sybgate.sybase.com>
Reply To: N/A
UTC Datetime: 1994-12-20 02:30:42 UTC
Raw Date: Mon, 19 Dec 94 18:30:42 PST
From: elton@sybase.com (Elton Wildermuth)
Date: Mon, 19 Dec 94 18:30:42 PST
To: cypherpunks@toad.com
Subject: Re: hiding strings in binaries
Message-ID: <9412200231.AA04630@fnord.sybgate.sybase.com>
MIME-Version: 1.0
Content-Type: text/plain
>I didn't write this program and I don't know how it works. It was posted
>on the nyx freenet by kstern@nyx.cs.du.edu. When you compile and run it,
>it prints out the lyrics to "The Twelve Days of Christmas".
I didn't write it either, but a friend asked how the hell it did
that, so I hacked on it for a couple hours and now I _do_ know how
it works: it's a substitution cipher just like rot-13, coupled
with a selector to print phrases in a predetermined order.
This string:
>"!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m .vpbks,fxntdCeghiry"
contains the substitution cipher. All the letters of the song are
in the 2nd half of the string, starting at '\n'. The substitutions
are the first half of the string. The program searches for a match
in the index section; when it finds a match, it adds a constant to
that character's array index to get the index of the character to
print. Thus, searching for '!' causes '\n' to print; searching for
'e' gets 'u'.
This string:
>"@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l,+,/n{n+,/+#n+,/#\
>;#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l \
>q#'+d'K#!/+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# \
>){nl]!/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#n'wk nw' \
>iwk{KK{nl]!/w{%'l##w#' i; :{nl]'/*{q#'ld;r#n'}{nlwb!/*de}'c \
>;;{nl'-{}rw]'/+,}##'*}#nc,',#nw]'/+kd'+e}+;#'rdq#w! nr'/ ') }+}{rl#'{n' ')# \
>}'+}##(!!/"
is the phrases of the song. Each '/' character is the end of a phrase:
"@n'+,#'" == "On the "; "*{}w+" == "first"; "w#cdnr" == "second"; etc.
The rest of the program is a selector to choose which phrase to print next.
It doesn't run everywhere (it presumes its character set is 7-bit ASCII),
and it depends on being invoked with no arguments. (Try it with one or two
arguments -- see what happens! It redefines the standard main() argument
'argv' as an integer purely so that it can be 100% recursive, and depends
on 'argc' being zero in the outermost level.)
It's one busy s.o.b., too, because _every_ increment of the lookup index
is a separate function call, as is the phrase selector and character
printer.
I gather that this was one of the entries in the "obfuscated 'C'"
programming contests that used to be held some years ago. (Are they
still held?)
-- Elton
Return to December 1994
Return to “fain@tyto.etho.caltech.edu (Dan Fain)”