SecondReality/FCP/PACK.C
2017-09-24 01:45:36 +02:00

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);
}