18
17
* MA 02110-1301, USA.
23
** 09/07/2k6 - Campioni del mondo!!!
24
** 14/07/2k6 - RCE'ed + standalone sect unpacker
25
** 15/07/2k6 - Merge started
26
** 17/07/2k6 - Rebuild
27
** 18/07/2k6 - Secured (well, hopefully...)
32
** Unpacks+rebuilds WWPack32 1.20
34
** Just boooooring stuff, blah.
45
** (have a look at older versions)
22
51
#include "clamav-config.h"
25
57
#include "cltypes.h"
26
58
#include "others.h"
28
59
#include "wwunpack.h"
35
if (CLI_ISCONTAINED(compd, szd, ccur, 4)) { \
36
bt = cli_readint32(ccur); \
39
cli_dbgmsg("WWPack: Out of bits\n"); \
53
bits = bt>>(32-(N)); \
61
if (CLI_ISCONTAINED(compd, szd, ccur, 4)) { \
62
bt = cli_readint32(ccur); \
68
cli_dbgmsg("WWPack: Out of bits\n"); \
73
int wwunpack(uint8_t *exe, uint32_t exesz, uint8_t *wwsect, struct cli_exe_section *sects, uint16_t scount, uint32_t pe, int desc) {
74
uint8_t *structs = wwsect + 0x2a1, *compd, *ccur, *unpd, *ucur, bc;
75
uint32_t src, srcend, szd, bt, bits;
78
cli_dbgmsg("in wwunpack\n");
61
#define VAALIGN(s) (((s)/0x1000+((s)%0x1000!=0))*0x1000)
62
#define FIXVS(v, r) (VAALIGN((r>v)?r:v))
65
static int getbitmap(uint32_t *bitmap, char **src, uint8_t *bits, char *buf, unsigned int size) {
66
if (! CLI_ISCONTAINED(buf, size, *src, 4)) return 1;
67
*bitmap=cli_readint32(*src);
73
static int getbits(uint8_t X, uint32_t *eax, uint32_t *bitmap, uint8_t *bits, char **src, char *buf, unsigned int size) {
81
if (getbitmap(bitmap, src, bits, buf, size)) return 1;
83
*eax|=*bitmap>>(32-X);
87
if (getbitmap(bitmap, src, bits, buf, size)) return 1;
92
static int wunpsect(char *packed, char *unpacked, unsigned int psize, unsigned int usize) {
93
char *src=packed, *dst=unpacked;
96
unsigned int lostbit, getmorestuff;
101
if (getbitmap(&bitmap, &src, &bits, packed, psize)) return 1;
80
if (!CLI_ISCONTAINED(wwsect, sects[scount].rsz, structs, 17)) {
81
cli_dbgmsg("WWPack: Array of structs out of section\n");
84
src = sects[scount].rva - cli_readint32(structs); /* src delta / dst delta - not used / dwords / end of src */
86
szd = cli_readint32(structs) * 4;
88
srcend = cli_readint32(structs);
91
unpd = ucur = exe+src+srcend+4-szd;
92
if (!szd || !CLI_ISCONTAINED(exe, exesz, unpd, szd)) {
93
cli_dbgmsg("WWPack: Compressed data out of file\n");
96
cli_dbgmsg("WWP: src: %x, szd: %x, srcend: %x - %x\n", src, szd, srcend, srcend+4-szd);
97
if (!(compd = cli_malloc(szd))) break;
98
memcpy(compd, unpd, szd);
99
memset(unpd, -1, szd); /*FIXME*/
104
uint32_t backbytes, backsize;
108
if (!bits) { /* BYTE copy */
109
if(ccur-compd>=szd || !CLI_ISCONTAINED(exe, exesz, ucur, 1))
117
if(bits==3) { /* WORD backcopy */
118
uint8_t shifted, subbed = 31;
125
backbytes = (1<<shifted)-subbed; /* 1h, 21h, 61h, 161h */
126
BITS(shifted); /* 5, 6, 8, 9 */
127
if(error || bits == 0x1ff) break;
129
if(!CLI_ISCONTAINED(exe, exesz, ucur, 2) || !CLI_ISCONTAINED(exe, exesz, ucur-backbytes, 2)) {
132
ucur[0]=*(ucur-backbytes);
133
ucur[1]=*(ucur-backbytes+1);
140
saved = bits; /* cmp al, 1 / pushf */
151
case 0: case 1: case 2: /* 5,6,7 */
159
bits+=(1<<backbytes)-31;
108
if (!lostbit && bits) {
109
if (!(CLI_ISCONTAINED(packed, psize, src, 1) && CLI_ISCONTAINED(unpacked, usize, dst, 1))) return 1;
115
if (getbitmap(&bitmap, &src, &bits, packed, psize)) return 1;
118
if (!(CLI_ISCONTAINED(packed, psize, src, 1) && CLI_ISCONTAINED(unpacked, usize, dst, 1))) return 1;
124
if (getbits(2, &eax, &bitmap, &bits, &src, packed, psize)) return 1;
127
/* 50ff - two_bytes */
130
if (getbits(2, &eax, &bitmap, &bits, &src, packed, psize)) return 1;
131
fetchbits=(eax&0xff)+5;
133
if ((int16_t)(eax&0xffff)<=0) {
135
backbytes=1<<fetchbits;
136
backbytes=(backbytes&0xff00)|((backbytes-31)&0xff);
140
backbytes=1<<fetchbits;
144
if (getbits(fetchbits, &eax, &bitmap, &bits, &src, packed, psize)) return 1;
145
if ((eax&0xffff)==0x1ff) break;
148
if (!(CLI_ISCONTAINED(unpacked, usize, dst-backbytes, 2) && CLI_ISCONTAINED(unpacked, usize, dst, 2))) return 1;
149
*dst=*(dst-backbytes);
151
*dst=*(dst-backbytes);
156
/* 5143 - more_backbytes */
161
if (getbits(3, &eax, &bitmap, &bits, &src, packed, psize)) return 1;
165
/* next_bit_or_reseed */
170
if (getbitmap(&bitmap, &src, &bits, packed, psize)) return 1;
174
/* jmp more_bb_commondock */
176
/* 5160 - more_bb_morethan3 */
178
/* next_bit_or_reseed */
183
if (getbitmap(&bitmap, &src, &bits, packed, psize)) return 1;
186
/* jmp more_bb_commondock */
189
if ((eax&0xff)>=0x0d) {
190
getmorestuff=0; /* jmp more_bb_PASTcommondock */
191
if ((eax&0xff)==0x0d) {
193
if (getbits(0x0e, &eax, &bitmap, &bits, &src, packed, psize)) return 1;
186
uint16_t shifted = 0x0d;
189
if(cnt==7) { cnt = 0x0e; shifted = 0; break; }
190
shifted=((shifted+2)<<1)-1;
197
if (getbits(0x0f, &eax, &bitmap, &bits, &src, packed, psize)) return 1;
200
/* jmp more_bb_PASTcommondock */
206
/* 5192 - more_bb_commondock */
207
uint16_t bk=(1<<(eax&0xff))-0x1f;
208
if (getbits((eax&0xff), &eax, &bitmap, &bits, &src, packed, psize)) return 1;
212
/* 51a7 - more_bb_pastcommondock */
217
if (oal<1) { /* overrides backsize */
218
/* 51bb - more_bb_again */
220
/* next_bit_or_reseed */
225
if (getbitmap(&bitmap, &src, &bits, packed, psize)) return 1;
229
/* next_bit_or_reseed */
234
if (getbitmap(&bitmap, &src, &bits, packed, psize)) return 1;
237
/* jmp setsize_and_backcopy */
204
if(!CLI_ISCONTAINED(exe, exesz, ucur, backsize) || !CLI_ISCONTAINED(exe, exesz, ucur-backbytes, backsize)) error=1;
205
else while(backsize--) {
206
*ucur=*(ucur-backbytes);
212
cli_dbgmsg("WWPack: decompression error\n");
215
if (error || !*structs++) break;
219
exe[pe+6]=(uint8_t)scount;
220
exe[pe+7]=(uint8_t)(scount>>8);
221
cli_writeint32(&exe[pe+0x28], cli_readint32(wwsect+0x295)+sects[scount].rva+0x299);
222
cli_writeint32(&exe[pe+0x50], cli_readint32(&exe[pe+0x50])-sects[scount].vsz);
224
structs = &exe[(0xffff&cli_readint32(&exe[pe+0x14]))+pe+0x18];
225
for(i=0 ; i<scount ; i++) {
226
cli_writeint32(structs+8, sects[i].vsz);
227
cli_writeint32(structs+12, sects[i].rva);
228
cli_writeint32(structs+16, sects[i].vsz);
229
cli_writeint32(structs+20, sects[i].rva);
232
memset(structs, 0, 0x28);
233
error = cli_writen(desc, exe, exesz)!=exesz;
239
/* 51ce - more_bb_again_and_again */
240
if (getbits(3, &eax, &bitmap, &bits, &src, packed, psize)) return 1;
244
/* jmp setsize_and_backcopy */
246
if (getbits(4, &eax, &bitmap, &bits, &src, packed, psize)) return 1;
250
/* jmp setsize_and_backcopy */
262
/* next_bit_or_reseed */
267
if (getbitmap(&bitmap, &src, &bits, packed, psize)) return 1;
270
if (!lostbit) continue;
271
if (getbits(c, &eax, &bitmap, &bits, &src, packed, psize)) return 1;
276
if (getbits(14, &eax, &bitmap, &bits, &src, packed, psize)) return 1;
283
/* 521b - setsize_and_backcopy */
287
/* 521e - backcopy */
288
if (!(CLI_ISCONTAINED(unpacked, usize, dst-backbytes, backsize) && CLI_ISCONTAINED(unpacked, usize, dst, backsize))) return 1;
290
*dst=*(dst-backbytes);
299
int wwunpack(char *exe, uint32_t exesz, uint32_t headsize, uint32_t min, uint32_t wwprva, uint32_t e_lfanew, char *wwp, uint32_t wwpsz, uint16_t sects) {
300
char *stuff=wwp+0x2a1, *packed, *unpacked;
303
cli_dbgmsg("in wwunpack\n");
307
if (!CLI_ISCONTAINED(wwp, wwpsz, stuff, 17)) {
308
cli_dbgmsg("WWPack: next chunk out ouf file, giving up.\n");
311
if ((csize=cli_readint32(stuff+8)*4)!=(uint32_t)cli_readint32(stuff+12)+4) {
312
cli_dbgmsg("WWPack: inconsistent/hacked data, go figure!\n");
315
rva = wwprva-cli_readint32(stuff);
316
if((packed = (char *) cli_calloc(csize, sizeof(char))) == NULL) {
317
cli_dbgmsg("WWPack: Can't allocate %d bytes\n", csize);
320
unpacked=exe+headsize+rva-min;
321
if (!CLI_ISCONTAINED(exe, exesz, unpacked, csize)) {
323
cli_dbgmsg("WWPack: packed data out of bounds, giving up.\n");
326
memcpy(packed, unpacked, csize);
327
if (wunpsect(packed, unpacked, csize, exesz-(unpacked-exe))) {
329
cli_dbgmsg("WWPack: unpacking failed.\n");
333
if (!stuff[16]) break;
341
csize=cli_readint32(wwp+0x295)+wwprva+0x299;
342
cli_dbgmsg("WWPack: found OEP @%x\n", csize);
343
cli_writeint32(stuff+0x28, csize);
345
csize=cli_readint32(stuff+0x50)-VAALIGN(wwpsz);
346
cli_writeint32(stuff+0x50, csize);
349
stuff+=0x18+(cli_readint32(stuff+0x14)&0xffff);
351
uint32_t v=cli_readint32(stuff+8);
352
uint32_t r=cli_readint32(stuff+16);
354
cli_writeint32(stuff+8, csize);
355
cli_writeint32(stuff+16, csize);
356
cli_writeint32(stuff+20, cli_readint32(stuff+12)-min+headsize);
359
memset(stuff, 0, 0x28);