2
* $Id: postproc.c,v 1.5 2003/06/22 11:12:28 andrew_belov Exp $
3
* ---------------------------------------------------------------------------
4
* This program stores the CRC and file size of ARJ.EXE in it, so an
5
* integrity check may be performed with ARJ i.
13
#define PP_NONE 0 /* No action */
14
#define PP_DEFAULT 1 /* Calculate and store the CRC */
15
#define PP_ARJSFX 2 /* Remove LZEXE signature */
17
/* Errorlevels/return codes. If something went wrong, look here */
19
#define POSTPROC_ERL_SUCCESS 0
20
#define POSTPROC_ERL_WARNING 1 /* Non-fatal error */
21
#define POSTPROC_ERL_CANTOPEN 2 /* Can't open file */
22
#define POSTPROC_ERL_BAD_EXE 3 /* Malformed EXE file */
23
#define POSTPROC_ERL_NO_INTEGR 4 /* Integrity pattern not found */
24
#define POSTPROC_ERL_CANT_WRITE 5 /* Data was not written */
26
/* Patterns in EXE files */
28
static unsigned char reg_crc_pattern[]={0xB0, 0x01, 0xB0, 0x02, 0xB0, 0x03, 0xB0,
30
static unsigned char encryption_pattern[]={0xB0, 0x02, 0xB0, 0x02, 0xB0, 0x03, 0xB0,
32
static unsigned char integrity_pattern[]={0xB0, 0x03, 0xB0, 0x02, 0xB0, 0x03, 0xB0,
34
static unsigned short self_check[]={0x9090, 0x9090, 0x138, 0x9090, 0x9090};
36
/* Processing buffer */
38
static char buf[PROC_BLOCK_SIZE];
40
static void _fput_dword(const unsigned long l, FILE *stream)
42
#ifdef WORDS_BIGENDIAN
48
fwrite(&l,4,1,stream);
52
/* Standard postprocessing for ARJ and REARJ */
54
static int pp_default(FILE *stream)
58
int bytes_read, byte_ctr;
63
fseek(stream, 0L, SEEK_END);
65
fseek(stream, 0L, SEEK_SET);
66
rp_len=strlen((char *)integrity_pattern);
70
fseek(stream, cur_pos, SEEK_SET);
71
if((bytes_read=fread(buf, 1, PROC_BLOCK_SIZE, stream))==0)
73
printf("Patch not found\n");
74
return(POSTPROC_ERL_BAD_EXE);
79
while(byte_ctr<bytes_read)
81
if(!memcmp(pb_ptr, integrity_pattern, rp_len))
86
if(byte_ctr<bytes_read)
88
cur_pos+=(long)PROC_BLOCK_SIZE/2; /* Dirty hack II */
90
wr_pos=(long)byte_ctr+cur_pos+rp_len;
92
fseek(stream, 0L, SEEK_SET);
93
for(cur_pos=0L; cur_pos<wr_pos; cur_pos++)
95
if((c=fgetc(stream))==-1)
97
crc32term=crc32_for_char(crc32term, (unsigned char)c);
100
fseek(stream, cur_pos, SEEK_SET);
103
if((c=fgetc(stream))==-1)
105
crc32term=crc32_for_char(crc32term, (unsigned char)c);
109
fseek(stream, wr_pos, SEEK_SET);
110
_fput_dword(crc32term, stream);
111
_fput_dword(fsize, stream);
113
return(POSTPROC_ERL_SUCCESS);
116
/* LZEXE signature removal from ARJSFX, and "aRJsfX" insertion into
117
Win32 packed modules */
119
static int pp_arjsfx(FILE *stream)
127
if(fread(buf, 1, p_len, stream)<p_len)
129
printf("Malformed executable, exiting");
130
return(POSTPROC_ERL_BAD_EXE);
132
if(buf[28]=='L'&&buf[29]=='Z')
134
if(buf[30]=='0'&&buf[31]=='9')
135
printf("LZEXE v 0.90");
136
else if(buf[30]=='9'&&buf[31]=='0')
137
printf("LZEXE v 0.90 (Russian hack-up)");
138
else if(buf[30]=='9'&&buf[31]=='1')
139
printf("LZEXE v 0.91");
142
printf("No replaceable signature found (normal for non-LZEXE packers).\n");
143
return(POSTPROC_ERL_SUCCESS);
145
printf(" signature found - ");
146
memcpy(buf+28, "RJSX", 4);
151
fseek(stream, 0L, SEEK_SET);
152
fwrite(buf, 1, p_len, stream);
153
printf("replaced\n");
158
if(fread(buf, 1, p_len, stream)<p_len)
160
printf("Malformed executable, exiting");
161
return(POSTPROC_ERL_BAD_EXE);
164
if(buf[0]=='M'&&buf[1]=='Z'&&strstr(buf+96, "DOS mode")!=NULL)
166
/* Remove duplicate LF and leave more space for the fun */
167
if(buf[0x75]==buf[0x76]&&buf[0x75]=='\r')
173
for(p_len=7; buf[p_len+0x79]=='\0'&&p_len>=0; p_len--)
176
printf("Slack area is clogged (%u byte(s) remaining) - can't stamp the ARJSFX signature!\n", p_len+1);
179
strcpy(buf+0x79, "aRJsfX");
180
fseek(stream, 0L, SEEK_SET);
181
fwrite(buf, 1, 128, stream);
182
printf("ARJSFX signature installed at offset 0x79\n");
187
Some "free" space in the ELF header ...
188
Reliable? For Linux as well? Info: <http://www.cs.purdue.edu/homes/cs503/lab1/objfiles.pdf>
192
if(fread(buf, 1, p_len, stream)<p_len)
194
printf("Malformed executable, exiting");
195
return(POSTPROC_ERL_BAD_EXE);
197
strcpy(buf+0x8, "aRJsfX");
198
fseek(stream, 0L, SEEK_SET);
199
fwrite(buf, 1, p_len, stream);
200
printf("ARJSFX signature installed at offset 0x08\n");
202
return(POSTPROC_ERL_SUCCESS);
208
static void pack_sfx(char *name)
214
char path[CCHMAXPATH];
215
char cmd_text[CMDLINE_MAX];
218
if((p=strrchr(path, PATHSEP_DEFAULT))!=NULL)
223
p[0]='\0'; /* Weird case, don't care about it */
227
sprintf(cmd_text, "LZEXE %s", name);
228
#elif TARGET==OS2&&defined(LIBC)
229
/* LXLITE must run at regular priority and flush the data to STDOUT */
230
sprintf(cmd_text, "LXLITE /CS /BDX- /I- /MF3 %s", name);
232
/* PETITE by Ian Luck. The problem with Win32 compressors is that some
233
desirable options (e.g. PECOMPACT) are GUI-based. */
234
sprintf(cmd_text, "PETITE -9 -b0 -v0 -y %s", name);
238
if(cmd_text[0]!='\0')
240
/* Relocation and cleanup for LZEXE-packed files */
242
sprintf(cmd_text, "copy %s %s", p, name);
246
e=strrchr(path, '.');
256
int main(int argc, char **argv)
262
printf("POSTPROC v 1.30 [17/01/2003] Not a part of any binary package!\n\n");
265
printf("Usage: POSTPROC <target> [-sfx],\n"
266
"Where: <target> is the EXE name to patch,\n"
267
" -sfx does ARJSFX postprocessing (packing and signing)\n"
268
" e.g, to patch ARJ.EXE, type POSTPROC ARJ.EXE\n");
269
exit(POSTPROC_ERL_WARNING);
272
/* Determine the type of post-processing */
275
else if(!strcmp(argv[2], "-sfx"))
279
if(pp_type==PP_ARJSFX)
282
if((stream=fopen(argv[1], m_rbp))==NULL)
284
printf("Can't open %s\n", argv[1]);
285
exit(POSTPROC_ERL_CANTOPEN);
287
/* Run the corresponding routine */
290
case PP_DEFAULT: rc=pp_default(stream); break;
291
case PP_ARJSFX: rc=pp_arjsfx(stream); break;
293
printf("No postprocessing action specified\n");
294
rc=POSTPROC_ERL_WARNING;