~ubuntu-branches/ubuntu/precise/arj/precise-security

« back to all changes in this revision

Viewing changes to postproc.c

  • Committer: Bazaar Package Importer
  • Author(s): Guillem Jover
  • Date: 2004-06-27 08:07:09 UTC
  • Revision ID: james.westby@ubuntu.com-20040627080709-1gkxm72ex66gkwe4
Tags: upstream-3.10.21
ImportĀ upstreamĀ versionĀ 3.10.21

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
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.
 
6
 *
 
7
 */
 
8
 
 
9
#include "arj.h"
 
10
 
 
11
/* Operations */
 
12
 
 
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 */
 
16
 
 
17
/* Errorlevels/return codes. If something went wrong, look here */
 
18
 
 
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 */
 
25
 
 
26
/* Patterns in EXE files */
 
27
 
 
28
static unsigned char reg_crc_pattern[]={0xB0, 0x01, 0xB0, 0x02, 0xB0, 0x03, 0xB0,
 
29
                               0x04, 0xB0, 0x05, 0};
 
30
static unsigned char encryption_pattern[]={0xB0, 0x02, 0xB0, 0x02, 0xB0, 0x03, 0xB0,
 
31
                                 0x04, 0xB0, 0x05, 0};
 
32
static unsigned char integrity_pattern[]={0xB0, 0x03, 0xB0, 0x02, 0xB0, 0x03, 0xB0,
 
33
                                 0x04, 0xB0, 0x05, 0};
 
34
static unsigned short self_check[]={0x9090, 0x9090, 0x138, 0x9090, 0x9090};
 
35
 
 
36
/* Processing buffer */
 
37
 
 
38
static char buf[PROC_BLOCK_SIZE];
 
39
 
 
40
static void _fput_dword(const unsigned long l, FILE *stream)
 
41
{
 
42
#ifdef WORDS_BIGENDIAN
 
43
 fputc(l    ,stream);
 
44
 fputc(l>>8 ,stream);
 
45
 fputc(l>>16,stream);
 
46
 fputc(l>>24,stream);
 
47
#else
 
48
 fwrite(&l,4,1,stream);
 
49
#endif
 
50
}
 
51
 
 
52
/* Standard postprocessing for ARJ and REARJ */
 
53
 
 
54
static int pp_default(FILE *stream)
 
55
{
 
56
 int rp_len;
 
57
 long cur_pos, wr_pos;
 
58
 int bytes_read, byte_ctr;
 
59
 char *pb_ptr;
 
60
 long fsize;
 
61
 int c;
 
62
 
 
63
 fseek(stream, 0L, SEEK_END);
 
64
 fsize=ftell(stream);
 
65
 fseek(stream, 0L, SEEK_SET);
 
66
 rp_len=strlen((char *)integrity_pattern);
 
67
 cur_pos=0L;
 
68
 while(1)
 
69
 {
 
70
  fseek(stream, cur_pos, SEEK_SET);
 
71
  if((bytes_read=fread(buf, 1, PROC_BLOCK_SIZE, stream))==0)
 
72
  {
 
73
   printf("Patch not found\n");
 
74
   return(POSTPROC_ERL_BAD_EXE);
 
75
  }
 
76
  bytes_read-=rp_len;
 
77
  pb_ptr=buf;
 
78
  byte_ctr=0;
 
79
  while(byte_ctr<bytes_read)
 
80
  {
 
81
   if(!memcmp(pb_ptr, integrity_pattern, rp_len))
 
82
    break;
 
83
   byte_ctr++;
 
84
   pb_ptr++;
 
85
  }
 
86
  if(byte_ctr<bytes_read)
 
87
   break;
 
88
  cur_pos+=(long)PROC_BLOCK_SIZE/2;     /* Dirty hack II */
 
89
 }
 
90
 wr_pos=(long)byte_ctr+cur_pos+rp_len;
 
91
 crc32term=CRC_MASK;
 
92
 fseek(stream, 0L, SEEK_SET);
 
93
 for(cur_pos=0L; cur_pos<wr_pos; cur_pos++)
 
94
 {
 
95
  if((c=fgetc(stream))==-1)
 
96
   break;
 
97
  crc32term=crc32_for_char(crc32term, (unsigned char)c);
 
98
 }
 
99
 cur_pos+=8L;
 
100
 fseek(stream, cur_pos, SEEK_SET);
 
101
 while(cur_pos<fsize)
 
102
 {
 
103
  if((c=fgetc(stream))==-1)
 
104
   break;
 
105
  crc32term=crc32_for_char(crc32term, (unsigned char)c);
 
106
  cur_pos++;
 
107
 }
 
108
 fsize+=2L;
 
109
 fseek(stream, wr_pos, SEEK_SET);
 
110
 _fput_dword(crc32term, stream);
 
111
 _fput_dword(fsize,     stream); 
 
112
 printf("Done\n");
 
113
 return(POSTPROC_ERL_SUCCESS);
 
114
}
 
115
 
 
116
/* LZEXE signature removal from ARJSFX, and "aRJsfX" insertion into
 
117
   Win32 packed modules */
 
118
 
 
119
static int pp_arjsfx(FILE *stream)
 
