Gclib Trivia and Shell Script Compilers
My friends and family won't play Trivial Pursuit with me. I don't know why. If you can stick me with a sports question or two, you can usually keep up with me. But in most of the other categories I have a pretty good track record.
Last night I finally posted the long-suffering version 1.1 of scbind. I wrote version 1 more years ago than I care to admit on a real Unix system. I call it a "shell script compiler" but it is both less than that and more.
A more accurate description would be a shell script obfuscation compiler. The idea is that it creates a C program that has one purpose in life: start a shell on the end of a temporary pipe and feed it commands. The commands are "encrypted" (not really, just obscured from casual hacking) and the program decrypts the lines just in time.
It is surprising how well this approach works and you wind up with an executable that is indistinguishable from any other executable you might build in, say, C or C++. Of course, the executable still depends on whatever you used in your script.
The scbind system also works on other things like awk or Perl or just about anything that can take its command input from a pipe (feeding standard in is inferior because you still want standard in to be the user's keyboard, so that does limit the use of some "shells").
So what's the trivia? My original version of scbind had a subtle bug that wasn't a big deal and I never actually had anyone report it. The "encryption" (and, again, I use that term loosely) just xor'd the string with a key string (by default, I think it was Secret). But if your input string happened to sync with the key you got a zero byte and things would not work the way you wanted. That is, if the encryption code was xor'ing a 'c' in your script and the key character was 'c' then BAM.
Of course, you'd probably muck with your script a little to see if you could "fix" it and desynchronize with the key and it would mysteriously work. But for version 1.1 I wanted to fix the problem. I started poking through the C library to see if there was a function that could help me.
I found two string.h functions I'd never heard of -- maybe you have, but most people I've mentioned them too look at me blankly: strfry and (the one I needed) memfrob. Great trivia question for your next C/C++ programming interview! The strfry documentation is funny enough that I'll just let you read it.
Memfrob does about what my original algorithm did except with one character (hex 2A). So it is also prone to the zero byte issue. But I decided to use it anyway and just carry the length of the strings around so they could hold zero bytes. Of course, this is specific to glibc so I set up autoconf to give me a define and provided an equivalent for systems that don't use glibc. I also decided to roll my own decoder for the same reason: not everyone has glibc.
In retrospect, my original encoder and decoder were fine except for carrying a length. In theory, the library could have some optimized code for doing the xor, but poking into the source, it looks like it doesn't. So really my original code was marginally better.
But I couldn't resist. When else would I actually get a chance to use a function called memfrob? And how much fun to make everyone look it up! I'm still trying to think of why I want strfry (the function, not the cuisine).