git-svn: trunk@2969
aCaB authored on 2007/03/25 00:54:09... | ... |
@@ -1,3 +1,7 @@ |
1 |
+Sat Mar 24 15:01:50 CET 2007 (acab) |
|
2 |
+----------------------------------- |
|
3 |
+ * libclamav/upx.c: improve upx rebuilder - more to come |
|
4 |
+ |
|
1 | 5 |
Sat Mar 24 13:49:59 CET 2007 (acab) |
2 | 6 |
----------------------------------- |
3 | 7 |
* libclamav/upx.c: improve upx rebuilder - more to come |
... | ... |
@@ -26,7 +26,7 @@ |
26 | 26 |
** 04/06/2k4 - Now we handle 2B, 2D and 2E :D |
27 | 27 |
** 28/08/2k4 - PE rebuild for nested packers |
28 | 28 |
** 12/12/2k4 - Improved PE rebuild code and added some debug info on failure |
29 |
-** 23/03/2k4 - New approach for rebuilding: |
|
29 |
+** 23/03/2k7 - New approach for rebuilding: |
|
30 | 30 |
o Get imports via magic |
31 | 31 |
o Get imports via leascan |
32 | 32 |
o if (!pe) pe=scan4pe(); |
... | ... |
@@ -35,7 +35,6 @@ |
35 | 35 |
|
36 | 36 |
/* |
37 | 37 |
TODO: |
38 |
- - scan4pe() |
|
39 | 38 |
- forgepe() |
40 | 39 |
- pass dll flag from pe.c |
41 | 40 |
- grab statistical magic data from teh zoo |
... | ... |
@@ -83,11 +82,41 @@ |
83 | 83 |
\x63\x6C\x61\x6D\x61\x76\x2E\x6E\x65\x74\x0D\x0A\x24\x00\x00\x00\ |
84 | 84 |
" |
85 | 85 |
|
86 |
+static char *checkpe(char *dst, uint32_t dsize, char *pehdr, uint32_t *valign, unsigned int *sectcnt) { |
|
87 |
+ char *sections; |
|
88 |
+ if (!CLI_ISCONTAINED(dst, dsize, pehdr, 0xf8)) { |
|
89 |
+ cli_dbgmsg("UPX: sections out of bounds\n"); |
|
90 |
+ return NULL; |
|
91 |
+ } |
|
92 |
+ |
|
93 |
+ if (cli_readint32(pehdr) != 0x4550 ) { |
|
94 |
+ cli_dbgmsg("UPX: No magic for PE\n"); |
|
95 |
+ return NULL; |
|
96 |
+ } |
|
97 |
+ |
|
98 |
+ if (!(*valign=cli_readint32(pehdr+0x38))) { |
|
99 |
+ cli_dbgmsg("UPX: Cant align to a NULL bound\n"); |
|
100 |
+ return NULL; |
|
101 |
+ } |
|
102 |
+ |
|
103 |
+ sections = pehdr+0xf8; |
|
104 |
+ if (!(*sectcnt = (unsigned char)pehdr[6] + (unsigned char)pehdr[7]*256)) { |
|
105 |
+ cli_dbgmsg("UPX: No sections?\n"); |
|
106 |
+ return NULL; |
|
107 |
+ } |
|
108 |
+ |
|
109 |
+ if (!CLI_ISCONTAINED(dst, dsize, sections, *sectcnt*0x28)) { |
|
110 |
+ cli_dbgmsg("UPX: Not enough space for all sects\n"); |
|
111 |
+ return NULL; |
|
112 |
+ } |
|
113 |
+ return sections; |
|
114 |
+} |
|
115 |
+ |
|
86 | 116 |
/* PE from UPX */ |
87 | 117 |
|
88 |
-static int pefromupx (char *src, uint32_t ssize, char *dst, uint32_t *dsize, uint32_t ep, uint32_t upx0, uint32_t upx1, uint32_t *magic) |
|
118 |
+static int pefromupx (char *src, uint32_t ssize, char *dst, uint32_t *dsize, uint32_t ep, uint32_t upx0, uint32_t upx1, uint32_t *magic, uint32_t dend) |
|
89 | 119 |
{ |
90 |
- char *imports, *sections, *pehdr, *newbuf; |
|
120 |
+ char *imports, *sections, *pehdr=NULL, *newbuf; |
|
91 | 121 |
unsigned int sectcnt=0, upd=1; |
92 | 122 |
uint32_t realstuffsz, valign=0; |
93 | 123 |
uint32_t foffset=0xd0+0xf8; |
... | ... |
@@ -121,60 +150,45 @@ static int pefromupx (char *src, uint32_t ssize, char *dst, uint32_t *dsize, uin |
121 | 121 |
realstuffsz = imports-dst; |
122 | 122 |
|
123 | 123 |
if (realstuffsz >= *dsize ) { |
124 |
- cli_dbgmsg("UPX: wrong realstuff size - giving up rebuild\n"); |
|
125 |
- return 0; |
|
126 |
- } |
|
127 |
- |
|
128 |
- pehdr = imports; |
|
129 |
- while (CLI_ISCONTAINED(dst, *dsize, pehdr, 8) && cli_readint32(pehdr)) { |
|
130 |
- pehdr+=8; |
|
131 |
- while(CLI_ISCONTAINED(dst, *dsize, pehdr, 2) && *pehdr) { |
|
132 |
- pehdr++; |
|
133 |
- while (CLI_ISCONTAINED(dst, *dsize, pehdr, 2) && *pehdr) |
|
124 |
+ cli_dbgmsg("UPX: wrong realstuff size\n"); |
|
125 |
+ /* fallback and eventually craft */ |
|
126 |
+ } else { |
|
127 |
+ pehdr = imports; |
|
128 |
+ while (CLI_ISCONTAINED(dst, *dsize, pehdr, 8) && cli_readint32(pehdr)) { |
|
129 |
+ pehdr+=8; |
|
130 |
+ while(CLI_ISCONTAINED(dst, *dsize, pehdr, 2) && *pehdr) { |
|
134 | 131 |
pehdr++; |
132 |
+ while (CLI_ISCONTAINED(dst, *dsize, pehdr, 2) && *pehdr) |
|
133 |
+ pehdr++; |
|
134 |
+ pehdr++; |
|
135 |
+ } |
|
135 | 136 |
pehdr++; |
136 | 137 |
} |
137 |
- pehdr++; |
|
138 |
+ |
|
139 |
+ pehdr+=4; |
|
140 |
+ if (!(sections=checkpe(dst, *dsize, pehdr, &valign, §cnt))) pehdr=NULL; |
|
138 | 141 |
} |
139 |
- |
|
140 |
- pehdr+=4; |
|
141 |
- } else { /* TODO: this one should be a separate if (!pe) */ |
|
142 |
- cli_dbgmsg("UPX: no luck - brutally scanning for PE (TODO)\n"); |
|
143 |
- /* TODO */ |
|
144 |
- return 0; |
|
145 | 142 |
} |
146 | 143 |
|
147 |
- /* TODO: forgepe() */ |
|
148 |
- |
|
149 |
- /* TODO: Kick the checks outta here and write a checkpe() */ |
|
150 |
- if (!CLI_ISCONTAINED(dst, *dsize, pehdr, 0xf8)) { |
|
151 |
- cli_dbgmsg("UPX: sections out of bounds - giving up rebuild\n"); |
|
152 |
- return 0; |
|
153 |
- } |
|
154 |
- |
|
155 |
- if (cli_readint32(pehdr) != 0x4550 ) { |
|
156 |
- cli_dbgmsg("UPX: No magic for PE - giving up rebuild\n"); |
|
157 |
- return 0; |
|
158 |
- } |
|
159 |
- |
|
160 |
- if (!(valign=cli_readint32(pehdr+0x38))) { |
|
161 |
- cli_dbgmsg("UPX: Cant align to a NULL bound - giving up rebuild\n"); |
|
162 |
- return 0; |
|
144 |
+ if (!pehdr && dend>0xf8+0x28) { |
|
145 |
+ cli_dbgmsg("UPX: no luck - scanning for PE\n"); |
|
146 |
+ pehdr = &dst[dend-0xf8-0x28]; |
|
147 |
+ while (pehdr>=dst) { |
|
148 |
+ if ((sections=checkpe(dst, *dsize, pehdr, &valign, §cnt))) |
|
149 |
+ break; |
|
150 |
+ pehdr--; |
|
151 |
+ } |
|
152 |
+ if (pehdr==dst) pehdr=NULL; |
|
163 | 153 |
} |
164 |
- |
|
165 |
- sections = pehdr+0xf8; |
|
166 |
- if ( ! (sectcnt = (unsigned char)pehdr[6]+256*(unsigned char)pehdr[7])) { |
|
167 |
- cli_dbgmsg("UPX: No sections? - giving up rebuild\n"); |
|
154 |
+ |
|
155 |
+ if (!pehdr) { |
|
156 |
+ cli_dbgmsg("UPX: no luck - brutally crafing a reasonable PE (TODO)\n"); |
|
157 |
+ /*TODO: forgepe() or escape via cli_rebuildpe() ?*/ |
|
168 | 158 |
return 0; |
169 | 159 |
} |
170 | 160 |
|
171 | 161 |
foffset = PESALIGN(foffset+0x28*sectcnt, valign); |
172 | 162 |
|
173 |
- if (!CLI_ISCONTAINED(dst, *dsize, sections, 0x28*sectcnt)) { |
|
174 |
- cli_dbgmsg("UPX: Not enough space for all sects - giving up rebuild\n"); |
|
175 |
- return 0; |
|
176 |
- } |
|
177 |
- |
|
178 | 163 |
for (upd = 0; upd <sectcnt ; upd++) { |
179 | 164 |
uint32_t vsize=PESALIGN((uint32_t)cli_readint32(sections+8), valign); |
180 | 165 |
uint32_t urva=PEALIGN((uint32_t)cli_readint32(sections+12), valign); |
... | ... |
@@ -249,7 +263,7 @@ static int doubleebx(char *src, uint32_t *myebx, uint32_t *scur, uint32_t ssize) |
249 | 249 |
int upx_inflate2b(char *src, uint32_t ssize, char *dst, uint32_t *dsize, uint32_t upx0, uint32_t upx1, uint32_t ep) |
250 | 250 |
{ |
251 | 251 |
int32_t backbytes, unp_offset = -1; |
252 |
- uint32_t backsize, myebx = 0, scur=0, dcur=0, i, magic[]={0x108,0x110,0}; |
|
252 |
+ uint32_t backsize, myebx = 0, scur=0, dcur=0, i, magic[]={/*0, TODO: removeme */0x108,0x110,0}; |
|
253 | 253 |
int oob; |
254 | 254 |
|
255 | 255 |
while (1) { |
... | ... |
@@ -318,7 +332,7 @@ int upx_inflate2b(char *src, uint32_t ssize, char *dst, uint32_t *dsize, uint32_ |
318 | 318 |
dcur+=backsize; |
319 | 319 |
} |
320 | 320 |
|
321 |
- return pefromupx (src, ssize, dst, dsize, ep, upx0, upx1, magic); |
|
321 |
+ return pefromupx (src, ssize, dst, dsize, ep, upx0, upx1, magic, dcur); |
|
322 | 322 |
} |
323 | 323 |
|
324 | 324 |
int upx_inflate2d(char *src, uint32_t ssize, char *dst, uint32_t *dsize, uint32_t upx0, uint32_t upx1, uint32_t ep) |
... | ... |
@@ -400,7 +414,7 @@ int upx_inflate2d(char *src, uint32_t ssize, char *dst, uint32_t *dsize, uint32_ |
400 | 400 |
dcur+=backsize; |
401 | 401 |
} |
402 | 402 |
|
403 |
- return pefromupx (src, ssize, dst, dsize, ep, upx0, upx1, magic); |
|
403 |
+ return pefromupx (src, ssize, dst, dsize, ep, upx0, upx1, magic, dcur); |
|
404 | 404 |
} |
405 | 405 |
|
406 | 406 |
int upx_inflate2e(char *src, uint32_t ssize, char *dst, uint32_t *dsize, uint32_t upx0, uint32_t upx1, uint32_t ep) |
... | ... |
@@ -489,5 +503,5 @@ int upx_inflate2e(char *src, uint32_t ssize, char *dst, uint32_t *dsize, uint32_ |
489 | 489 |
dcur+=backsize; |
490 | 490 |
} |
491 | 491 |
|
492 |
- return pefromupx (src, ssize, dst, dsize, ep, upx0, upx1, magic); |
|
492 |
+ return pefromupx (src, ssize, dst, dsize, ep, upx0, upx1, magic, dcur); |
|
493 | 493 |
} |