358 lines
7.6 KiB
C
358 lines
7.6 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include <process.h>
|
|
|
|
extern char unpack_start,unpack_end;
|
|
extern char unpack_crc0,unpack_crc1;
|
|
extern char unpack_stack0,unpack_stack1;
|
|
extern char unpack_data,unpack_dataend,unpack_data2,unpack_code;
|
|
extern char unpack_crypt1;
|
|
extern char unpack_crypt2;
|
|
extern char unpack_crypt3;
|
|
extern char unpack_crypt4;
|
|
extern char unpack_crypt10;
|
|
extern char unpack_crypt11;
|
|
extern char unpack_crypt12;
|
|
extern char unpack_crypt13;
|
|
extern char unpack_crypt14;
|
|
extern char unpack_crypt15;
|
|
extern char unpack_crypt16;
|
|
extern char unpack_endcrypt;
|
|
int unpack_len,unpack_stacklen;
|
|
|
|
int protect(FILE *fin,FILE *fout,int lastone);
|
|
|
|
int lzexeoff=0;
|
|
|
|
int exerand(void)
|
|
{
|
|
int a;
|
|
a=rand();
|
|
if(a<4096) return(0);
|
|
else if(a<8192) return(rand()&0xf);
|
|
else if(a<16384) return(rand()&0x7f);
|
|
else return(rand());
|
|
}
|
|
|
|
void error(int a)
|
|
{
|
|
switch(a)
|
|
{
|
|
case 0 : printf("Done!\n"); break;
|
|
case 1 : printf("File not packed with LZEXE!\n");
|
|
if(lzexeoff) return;
|
|
break;
|
|
case 2 : printf("File input/output error!\n"); break;
|
|
case 3 : printf("Internal error #1\n"); break;
|
|
case 4 : printf("Internal error #2\n"); break;
|
|
case 5 : printf("File open error!\n"); break;
|
|
default : printf("Unknown error!\n"); break;
|
|
}
|
|
exit(1);
|
|
}
|
|
|
|
char storage[8192];
|
|
|
|
long mcrc=0;
|
|
int mcrcon=0;
|
|
int passes=2;
|
|
|
|
main(int argc,char *argv[])
|
|
{
|
|
FILE *fin,*fout;
|
|
char str1[64],str2[64],str3[64];
|
|
int a;
|
|
time_t tm;
|
|
|
|
/* logotexts */
|
|
printf("Future Protector IV Release 1.1 Copyright (C) 1991 Sami Tammilehto\n");
|
|
if(argc==1)
|
|
{
|
|
printf("To use. Use. Illegal use prohibited. Legal switches allowed.\n");
|
|
return(0);
|
|
}
|
|
for(a=1;a<argc;a++) if(*argv[a]=='/' || *argv[a]=='-') switch(*(argv[a]+1))
|
|
{
|
|
case '?' :
|
|
case 'H' :
|
|
//printf("-m######## machine dependant crypt code entry\n");
|
|
printf("-l skip LZEXE checks\n");
|
|
printf("-1 one pass only\n");
|
|
return(0);
|
|
case '1' :
|
|
passes=1;
|
|
break;
|
|
case 'm' :
|
|
case 'M' :
|
|
mcrcon=1;
|
|
if(strlen(argv[a])>10) *(argv[a]+2+8)=0;
|
|
sscanf(argv[a]+2,"%lX",&mcrc);
|
|
case 'l' :
|
|
lzexeoff=1;
|
|
break;
|
|
}
|
|
|
|
/* inits */
|
|
unpack_len=&unpack_end-&unpack_start;
|
|
if(unpack_len>4000) error(4);
|
|
unpack_stacklen=&unpack_stack1-&unpack_stack0;
|
|
srand((unsigned)time(&tm));
|
|
|
|
memcpy(storage,&unpack_start,unpack_len);
|
|
|
|
/* filenames/backup handling */
|
|
if(strchr(argv[1],'.')) *strchr(argv[1],'.')=0;
|
|
strupr(argv[1]);
|
|
strcpy(str1,argv[1]);
|
|
strcat(str1,".OLD");
|
|
strcpy(str2,argv[1]);
|
|
strcat(str2,".TMP");
|
|
strcpy(str3,argv[1]);
|
|
strcat(str3,".EXE");
|
|
if(passes==1)
|
|
{
|
|
strcpy(str2,str3);
|
|
}
|
|
{
|
|
FILE *f1;
|
|
printf("Opening %s\n",str3);
|
|
f1=fopen(str3,"rb");
|
|
if(f1==NULL) error(5);
|
|
for(a=0;a<28;a++) fgetc(f1);
|
|
if(fgetc(f1)!='L') error(1);
|
|
else if(fgetc(f1)!='Z') error(1);
|
|
else if(fgetc(f1)!='9') error(1);
|
|
else if(fgetc(f1)!='1') error(1);
|
|
fclose(f1);
|
|
}
|
|
remove(str1);
|
|
rename(str3,str1);
|
|
remove(str2);
|
|
printf("Protecting %s (backup saved as %s).\n",str3,str1);
|
|
printf("Size increase %i bytes. ",2*(&unpack_end-&unpack_start));
|
|
if(mcrc)
|
|
{
|
|
printf("Machine code %08lXh entered. ",mcrc);
|
|
}
|
|
printf("\n");
|
|
/* protect */
|
|
fin=fopen(str1,"rb");
|
|
fout=fopen(str2,"wb");
|
|
printf("%s->%s\n",str1,str2);
|
|
if(!fin || !fout) error(2);
|
|
a=protect(fin,fout,0);
|
|
if(a) error(a);
|
|
fclose(fin);
|
|
fclose(fout);
|
|
if(passes>1)
|
|
{
|
|
/* pass 2 */
|
|
memcpy(&unpack_start,storage,unpack_len);
|
|
fin=fopen(str2,"rb");
|
|
fout=fopen(str3,"wb");
|
|
printf("%s->%s\n",str2,str3);
|
|
if(!fin || !fout) error(2);
|
|
a=protect(fin,fout,1/*final*/);
|
|
if(a) error(a);
|
|
fclose(fin);
|
|
fclose(fout);
|
|
remove(str2); /* remove tmp */
|
|
}
|
|
/* return, 0 for no errors */
|
|
return(a);
|
|
}
|
|
|
|
int calccrc(char *start,char *end)
|
|
{
|
|
unsigned char *p;
|
|
int len=end-start;
|
|
int crc=0,a;
|
|
p=(char *)start;
|
|
for(a=0;a<len;a++)
|
|
{
|
|
crc+=*(p++);
|
|
_asm
|
|
{
|
|
mov ax,crc
|
|
rol ax,1
|
|
mov crc,ax
|
|
}
|
|
}
|
|
return(crc);
|
|
}
|
|
|
|
int crypt(int type,char *start,unsigned key)
|
|
{
|
|
int a,e;
|
|
unsigned *ip=(unsigned *)start;
|
|
e=(&unpack_endcrypt-start)/2;
|
|
if(type==0) for(a=0;a<e;a++)
|
|
{
|
|
ip[a]+=key;
|
|
}
|
|
else if(type==1) for(a=0;a<e;a++)
|
|
{
|
|
ip[a]^=key;
|
|
}
|
|
else if(type==10+0) for(a=0;a<e;a++)
|
|
{
|
|
ip[a]+=key;
|
|
key++;
|
|
}
|
|
else if(type==10+1) for(a=0;a<e;a++)
|
|
{
|
|
ip[a]^=key;
|
|
key++;
|
|
}
|
|
else if(type==20+0) for(a=0;a<e;a++)
|
|
{
|
|
ip[a]+=key;
|
|
key--;
|
|
}
|
|
else if(type==20+1) for(a=0;a<e;a++)
|
|
{
|
|
ip[a]^=key;
|
|
key--;
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
int protect(FILE *fin,FILE *fout,int lastone)
|
|
{
|
|
int regkey=rand();
|
|
int key1=0x1234,key2=0x4321;
|
|
static char tmp[16384];
|
|
int *ip=(int *)tmp;
|
|
int cnt,a,b1,b2,amax;
|
|
unsigned int u;
|
|
long l;
|
|
unsigned cs0para;
|
|
unsigned header[16];
|
|
|
|
fread(header,2,16,fin);
|
|
|
|
fwrite(header,2,16,fout);
|
|
key1=header[11]+header[8]+regkey;
|
|
key2=header[10]+header[7]+regkey;
|
|
if(mcrc)
|
|
{
|
|
key1+=mcrc&65535L;
|
|
key2+=mcrc>>16L;
|
|
}
|
|
while(!ferror(fin) && !ferror(fout))
|
|
{
|
|
cnt=fread(tmp,1,16384,fin);
|
|
if(cnt==0) break;
|
|
if(cnt<16384)
|
|
{
|
|
for(cnt;cnt&15;cnt++)
|
|
{
|
|
tmp[cnt]=(char)exerand();
|
|
}
|
|
}
|
|
if(cnt&15) return(3);
|
|
amax=cnt/2;
|
|
for(a=0;a<amax;a+=8)
|
|
{ /* crypt tmp */
|
|
b1=ip[a+0]+ip[a+1]+ip[a+2]+ip[a+3];
|
|
b2=ip[a+4]+ip[a+5]+ip[a+6]+ip[a+7];
|
|
ip[a+0]+=key1;
|
|
ip[a+1]+=key2;
|
|
key1^=0x5354;
|
|
key2^=0x1525;
|
|
ip[a+2]+=key1;
|
|
ip[a+3]+=key2;
|
|
_asm
|
|
{
|
|
mov ax,key1
|
|
add ax,1234h
|
|
ror ax,1
|
|
mov key1,ax
|
|
mov ax,key2
|
|
add ax,4321h
|
|
rol ax,1
|
|
mov key2,ax
|
|
}
|
|
ip[a+4]+=key1;
|
|
ip[a+5]+=key2;
|
|
key1^=0x5354;
|
|
key2^=0x1525;
|
|
ip[a+6]+=key1;
|
|
ip[a+7]+=key2;
|
|
_asm
|
|
{
|
|
mov ax,key1
|
|
add ax,1234h
|
|
ror ax,1
|
|
mov key1,ax
|
|
mov ax,key2
|
|
add ax,4321h
|
|
rol ax,1
|
|
mov key2,ax
|
|
}
|
|
key1+=b1;
|
|
key2+=b2;
|
|
}
|
|
fwrite(tmp,1,cnt,fout);
|
|
}
|
|
if(ferror(fin) || ferror(fout)) return(2);
|
|
l=ftell(fout); cs0para=(unsigned)(l>>4)-2;
|
|
|
|
/* modify unpacker code */
|
|
{
|
|
unsigned *p;
|
|
p=(unsigned *)&unpack_data;
|
|
/* set data1 (addresses) */
|
|
p[0]=header[11]; /* cs */
|
|
p[1]=header[10]; /* ip */
|
|
p[2]=header[7]; /* ss */
|
|
p[3]=header[8]; /* sp */
|
|
p[4]=cs0para; /* cs0 */
|
|
/* set data2 */
|
|
p=(unsigned *)&unpack_data2;
|
|
p[0]=regkey; /* key */
|
|
p[1]=mcrcon; /* MACHINE CRC? */
|
|
p[2]=key1; /* key */
|
|
p[3]=key2; /* key */
|
|
/* randomize stack */
|
|
for(a=0;a<unpack_stacklen-2;a++) *(&unpack_stack0+a)=(char)exerand();
|
|
/* crypt */
|
|
u=calccrc(&unpack_crc0,&unpack_crc1);
|
|
crypt(10/*+add*/,&unpack_crypt16,0x3fac);
|
|
crypt( 1/* xor*/,&unpack_crypt15,0x5cac);
|
|
crypt( 0/* add*/,&unpack_crypt14,0 /*u*/);
|
|
crypt( 0/* add*/,&unpack_crypt13,0x0663);
|
|
crypt(21/*-xor*/,&unpack_crypt12,0x0466);
|
|
crypt(20/*-add*/,&unpack_crypt11,0x0656);
|
|
crypt( 1/* xor*/,&unpack_crypt10,0x0666);
|
|
crypt( 1/* xor*/,&unpack_crypt4,0x4536);
|
|
crypt(10/*+add*/,&unpack_crypt3,0x0073);
|
|
crypt(11/*+xor*/,&unpack_crypt2,0x4493);
|
|
crypt(10/*+add*/,&unpack_crypt1,0x5f27);
|
|
}
|
|
/* save unpacker */
|
|
fwrite(&unpack_start,1,unpack_len,fout);
|
|
if(ferror(fout)) return(2);
|
|
|
|
/* modify header */
|
|
l=ftell(fout)-1;
|
|
header[2]=(unsigned)(l/512)+1;
|
|
header[1]=(unsigned)l&511;
|
|
header[11]=header[7]=cs0para; /* cs/ss */
|
|
header[10]=&unpack_code-&unpack_start; /* ip */
|
|
header[8]=&unpack_stack1-&unpack_start; /* sp */
|
|
if(lastone)
|
|
{
|
|
header[14]=0;
|
|
header[15]=0;
|
|
}
|
|
/* save header */
|
|
fseek(fout,0L,SEEK_SET);
|
|
fwrite(header,2,16,fout);
|
|
if(ferror(fout)) return(2);
|
|
|
|
return(0);
|
|
}
|
|
|