Newsgroups: sci.crypt
Path: msuinfo!caen!zaphod.mps.ohio-state.edu!usc!elroy.jpl.nasa.gov!ames!sgi!rigden.wpd.sgi.com!rpw3
From: rpw3@rigden.wpd.sgi.com (Rob Warnock)
Subject: Re: Encryption schemes that preserve syntax?
Message-ID: <g68h5i0@sgi.sgi.com>
Sender: rpw3@rigden.wpd.sgi.com
Organization: Silicon Graphics, Inc.  Mountain View, CA
Date: Fri, 24 Jan 1992 02:45:30 GMT

ttoupin@diana.cair.du.edu (Tory Toupin) writes:
+---------------
| Are there any encryption schemes that preserve the syntax of the language
| that is being encrypted?  For example, you take take a Pascal program and
| encrypt it; the encrypted form is still in Pascal (which may or may not
| run or link, but should certainly compile).
+---------------

I would call these "obfuscations" rather than true "encryptions", but yes,
there have been many such schemes in the past. For example, there are business
application programs that are written in BASIC which can be run on any normal
BASIC system, but which are difficult for humans to reverse-engineer. The same
has been done form time to time for FORTRAN, COBOL, C, etc.

The basic idea is this: You write (or otherwise obtain) a parser for the
language in question. Your obfuscator then reads & parses the entire source
code to be "protected", building a full symbol table. It then emits new code
for which all of the local names have been changed to be some difficult-to-read
form (e.g., all the names are of the form "O10I01OI", etc.), all the unneeded
spaces and newlines are scrunched out, lines are packed to approx. equal
lengths, and other such trash.

An example of sych an obfuscator for C is available in the comp.sources.unix
archives, archive name "opqcp/part01" [Volume 13, Issue 68, June 1990].

The "security" provided by such schemes is debatable, but in some environments
it is sufficient for the main purpose, which is to make the potential perp
think twice about going to "all that trouble", or a worst, to be able to
show in court that the perpetrator had to go to significant trouble to
copy/de-compile your code.  Sometimes that's enough.


- Rob Warnock
  <rpw3@sgi.com>

p.s.
For a more humorous view of this issue, see the annual "International
Obfuscated C Code Contest", the results of which are posted to various
newsgroups. The 1991 contest was the 8th in the series. For example,
the attached program "davidguy" is less than 1700 bytes of source, yet
is, in the words of the contest judges:

	"...a fully-functional X client. It talks directly to the X server
	through a socket without using Xlib, Xt or any other wussie toolkit
	junk.  With no arguments, it will try to run locally using the
	unix-domain socket (only on BSD :-( ) or you can give it a command
	line argument identifying a display host address (in dotted octet
	notation, like 127.0.0.1:0.0) where the X server is running. It handles
	color and monochrome displays, and performs whatever byte-swapping
	and bit-reversal is needed (so that the program works even when the
	server and the client have different architectures). It buffers
	communication to the X server for efficiency."

============ attachment ================================================

From the "8th International Obfuscated C Code Contest" winners:

# ============= 1991/davidguy.c ==============
echo "x - extracting 1991/davidguy.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > 1991/davidguy.c &&
X#define u unsigned
X#define w char*
X#define j(x)(*(*(x*)&T)++)
X#define H j(short*)
X#define K j(w)
X#define e j(u*)
X#define r register u
X#define R(b)write(A,T=h,4*b);
X#define S (u*)sbrk(Q*4+U*8)+U
X#define E(a,b,c)a=c&1<<31|b/2;c=c*2|b&1;
X#define V q=h^*L;L+=F;E(d,q,x)E(f,d,s)g=f&q;f^=q
X#define W while(
X#define Z q=I&f;M|=q&c;c^=q;I^=f;M|=g&c;c^=g
X#define Y W(F= *s++-'0')<=9)*T=10**T+F;K
X#define D(q,s)c);W q>s)G= *--q,*q= *s,*s++=G;
X#define P if(i^z){x=Q+(n=D(x,n)
X#define C if(i){q=Q*4+(s=(w)D(q,s)
Xu A,U,Q,J,X[9999],B;main(a,b)w*b;{r*c,*d,y=0,f,g,F,I,M,N,z,*x,*n,i,G;w q,*h=(w
X)X,*T,*s=".slo.-W00,tmhw.W/";T=h;if(a>1){e;s=b[1];Y;Y;Y;Y;T=h;H;K=23;Y+=112;T=
Xh;Y;y= *--T;H=2;}else{H=1;W*s)K=1+*s++;}connect(A=socket(a,1,0),T=h,24-a*4);H=
X17004;H=11;e=0;e=0;i=66==*h;R(3)read(A,h,8);e;H;read(A,h,4*H);T=h;e;F=e;e;e;I=
X11+H;f=H-6;K;U=K;i^=K;z=!K;T+=I/4*4+8*U;W y--){T+=39;I=K;W I--)H,T+=4+24*H;}I=
Xe;e;B=(!e^**b&1)-1;e;e;U=H/32;J=H/30*30;T+=14;M=K;f/=U;T=h;K=55;K;H=4;e=F;e=I;
Xe=0;R(4)N=F+8192;K=53;K=M;H=4;e=N;e=I;H=U*32;H=J;R(4)K=2;K;H=4;e=I;e=1;e=N;R(4
X)Q=J*U;c=S;d=S;L(c);W 1){P}C}y=0;W y<J){K=72;K=0;g=J-y;H=6+U*(g>f?g=f:g);e=N;e
X=F;H=U*32;H=g;H=0;H=y;K=0;K=1;R(6)write(A,c+y*U,g*U*4);y+=g;}K=61;K=0;H=4;e=I;
Xe=0;e=0;R(4)C}P}v(c,d);}}L(A)r*A;{r*T=A+Q,X=getpid();W A<T)*A++=X=3*X^X/2;}v(n
X,O)u*n,*O;{r*A,F=U,*L=n-F,*G=L+Q,I,c,d,M,f,g,N,q,i=0,X,T,v,s,x,*y,*z,h=B;W L<n
X){*L= *G;G++[F]=L++[F];}W i<J){z=O+i*F;y=n+i*F-F;i+=30;L=y-1;A=L+U*32;W L<A){L
X+=F;E(X,(*L^h),x)E(q,X,s)}X=0;W X++<F){L=y++;G=z++;V;c=g|f&d;I=f^d;V;W L<=A){M
X=0;Z;N=d;T=f;v=g;V;Z;c^=I&d;*G=h^c&~M&(I^d|N);G+=F;c=v|T&N;I=T^N;}}}z=O;y=n;I=
XJ;W--I!=-1){f= *z>>31;G=z+F;L=y+F;W G>z){M= *--G;*--L=(M*2)+f;f=M>>31;}z+=F;y+
X=F;}}
SHAR_EOF