120
{
 
121
 int p_len;
 
122
 int sig_found;
 
123
 
 
124
#if TARGET==DOS
 
125
 p_len=32;
 
126
 sig_found=0;
 
127
 if(fread(buf, 1, p_len, stream)<p_len)
 
128
 {
 
129
  printf("Malformed executable, exiting");
 
130
  return(POSTPROC_ERL_BAD_EXE);
 
131
 }
 
132
 if(buf[28]=='L'&&buf[29]=='Z')
 
133
 {
 
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");
 
140
  else
 
141
  {
 
142
   printf("No replaceable signature found (normal for non-LZEXE packers).\n");
 
143
   return(POSTPROC_ERL_SUCCESS);
 
144
  }
 
145
  printf(" signature found - ");
 
146
  memcpy(buf+28, "RJSX", 4);
 
147
  sig_found=1;
 
148
 }
 
149
 if(sig_found)
 
150
 {
 
151
  fseek(stream, 0L, SEEK_SET);
 
152
  fwrite(buf, 1, p_len, stream);
 
153
  printf("replaced\n");
 
154
 }
 
155
#elif TARGET==WIN32
 
156
 p_len=128;
 
157
 sig_found=0;
 
158
 if(fread(buf, 1, p_len, stream)<p_len)
 
159
 {
 
160
  printf("Malformed executable, exiting");
 
161
  return(POSTPROC_ERL_BAD_EXE);
 
162
 }
 
163
 buf[128]='\0';
 
164
 if(buf[0]=='M'&&buf[1]=='Z'&&strstr(buf+96, "DOS mode")!=NULL)
 
165
 {
 
166
  /* Remove duplicate LF and leave more space for the fun */
 
167
  if(buf[0x75]==buf[0x76]&&buf[0x75]=='\r')
 
168
  {
 
169
   buf[0x76]='\n';
 
170
   buf[0x77]='$';
 
171
   buf[0x78]='\0';
 
172
  }
 
173
  for(p_len=7; buf[p_len+0x79]=='\0'&&p_len>=0; p_len--)
 
174
   ;
 
175
  if(p_len>0)
 
176
   printf("Slack area is clogged (%u byte(s) remaining) - can't stamp the ARJSFX signature!\n", p_len+1);
 
177
  else
 
178
  {
 
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");
 
183
  }
 
184
 }
 
185
#elif defined(SUNOS)
 
186
 /*
 
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>
 
189
 */
 
190
 p_len=16;
 
191
 sig_found=0;
 
192
 if(fread(buf, 1, p_len, stream)<p_len)
 
193
 {
 
194
  printf("Malformed executable, exiting");
 
195
  return(POSTPROC_ERL_BAD_EXE);
 
196
 }
 
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");
 
201
#endif
 
202
 return(POSTPROC_ERL_SUCCESS);
 
203
}
 
204
 
 
205
/* ARJSFX packer */
 
206
 
 
207
#ifndef NP_SFX
 
208
static void pack_sfx(char *name)
 
209
{
 
210
 char *p;
 
211
 #if TARGET==DOS
 
212
  char *e;
 
213
 #endif
 
214
 char path[CCHMAXPATH];
 
215
 char cmd_text[CMDLINE_MAX];
 
216
 
 
217
 strcpy(path, name);
 
218
 if((p=strrchr(path, PATHSEP_DEFAULT))!=NULL)
 
219
  *p='\0';
 
220
 else
 
221
 {
 
222
  p=path;
 
223
  p[0]='\0';                            /* Weird case, don't care about it */
 
224
 }
 
225
 p++;
 
226
 #if TARGET==DOS
 
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);
 
231
 #elif TARGET==WIN32
 
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);
 
235
 #else
 
236
  cmd_text[0]='\0';
 
237
 #endif
 
238
 if(cmd_text[0]!='\0')
 
239
  system(cmd_text);
 
240
 /* Relocation and cleanup for LZEXE-packed files */
 
241
 #if TARGET==DOS
 
242
  sprintf(cmd_text, "copy %s %s", p, name);
 
243
  system(cmd_text);
 
244
  unlink(p);
 
245
  strcpy(path, name);
 
246
  e=strrchr(path, '.');
 
247
  if(e!=NULL)
 
248
   strcpy(e, ".OLD");
 
249
  unlink(path);
 
250
 #endif
 
251
}
 
252
#endif
 
253
 
 
254
/* Main routine */
 
255
 
 
256
int main(int argc, char **argv)
 
257
{
 
258
 FILE *stream;
 
259
 int pp_type=PP_NONE;
 
260
 int rc;
 
261
 
 
262
 printf("POSTPROC v 1.30  [17/01/2003]  Not a part of any binary package!\n\n");
 
263
 if(argc<2)
 
264
 {
 
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);
 
270
 }
 
271
 build_crc32_table();
 
272
 /* Determine the type of post-processing */
 
273
 if(argc==2)
 
274
  pp_type=PP_DEFAULT;
 
275
 else if(!strcmp(argv[2], "-sfx"))
 
276
  pp_type=PP_ARJSFX;
 
277
 /* Pack the SFX */
 
278
 #ifndef NP_SFX
 
279
  if(pp_type==PP_ARJSFX)
 
280
   pack_sfx(argv[1]);
 
281
 #endif
 
282
 if((stream=fopen(argv[1], m_rbp))==NULL)
 
283
 {
 
284
  printf("Can't open %s\n", argv[1]);
 
285
  exit(POSTPROC_ERL_CANTOPEN);
 
286
 }
 
287
 /* Run the corresponding routine */
 
288
 switch(pp_type)
 
289
 {
 
290
  case PP_DEFAULT:  rc=pp_default(stream); break;
 
291
  case PP_ARJSFX:   rc=pp_arjsfx(stream); break;
 
292
  default:
 
293
   printf("No postprocessing action specified\n");
 
294
   rc=POSTPROC_ERL_WARNING;
 
295
 }
 
296
 fclose(stream);
 
297
 return(rc);
 
298
}