source: trunk/src/exepack.c@ 278

Last change on this file since 278 was 1, checked in by katerina, 19 years ago

Initial import

File size: 5.8 KB
Line 
1#include "config.h"
2
3
4#include <stdlib.h>
5#include <stdio.h>
6
7#include <sys/types.h>
8#include <sys/wait.h>
9#include <sys/stat.h>
10#include <fcntl.h>
11#include <time.h>
12#include <unistd.h>
13#include <errno.h>
14
15extern char **environ;
16
17
18#include "minilzo.h"
19
20/* integer data type that is _exactly_ 32 bit
21 */
22#if defined(HAVE_INT_32)
23#define UINT32 unsigned int
24#elif defined(HAVE_LONG_32)
25#define UINT32 unsigned long
26#elif defined(HAVE_SHORT_32)
27#define UINT32 unsigned short
28#endif
29
30
31#include "exepack.data"
32
33
34static UINT32 cstate[3], astate[3];
35
36/* interval [0, 4294967296]
37 */
38static UINT32 taus_get_long (UINT32 * state)
39{
40#define TAUSWORTHE(s,a,b,c,d) ((s &c) <<d) ^ (((s <<a) ^s) >>b)
41
42 state[0] = TAUSWORTHE (state[0], 13, 19, 4294967294UL, 12);
43 state[1] = TAUSWORTHE (state[1], 2, 25, 4294967288UL, 4);
44 state[2] = TAUSWORTHE (state[2], 3, 11, 4294967280UL, 17);
45
46 return (state[0] ^ state[1] ^ state[2]);
47}
48
49void taus_set_from_state (UINT32 * state, UINT32 * state0)
50{
51 state[0] = state0[0] | (UINT32) 0x03;
52 state[1] = state0[1] | (UINT32) 0x09;
53 state[2] = state0[2] | (UINT32) 0x17;
54
55 /* 'warm up'
56 */
57 taus_get_long (state);
58 taus_get_long (state);
59 taus_get_long (state);
60 taus_get_long (state);
61 taus_get_long (state);
62 taus_get_long (state);
63
64 return;
65}
66
67void set2 (char * pos, char c1, char c2)
68{
69 pos[0] = c1;
70 pos[1] = c2;
71 return;
72}
73
74void set4 (char * pos, char c1, char c2, char c3, char c4)
75{
76 pos[0] = c1;
77 pos[1] = c2;
78 pos[2] = c3;
79 pos[3] = c4;
80 return;
81}
82
83int main(int argc, char *argv[])
84{
85 int file;
86
87 unsigned long i = argc; /* dummy use of argc to fix compiler warning */
88 unsigned long len = 0;
89
90 struct stat sbuf;
91 struct stat fbuf;
92
93 /* For compression.
94 */
95 lzo_byte * inbuf;
96 lzo_byte * outbuf;
97 int r;
98 lzo_uint in_len;
99 lzo_uint out_len;
100
101
102 char * p;
103
104 char fname[128];
105#if defined (__linux__)
106 char pname[128];
107#endif
108
109 UINT32 pid;
110
111 /* no SUID
112 */
113 if (getuid() != geteuid())
114 {
115 setuid(getuid());
116 }
117
118 /* reset umask
119 */
120 umask(0);
121
122
123 astate[0] = programkey_0[0];
124 astate[1] = programkey_0[1];
125 astate[2] = programkey_0[2];
126
127 taus_set_from_state (cstate, astate);
128
129 out_len = (unsigned long) programlen_compressed_0;
130 len = (unsigned long) programlen_0;
131
132 outbuf = program_0;
133
134 /* Decode.
135 */
136 for (i = 0; i < out_len; ++i)
137 {
138 outbuf[i] ^= (taus_get_long (cstate) & 0xff);
139 }
140
141
142 inbuf = (lzo_byte *) malloc (sizeof(lzo_byte) * len);
143
144
145 /*
146 * Step 1: initialize the LZO library
147 */
148 if (lzo_init() != LZO_E_OK)
149 {
150 return 1;
151 }
152
153 /*
154 * Step 2: decompress again, now going from `out' to `in'
155 */
156 r = lzo1x_decompress_safe (outbuf, out_len, inbuf, &in_len, NULL);
157
158 if (r == LZO_E_OK && in_len == len)
159 {
160 /*
161 printf("decompressed %lu bytes back into %lu bytes\n",
162 (long) out_len, (long) in_len);
163 */
164 ;
165 }
166 else
167 {
168 /*
169 printf("internal error - decompression failed: %d\n",
170 r);
171 */
172 return 2;
173 }
174
175 /*
176 * Step 3: choose a filename
177 */
178
179 nameIt:
180
181 p = fname;
182
183 /* --- use /tmp if the sticky bit is set ---
184 */
185#if defined(S_ISVTX)
186
187 set4 (p, '/', 't', 'm', 'p');
188 p += 4;
189 *p = '\0';
190
191 if ( 0 != stat(fname, &sbuf))
192 {
193 if ( (sbuf.st_mode & S_ISVTX) != S_ISVTX)
194 {
195 p = fname;
196 set4 (p, '/', 'u', 's', 'r');
197 p += 4;
198 set4 (p, '/', 'b', 'i', 'n');
199 p += 4;
200 }
201 }
202
203#else
204
205 set4 (p, '/', 'u', 's', 'r');
206 p += 4;
207 set4 (p, '/', 'b', 'i', 'n');
208 p += 4;
209
210#endif
211
212 set4 (p, '/', 't', 'm', 'p');
213
214 p += 4;
215
216 cstate[0] ^= (UINT32) getpid ();
217 cstate[1] ^= (UINT32) time (NULL);
218 cstate[0] |= (UINT32) 0x03;
219 cstate[1] |= (UINT32) 0x09;
220
221 pid = (UINT32) (taus_get_long (cstate) ^ taus_get_long (cstate));
222
223 for (i = 0; i < 4; ++i)
224 {
225 *p = 'a' + (pid % 26);
226 pid /= 26;
227 ++p;
228 }
229
230 pid = (UINT32) (taus_get_long (cstate) ^ taus_get_long (cstate));
231
232 for (i = 0; i < 4; ++i)
233 {
234 *p = 'a' + (pid % 26);
235 pid /= 26;
236 ++p;
237 }
238
239 pid = (UINT32) (taus_get_long (cstate) ^ taus_get_long (cstate));
240
241 for (i = 0; i < 3; ++i)
242 {
243 *p = 'a' + (pid % 26);
244 pid /= 26;
245 ++p;
246 }
247 *p = '\0';
248
249 if ( (-1) != stat(fname, &sbuf) || errno != ENOENT)
250 {
251 /* because cstate[2] is not initialized, the next name will
252 * be different
253 */
254 goto nameIt;
255 }
256
257 if ((file = open (fname, O_CREAT|O_EXCL|O_WRONLY, 0700)) < 0)
258 {
259 return (4);
260 }
261
262 write(file, inbuf, in_len);
263
264#if defined(__linux__)
265
266 if ( 0 != fstat(file, &sbuf))
267 {
268 return (5);
269 }
270
271 /* Must reopen for read only.
272 */
273 close(file);
274 file = open (fname, O_RDONLY, 0);
275
276 if ( 0 != fstat(file, &fbuf))
277 {
278 return (6);
279 }
280
281 /* check mode, inode, owner, and device, to make sure it is the same file
282 */
283 if (sbuf.st_mode != fbuf.st_mode ||
284 sbuf.st_ino != fbuf.st_ino ||
285 sbuf.st_uid != fbuf.st_uid ||
286 sbuf.st_gid != fbuf.st_gid ||
287 sbuf.st_dev != fbuf.st_dev )
288 {
289 close ( file );
290 return ( 6 );
291 }
292
293 p = pname;
294 set4(p, '/', 'p', 'r', 'o');
295 p += 4;
296
297 set2(p, 'c', '/');
298 p += 2;
299
300 set4(p, 's', 'e', 'l', 'f');
301 p += 4;
302
303 set4(p, '/', 'f', 'd', '/');
304 p += 4;
305
306 sprintf(p, "%d", file);
307
308
309 if (0 == access(pname, R_OK|X_OK))
310 {
311 unlink (fname);
312 fcntl (file, F_SETFD, FD_CLOEXEC);
313 execve (pname, argv, environ);
314 return (8);
315 }
316#endif
317
318 /* /proc not working, or not linux
319 */
320 close (file);
321
322 if ( (i = fork()) != 0)
323 {
324 wait (NULL);
325 execve (fname, argv, environ);
326 unlink (fname);
327 return (9);
328 }
329 else if (i == 0)
330 {
331 if (0 == fork())
332 {
333 sleep (3);
334 unlink (fname);
335 }
336 return (0);
337 }
338
339 /* only reached in case of error
340 */
341 unlink (fname);
342 return (-1);
343}
344
Note: See TracBrowser for help on using the repository browser.