git-svn: trunk@2054
aCaB authored on 2006/06/30 03:43:35... | ... |
@@ -87,6 +87,30 @@ static uint32_t cli_rawaddr(uint32_t rva, struct pe_image_section_hdr *shp, uint |
87 | 87 |
return rva - EC32(shp[i].VirtualAddress) + EC32(shp[i].PointerToRawData); |
88 | 88 |
} |
89 | 89 |
|
90 |
+static void xckriz(char **opcode, int *len, int checksize, int reg) { |
|
91 |
+ while(*len>6) { |
|
92 |
+ if (**opcode>='\x48' && **opcode<='\x4f' && **opcode!='\x4c') { |
|
93 |
+ if ((char)(**opcode-reg)=='\x48') break; |
|
94 |
+ (*len)--; |
|
95 |
+ (*opcode)++; |
|
96 |
+ continue; |
|
97 |
+ } |
|
98 |
+ if (**opcode>='\xb8' && **opcode<='\xbf' && **opcode!='\xbc') { |
|
99 |
+ if (checksize && cli_readint32(*opcode+1)==0x0fd2) break; |
|
100 |
+ (*len)-=5; |
|
101 |
+ (*opcode)+=5; |
|
102 |
+ continue; |
|
103 |
+ } |
|
104 |
+ if (**opcode=='\x81') { |
|
105 |
+ (*len)-=6; |
|
106 |
+ (*opcode)+=6; |
|
107 |
+ continue; |
|
108 |
+ } |
|
109 |
+ break; |
|
110 |
+ } |
|
111 |
+} |
|
112 |
+ |
|
113 |
+ |
|
90 | 114 |
/* |
91 | 115 |
static int cli_ddump(int desc, int offset, int size, const char *file) |
92 | 116 |
{ |
... | ... |
@@ -590,6 +614,67 @@ int cli_scanpe(int desc, cli_ctx *ctx) |
590 | 590 |
} |
591 | 591 |
} |
592 | 592 |
|
593 |
+ /* Kriz */ |
|
594 |
+ if(SCAN_ALGO && CLI_ISCONTAINED(EC32(section_hdr[nsections - 1].PointerToRawData), EC32(section_hdr[nsections - 1].SizeOfRawData), ep, 0x0fd2)) { |
|
595 |
+ cli_dbgmsg("in kriz\n"); |
|
596 |
+ lseek(desc, ep, SEEK_SET); |
|
597 |
+ if(read(desc, buff, 200) == 200) { |
|
598 |
+ while (1) { |
|
599 |
+ char *krizpos=buff+3; |
|
600 |
+ char *krizmov, *krizxor; |
|
601 |
+ int krizleft = 200-3; |
|
602 |
+ int krizrega,krizregb; |
|
603 |
+ |
|
604 |
+ if (buff[1]!='\x9c' || buff[2]!='\x60') break; /* EP+1 */ |
|
605 |
+ xckriz(&krizpos, &krizleft, 0, 8); |
|
606 |
+ if (krizleft < 6 || *krizpos!='\xe8' || krizpos[2] || krizpos[3] || krizpos[4]) break; /* call DELTA */ |
|
607 |
+ krizleft-=5+(unsigned char)krizpos[1]; |
|
608 |
+ if (krizleft < 2) break; |
|
609 |
+ krizpos+=5+(unsigned char)krizpos[1]; |
|
610 |
+ if (*krizpos<'\x58' || *krizpos>'\x5f' || *krizpos=='\x5c') break; /* pop DELTA */ |
|
611 |
+ krizrega=*krizpos-'\x58'; |
|
612 |
+ cli_dbgmsg("kriz: pop delta using %d\n", krizrega); |
|
613 |
+ krizpos+=1; |
|
614 |
+ krizleft-=1; |
|
615 |
+ xckriz(&krizpos, &krizleft, 1, 8); |
|
616 |
+ if (krizleft <6 || *krizpos<'\xb8' || *krizpos>'\xbf' || *krizpos=='\xbc' || cli_readint32(krizpos+1)!=0x0fd2) break; |
|
617 |
+ krizregb=*krizpos-'\xb8'; |
|
618 |
+ if (krizrega==krizregb) break; |
|
619 |
+ cli_dbgmsg("kriz: using %d for size\n", krizregb); |
|
620 |
+ krizpos+=5; |
|
621 |
+ krizleft-=5; |
|
622 |
+ krizmov = krizpos; |
|
623 |
+ xckriz(&krizpos, &krizleft, 0, 8); |
|
624 |
+ krizxor=krizpos; |
|
625 |
+ if (krizleft && *krizpos=='\x3e') { |
|
626 |
+ /* strip ds: */ |
|
627 |
+ krizpos++; |
|
628 |
+ krizleft--; |
|
629 |
+ } |
|
630 |
+ if (krizleft<8 || *krizpos!='\x80' || (char)(krizpos[1]-krizrega)!='\xb0') { |
|
631 |
+ cli_dbgmsg("kriz: bogus opcode or register\n"); |
|
632 |
+ break; |
|
633 |
+ } |
|
634 |
+ krizpos+=7; |
|
635 |
+ krizleft-=7; |
|
636 |
+ xckriz(&krizpos, &krizleft, 0, krizrega); |
|
637 |
+ if (! krizleft || (char)(*krizpos-krizrega)!='\x48') break; /* dec delta */ |
|
638 |
+ krizpos++; |
|
639 |
+ krizleft--; |
|
640 |
+ cli_dbgmsg("kriz: dec delta found\n"); |
|
641 |
+ xckriz(&krizpos, &krizleft, 0, krizregb); |
|
642 |
+ if (krizleft <4 || (char)(*krizpos-krizregb)!='\x48' || krizpos[1]!='\x75') break; /* dec size + jne loop */ |
|
643 |
+ if (krizpos+3+(int)krizpos[2]<krizmov || krizpos+3+(int)krizpos[2]>krizxor) { |
|
644 |
+ cli_dbgmsg("kriz: jmp back out of range (%d>%d>%d)\n", krizmov-(krizpos+3), (int)krizpos[2], krizxor-(krizpos+3)); |
|
645 |
+ break; |
|
646 |
+ } |
|
647 |
+ *ctx->virname = "Win32.Kriz"; |
|
648 |
+ free(section_hdr); |
|
649 |
+ return CL_VIRUS; |
|
650 |
+ } |
|
651 |
+ } |
|
652 |
+ } |
|
653 |
+ |
|
593 | 654 |
/* W32.Magistr.A/B */ |
594 | 655 |
if(SCAN_ALGO && !dll && (EC32(section_hdr[nsections - 1].Characteristics) & 0x80000000)) { |
595 | 656 |
uint32_t rsize, vsize; |
... | ... |
@@ -69,16 +69,9 @@ |
69 | 69 |
\x63\x6C\x61\x6D\x61\x76\x2E\x6E\x65\x74\x0D\x0A\x24\x00\x00\x00\ |
70 | 70 |
" |
71 | 71 |
|
72 |
-#if WORDS_BIGENDIAN == 0 |
|
73 |
-#define CLI_READLE32(x) (*(int32_t *)(x)) |
|
74 |
-#else |
|
75 |
-#define CLI_READLE32(x) (((*x) >> 24) | ((*(x+1) & 0x00FF0000) >> 8) | \ |
|
76 |
- ((*(x+2) & 0x0000FF00) << 8) | (*(x) << 24)) |
|
77 |
-#endif |
|
78 |
- |
|
79 | 72 |
/* PE from UPX */ |
80 | 73 |
|
81 |
-static int pefromupx (char *src, char *dst, uint32_t *dsize, uint32_t ep, uint32_t upx0, uint32_t upx1, uint32_t magic) |
|
74 |
+int pefromupx (char *src, char *dst, uint32_t *dsize, uint32_t ep, uint32_t upx0, uint32_t upx1, uint32_t magic) |
|
82 | 75 |
{ |
83 | 76 |
char *imports, *sections, *pehdr, *newbuf; |
84 | 77 |
int sectcnt, upd=1; |
... | ... |
@@ -88,7 +81,7 @@ static int pefromupx (char *src, char *dst, uint32_t *dsize, uint32_t ep, uint32 |
88 | 88 |
if((dst == NULL) || (src == NULL)) |
89 | 89 |
return 0; |
90 | 90 |
|
91 |
- imports = dst + CLI_READLE32(src + ep - upx1 + magic); |
|
91 |
+ imports = dst + cli_readint32(src + ep - upx1 + magic); |
|
92 | 92 |
|
93 | 93 |
realstuffsz = imports-dst; |
94 | 94 |
|
... | ... |
@@ -98,7 +91,7 @@ static int pefromupx (char *src, char *dst, uint32_t *dsize, uint32_t ep, uint32 |
98 | 98 |
} |
99 | 99 |
|
100 | 100 |
pehdr = imports; |
101 |
- while (CLI_ISCONTAINED(dst, *dsize, pehdr, 8) && CLI_READLE32(pehdr)) { |
|
101 |
+ while (CLI_ISCONTAINED(dst, *dsize, pehdr, 8) && cli_readint32(pehdr)) { |
|
102 | 102 |
pehdr+=8; |
103 | 103 |
while(CLI_ISCONTAINED(dst, *dsize, pehdr, 2) && *pehdr) { |
104 | 104 |
pehdr++; |
... | ... |
@@ -114,24 +107,13 @@ static int pefromupx (char *src, char *dst, uint32_t *dsize, uint32_t ep, uint32 |
114 | 114 |
cli_dbgmsg("UPX: sections out of bounds - giving up rebuild\n"); |
115 | 115 |
return 0; |
116 | 116 |
} |
117 |
- |
|
118 |
- if ( CLI_READLE32(pehdr) != 0x4550 ) { |
|
119 |
- cli_dbgmsg("UPX: OOPS: no magic for PE - scanning\n"); |
|
120 |
- while (CLI_ISCONTAINED(dst, *dsize, pehdr, 2) && |
|
121 |
- CLI_READLE32(pehdr) != 0x4550) { |
|
122 |
- pehdr+=2; |
|
123 |
- while (CLI_ISCONTAINED(dst, *dsize, pehdr, 2) && *pehdr) |
|
124 |
- pehdr++; |
|
125 |
- pehdr++; |
|
126 |
- } |
|
127 |
- } |
|
128 | 117 |
|
129 |
- if (!CLI_ISCONTAINED(dst, *dsize, pehdr, 0xf8)){ |
|
130 |
- cli_dbgmsg("UPX: Magic for PE - not found, aborting!\n"); |
|
118 |
+ if ( cli_readint32(pehdr) != 0x4550 ) { |
|
119 |
+ cli_dbgmsg("UPX: No magic for PE - giving up rebuild\n"); |
|
131 | 120 |
return 0; |
132 | 121 |
} |
133 | 122 |
|
134 |
- if (! CLI_READLE32(pehdr+0x38)) { |
|
123 |
+ if (! cli_readint32(pehdr+0x38)) { |
|
135 | 124 |
cli_dbgmsg("UPX: Cant align to a NULL bound - giving up rebuild\n"); |
136 | 125 |
return 0; |
137 | 126 |
} |
... | ... |
@@ -150,9 +132,9 @@ static int pefromupx (char *src, char *dst, uint32_t *dsize, uint32_t ep, uint32 |
150 | 150 |
} |
151 | 151 |
|
152 | 152 |
for (upd = 0; upd <sectcnt ; upd++) { |
153 |
- uint32_t vsize=CLI_READLE32(sections+8)-1; |
|
154 |
- uint32_t rsize=CLI_READLE32(sections+16); |
|
155 |
- uint32_t urva=CLI_READLE32(sections+12); |
|
153 |
+ uint32_t vsize=cli_readint32(sections+8)-1; |
|
154 |
+ uint32_t rsize=cli_readint32(sections+16); |
|
155 |
+ uint32_t urva=cli_readint32(sections+12); |
|
156 | 156 |
|
157 | 157 |
vsize=(((vsize/0x1000)+1)*0x1000); /* FIXME: get bounds from header */ |
158 | 158 |
|
... | ... |
@@ -169,7 +151,7 @@ static int pefromupx (char *src, char *dst, uint32_t *dsize, uint32_t ep, uint32 |
169 | 169 |
} |
170 | 170 |
|
171 | 171 |
/* Am i been fooled? There are better ways ;) */ |
172 |
- if ( rsize+4 < vsize && CLI_READLE32(dst+urva-upx0+rsize) ) { |
|
172 |
+ if ( rsize+4 < vsize && cli_readint32(dst+urva-upx0+rsize) ) { |
|
173 | 173 |
cli_dbgmsg("UPX: Am i been fooled? - giving up rebuild\n", upd); |
174 | 174 |
return 0; |
175 | 175 |
} |
... | ... |
@@ -192,7 +174,7 @@ static int pefromupx (char *src, char *dst, uint32_t *dsize, uint32_t ep, uint32 |
192 | 192 |
memcpy(newbuf+0xd0, pehdr,0xf8+0x28*sectcnt); |
193 | 193 |
sections = pehdr+0xf8; |
194 | 194 |
for (upd = 0; upd <sectcnt ; upd++) { |
195 |
- memcpy(newbuf+CLI_READLE32(sections+20), dst+CLI_READLE32(sections+12)-upx0, CLI_READLE32(sections+16)); |
|
195 |
+ memcpy(newbuf+cli_readint32(sections+20), dst+cli_readint32(sections+12)-upx0, cli_readint32(sections+16)); |
|
196 | 196 |
sections+=0x28; |
197 | 197 |
} |
198 | 198 |
|
... | ... |
@@ -207,32 +189,6 @@ static int pefromupx (char *src, char *dst, uint32_t *dsize, uint32_t ep, uint32 |
207 | 207 |
return 1; |
208 | 208 |
} |
209 | 209 |
|
210 |
-static int upx_find_ep(char *src, uint32_t ssize, uint32_t upx1, uint32_t ep) |
|
211 |
-{ |
|
212 |
- int32_t len; |
|
213 |
- int i; |
|
214 |
- |
|
215 |
- len = ssize - (ep - upx1); |
|
216 |
- |
|
217 |
- /* Verify decompressor length. Avoid crashing on multiple |
|
218 |
- * compressed files. exe packed by UPX and PEC. */ |
|
219 |
- if (!CLI_ISCONTAINED(src, ssize, src + ep - upx1 + 0xc0, len)) |
|
220 |
- return -1; |
|
221 |
- |
|
222 |
- /* Shift to decompressor start */ |
|
223 |
- src += (ep - upx1); |
|
224 |
- |
|
225 |
- for (i = 0xC0; i != len - 10; i++){ |
|
226 |
- if ((CLI_READLE32(src+i) & 0x0000FFFF) == 0x0000BE8D){ |
|
227 |
- cli_dbgmsg("UPX: found at %p, off: %x val: %08x\n", src+i+6, i+6, CLI_READLE32(src+i+6)); |
|
228 |
- if (CLI_READLE32(src+i+6) == 0xC009078B){ |
|
229 |
- return i+2; |
|
230 |
- } |
|
231 |
- } |
|
232 |
- } |
|
233 |
- cli_dbgmsg("UPX: upx_find_ep %p, %d - FAILED!\n", src, len); |
|
234 |
- return -1; |
|
235 |
-} |
|
236 | 210 |
|
237 | 211 |
/* [doubleebx] */ |
238 | 212 |
|
... | ... |
@@ -244,7 +200,7 @@ static int doubleebx(char *src, int32_t *myebx, int *scur, int ssize) |
244 | 244 |
if ( !(oldebx & 0x7fffffff)) { |
245 | 245 |
if (! CLI_ISCONTAINED(src, ssize, src+*scur, 4)) |
246 | 246 |
return -1; |
247 |
- oldebx = CLI_READLE32(src+*scur); |
|
247 |
+ oldebx = cli_readint32(src+*scur); |
|
248 | 248 |
*myebx = oldebx*2+1; |
249 | 249 |
*scur+=4; |
250 | 250 |
} |
... | ... |
@@ -327,9 +283,11 @@ int upx_inflate2b(char *src, uint32_t ssize, char *dst, uint32_t *dsize, uint32_ |
327 | 327 |
dcur+=backsize; |
328 | 328 |
} |
329 | 329 |
|
330 |
- scur = upx_find_ep(src, ssize, upx1, ep); |
|
331 |
- if (scur != -1) |
|
332 |
- return pefromupx (src, dst, dsize, ep, upx0, upx1, scur); |
|
330 |
+ |
|
331 |
+ if ( ep - upx1 + 0x108 <= ssize-5 && /* Wondering how we got so far?! */ |
|
332 |
+ src[ep - upx1 + 0x106] == '\x8d' && /* lea edi, ... */ |
|
333 |
+ src[ep - upx1 + 0x107] == '\xbe' ) /* ... [esi + offset] */ |
|
334 |
+ return pefromupx (src, dst, dsize, ep, upx0, upx1, 0x108); |
|
333 | 335 |
|
334 | 336 |
cli_dbgmsg("UPX: bad magic for 2b\n"); |
335 | 337 |
return 0; |
... | ... |
@@ -415,10 +373,12 @@ int upx_inflate2d(char *src, uint32_t ssize, char *dst, uint32_t *dsize, uint32_ |
415 | 415 |
dcur+=backsize; |
416 | 416 |
} |
417 | 417 |
|
418 |
- scur = upx_find_ep(src, ssize, upx1, ep); |
|
419 |
- if (scur != -1) |
|
420 |
- return pefromupx (src, dst, dsize, ep, upx0, upx1, scur); |
|
421 |
- |
|
418 |
+ if ( ep - upx1 + 0x124 <= ssize-5 ) { /* Wondering how we got so far?! */ |
|
419 |
+ if ( src[ep - upx1 + 0x11a] == '\x8d' && src[ep - upx1 + 0x11b] == '\xbe' ) |
|
420 |
+ return pefromupx (src, dst, dsize, ep, upx0, upx1, 0x11c); |
|
421 |
+ if ( src[ep - upx1 + 0x122] == '\x8d' && src[ep - upx1 + 0x123] == '\xbe' ) |
|
422 |
+ return pefromupx (src, dst, dsize, ep, upx0, upx1, 0x124); |
|
423 |
+ } |
|
422 | 424 |
cli_dbgmsg("UPX: bad magic for 2d\n"); |
423 | 425 |
return 0; |
424 | 426 |
} |
... | ... |
@@ -512,10 +472,12 @@ int upx_inflate2e(char *src, uint32_t ssize, char *dst, uint32_t *dsize, uint32_ |
512 | 512 |
dcur+=backsize; |
513 | 513 |
} |
514 | 514 |
|
515 |
- scur = upx_find_ep(src, ssize, upx1, ep); |
|
516 |
- if (scur != -1) |
|
517 |
- return pefromupx (src, dst, dsize, ep, upx0, upx1, scur); |
|
518 |
- |
|
515 |
+ if ( ep - upx1 + 0x130 <= ssize-5 ) { /* Wondering how we got so far?! */ |
|
516 |
+ if ( src[ep - upx1 + 0x126] == '\x8d' && src[ep - upx1 + 0x127] == '\xbe' ) |
|
517 |
+ return pefromupx (src, dst, dsize, ep, upx0, upx1, 0x128); |
|
518 |
+ if ( src[ep - upx1 + 0x12e] == '\x8d' && src[ep - upx1 + 0x12f] == '\xbe' ) |
|
519 |
+ return pefromupx (src, dst, dsize, ep, upx0, upx1, 0x130); |
|
520 |
+ } |
|
519 | 521 |
cli_dbgmsg("UPX: bad magic for 2e\n"); |
520 | 522 |
return 0; |
521 | 523 |
} |