git-svn: trunk@3202
aCaB authored on 2007/09/04 09:38:30... | ... |
@@ -1,3 +1,8 @@ |
1 |
+Tue Sep 4 01:31:23 CEST 2007 (acab) |
|
2 |
+------------------------------------ |
|
3 |
+ * libclamav:pe.c General "tidy" and some algo hacks. Old and inefficient |
|
4 |
+ sue cryptor replaced with a signature. |
|
5 |
+ |
|
1 | 6 |
Sun Sep 2 12:41:46 BST 2007 (njh) |
2 | 7 |
---------------------------------- |
3 | 8 |
* clamav-milter: Fix compilation error from fix to bug 577 |
... | ... |
@@ -82,12 +82,12 @@ am_libclamav_la_OBJECTS = matcher-ac.lo matcher-bm.lo matcher-ncore.lo \ |
82 | 82 |
scanners.lo filetypes.lo rtf.lo blob.lo mbox.lo message.lo \ |
83 | 83 |
snprintf.lo table.lo text.lo ole2_extract.lo vba_extract.lo \ |
84 | 84 |
msexpand.lo pe.lo upx.lo htmlnorm.lo chmunpack.lo rebuildpe.lo \ |
85 |
- petite.lo wwunpack.lo suecrypt.lo unsp.lo aspack.lo \ |
|
86 |
- packlibs.lo fsg.lo mew.lo upack.lo line.lo untar.lo unzip.lo \ |
|
87 |
- special.lo binhex.lo is_tar.lo tnef.lo unrar15.lo unrarvm.lo \ |
|
88 |
- unrar.lo unrarfilter.lo unrarppm.lo unrar20.lo unrarcmd.lo \ |
|
89 |
- unarj.lo LZMADecode.lo bzlib.lo infblock.lo nulsft.lo pdf.lo \ |
|
90 |
- spin.lo yc.lo elf.lo sis.lo uuencode.lo pst.lo phishcheck.lo \ |
|
85 |
+ petite.lo wwunpack.lo unsp.lo aspack.lo packlibs.lo fsg.lo \ |
|
86 |
+ mew.lo upack.lo line.lo untar.lo unzip.lo special.lo binhex.lo \ |
|
87 |
+ is_tar.lo tnef.lo unrar15.lo unrarvm.lo unrar.lo \ |
|
88 |
+ unrarfilter.lo unrarppm.lo unrar20.lo unrarcmd.lo unarj.lo \ |
|
89 |
+ LZMADecode.lo bzlib.lo infblock.lo nulsft.lo pdf.lo spin.lo \ |
|
90 |
+ yc.lo elf.lo sis.lo uuencode.lo pst.lo phishcheck.lo \ |
|
91 | 91 |
phish_domaincheck_db.lo phish_whitelist.lo regex_list.lo \ |
92 | 92 |
sha256.lo mspack.lo cab.lo entconv.lo hashtab.lo dconf.lo \ |
93 | 93 |
lockdb.lo |
... | ... |
@@ -149,6 +149,7 @@ F77 = @F77@ |
149 | 149 |
FFLAGS = @FFLAGS@ |
150 | 150 |
FRESHCLAM_LIBS = @FRESHCLAM_LIBS@ |
151 | 151 |
GETENT = @GETENT@ |
152 |
+GREP = @GREP@ |
|
152 | 153 |
HAVE_MILTER_FALSE = @HAVE_MILTER_FALSE@ |
153 | 154 |
HAVE_MILTER_TRUE = @HAVE_MILTER_TRUE@ |
154 | 155 |
INSTALL_DATA = @INSTALL_DATA@ |
... | ... |
@@ -182,12 +183,9 @@ STRIP = @STRIP@ |
182 | 182 |
THREAD_LIBS = @THREAD_LIBS@ |
183 | 183 |
TH_SAFE = @TH_SAFE@ |
184 | 184 |
VERSION = @VERSION@ |
185 |
-ac_ct_AR = @ac_ct_AR@ |
|
186 | 185 |
ac_ct_CC = @ac_ct_CC@ |
187 | 186 |
ac_ct_CXX = @ac_ct_CXX@ |
188 | 187 |
ac_ct_F77 = @ac_ct_F77@ |
189 |
-ac_ct_RANLIB = @ac_ct_RANLIB@ |
|
190 |
-ac_ct_STRIP = @ac_ct_STRIP@ |
|
191 | 188 |
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ |
192 | 189 |
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ |
193 | 190 |
am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ |
... | ... |
@@ -204,23 +202,30 @@ build_cpu = @build_cpu@ |
204 | 204 |
build_os = @build_os@ |
205 | 205 |
build_vendor = @build_vendor@ |
206 | 206 |
datadir = @datadir@ |
207 |
+datarootdir = @datarootdir@ |
|
208 |
+docdir = @docdir@ |
|
209 |
+dvidir = @dvidir@ |
|
207 | 210 |
exec_prefix = @exec_prefix@ |
208 | 211 |
host = @host@ |
209 | 212 |
host_alias = @host_alias@ |
210 | 213 |
host_cpu = @host_cpu@ |
211 | 214 |
host_os = @host_os@ |
212 | 215 |
host_vendor = @host_vendor@ |
216 |
+htmldir = @htmldir@ |
|
213 | 217 |
includedir = @includedir@ |
214 | 218 |
infodir = @infodir@ |
215 | 219 |
install_sh = @install_sh@ |
216 | 220 |
libdir = @libdir@ |
217 | 221 |
libexecdir = @libexecdir@ |
222 |
+localedir = @localedir@ |
|
218 | 223 |
localstatedir = @localstatedir@ |
219 | 224 |
mandir = @mandir@ |
220 | 225 |
mkdir_p = @mkdir_p@ |
221 | 226 |
oldincludedir = @oldincludedir@ |
227 |
+pdfdir = @pdfdir@ |
|
222 | 228 |
prefix = @prefix@ |
223 | 229 |
program_transform_name = @program_transform_name@ |
230 |
+psdir = @psdir@ |
|
224 | 231 |
sbindir = @sbindir@ |
225 | 232 |
sendmailprog = @sendmailprog@ |
226 | 233 |
sharedstatedir = @sharedstatedir@ |
... | ... |
@@ -295,8 +300,6 @@ libclamav_la_SOURCES = \ |
295 | 295 |
petite.h \ |
296 | 296 |
wwunpack.c \ |
297 | 297 |
wwunpack.h \ |
298 |
- suecrypt.c \ |
|
299 |
- suecrypt.h \ |
|
300 | 298 |
unsp.c \ |
301 | 299 |
unsp.h \ |
302 | 300 |
aspack.c \ |
... | ... |
@@ -513,7 +516,6 @@ distclean-compile: |
513 | 513 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/special.Plo@am__quote@ |
514 | 514 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spin.Plo@am__quote@ |
515 | 515 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str.Plo@am__quote@ |
516 |
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/suecrypt.Plo@am__quote@ |
|
517 | 516 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/table.Plo@am__quote@ |
518 | 517 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/text.Plo@am__quote@ |
519 | 518 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tnef.Plo@am__quote@ |
... | ... |
@@ -55,8 +55,6 @@ static struct dconf_module modules[] = { |
55 | 55 |
{ "PE", "UPX", PE_CONF_UPX, 1 }, |
56 | 56 |
{ "PE", "FSG", PE_CONF_FSG, 1 }, |
57 | 57 |
|
58 |
- { "PE", "SUE", PE_CONF_SUE, 1 }, |
|
59 |
- |
|
60 | 58 |
{ "PE", "PETITE", PE_CONF_PETITE, 1 }, |
61 | 59 |
{ "PE", "PESPIN", PE_CONF_PESPIN, 1 }, |
62 | 60 |
{ "PE", "YC", PE_CONF_YC, 1 }, |
... | ... |
@@ -42,7 +42,7 @@ struct cli_dconf { |
42 | 42 |
#define PE_CONF_MD5SECT 0x10 |
43 | 43 |
#define PE_CONF_UPX 0x20 |
44 | 44 |
#define PE_CONF_FSG 0x40 |
45 |
-#define PE_CONF_SUE 0x80 |
|
45 |
+/*#define PE_CONF_REUSEME 0x80 */ |
|
46 | 46 |
#define PE_CONF_PETITE 0x100 |
47 | 47 |
#define PE_CONF_PESPIN 0x200 |
48 | 48 |
#define PE_CONF_YC 0x400 |
... | ... |
@@ -32,6 +32,7 @@ |
32 | 32 |
#include <unistd.h> |
33 | 33 |
#endif |
34 | 34 |
#include <time.h> |
35 |
+#include <stdarg.h> |
|
35 | 36 |
|
36 | 37 |
#include "cltypes.h" |
37 | 38 |
#include "clamav.h" |
... | ... |
@@ -44,7 +45,6 @@ |
44 | 44 |
#include "yc.h" |
45 | 45 |
#include "aspack.h" |
46 | 46 |
#include "wwunpack.h" |
47 |
-#include "suecrypt.h" |
|
48 | 47 |
#include "unsp.h" |
49 | 48 |
#include "scanners.h" |
50 | 49 |
#include "str.h" |
... | ... |
@@ -80,19 +80,114 @@ |
80 | 80 |
#define PEALIGN(o,a) (((a))?(((o)/(a))*(a)):(o)) |
81 | 81 |
#define PESALIGN(o,a) (((a))?(((o)/(a)+((o)%(a)!=0))*(a)):(o)) |
82 | 82 |
|
83 |
+#define CLI_UNPSIZELIMITS(NAME,CHK) \ |
|
84 |
+if(ctx->limits && ctx->limits->maxfilesize && (CHK) > ctx->limits->maxfilesize) { \ |
|
85 |
+ cli_dbgmsg(NAME": Sizes exceeded (%lu > %lu)\n", (CHK), ctx->limits->maxfilesize); \ |
|
86 |
+ free(exe_sections); \ |
|
87 |
+ if(BLOCKMAX) { \ |
|
88 |
+ *ctx->virname = "PE."NAME".ExceededFileSize"; \ |
|
89 |
+ return CL_VIRUS; \ |
|
90 |
+ } else { \ |
|
91 |
+ return CL_CLEAN; \ |
|
92 |
+ } \ |
|
93 |
+} |
|
94 |
+ |
|
95 |
+#define CLI_UNPTEMP(NAME,...) \ |
|
96 |
+if(!(tempfile = cli_gentemp(NULL))) { \ |
|
97 |
+ cli_multifree(__VA_ARGS__,0); \ |
|
98 |
+ return CL_EMEM; \ |
|
99 |
+} \ |
|
100 |
+if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) { \ |
|
101 |
+ cli_dbgmsg(NAME": Can't create file %s\n", tempfile); \ |
|
102 |
+ cli_multifree(tempfile,__VA_ARGS__,0); \ |
|
103 |
+ return CL_EIO; \ |
|
104 |
+} |
|
105 |
+ |
|
106 |
+#define CLI_TMPUNLK() if(!cli_leavetemps_flag) unlink(tempfile) |
|
107 |
+ |
|
108 |
+#define FSGCASE(NAME,FREESEC) \ |
|
109 |
+ case 0: /* Unpacked and NOT rebuilt */ \ |
|
110 |
+ cli_dbgmsg(NAME": Successfully decompressed\n"); \ |
|
111 |
+ close(ndesc); \ |
|
112 |
+ unlink(tempfile); \ |
|
113 |
+ free(tempfile); \ |
|
114 |
+ FREESEC; \ |
|
115 |
+ found = 0; \ |
|
116 |
+ upx_success = 1; \ |
|
117 |
+ break; /* FSG ONLY! - scan raw data after upx block */ |
|
118 |
+ |
|
119 |
+#define SPINCASE() \ |
|
120 |
+ case 2: \ |
|
121 |
+ free(spinned); \ |
|
122 |
+ close(ndesc); \ |
|
123 |
+ unlink(tempfile); \ |
|
124 |
+ cli_dbgmsg("PESpin: Size exceeded\n"); \ |
|
125 |
+ if(BLOCKMAX) { \ |
|
126 |
+ free(tempfile); \ |
|
127 |
+ free(exe_sections); \ |
|
128 |
+ *ctx->virname = "PE.Pespin.ExceededFileSize"; \ |
|
129 |
+ return CL_VIRUS; \ |
|
130 |
+ } \ |
|
131 |
+ free(tempfile); \ |
|
132 |
+ break; \ |
|
133 |
+ |
|
134 |
+#define CLI_UNPRESULTS_(NAME,FSGSTUFF,EXPR,GOOD,...) \ |
|
135 |
+ switch(EXPR) { \ |
|
136 |
+ case GOOD: /* Unpacked and rebuilt */ \ |
|
137 |
+ if(cli_leavetemps_flag) \ |
|
138 |
+ cli_dbgmsg(NAME": Unpacked and rebuilt executable saved in %s\n", tempfile); \ |
|
139 |
+ else \ |
|
140 |
+ cli_dbgmsg(NAME": Unpacked and rebuilt executable\n"); \ |
|
141 |
+ cli_multifree(__VA_ARGS__,exe_sections,0); \ |
|
142 |
+ fsync(ndesc); \ |
|
143 |
+ lseek(ndesc, 0, SEEK_SET); \ |
|
144 |
+ cli_dbgmsg("***** Scanning rebuilt PE file *****\n"); \ |
|
145 |
+ if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) { \ |
|
146 |
+ close(ndesc); \ |
|
147 |
+ CLI_TMPUNLK(); \ |
|
148 |
+ free(tempfile); \ |
|
149 |
+ return CL_VIRUS; \ |
|
150 |
+ } \ |
|
151 |
+ close(ndesc); \ |
|
152 |
+ CLI_TMPUNLK(); \ |
|
153 |
+ free(tempfile); \ |
|
154 |
+ return CL_CLEAN; \ |
|
155 |
+\ |
|
156 |
+FSGSTUFF \ |
|
157 |
+\ |
|
158 |
+ default: \ |
|
159 |
+ cli_dbgmsg(NAME": Unpacking failed\n"); \ |
|
160 |
+ close(ndesc); \ |
|
161 |
+ unlink(tempfile); \ |
|
162 |
+ cli_multifree(__VA_ARGS__,tempfile,0); \ |
|
163 |
+ } |
|
164 |
+ |
|
165 |
+ |
|
166 |
+#define CLI_UNPRESULTS(NAME,EXPR,GOOD,...) CLI_UNPRESULTS_(NAME,,EXPR,GOOD,__VA_ARGS__) |
|
167 |
+#define CLI_UNPRESULTSFSG1(NAME,EXPR,GOOD,...) CLI_UNPRESULTS_(NAME,FSGCASE(NAME,free(sections)),EXPR,GOOD,__VA_ARGS__) |
|
168 |
+#define CLI_UNPRESULTSFSG2(NAME,EXPR,GOOD,...) CLI_UNPRESULTS_(NAME,FSGCASE(NAME,),EXPR,GOOD,__VA_ARGS__) |
|
83 | 169 |
|
84 | 170 |
struct offset_list { |
85 | 171 |
uint32_t offset; |
86 | 172 |
struct offset_list *next; |
87 | 173 |
}; |
88 | 174 |
|
175 |
+static void cli_multifree(void *f, ...) { |
|
176 |
+ void *ff; |
|
177 |
+ va_list ap; |
|
178 |
+ free(f); |
|
179 |
+ va_start(ap, f); |
|
180 |
+ while((ff=va_arg(ap, void*))) free(ff); |
|
181 |
+ va_end(ap); |
|
182 |
+} |
|
183 |
+ |
|
89 | 184 |
static uint32_t cli_rawaddr(uint32_t rva, struct cli_exe_section *shp, uint16_t nos, unsigned int *err, size_t fsize, uint32_t hdr_size) |
90 | 185 |
{ |
91 |
- int i, found = 0; |
|
92 |
- uint32_t ret; |
|
186 |
+ int i, found = 0; |
|
187 |
+ uint32_t ret; |
|
93 | 188 |
|
94 | 189 |
if (rva<hdr_size) { /* Out of section EP - mapped to imagebase+rva */ |
95 |
- if (rva >= fsize) { |
|
190 |
+ if (rva >= fsize) { |
|
96 | 191 |
*err=1; |
97 | 192 |
return 0; |
98 | 193 |
} |
... | ... |
@@ -117,33 +212,9 @@ static uint32_t cli_rawaddr(uint32_t rva, struct cli_exe_section *shp, uint16_t |
117 | 117 |
return ret; |
118 | 118 |
} |
119 | 119 |
|
120 |
-static void xckriz(char **opcode, int *len, int checksize, int reg) { |
|
121 |
- while(*len>6) { |
|
122 |
- if (**opcode>='\x48' && **opcode<='\x4f' && **opcode!='\x4c') { |
|
123 |
- if ((char)(**opcode-reg)=='\x48') break; |
|
124 |
- (*len)--; |
|
125 |
- (*opcode)++; |
|
126 |
- continue; |
|
127 |
- } |
|
128 |
- if (**opcode>='\xb8' && **opcode<='\xbf' && **opcode!='\xbc') { |
|
129 |
- if (checksize && cli_readint32(*opcode+1)==0x0fd2) break; |
|
130 |
- (*len)-=5; |
|
131 |
- (*opcode)+=5; |
|
132 |
- continue; |
|
133 |
- } |
|
134 |
- if (**opcode=='\x81') { |
|
135 |
- (*len)-=6; |
|
136 |
- (*opcode)+=6; |
|
137 |
- continue; |
|
138 |
- } |
|
139 |
- break; |
|
140 |
- } |
|
141 |
-} |
|
142 |
- |
|
143 | 120 |
|
144 | 121 |
/* |
145 |
-static int cli_ddump(int desc, int offset, int size, const char *file) |
|
146 |
-{ |
|
122 |
+static int cli_ddump(int desc, int offset, int size, const char *file) { |
|
147 | 123 |
int pos, ndesc, bread, sum = 0; |
148 | 124 |
char buff[FILEBUFF]; |
149 | 125 |
|
... | ... |
@@ -195,39 +266,40 @@ static int cli_ddump(int desc, int offset, int size, const char *file) |
195 | 195 |
} |
196 | 196 |
*/ |
197 | 197 |
|
198 |
-static unsigned int cli_md5sect(int fd, uint32_t offset, uint32_t size, unsigned char *digest) |
|
199 |
-{ |
|
200 |
- size_t bread, sum = 0; |
|
201 |
- off_t pos; |
|
202 |
- char buff[FILEBUFF]; |
|
203 |
- cli_md5_ctx md5ctx; |
|
198 |
+static off_t cli_seeksect(int fd, struct cli_exe_section *s) { |
|
199 |
+ off_t ret; |
|
204 | 200 |
|
201 |
+ if(!s->rsz) return 0; |
|
202 |
+ if((ret=lseek(fd, s->raw, SEEK_SET)) == -1) |
|
203 |
+ cli_dbgmsg("cli_seeksect: lseek() failed\n"); |
|
204 |
+ return ret+1; |
|
205 |
+} |
|
206 |
+ |
|
207 |
+static unsigned int cli_md5sect(int fd, struct cli_exe_section *s, unsigned char *digest) { |
|
208 |
+ void *hashme; |
|
209 |
+ cli_md5_ctx md5; |
|
205 | 210 |
|
206 |
- if((pos = lseek(fd, 0, SEEK_CUR)) == -1) { |
|
207 |
- cli_dbgmsg("cli_md5sect: Invalid descriptor %d\n", fd); |
|
211 |
+ if (s->rsz > CLI_MAX_ALLOCATION) { |
|
212 |
+ cli_dbgmsg("cli_md5sect: skipping md5 calculation for too big section\n"); |
|
208 | 213 |
return 0; |
209 | 214 |
} |
210 | 215 |
|
211 |
- if(lseek(fd, offset, SEEK_SET) == -1) { |
|
212 |
- cli_dbgmsg("cli_md5sect: lseek() failed\n"); |
|
213 |
- lseek(fd, pos, SEEK_SET); |
|
216 |
+ if(!cli_seeksect(fd, s)) return 0; |
|
217 |
+ |
|
218 |
+ if(!(hashme=cli_malloc(s->rsz))) { |
|
219 |
+ cli_dbgmsg("cli_md5sect: out of memory\n"); |
|
214 | 220 |
return 0; |
215 | 221 |
} |
216 | 222 |
|
217 |
- cli_md5_init(&md5ctx); |
|
218 |
- |
|
219 |
- while((bread = cli_readn(fd, buff, FILEBUFF)) > 0) { |
|
220 |
- if(sum + bread >= size) { |
|
221 |
- cli_md5_update(&md5ctx, buff, size - sum); |
|
222 |
- break; |
|
223 |
- } else { |
|
224 |
- cli_md5_update(&md5ctx, buff, bread); |
|
225 |
- sum += bread; |
|
226 |
- } |
|
223 |
+ if(cli_readn(fd, hashme, s->rsz)!=s->rsz) { |
|
224 |
+ cli_dbgmsg("cli_md5sect: unable to read section data\n"); |
|
225 |
+ return 0; |
|
227 | 226 |
} |
228 | 227 |
|
229 |
- cli_md5_final(digest, &md5ctx); |
|
230 |
- lseek(fd, pos, SEEK_SET); |
|
228 |
+ cli_md5_init(&md5); |
|
229 |
+ cli_md5_update(&md5, hashme, s->rsz); |
|
230 |
+ free(hashme); |
|
231 |
+ cli_md5_final(digest, &md5); |
|
231 | 232 |
return 1; |
232 | 233 |
} |
233 | 234 |
|
... | ... |
@@ -246,7 +318,8 @@ int cli_scanpe(int desc, cli_ctx *ctx) |
246 | 246 |
} pe_opt; |
247 | 247 |
struct pe_image_section_hdr *section_hdr; |
248 | 248 |
struct stat sb; |
249 |
- char sname[9], buff[4096], *tempfile; |
|
249 |
+ char sname[9], buff[4096], epbuff[4096], *tempfile; |
|
250 |
+ uint32_t epsize; |
|
250 | 251 |
unsigned char *ubuff; |
251 | 252 |
ssize_t bytes; |
252 | 253 |
unsigned int i, found, upx_success = 0, min = 0, max = 0, err; |
... | ... |
@@ -317,6 +390,7 @@ int cli_scanpe(int desc, cli_ctx *ctx) |
317 | 317 |
switch(EC16(file_hdr.Machine)) { |
318 | 318 |
case 0x0: |
319 | 319 |
cli_dbgmsg("Machine type: Unknown\n"); |
320 |
+ break; |
|
320 | 321 |
case 0x14c: |
321 | 322 |
cli_dbgmsg("Machine type: 80386\n"); |
322 | 323 |
break; |
... | ... |
@@ -700,7 +774,6 @@ int cli_scanpe(int desc, cli_ctx *ctx) |
700 | 700 |
} |
701 | 701 |
|
702 | 702 |
if (exe_sections[i].rsz) { /* Don't bother with virtual only sections */ |
703 |
- unsigned char md5_dig[16]; |
|
704 | 703 |
if (exe_sections[i].raw >= fsize) { /* really broken */ |
705 | 704 |
cli_dbgmsg("Broken PE file - Section %d starts beyond the end of file (Offset@ %d, Total filesize %d)\n", i, exe_sections[i].raw, fsize); |
706 | 705 |
free(section_hdr); |
... | ... |
@@ -713,26 +786,21 @@ int cli_scanpe(int desc, cli_ctx *ctx) |
713 | 713 |
return CL_CLEAN; /* no ninjas to see here! move along! */ |
714 | 714 |
} |
715 | 715 |
|
716 |
+ if(SCAN_ALGO && (DCONF & PE_CONF_POLIPOS) && !*sname && exe_sections[i].vsz > 40000 && exe_sections[i].vsz < 70000 && exe_sections[i].chr == 0xe0000060) polipos = i; |
|
717 |
+ |
|
716 | 718 |
/* check MD5 section sigs */ |
717 | 719 |
md5_sect = ctx->engine->md5_sect; |
718 | 720 |
if((DCONF & PE_CONF_MD5SECT) && md5_sect) { |
719 | 721 |
found = 0; |
720 | 722 |
for(j = 0; j < md5_sect->soff_len && md5_sect->soff[j] <= exe_sections[i].rsz; j++) { |
721 | 723 |
if(md5_sect->soff[j] == exe_sections[i].rsz) { |
722 |
- found = 1; |
|
723 |
- break; |
|
724 |
- } |
|
725 |
- } |
|
726 |
- |
|
727 |
- if(found) { |
|
728 |
- if(!cli_md5sect(desc, exe_sections[i].raw, exe_sections[i].rsz, md5_dig)) { |
|
729 |
- cli_errmsg("PE: Can't calculate MD5 for section %u\n", i); |
|
730 |
- } else { |
|
731 |
- if(cli_bm_scanbuff(md5_dig, 16, ctx->virname, ctx->engine->md5_sect, 0, 0, -1) == CL_VIRUS) { |
|
732 |
- free(section_hdr); |
|
733 |
- free(exe_sections); |
|
734 |
- return CL_VIRUS; |
|
724 |
+ unsigned char md5_dig[16]; |
|
725 |
+ if(cli_md5sect(desc, &exe_sections[i], md5_dig) && cli_bm_scanbuff(md5_dig, 16, ctx->virname, ctx->engine->md5_sect, 0, 0, -1) == CL_VIRUS) { |
|
726 |
+ free(section_hdr); |
|
727 |
+ free(exe_sections); |
|
728 |
+ return CL_VIRUS; |
|
735 | 729 |
} |
730 |
+ break; |
|
736 | 731 |
} |
737 | 732 |
} |
738 | 733 |
} |
... | ... |
@@ -764,15 +832,6 @@ int cli_scanpe(int desc, cli_ctx *ctx) |
764 | 764 |
if(exe_sections[i].rva + exe_sections[i].rsz > max) |
765 | 765 |
max = exe_sections[i].rva + exe_sections[i].rsz; |
766 | 766 |
} |
767 |
- |
|
768 |
- if(SCAN_ALGO && (DCONF & PE_CONF_POLIPOS) && !strlen(sname)) { |
|
769 |
- if(exe_sections[i].vsz > 40000 && exe_sections[i].vsz < 70000) { |
|
770 |
- if(exe_sections[i].chr == 0xe0000060) { |
|
771 |
- polipos = i; |
|
772 |
- } |
|
773 |
- } |
|
774 |
- } |
|
775 |
- |
|
776 | 767 |
} |
777 | 768 |
|
778 | 769 |
free(section_hdr); |
... | ... |
@@ -795,91 +854,113 @@ int cli_scanpe(int desc, cli_ctx *ctx) |
795 | 795 |
return CL_CLEAN; |
796 | 796 |
} |
797 | 797 |
|
798 |
+ lseek(desc, ep, SEEK_SET); |
|
799 |
+ epsize = cli_readn(desc, epbuff, 4096); |
|
798 | 800 |
|
799 | 801 |
/* Attempt to detect some popular polymorphic viruses */ |
800 | 802 |
|
801 | 803 |
/* W32.Parite.B */ |
802 |
- if(SCAN_ALGO && (DCONF & PE_CONF_PARITE) && !dll && ep == exe_sections[nsections - 1].raw) { |
|
803 |
- lseek(desc, ep, SEEK_SET); |
|
804 |
- if(cli_readn(desc, buff, 4096) == 4096) { |
|
805 |
- const char *pt = cli_memstr(buff, 4040, "\x47\x65\x74\x50\x72\x6f\x63\x41\x64\x64\x72\x65\x73\x73\x00", 15); |
|
806 |
- if(pt) { |
|
807 |
- uint32_t dw1, dw2; |
|
808 |
- |
|
809 |
- pt += 15; |
|
810 |
- if(((dw1 = cli_readint32(pt)) ^ (dw2 = cli_readint32(pt + 4))) == 0x505a4f && ((dw1 = cli_readint32(pt + 8)) ^ (dw2 = cli_readint32(pt + 12))) == 0xffffb && ((dw1 = cli_readint32(pt + 16)) ^ (dw2 = cli_readint32(pt + 20))) == 0xb8) { |
|
811 |
- *ctx->virname = "W32.Parite.B"; |
|
812 |
- free(exe_sections); |
|
813 |
- return CL_VIRUS; |
|
814 |
- } |
|
804 |
+ if(SCAN_ALGO && (DCONF & PE_CONF_PARITE) && !dll && epsize == 4096 && ep == exe_sections[nsections - 1].raw) { |
|
805 |
+ const char *pt = cli_memstr(epbuff, 4040, "\x47\x65\x74\x50\x72\x6f\x63\x41\x64\x64\x72\x65\x73\x73\x00", 15); |
|
806 |
+ if(pt) { |
|
807 |
+ pt += 15; |
|
808 |
+ if( (uint32_t)cli_readint32(pt) ^ (uint32_t)cli_readint32(pt + 4) == 0x505a4f && (uint32_t)cli_readint32(pt + 8) ^ (uint32_t)cli_readint32(pt + 12) == 0xffffb && (uint32_t)cli_readint32(pt + 16) ^ (uint32_t)cli_readint32(pt + 20) == 0xb8) { |
|
809 |
+ *ctx->virname = "W32.Parite.B"; |
|
810 |
+ free(exe_sections); |
|
811 |
+ return CL_VIRUS; |
|
815 | 812 |
} |
816 | 813 |
} |
817 | 814 |
} |
818 | 815 |
|
819 | 816 |
/* Kriz */ |
820 |
- if(SCAN_ALGO && (DCONF & PE_CONF_KRIZ) && CLI_ISCONTAINED(exe_sections[nsections - 1].raw, exe_sections[nsections - 1].rsz, ep, 0x0fd2)) { |
|
817 |
+ if(SCAN_ALGO && (DCONF & PE_CONF_KRIZ) && epsize >= 200 && CLI_ISCONTAINED(exe_sections[nsections - 1].raw, exe_sections[nsections - 1].rsz, ep, 0x0fd2) && epbuff[1]=='\x9c' || epbuff[2]=='\x60') { |
|
818 |
+ enum {KZSTRASH,KZSCDELTA,KZSPDELTA,KZSGETSIZE,KZSXORPRFX,KZSXOR,KZSDDELTA,KZSLOOP,KZSTOP}; |
|
819 |
+ uint8_t kzs[] = {KZSTRASH,KZSCDELTA,KZSPDELTA,KZSGETSIZE,KZSTRASH,KZSXORPRFX,KZSXOR,KZSTRASH,KZSDDELTA,KZSTRASH,KZSLOOP,KZSTOP}; |
|
820 |
+ uint8_t *kzstate = kzs; |
|
821 |
+ uint8_t *kzcode = epbuff + 3; |
|
822 |
+ uint8_t kzdptr=0xff, kzdsize=0xff; |
|
823 |
+ int kzlen = 197, kzinitlen=0xffff, kzxorlen=-1; |
|
821 | 824 |
cli_dbgmsg("in kriz\n"); |
822 |
- lseek(desc, ep, SEEK_SET); |
|
823 |
- if(cli_readn(desc, buff, 200) == 200) { |
|
824 |
- while (1) { |
|
825 |
- char *krizpos=buff+3; |
|
826 |
- char *krizmov, *krizxor; |
|
827 |
- int krizleft = 200-3; |
|
828 |
- int krizrega,krizregb; |
|
829 |
- |
|
830 |
- if (buff[1]!='\x9c' || buff[2]!='\x60') break; /* EP+1 */ |
|
831 |
- xckriz(&krizpos, &krizleft, 0, 8); |
|
832 |
- if (krizleft < 6 || *krizpos!='\xe8' || krizpos[2] || krizpos[3] || krizpos[4]) break; /* call DELTA */ |
|
833 |
- krizleft-=5+(unsigned char)krizpos[1]; |
|
834 |
- if (krizleft < 2) break; |
|
835 |
- krizpos+=5+(unsigned char)krizpos[1]; |
|
836 |
- if (*krizpos<'\x58' || *krizpos>'\x5f' || *krizpos=='\x5c') break; /* pop DELTA */ |
|
837 |
- krizrega=*krizpos-'\x58'; |
|
838 |
- cli_dbgmsg("kriz: pop delta using %d\n", krizrega); |
|
839 |
- krizpos+=1; |
|
840 |
- krizleft-=1; |
|
841 |
- xckriz(&krizpos, &krizleft, 1, 8); |
|
842 |
- if (krizleft <6 || *krizpos<'\xb8' || *krizpos>'\xbf' || *krizpos=='\xbc' || cli_readint32(krizpos+1)!=0x0fd2) break; |
|
843 |
- krizregb=*krizpos-'\xb8'; |
|
844 |
- if (krizrega==krizregb) break; |
|
845 |
- cli_dbgmsg("kriz: using %d for size\n", krizregb); |
|
846 |
- krizpos+=5; |
|
847 |
- krizleft-=5; |
|
848 |
- krizmov = krizpos; |
|
849 |
- xckriz(&krizpos, &krizleft, 0, 8); |
|
850 |
- krizxor=krizpos; |
|
851 |
- if (krizleft && *krizpos=='\x3e') { |
|
852 |
- /* strip ds: */ |
|
853 |
- krizpos++; |
|
854 |
- krizleft--; |
|
855 |
- } |
|
856 |
- if (krizleft<8 || *krizpos!='\x80' || (char)(krizpos[1]-krizrega)!='\xb0') { |
|
857 |
- cli_dbgmsg("kriz: bogus opcode or register\n"); |
|
825 |
+ |
|
826 |
+ while(*kzstate!=KZSTOP) { |
|
827 |
+ uint8_t op; |
|
828 |
+ if(kzlen<=6) break; |
|
829 |
+ op = *kzcode++; |
|
830 |
+ kzlen--; |
|
831 |
+ switch (*kzstate) { |
|
832 |
+ case KZSTRASH: case KZSGETSIZE: { |
|
833 |
+ int opsz=0; |
|
834 |
+ switch(op) { |
|
835 |
+ case 0x81: |
|
836 |
+ kzcode+=5; |
|
837 |
+ kzlen-=5; |
|
858 | 838 |
break; |
839 |
+ case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbd: case 0xbe: case 0xbf: |
|
840 |
+ if(*kzstate==KZSGETSIZE && cli_readint32(kzcode)==0x0fd2) { |
|
841 |
+ kzinitlen = kzlen-5; |
|
842 |
+ kzdsize=op-0xb8; |
|
843 |
+ kzstate++; |
|
844 |
+ op=4; /* fake the register to avoid breaking out */ |
|
845 |
+ cli_dbgmsg("kriz: using #%d as size counter\n", kzdsize); |
|
846 |
+ } |
|
847 |
+ opsz=4; |
|
848 |
+ case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4d: case 0x4e: case 0x4f: |
|
849 |
+ op&=7; |
|
850 |
+ if(op!=kzdptr && op!=kzdsize) { |
|
851 |
+ kzcode+=opsz; |
|
852 |
+ kzlen-=opsz; |
|
853 |
+ break; |
|
854 |
+ } |
|
855 |
+ default: |
|
856 |
+ kzcode--; |
|
857 |
+ kzlen++; |
|
858 |
+ kzstate++; |
|
859 | 859 |
} |
860 |
- krizpos+=7; |
|
861 |
- krizleft-=7; |
|
862 |
- xckriz(&krizpos, &krizleft, 0, krizrega); |
|
863 |
- if (! krizleft || (char)(*krizpos-krizrega)!='\x48') break; /* dec delta */ |
|
864 |
- krizpos++; |
|
865 |
- krizleft--; |
|
866 |
- cli_dbgmsg("kriz: dec delta found\n"); |
|
867 |
- xckriz(&krizpos, &krizleft, 0, krizregb); |
|
868 |
- if (krizleft <4 || (char)(*krizpos-krizregb)!='\x48' || krizpos[1]!='\x75') break; /* dec size + jne loop */ |
|
869 |
- if (krizpos+3+(int)krizpos[2]<krizmov || krizpos+3+(int)krizpos[2]>krizxor) { |
|
870 |
- cli_dbgmsg("kriz: jmp back out of range (%d>%d>%d)\n", krizmov-(krizpos+3), (int)krizpos[2], krizxor-(krizpos+3)); |
|
871 |
- break; |
|
860 |
+ break; |
|
861 |
+ } |
|
862 |
+ case KZSCDELTA: |
|
863 |
+ if(op==0xe8 && (uint32_t)cli_readint32(kzcode) < 0xff) { |
|
864 |
+ kzlen-=*kzcode+4; |
|
865 |
+ kzcode+=*kzcode+4; |
|
866 |
+ kzstate++; |
|
867 |
+ } else *kzstate=KZSTOP; |
|
868 |
+ break; |
|
869 |
+ case KZSPDELTA: |
|
870 |
+ if((op&0xf8)==0x58 && (kzdptr=op-0x58)!=4) { |
|
871 |
+ kzstate++; |
|
872 |
+ cli_dbgmsg("kriz: using #%d as pointer\n", kzdptr); |
|
873 |
+ } else *kzstate=KZSTOP; |
|
874 |
+ break; |
|
875 |
+ case KZSXORPRFX: |
|
876 |
+ kzstate++; |
|
877 |
+ if(op==0x3e) break; |
|
878 |
+ case KZSXOR: |
|
879 |
+ if (op==0x80 && *kzcode==kzdptr+0xb0) { |
|
880 |
+ kzxorlen=kzlen; |
|
881 |
+ kzcode+=+6; |
|
882 |
+ kzlen-=+6; |
|
883 |
+ kzstate++; |
|
884 |
+ } else *kzstate=KZSTOP; |
|
885 |
+ break; |
|
886 |
+ case KZSDDELTA: |
|
887 |
+ if (op==kzdptr+0x48) kzstate++; |
|
888 |
+ else *kzstate=KZSTOP; |
|
889 |
+ break; |
|
890 |
+ case KZSLOOP: |
|
891 |
+ if (op==kzdsize+0x48 && *kzcode==0x75 && kzlen-(int8_t)kzcode[1]-3<=kzinitlen && kzlen-(int8_t)kzcode[1]>=kzxorlen) { |
|
892 |
+ *ctx->virname = "W32.Kriz"; |
|
893 |
+ free(exe_sections); |
|
894 |
+ return CL_VIRUS; |
|
872 | 895 |
} |
873 |
- *ctx->virname = "Win32.Kriz"; |
|
874 |
- free(exe_sections); |
|
875 |
- return CL_VIRUS; |
|
896 |
+ cli_dbgmsg("kriz: loop out of bounds, corrupted sample?\n"); |
|
897 |
+ kzstate++; |
|
876 | 898 |
} |
877 | 899 |
} |
878 | 900 |
} |
879 | 901 |
|
880 | 902 |
/* W32.Magistr.A/B */ |
881 | 903 |
if(SCAN_ALGO && (DCONF & PE_CONF_MAGISTR) && !dll && (nsections>1) && (exe_sections[nsections - 1].chr & 0x80000000)) { |
882 |
- uint32_t rsize, vsize, dam = 0; |
|
904 |
+ uint32_t rsize, vsize, dam = 0; |
|
883 | 905 |
|
884 | 906 |
vsize = exe_sections[nsections - 1].uvsz; |
885 | 907 |
rsize = exe_sections[nsections - 1].rsz; |
... | ... |
@@ -915,169 +996,64 @@ int cli_scanpe(int desc, cli_ctx *ctx) |
915 | 915 |
} |
916 | 916 |
|
917 | 917 |
/* W32.Polipos.A */ |
918 |
- if(polipos && !dll && nsections > 2 && nsections < 13 && e_lfanew <= 0x800 && (EC16(optional_hdr32.Subsystem) == 2 || EC16(optional_hdr32.Subsystem) == 3) && EC16(file_hdr.Machine) == 0x14c && optional_hdr32.SizeOfStackReserve >= 0x80000) { |
|
919 |
- uint32_t remaining = exe_sections[0].rsz; |
|
920 |
- uint32_t chunk = sizeof(buff); |
|
921 |
- uint32_t val, shift, raddr, total = 0; |
|
922 |
- const char *jpt; |
|
923 |
- struct offset_list *offlist = NULL, *offnode; |
|
924 |
- |
|
925 |
- |
|
926 |
- cli_dbgmsg("Detected W32.Polipos.A characteristics\n"); |
|
927 |
- |
|
928 |
- if(remaining < chunk) |
|
929 |
- chunk = remaining; |
|
930 |
- |
|
931 |
- lseek(desc, exe_sections[0].raw, SEEK_SET); |
|
932 |
- while((bytes = cli_readn(desc, buff, chunk)) > 0) { |
|
933 |
- shift = 0; |
|
934 |
- while((uint32_t)bytes - 5 > shift) { |
|
935 |
- jpt = buff + shift; |
|
936 |
- if(*jpt!='\xe9' && *jpt!='\xe8') { |
|
937 |
- shift++; |
|
938 |
- continue; |
|
939 |
- } |
|
940 |
- val = cli_readint32(jpt + 1); |
|
941 |
- val += 5 + exe_sections[0].rva + total + shift; |
|
942 |
- raddr = cli_rawaddr(val, exe_sections, nsections, &err, fsize, hdr_size); |
|
943 |
- |
|
944 |
- if(!err && (raddr >= exe_sections[polipos].raw && raddr < exe_sections[polipos].raw + exe_sections[polipos].rsz) && (!offlist || (raddr != offlist->offset))) { |
|
945 |
- offnode = (struct offset_list *) cli_malloc(sizeof(struct offset_list)); |
|
946 |
- if(!offnode) { |
|
947 |
- free(exe_sections); |
|
948 |
- while(offlist) { |
|
949 |
- offnode = offlist; |
|
950 |
- offlist = offlist->next; |
|
951 |
- free(offnode); |
|
952 |
- } |
|
953 |
- return CL_EMEM; |
|
954 |
- } |
|
955 |
- offnode->offset = raddr; |
|
956 |
- offnode->next = offlist; |
|
957 |
- offlist = offnode; |
|
958 |
- } |
|
959 |
- |
|
960 |
- shift++; |
|
961 |
- } |
|
962 |
- |
|
963 |
- if(remaining < chunk) { |
|
964 |
- chunk = remaining; |
|
965 |
- } else { |
|
966 |
- remaining -= bytes; |
|
967 |
- if(remaining < chunk) { |
|
968 |
- chunk = remaining; |
|
918 |
+ while(polipos && !dll && nsections > 2 && nsections < 13 && e_lfanew <= 0x800 && (EC16(optional_hdr32.Subsystem) == 2 || EC16(optional_hdr32.Subsystem) == 3) && EC16(file_hdr.Machine) == 0x14c && optional_hdr32.SizeOfStackReserve >= 0x80000) { |
|
919 |
+ uint32_t jump, jold, *jumps = NULL; |
|
920 |
+ uint8_t *code; |
|
921 |
+ unsigned int xsjs = 0; |
|
922 |
+ |
|
923 |
+ if(exe_sections[0].rsz > CLI_MAX_ALLOCATION) break; |
|
924 |
+ if(!cli_seeksect(desc, &exe_sections[0])) break; |
|
925 |
+ if(!(code=cli_malloc(exe_sections[0].rsz))) { |
|
926 |
+ free(exe_sections); |
|
927 |
+ return CL_EMEM; |
|
928 |
+ } |
|
929 |
+ if(cli_readn(desc, code, exe_sections[0].rsz)!=exe_sections[0].rsz) { |
|
930 |
+ free(exe_sections); |
|
931 |
+ return CL_EIO; |
|
932 |
+ } |
|
933 |
+ for(i=0; i<exe_sections[0].rsz - 5; i++) { |
|
934 |
+ if((uint8_t)(code[i]-0xe8) > 1) continue; |
|
935 |
+ jump = cli_rawaddr(exe_sections[0].rva+i+5+cli_readint32(&code[i+1]), exe_sections, nsections, &err, fsize, hdr_size); |
|
936 |
+ if(err || !CLI_ISCONTAINED(exe_sections[polipos].raw, exe_sections[polipos].rsz, jump, 9)) continue; |
|
937 |
+ if(xsjs % 128 == 0) { |
|
938 |
+ if(xsjs == 1280) break; |
|
939 |
+ if(!(jumps=(uint32_t *)cli_realloc2(jumps, (xsjs+128)*sizeof(uint32_t)))) { |
|
940 |
+ free(code); |
|
941 |
+ free(exe_sections); |
|
942 |
+ return CL_EMEM; |
|
969 | 943 |
} |
970 | 944 |
} |
971 |
- |
|
972 |
- if(!remaining) |
|
973 |
- break; |
|
974 |
- |
|
975 |
- total += bytes; |
|
976 |
- } |
|
977 |
- |
|
978 |
- offnode = offlist; |
|
979 |
- while(offnode) { |
|
980 |
- cli_dbgmsg("Polipos: Checking offset 0x%x (%u)", offnode->offset, offnode->offset); |
|
981 |
- lseek(desc, offnode->offset, SEEK_SET); |
|
982 |
- if(cli_readn(desc, buff, 9) == 9) { |
|
983 |
- ubuff = (unsigned char *) buff; |
|
984 |
- if(ubuff[0] == 0x55 && ubuff[1] == 0x8b && ubuff[2] == 0xec && |
|
985 |
- ((ubuff[3] == 0x83 && ubuff[4] == 0xec && ubuff[6] == 0x60) || ubuff[3] == 0x60 || |
|
986 |
- (ubuff[3] == 0x81 && ubuff[4] == 0xec && ubuff[7] == 0x00 && ubuff[8] == 0x00))) { |
|
987 |
- ret = CL_VIRUS; |
|
988 |
- *ctx->virname = "W32.Polipos.A"; |
|
945 |
+ j=0; |
|
946 |
+ for(; j<xsjs; j++) { |
|
947 |
+ if(jumps[j]<jump) continue; |
|
948 |
+ if(jumps[j]==jump) { |
|
949 |
+ xsjs--; |
|
989 | 950 |
break; |
990 | 951 |
} |
952 |
+ jold=jumps[j]; |
|
953 |
+ jumps[j]=jump; |
|
954 |
+ jump=jold; |
|
955 |
+ } |
|
956 |
+ jumps[j]=jump; |
|
957 |
+ xsjs++; |
|
958 |
+ } |
|
959 |
+ free(code); |
|
960 |
+ if(!xsjs) break; |
|
961 |
+ cli_dbgmsg("Polipos: Checking %d xsect jump(s)\n", xsjs); |
|
962 |
+ for(i=0;i<xsjs;i++) { |
|
963 |
+ lseek(desc, jumps[i], SEEK_SET); |
|
964 |
+ if(cli_readn(desc, buff, 9) != 9) continue; |
|
965 |
+ if((jump=cli_readint32(buff))==0x60ec8b55 || (buff[4]=='\xec' && ((jump==0x83ec8b55 && buff[6]=='\x60') || (jump==0x81ec8b55 && !buff[7] && !buff[8])))) { |
|
966 |
+ *ctx->virname = "W32.Polipos.A"; |
|
967 |
+ free(jumps); |
|
968 |
+ free(exe_sections); |
|
969 |
+ return CL_VIRUS; |
|
991 | 970 |
} |
992 |
- |
|
993 |
- offnode = offnode->next; |
|
994 |
- } |
|
995 |
- |
|
996 |
- while(offlist) { |
|
997 |
- offnode = offlist; |
|
998 |
- offlist = offlist->next; |
|
999 |
- free(offnode); |
|
1000 |
- } |
|
1001 |
- |
|
1002 |
- if(ret == CL_VIRUS) { |
|
1003 |
- free(exe_sections); |
|
1004 |
- return CL_VIRUS; |
|
1005 | 971 |
} |
972 |
+ free(jumps); |
|
973 |
+ break; |
|
1006 | 974 |
} |
1007 | 975 |
|
1008 |
- /* SUE */ |
|
1009 |
- |
|
1010 |
- if((DCONF & PE_CONF_SUE) && nsections > 2 && vep == exe_sections[nsections - 1].rva && exe_sections[nsections - 1].rsz > 0x350 && exe_sections[nsections - 1].rsz < 0x292+0x350+1000) { |
|
1011 |
- |
|
1012 |
- |
|
1013 |
- char *sue=buff+0x74; |
|
1014 |
- uint32_t key = 0; |
|
1015 |
- |
|
1016 |
- if(lseek(desc, ep-4, SEEK_SET) == -1) { |
|
1017 |
- cli_dbgmsg("SUE: lseek() failed\n"); |
|
1018 |
- free(exe_sections); |
|
1019 |
- return CL_EIO; |
|
1020 |
- } |
|
1021 |
- if((unsigned int) cli_readn(desc, buff, exe_sections[nsections - 1].rsz+4) == exe_sections[nsections - 1].rsz+4) { |
|
1022 |
- found=0; |
|
1023 |
- while(CLI_ISCONTAINED(buff+4, exe_sections[nsections - 1].rsz, sue, 4*3)) { |
|
1024 |
- if((cli_readint32(sue)^cli_readint32(sue+4))==0x5c41090e && (cli_readint32(sue)^cli_readint32(sue+8))==0x021e0145) { |
|
1025 |
- found=1; |
|
1026 |
- key=(cli_readint32(sue)^0x6e72656b); |
|
1027 |
- break; |
|
1028 |
- } |
|
1029 |
- sue++; |
|
1030 |
- } |
|
1031 |
- cli_dbgmsg("SUE: key(%x) found @%x\n", key, sue-buff); |
|
1032 |
- if (found && CLI_ISCONTAINED(buff, exe_sections[nsections - 1].rsz, sue-0x74, 0xbe) && |
|
1033 |
- (sue=sudecrypt(desc, fsize, exe_sections, nsections-1, sue, key, cli_readint32(buff), e_lfanew))) { |
|
1034 |
- if(!(tempfile = cli_gentemp(NULL))) { |
|
1035 |
- free(sue); |
|
1036 |
- free(exe_sections); |
|
1037 |
- return CL_EMEM; |
|
1038 |
- } |
|
1039 |
- |
|
1040 |
- if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) { |
|
1041 |
- cli_dbgmsg("sue: Can't create file %s\n", tempfile); |
|
1042 |
- free(tempfile); |
|
1043 |
- free(sue); |
|
1044 |
- free(exe_sections); |
|
1045 |
- return CL_EIO; |
|
1046 |
- } |
|
1047 |
- |
|
1048 |
- if((unsigned int) cli_writen(ndesc, sue, ep) != ep) { |
|
1049 |
- cli_dbgmsg("sue: Can't write %d bytes\n", ep); |
|
1050 |
- close(ndesc); |
|
1051 |
- free(tempfile); |
|
1052 |
- free(sue); |
|
1053 |
- free(exe_sections); |
|
1054 |
- return CL_EIO; |
|
1055 |
- } |
|
1056 |
- |
|
1057 |
- free(sue); |
|
1058 |
- if (cli_leavetemps_flag) |
|
1059 |
- cli_dbgmsg("SUE: Decrypted executable saved in %s\n", tempfile); |
|
1060 |
- else |
|
1061 |
- cli_dbgmsg("SUE: Executable decrypted\n"); |
|
1062 |
- fsync(ndesc); |
|
1063 |
- lseek(ndesc, 0, SEEK_SET); |
|
1064 |
- |
|
1065 |
- if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) { |
|
1066 |
- free(exe_sections); |
|
1067 |
- close(ndesc); |
|
1068 |
- if(!cli_leavetemps_flag) |
|
1069 |
- unlink(tempfile); |
|
1070 |
- free(tempfile); |
|
1071 |
- return CL_VIRUS; |
|
1072 |
- } |
|
1073 |
- close(ndesc); |
|
1074 |
- if(!cli_leavetemps_flag) |
|
1075 |
- unlink(tempfile); |
|
1076 |
- free(tempfile); |
|
1077 |
- } |
|
1078 |
- } |
|
1079 |
- |
|
1080 |
- } |
|
1081 | 976 |
|
1082 | 977 |
/* UPX, FSG, MEW support */ |
1083 | 978 |
|
... | ... |
@@ -1094,169 +1070,92 @@ int cli_scanpe(int desc, cli_ctx *ctx) |
1094 | 1094 |
} |
1095 | 1095 |
|
1096 | 1096 |
/* MEW support */ |
1097 |
- if (found && (DCONF & PE_CONF_MEW)) { |
|
1097 |
+ if (found && (DCONF & PE_CONF_MEW) && epsize>=16 && epbuff[0]=='\xe9') { |
|
1098 | 1098 |
uint32_t fileoffset; |
1099 |
- /* Check EP for MEW */ |
|
1100 |
- if(lseek(desc, ep, SEEK_SET) == -1) { |
|
1101 |
- cli_dbgmsg("MEW: lseek() failed\n"); |
|
1102 |
- free(exe_sections); |
|
1103 |
- return CL_EIO; |
|
1104 |
- } |
|
1105 | 1099 |
|
1106 |
- if((bytes = read(desc, buff, 25)) != 25 && bytes < 16) { |
|
1107 |
- cli_dbgmsg("MEW: Can't read at least 16 bytes at 0x%x (%d) %d\n", ep, ep, bytes); |
|
1108 |
- cli_dbgmsg("MEW: Broken or not compressed file\n"); |
|
1109 |
- free(exe_sections); |
|
1110 |
- return CL_CLEAN; |
|
1111 |
- } |
|
1100 |
+ fileoffset = (vep + cli_readint32(epbuff + 1) + 5); |
|
1101 |
+ while (fileoffset == 0x154 || fileoffset == 0x158) { |
|
1102 |
+ uint32_t offdiff, uselzma; |
|
1112 | 1103 |
|
1113 |
- fileoffset = (vep + cli_readint32(buff + 1) + 5); |
|
1114 |
- do { |
|
1115 |
- if (found && (buff[0] == '\xe9') && (fileoffset == 0x154 || fileoffset == 0x158)) |
|
1116 |
- { |
|
1117 |
- uint32_t offdiff, uselzma; |
|
1104 |
+ cli_dbgmsg ("MEW: found MEW characteristics %08X + %08X + 5 = %08X\n", |
|
1105 |
+ cli_readint32(epbuff + 1), vep, cli_readint32(epbuff + 1) + vep + 5); |
|
1118 | 1106 |
|
1119 |
- cli_dbgmsg ("MEW characteristics found: %08X + %08X + 5 = %08X\n", |
|
1120 |
- cli_readint32(buff + 1), vep, cli_readint32(buff + 1) + vep + 5); |
|
1107 |
+ if(lseek(desc, fileoffset, SEEK_SET) == -1) { |
|
1108 |
+ cli_dbgmsg("MEW: lseek() failed\n"); |
|
1109 |
+ free(exe_sections); |
|
1110 |
+ return CL_EIO; |
|
1111 |
+ } |
|
1121 | 1112 |
|
1122 |
- if(lseek(desc, fileoffset, SEEK_SET) == -1) { |
|
1123 |
- cli_dbgmsg("MEW: lseek() failed\n"); |
|
1124 |
- free(exe_sections); |
|
1125 |
- return CL_EIO; |
|
1126 |
- } |
|
1113 |
+ if((bytes = read(desc, buff, 0xb0)) != 0xb0) { |
|
1114 |
+ cli_dbgmsg("MEW: Can't read 0xb0 bytes at 0x%x (%d) %d\n", fileoffset, fileoffset, bytes); |
|
1115 |
+ break; |
|
1116 |
+ } |
|
1127 | 1117 |
|
1128 |
- if((bytes = read(desc, buff, 0xb0)) != 0xb0) { |
|
1129 |
- cli_dbgmsg("MEW: Can't read 0xb0 bytes at 0x%x (%d) %d\n", fileoffset, fileoffset, bytes); |
|
1130 |
- break; |
|
1131 |
- } |
|
1118 |
+ if (fileoffset == 0x154) cli_dbgmsg("MEW: Win9x compatibility was set!\n"); |
|
1119 |
+ else cli_dbgmsg("MEW: Win9x compatibility was NOT set!\n"); |
|
1132 | 1120 |
|
1133 |
- if (fileoffset == 0x154) |
|
1134 |
- cli_dbgmsg("MEW: Win9x compatibility was set!\n"); |
|
1135 |
- else |
|
1136 |
- cli_dbgmsg("MEW: Win9x compatibility was NOT set!\n"); |
|
1121 |
+ if((offdiff = cli_readint32(buff+1) - EC32(optional_hdr32.ImageBase)) <= exe_sections[i + 1].rva || offdiff >= exe_sections[i + 1].rva + exe_sections[i + 1].raw - 4) { |
|
1122 |
+ cli_dbgmsg("MEW: ESI is not in proper section\n"); |
|
1123 |
+ break; |
|
1124 |
+ } |
|
1125 |
+ offdiff -= exe_sections[i + 1].rva; |
|
1137 | 1126 |
|
1138 |
- /* is it always 0x1C and 0x21C or not */ |
|
1139 |
- if((offdiff = cli_readint32(buff+1) - EC32(optional_hdr32.ImageBase)) <= exe_sections[i + 1].rva || offdiff >= exe_sections[i + 1].rva + exe_sections[i + 1].raw - 4) |
|
1140 |
- { |
|
1141 |
- cli_dbgmsg("MEW: ESI is not in proper section\n"); |
|
1142 |
- break; |
|
1143 |
- } |
|
1144 |
- offdiff -= exe_sections[i + 1].rva; |
|
1127 |
+ if(!cli_seeksect(desc, &exe_sections[i + 1])) { |
|
1128 |
+ free(exe_sections); |
|
1129 |
+ return CL_EIO; |
|
1130 |
+ } |
|
1131 |
+ ssize = exe_sections[i + 1].vsz; |
|
1132 |
+ dsize = exe_sections[i].vsz; |
|
1145 | 1133 |
|
1146 |
- if(lseek(desc, exe_sections[i + 1].raw, SEEK_SET) == -1) { |
|
1147 |
- cli_dbgmsg("MEW: lseek() failed\n"); /* ACAB: lseek won't fail here but checking doesn't hurt even */ |
|
1148 |
- free(exe_sections); |
|
1149 |
- return CL_EIO; |
|
1150 |
- } |
|
1151 |
- ssize = exe_sections[i + 1].vsz; |
|
1152 |
- dsize = exe_sections[i].vsz; |
|
1134 |
+ cli_dbgmsg("MEW: ssize %08x dsize %08x offdiff: %08x\n", ssize, dsize, offdiff); |
|
1153 | 1135 |
|
1154 |
- cli_dbgmsg("MEW: ssize %08x dsize %08x offdiff: %08x\n", ssize, dsize, offdiff); |
|
1155 |
- if(ctx->limits && ctx->limits->maxfilesize && (ssize + dsize > ctx->limits->maxfilesize || exe_sections[i + 1].rsz > ctx->limits->maxfilesize)) { |
|
1156 |
- cli_dbgmsg("MEW: Sizes exceeded (ssize: %u, dsize: %u, max: %lu)\n", ssize, dsize , ctx->limits->maxfilesize); |
|
1157 |
- free(exe_sections); |
|
1158 |
- if(BLOCKMAX) { |
|
1159 |
- *ctx->virname = "PE.MEW.ExceededFileSize"; |
|
1160 |
- return CL_VIRUS; |
|
1161 |
- } else { |
|
1162 |
- return CL_CLEAN; |
|
1163 |
- } |
|
1164 |
- } |
|
1136 |
+ CLI_UNPSIZELIMITS("MEW", MAX(ssize + dsize, exe_sections[i + 1].rsz)); |
|
1165 | 1137 |
|
1166 |
- /* allocate needed buffer */ |
|
1167 |
- if (!(src = cli_calloc (ssize + dsize, sizeof(char)))) { |
|
1168 |
- free(exe_sections); |
|
1169 |
- return CL_EMEM; |
|
1170 |
- } |
|
1138 |
+ /* allocate needed buffer */ |
|
1139 |
+ if (!(src = cli_calloc (ssize + dsize, sizeof(char)))) { |
|
1140 |
+ free(exe_sections); |
|
1141 |
+ return CL_EMEM; |
|
1142 |
+ } |
|
1171 | 1143 |
|
1172 |
- if (exe_sections[i + 1].rsz < offdiff + 12 || exe_sections[i + 1].rsz > ssize) |
|
1173 |
- { |
|
1174 |
- cli_dbgmsg("MEW: Size mismatch: %08x\n", exe_sections[i + 1].rsz); |
|
1175 |
- free(src); |
|
1176 |
- break; |
|
1177 |
- } |
|
1144 |
+ if (exe_sections[i + 1].rsz < offdiff + 12 || exe_sections[i + 1].rsz > ssize) { |
|
1145 |
+ cli_dbgmsg("MEW: Size mismatch: %08x\n", exe_sections[i + 1].rsz); |
|
1146 |
+ free(src); |
|
1147 |
+ break; |
|
1148 |
+ } |
|
1178 | 1149 |
|
1179 |
- if((bytes = read(desc, src + dsize, exe_sections[i + 1].rsz)) != exe_sections[i + 1].rsz) { |
|
1180 |
- cli_dbgmsg("MEW: Can't read %d bytes [readed: %d]\n", exe_sections[i + 1].rsz, bytes); |
|
1181 |
- free(exe_sections); |
|
1182 |
- free(src); |
|
1183 |
- return CL_EIO; |
|
1184 |
- } |
|
1185 |
- cli_dbgmsg("MEW: %d (%08x) bytes read\n", bytes, bytes); |
|
1186 |
- /* count offset to lzma proc, if lzma used, 0xe8 -> call */ |
|
1187 |
- if (buff[0x7b] == '\xe8') |
|
1188 |
- { |
|
1189 |
- if (!CLI_ISCONTAINED(exe_sections[1].rva, exe_sections[1].vsz, cli_readint32(buff + 0x7c) + fileoffset + 0x80, 4)) |
|
1190 |
- { |
|
1191 |
- cli_dbgmsg("MEW: lzma proc out of bounds!\n"); |
|
1192 |
- free(src); |
|
1193 |
- break; /* to next unpacker in chain */ |
|
1194 |
- } |
|
1195 |
- uselzma = cli_readint32(buff + 0x7c) - (exe_sections[0].rva - fileoffset - 0x80); |
|
1196 |
- } else |
|
1197 |
- uselzma = 0; |
|
1150 |
+ if((bytes = read(desc, src + dsize, exe_sections[i + 1].rsz)) != exe_sections[i + 1].rsz) { |
|
1151 |
+ cli_dbgmsg("MEW: Can't read %d bytes [readed: %d]\n", exe_sections[i + 1].rsz, bytes); |
|
1152 |
+ free(exe_sections); |
|
1153 |
+ free(src); |
|
1154 |
+ return CL_EIO; |
|
1155 |
+ } |
|
1156 |
+ cli_dbgmsg("MEW: %d (%08x) bytes read\n", bytes, bytes); |
|
1198 | 1157 |
|
1199 |
- if(!(tempfile = cli_gentemp(NULL))) { |
|
1200 |
- free(exe_sections); |
|
1201 |
- free(src); |
|
1202 |
- return CL_EMEM; |
|
1203 |
- } |
|
1204 |
- if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC, S_IRWXU)) < 0) { |
|
1205 |
- cli_dbgmsg("MEW: Can't create file %s\n", tempfile); |
|
1206 |
- free(tempfile); |
|
1207 |
- free(exe_sections); |
|
1158 |
+ /* count offset to lzma proc, if lzma used, 0xe8 -> call */ |
|
1159 |
+ if (buff[0x7b] == '\xe8') { |
|
1160 |
+ if (!CLI_ISCONTAINED(exe_sections[1].rva, exe_sections[1].vsz, cli_readint32(buff + 0x7c) + fileoffset + 0x80, 4)) { |
|
1161 |
+ cli_dbgmsg("MEW: lzma proc out of bounds!\n"); |
|
1208 | 1162 |
free(src); |
1209 |
- return CL_EIO; |
|
1210 |
- } |
|
1211 |
- dest = src; |
|
1212 |
- switch(unmew11(i, src, offdiff, ssize, dsize, EC32(optional_hdr32.ImageBase), exe_sections[0].rva, uselzma, NULL, NULL, ndesc)) { |
|
1213 |
- case 1: /* Everything OK */ |
|
1214 |
- cli_dbgmsg("MEW: Unpacked and rebuilt executable saved in %s\n", tempfile); |
|
1215 |
- free(src); |
|
1216 |
- fsync(ndesc); |
|
1217 |
- lseek(ndesc, 0, SEEK_SET); |
|
1218 |
- |
|
1219 |
- cli_dbgmsg("***** Scanning rebuilt PE file *****\n"); |
|
1220 |
- if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) { |
|
1221 |
- free(exe_sections); |
|
1222 |
- close(ndesc); |
|
1223 |
- if(!cli_leavetemps_flag) |
|
1224 |
- unlink(tempfile); |
|
1225 |
- free(tempfile); |
|
1226 |
- return CL_VIRUS; |
|
1227 |
- } |
|
1228 |
- close(ndesc); |
|
1229 |
- if(!cli_leavetemps_flag) |
|
1230 |
- unlink(tempfile); |
|
1231 |
- free(tempfile); |
|
1232 |
- free(exe_sections); |
|
1233 |
- return CL_CLEAN; |
|
1234 |
- default: /* Everything gone wrong */ |
|
1235 |
- cli_dbgmsg("MEW: Unpacking failed\n"); |
|
1236 |
- close(ndesc); |
|
1237 |
- unlink(tempfile); /* It's empty anyway */ |
|
1238 |
- free(tempfile); |
|
1239 |
- free(src); |
|
1240 |
- break; |
|
1163 |
+ break; /* to next unpacker in chain */ |
|
1241 | 1164 |
} |
1165 |
+ uselzma = cli_readint32(buff + 0x7c) - (exe_sections[0].rva - fileoffset - 0x80); |
|
1166 |
+ } else { |
|
1167 |
+ uselzma = 0; |
|
1242 | 1168 |
} |
1243 |
- } while (0); |
|
1244 |
- } |
|
1245 | 1169 |
|
1246 |
- if(found || upack) { |
|
1247 |
- /* Check EP for UPX vs. FSG vs. Upack */ |
|
1248 |
- if(lseek(desc, ep, SEEK_SET) == -1) { |
|
1249 |
- cli_dbgmsg("UPX/FSG: lseek() failed\n"); |
|
1250 |
- free(exe_sections); |
|
1251 |
- return CL_EIO; |
|
1170 |
+ CLI_UNPTEMP("MEW",src,exe_sections); |
|
1171 |
+ CLI_UNPRESULTS("MEW",(unmew11(i, src, offdiff, ssize, dsize, EC32(optional_hdr32.ImageBase), exe_sections[0].rva, uselzma, NULL, NULL, ndesc)),1,src); |
|
1172 |
+ break; |
|
1252 | 1173 |
} |
1174 |
+ } |
|
1253 | 1175 |
|
1254 |
- if(cli_readn(desc, buff, 168) != 168) { |
|
1255 |
- cli_dbgmsg("UPX/FSG: Can't read 168 bytes at 0x%x (%d)\n", ep, ep); |
|
1256 |
- cli_dbgmsg("UPX/FSG: Broken or not UPX/FSG compressed file\n"); |
|
1257 |
- free(exe_sections); |
|
1258 |
- return CL_CLEAN; |
|
1259 |
- } |
|
1176 |
+ if(epsize<168) { |
|
1177 |
+ free(exe_sections); |
|
1178 |
+ return CL_CLEAN; |
|
1179 |
+ } |
|
1180 |
+ |
|
1181 |
+ if (found || upack) { |
|
1182 |
+ /* Check EP for UPX vs. FSG vs. Upack */ |
|
1260 | 1183 |
|
1261 | 1184 |
/* Upack 0.39 produces 2 types of executables |
1262 | 1185 |
* 3 sections: | 2 sections (one empty, I don't chech found if !upack, since it's in OR above): |
... | ... |
@@ -1278,947 +1177,593 @@ int cli_scanpe(int desc, cli_ctx *ctx) |
1278 | 1278 |
* |
1279 | 1279 |
*/ |
1280 | 1280 |
/* upack 0.39-3s + sample 0151477*/ |
1281 |
- if(((upack && nsections == 3) && /* 3 sections */ |
|
1281 |
+ while(((upack && nsections == 3) && /* 3 sections */ |
|
1282 | 1282 |
( |
1283 |
- buff[0] == '\xbe' && cli_readint32(buff + 1) - EC32(optional_hdr32.ImageBase) > min && /* mov esi */ |
|
1284 |
- buff[5] == '\xad' && buff[6] == '\x50' /* lodsd; push eax */ |
|
1283 |
+ epbuff[0] == '\xbe' && cli_readint32(epbuff + 1) - EC32(optional_hdr32.ImageBase) > min && /* mov esi */ |
|
1284 |
+ epbuff[5] == '\xad' && epbuff[6] == '\x50' /* lodsd; push eax */ |
|
1285 | 1285 |
) |
1286 | 1286 |
|| |
1287 | 1287 |
/* based on 0297729 sample from aCaB */ |
1288 |
- (buff[0] == '\xbe' && cli_readint32(buff + 1) - EC32(optional_hdr32.ImageBase) > min && /* mov esi */ |
|
1289 |
- buff[5] == '\xff' && buff[6] == '\x36' /* push [esi] */ |
|
1288 |
+ (epbuff[0] == '\xbe' && cli_readint32(epbuff + 1) - EC32(optional_hdr32.ImageBase) > min && /* mov esi */ |
|
1289 |
+ epbuff[5] == '\xff' && epbuff[6] == '\x36' /* push [esi] */ |
|
1290 | 1290 |
) |
1291 | 1291 |
) |
1292 | 1292 |
|| |
1293 | 1293 |
((!upack && nsections == 2) && /* 2 sections */ |
1294 | 1294 |
( /* upack 0.39-2s */ |
1295 |
- buff[0] == '\x60' && buff[1] == '\xe8' && cli_readint32(buff+2) == 0x9 /* pusha; call+9 */ |
|
1295 |
+ epbuff[0] == '\x60' && epbuff[1] == '\xe8' && cli_readint32(epbuff+2) == 0x9 /* pusha; call+9 */ |
|
1296 | 1296 |
) |
1297 | 1297 |
|| |
1298 | 1298 |
( /* upack 1.1/1.2, based on 2 samples */ |
1299 |
- buff[0] == '\xbe' && cli_readint32(buff+1) - EC32(optional_hdr32.ImageBase) < min && /* mov esi */ |
|
1300 |
- cli_readint32(buff + 1) - EC32(optional_hdr32.ImageBase) > 0 && |
|
1301 |
- buff[5] == '\xad' && buff[6] == '\x8b' && buff[7] == '\xf8' /* loads; mov edi, eax */ |
|
1299 |
+ epbuff[0] == '\xbe' && cli_readint32(epbuff+1) - EC32(optional_hdr32.ImageBase) < min && /* mov esi */ |
|
1300 |
+ cli_readint32(epbuff + 1) - EC32(optional_hdr32.ImageBase) > 0 && |
|
1301 |
+ epbuff[5] == '\xad' && epbuff[6] == '\x8b' && epbuff[7] == '\xf8' /* loads; mov edi, eax */ |
|
1302 | 1302 |
) |
1303 | 1303 |
) |
1304 |
- ){ |
|
1305 |
- uint32_t vma, off; |
|
1306 |
- int a,b,c; |
|
1307 |
- |
|
1308 |
- cli_dbgmsg("Upack characteristics found.\n"); |
|
1309 |
- a = exe_sections[0].vsz; |
|
1310 |
- b = exe_sections[1].vsz; |
|
1311 |
- if (upack) { |
|
1312 |
- cli_dbgmsg("Upack: var set\n"); |
|
1313 |
- c = exe_sections[2].vsz; |
|
1314 |
- ssize = exe_sections[0].ursz + exe_sections[0].uraw; |
|
1315 |
- off = exe_sections[0].rva; |
|
1316 |
- vma = EC32(optional_hdr32.ImageBase) + exe_sections[0].rva; |
|
1317 |
- } else { |
|
1318 |
- cli_dbgmsg("Upack: var NOT set\n"); |
|
1319 |
- c = exe_sections[1].rva; |
|
1320 |
- ssize = exe_sections[1].uraw; |
|
1321 |
- off = 0; |
|
1322 |
- vma = exe_sections[1].rva - exe_sections[1].uraw; |
|
1323 |
- } |
|
1324 |
- |
|
1325 |
- dsize = a+b+c; |
|
1326 |
- if (ctx->limits && ctx->limits->maxfilesize && (dsize > ctx->limits->maxfilesize || ssize > ctx->limits->maxfilesize || exe_sections[1].ursz > ctx->limits->maxfilesize)) |
|
1327 |
- { |
|
1328 |
- cli_dbgmsg("Upack: Sizes exceeded (a: %u, b: %u, c: %ux, max: %lu)\n", a, b, c, ctx->limits->maxfilesize); |
|
1329 |
- free(exe_sections); |
|
1330 |
- if(BLOCKMAX) { |
|
1331 |
- *ctx->virname = "PE.Upack.ExceededFileSize"; |
|
1332 |
- return CL_VIRUS; |
|
1333 |
- } else { |
|
1334 |
- return CL_CLEAN; |
|
1335 |
- } |
|
1336 |
- } |
|
1337 |
- /* these are unsigned so if vaddr - off < 0, it should be ok */ |
|
1338 |
- if (exe_sections[1].rva - off > dsize || exe_sections[1].rva - off > dsize - exe_sections[1].ursz || (upack && (exe_sections[2].rva - exe_sections[0].rva > dsize || exe_sections[2].rva - exe_sections[0].rva > dsize - ssize)) || ssize > dsize) |
|
1339 |
- { |
|
1340 |
- cli_dbgmsg("Upack: probably malformed pe-header, skipping to next unpacker\n"); |
|
1341 |
- goto skip_upack_and_go_to_next_unpacker; |
|
1342 |
- } |
|
1343 |
- |
|
1344 |
- if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) { |
|
1345 |
- free(exe_sections); |
|
1346 |
- return CL_EMEM; |
|
1347 |
- } |
|
1348 |
- src = NULL; |
|
1349 |
- |
|
1350 |
- lseek(desc, 0, SEEK_SET); |
|
1351 |
- if(read(desc, dest, ssize) != ssize) { |
|
1352 |
- cli_dbgmsg("Upack: Can't read raw data of section 0\n"); |
|
1353 |
- free(exe_sections); |
|
1354 |
- free(dest); |
|
1355 |
- return CL_EIO; |
|
1356 |
- } |
|
1304 |
+ ) { |
|
1305 |
+ uint32_t vma, off; |
|
1306 |
+ int a,b,c; |
|
1307 |
+ |
|
1308 |
+ cli_dbgmsg("Upack characteristics found.\n"); |
|
1309 |
+ a = exe_sections[0].vsz; |
|
1310 |
+ b = exe_sections[1].vsz; |
|
1311 |
+ if (upack) { |
|
1312 |
+ cli_dbgmsg("Upack: var set\n"); |
|
1313 |
+ c = exe_sections[2].vsz; |
|
1314 |
+ ssize = exe_sections[0].ursz + exe_sections[0].uraw; |
|
1315 |
+ off = exe_sections[0].rva; |
|
1316 |
+ vma = EC32(optional_hdr32.ImageBase) + exe_sections[0].rva; |
|
1317 |
+ } else { |
|
1318 |
+ cli_dbgmsg("Upack: var NOT set\n"); |
|
1319 |
+ c = exe_sections[1].rva; |
|
1320 |
+ ssize = exe_sections[1].uraw; |
|
1321 |
+ off = 0; |
|
1322 |
+ vma = exe_sections[1].rva - exe_sections[1].uraw; |
|
1323 |
+ } |
|
1357 | 1324 |
|
1358 |
- if (upack) |
|
1359 |
- memmove(dest + exe_sections[2].rva - exe_sections[0].rva, dest, ssize); |
|
1325 |
+ dsize = a+b+c; |
|
1360 | 1326 |
|
1361 |
- lseek(desc, exe_sections[1].uraw, SEEK_SET); |
|
1327 |
+ CLI_UNPSIZELIMITS("Upack", MAX(MAX(dsize, ssize), exe_sections[1].ursz)); |
|
1362 | 1328 |
|
1363 |
- if(read(desc, dest + exe_sections[1].rva - off, exe_sections[1].ursz) != exe_sections[1].ursz) { |
|
1364 |
- cli_dbgmsg("Upack: Can't read raw data of section 1\n"); |
|
1365 |
- free(exe_sections); |
|
1366 |
- free(dest); |
|
1367 |
- return CL_EIO; |
|
1368 |
- } |
|
1369 |
- |
|
1370 |
- if(!(tempfile = cli_gentemp(NULL))) { |
|
1371 |
- free(exe_sections); |
|
1372 |
- free(dest); |
|
1373 |
- return CL_EMEM; |
|
1374 |
- } |
|
1329 |
+ if (exe_sections[1].rva - off > dsize || exe_sections[1].rva - off > dsize - exe_sections[1].ursz || (upack && (exe_sections[2].rva - exe_sections[0].rva > dsize || exe_sections[2].rva - exe_sections[0].rva > dsize - ssize)) || ssize > dsize) { |
|
1330 |
+ cli_dbgmsg("Upack: probably malformed pe-header, skipping to next unpacker\n"); |
|
1331 |
+ break; |
|
1332 |
+ } |
|
1333 |
+ |
|
1334 |
+ if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) { |
|
1335 |
+ free(exe_sections); |
|
1336 |
+ return CL_EMEM; |
|
1337 |
+ } |
|
1375 | 1338 |
|
1376 |
- if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC, S_IRWXU)) < 0) { |
|
1377 |
- cli_dbgmsg("Upack: Can't create file %s\n", tempfile); |
|
1378 |
- free(tempfile); |
|
1379 |
- free(exe_sections); |
|
1380 |
- free(dest); |
|
1381 |
- return CL_EIO; |
|
1382 |
- } |
|
1339 |
+ lseek(desc, 0, SEEK_SET); |
|
1340 |
+ if(read(desc, dest, ssize) != ssize) { |
|
1341 |
+ cli_dbgmsg("Upack: Can't read raw data of section 0\n"); |
|
1342 |
+ free(exe_sections); |
|
1343 |
+ free(dest); |
|
1344 |
+ return CL_EIO; |
|
1345 |
+ } |
|
1383 | 1346 |
|
1384 |
- switch (unupack(upack, dest, dsize, buff, vma, ep, EC32(optional_hdr32.ImageBase), exe_sections[0].rva, ndesc)) |
|
1385 |
- { |
|
1386 |
- case 1: /* Everything OK */ |
|
1387 |
- cli_dbgmsg("Upack: Unpacked and rebuilt executable saved in %s\n", tempfile); |
|
1388 |
- free(dest); |
|
1389 |
- fsync(ndesc); |
|
1390 |
- lseek(ndesc, 0, SEEK_SET); |
|
1391 |
- |
|
1392 |
- cli_dbgmsg("***** Scanning rebuilt PE file *****\n"); |
|
1393 |
- if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) { |
|
1394 |
- free(exe_sections); |
|
1395 |
- close(ndesc); |
|
1396 |
- if(!cli_leavetemps_flag) |
|
1397 |
- unlink(tempfile); |
|
1398 |
- free(tempfile); |
|
1399 |
- return CL_VIRUS; |
|
1400 |
- } |
|
1401 |
- |
|
1402 |
- close(ndesc); |
|
1403 |
- if(!cli_leavetemps_flag) |
|
1404 |
- unlink(tempfile); |
|
1405 |
- free(tempfile); |
|
1406 |
- free(exe_sections); |
|
1407 |
- return CL_CLEAN; |
|
1408 |
- |
|
1409 |
- default: /* Everything gone wrong */ |
|
1410 |
- cli_dbgmsg("Upack: Unpacking failed\n"); |
|
1411 |
- close(ndesc); |
|
1412 |
- unlink(tempfile); /* It's empty anyway */ |
|
1413 |
- free(tempfile); |
|
1414 |
- free(dest); |
|
1415 |
- break; |
|
1416 |
- } |
|
1417 |
- } |
|
1418 |
-skip_upack_and_go_to_next_unpacker: |
|
1347 |
+ if(upack) memmove(dest + exe_sections[2].rva - exe_sections[0].rva, dest, ssize); |
|
1419 | 1348 |
|
1420 |
- if((DCONF & PE_CONF_FSG) && buff[0] == '\x87' && buff[1] == '\x25') { |
|
1349 |
+ lseek(desc, exe_sections[1].uraw, SEEK_SET); |
|
1421 | 1350 |
|
1422 |
- /* FSG v2.0 support - thanks to aCaB ! */ |
|
1351 |
+ if(read(desc, dest + exe_sections[1].rva - off, exe_sections[1].ursz) != exe_sections[1].ursz) { |
|
1352 |
+ cli_dbgmsg("Upack: Can't read raw data of section 1\n"); |
|
1353 |
+ free(exe_sections); |
|
1354 |
+ free(dest); |
|
1355 |
+ return CL_EIO; |
|
1356 |
+ } |
|
1423 | 1357 |
|
1424 |
- ssize = exe_sections[i + 1].rsz; |
|
1425 |
- dsize = exe_sections[i].vsz; |
|
1358 |
+ CLI_UNPTEMP("Upack",dest,exe_sections); |
|
1359 |
+ CLI_UNPRESULTS("Upack",(unupack(upack, dest, dsize, epbuff, vma, ep, EC32(optional_hdr32.ImageBase), exe_sections[0].rva, ndesc)),1,dest); |
|
1360 |
+ break; |
|
1361 |
+ } |
|
1362 |
+ } |
|
1426 | 1363 |
|
1427 |
- while(found) { |
|
1428 |
- uint32_t newesi, newedi, newebx, newedx; |
|
1364 |
+ |
|
1365 |
+ while(found && (DCONF & PE_CONF_FSG) && epbuff[0] == '\x87' && epbuff[1] == '\x25') { |
|
1429 | 1366 |
|
1430 |
- if(ctx->limits && ctx->limits->maxfilesize && (ssize > ctx->limits->maxfilesize || dsize > ctx->limits->maxfilesize)) { |
|
1431 |
- cli_dbgmsg("FSG: Sizes exceeded (ssize: %u, dsize: %u, max: %lu)\n", ssize, dsize , ctx->limits->maxfilesize); |
|
1432 |
- free(exe_sections); |
|
1433 |
- if(BLOCKMAX) { |
|
1434 |
- *ctx->virname = "PE.FSG.ExceededFileSize"; |
|
1435 |
- return CL_VIRUS; |
|
1436 |
- } else { |
|
1437 |
- return CL_CLEAN; |
|
1438 |
- } |
|
1439 |
- } |
|
1367 |
+ /* FSG v2.0 support - thanks to aCaB ! */ |
|
1440 | 1368 |
|
1441 |
- if(ssize <= 0x19 || dsize <= ssize) { |
|
1442 |
- cli_dbgmsg("FSG: Size mismatch (ssize: %d, dsize: %d)\n", ssize, dsize); |
|
1443 |
- free(exe_sections); |
|
1444 |
- return CL_CLEAN; |
|
1445 |
- } |
|
1369 |
+ uint32_t newesi, newedi, newebx, newedx; |
|
1370 |
+ |
|
1371 |
+ ssize = exe_sections[i + 1].rsz; |
|
1372 |
+ dsize = exe_sections[i].vsz; |
|
1446 | 1373 |
|
1447 |
- newedx = cli_readint32(buff + 2) - EC32(optional_hdr32.ImageBase); |
|
1448 |
- if(!CLI_ISCONTAINED(exe_sections[i + 1].rva, exe_sections[i + 1].rsz, newedx, 4)) { |
|
1449 |
- cli_dbgmsg("FSG: xchg out of bounds (%x), giving up\n", newedx); |
|
1450 |
- break; |
|
1451 |
- } |
|
1374 |
+ CLI_UNPSIZELIMITS("FSG", MAX(dsize, ssize)); |
|
1452 | 1375 |
|
1453 |
- if((src = (char *) cli_malloc(ssize)) == NULL) { |
|
1454 |
- free(exe_sections); |
|
1455 |
- return CL_EMEM; |
|
1456 |
- } |
|
1376 |
+ if(ssize <= 0x19 || dsize <= ssize) { |
|
1377 |
+ cli_dbgmsg("FSG: Size mismatch (ssize: %d, dsize: %d)\n", ssize, dsize); |
|
1378 |
+ free(exe_sections); |
|
1379 |
+ return CL_CLEAN; |
|
1380 |
+ } |
|
1381 |
+ |
|
1382 |
+ newedx = cli_readint32(epbuff + 2) - EC32(optional_hdr32.ImageBase); |
|
1383 |
+ if(!CLI_ISCONTAINED(exe_sections[i + 1].rva, exe_sections[i + 1].rsz, newedx, 4)) { |
|
1384 |
+ cli_dbgmsg("FSG: xchg out of bounds (%x), giving up\n", newedx); |
|
1385 |
+ break; |
|
1386 |
+ } |
|
1387 |
+ |
|
1388 |
+ if((src = (char *) cli_malloc(ssize)) == NULL) { |
|
1389 |
+ free(exe_sections); |
|
1390 |
+ return CL_EMEM; |
|
1391 |
+ } |
|
1457 | 1392 |
|
1458 |
- lseek(desc, exe_sections[i + 1].raw, SEEK_SET); |
|
1459 |
- if((unsigned int) cli_readn(desc, src, ssize) != ssize) { |
|
1460 |
- cli_dbgmsg("Can't read raw data of section %d\n", i + 1); |
|
1461 |
- free(exe_sections); |
|
1462 |
- free(src); |
|
1463 |
- return CL_EIO; |
|
1464 |
- } |
|
1393 |
+ if(!cli_seeksect(desc, &exe_sections[i + 1]) || (unsigned int) cli_readn(desc, src, ssize) != ssize) { |
|
1394 |
+ cli_dbgmsg("Can't read raw data of section %d\n", i + 1); |
|
1395 |
+ free(exe_sections); |
|
1396 |
+ free(src); |
|
1397 |
+ return CL_EIO; |
|
1398 |
+ } |
|
1465 | 1399 |
|
1466 |
- dest = src + newedx - exe_sections[i + 1].rva; |
|
1467 |
- if(newedx < exe_sections[i + 1].rva || !CLI_ISCONTAINED(src, ssize, dest, 4)) { |
|
1468 |
- cli_dbgmsg("FSG: New ESP out of bounds\n"); |
|
1469 |
- free(src); |
|
1470 |
- break; |
|
1471 |
- } |
|
1400 |
+ dest = src + newedx - exe_sections[i + 1].rva; |
|
1401 |
+ if(newedx < exe_sections[i + 1].rva || !CLI_ISCONTAINED(src, ssize, dest, 4)) { |
|
1402 |
+ cli_dbgmsg("FSG: New ESP out of bounds\n"); |
|
1403 |
+ free(src); |
|
1404 |
+ break; |
|
1405 |
+ } |
|
1472 | 1406 |
|
1473 |
- newedx = cli_readint32(dest) - EC32(optional_hdr32.ImageBase); |
|
1474 |
- if(!CLI_ISCONTAINED(exe_sections[i + 1].rva, exe_sections[i + 1].rsz, newedx, 4)) { |
|
1475 |
- cli_dbgmsg("FSG: New ESP (%x) is wrong\n", newedx); |
|
1476 |
- free(src); |
|
1477 |
- break; |
|
1478 |
- } |
|
1407 |
+ newedx = cli_readint32(dest) - EC32(optional_hdr32.ImageBase); |
|
1408 |
+ if(!CLI_ISCONTAINED(exe_sections[i + 1].rva, exe_sections[i + 1].rsz, newedx, 4)) { |
|
1409 |
+ cli_dbgmsg("FSG: New ESP (%x) is wrong\n", newedx); |
|
1410 |
+ free(src); |
|
1411 |
+ break; |
|
1412 |
+ } |
|
1479 | 1413 |
|
1480 |
- dest = src + newedx - exe_sections[i + 1].rva; |
|
1481 |
- if(!CLI_ISCONTAINED(src, ssize, dest, 32)) { |
|
1482 |
- cli_dbgmsg("FSG: New stack out of bounds\n"); |
|
1483 |
- free(src); |
|
1484 |
- break; |
|
1485 |
- } |
|
1414 |
+ dest = src + newedx - exe_sections[i + 1].rva; |
|
1415 |
+ if(!CLI_ISCONTAINED(src, ssize, dest, 32)) { |
|
1416 |
+ cli_dbgmsg("FSG: New stack out of bounds\n"); |
|
1417 |
+ free(src); |
|
1418 |
+ break; |
|
1419 |
+ } |
|
1486 | 1420 |
|
1487 |
- newedi = cli_readint32(dest) - EC32(optional_hdr32.ImageBase); |
|
1488 |
- newesi = cli_readint32(dest + 4) - EC32(optional_hdr32.ImageBase); |
|
1489 |
- newebx = cli_readint32(dest + 16) - EC32(optional_hdr32.ImageBase); |
|
1490 |
- newedx = cli_readint32(dest + 20); |
|
1421 |
+ newedi = cli_readint32(dest) - EC32(optional_hdr32.ImageBase); |
|
1422 |
+ newesi = cli_readint32(dest + 4) - EC32(optional_hdr32.ImageBase); |
|
1423 |
+ newebx = cli_readint32(dest + 16) - EC32(optional_hdr32.ImageBase); |
|
1424 |
+ newedx = cli_readint32(dest + 20); |
|
1491 | 1425 |
|
1492 |
- if(newedi != exe_sections[i].rva) { |
|
1493 |
- cli_dbgmsg("FSG: Bad destination buffer (edi is %x should be %x)\n", newedi, exe_sections[i].rva); |
|
1494 |
- free(src); |
|
1495 |
- break; |
|
1496 |
- } |
|
1426 |
+ if(newedi != exe_sections[i].rva) { |
|
1427 |
+ cli_dbgmsg("FSG: Bad destination buffer (edi is %x should be %x)\n", newedi, exe_sections[i].rva); |
|
1428 |
+ free(src); |
|
1429 |
+ break; |
|
1430 |
+ } |
|
1497 | 1431 |
|
1498 |
- if(newesi < exe_sections[i + 1].rva || newesi - exe_sections[i + 1].rva >= exe_sections[i + 1].rsz) { |
|
1499 |
- cli_dbgmsg("FSG: Source buffer out of section bounds\n"); |
|
1500 |
- free(src); |
|
1501 |
- break; |
|
1502 |
- } |
|
1432 |
+ if(newesi < exe_sections[i + 1].rva || newesi - exe_sections[i + 1].rva >= exe_sections[i + 1].rsz) { |
|
1433 |
+ cli_dbgmsg("FSG: Source buffer out of section bounds\n"); |
|
1434 |
+ free(src); |
|
1435 |
+ break; |
|
1436 |
+ } |
|
1503 | 1437 |
|
1504 |
- if(!CLI_ISCONTAINED(exe_sections[i + 1].rva, exe_sections[i + 1].rsz, newebx, 16)) { |
|
1505 |
- cli_dbgmsg("FSG: Array of functions out of bounds\n"); |
|
1506 |
- free(src); |
|
1507 |
- break; |
|
1508 |
- } |
|
1438 |
+ if(!CLI_ISCONTAINED(exe_sections[i + 1].rva, exe_sections[i + 1].rsz, newebx, 16)) { |
|
1439 |
+ cli_dbgmsg("FSG: Array of functions out of bounds\n"); |
|
1440 |
+ free(src); |
|
1441 |
+ break; |
|
1442 |
+ } |
|
1509 | 1443 |
|
1510 |
- newedx=cli_readint32(newebx + 12 - exe_sections[i + 1].rva + src) - EC32(optional_hdr32.ImageBase); |
|
1511 |
- cli_dbgmsg("FSG: found old EP @%x\n",newedx); |
|
1444 |
+ newedx=cli_readint32(newebx + 12 - exe_sections[i + 1].rva + src) - EC32(optional_hdr32.ImageBase); |
|
1445 |
+ cli_dbgmsg("FSG: found old EP @%x\n",newedx); |
|
1512 | 1446 |
|
1513 |
- if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) { |
|
1514 |
- free(exe_sections); |
|
1515 |
- free(src); |
|
1516 |
- return CL_EMEM; |
|
1517 |
- } |
|
1447 |
+ if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) { |
|
1448 |
+ free(exe_sections); |
|
1449 |
+ free(src); |
|
1450 |
+ return CL_EMEM; |
|
1451 |
+ } |
|
1518 | 1452 |
|
1519 |
- if(!(tempfile = cli_gentemp(NULL))) { |
|
1520 |
- free(exe_sections); |
|
1521 |
- free(src); |
|
1522 |
- free(dest); |
|
1523 |
- return CL_EMEM; |
|
1524 |
- } |
|
1453 |
+ CLI_UNPTEMP("FSG",src,dest,exe_sections); |
|
1454 |
+ CLI_UNPRESULTSFSG2("FSG",(unfsg_200(newesi - exe_sections[i + 1].rva + src, dest, ssize + exe_sections[i + 1].rva - newesi, dsize, newedi, EC32(optional_hdr32.ImageBase), newedx, ndesc)),1,src,dest); |
|
1455 |
+ break; |
|
1456 |
+ } |
|
1525 | 1457 |
|
1526 |
- if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) { |
|
1527 |
- cli_dbgmsg("FSG: Can't create file %s\n", tempfile); |
|
1528 |
- free(tempfile); |
|
1529 |
- free(exe_sections); |
|
1530 |
- free(src); |
|
1531 |
- free(dest); |
|
1532 |
- return CL_EIO; |
|
1533 |
- } |
|
1534 |
- |
|
1535 |
- switch (unfsg_200(newesi - exe_sections[i + 1].rva + src, dest, ssize + exe_sections[i + 1].rva - newesi, dsize, newedi, EC32(optional_hdr32.ImageBase), newedx, ndesc)) { |
|
1536 |
- case 1: /* Everything OK */ |
|
1537 |
- cli_dbgmsg("FSG: Unpacked and rebuilt executable saved in %s\n", tempfile); |
|
1538 |
- free(src); |
|
1539 |
- free(dest); |
|
1540 |
- fsync(ndesc); |
|
1541 |
- lseek(ndesc, 0, SEEK_SET); |
|
1542 |
- |
|
1543 |
- cli_dbgmsg("***** Scanning rebuilt PE file *****\n"); |
|
1544 |
- if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) { |
|
1545 |
- free(exe_sections); |
|
1546 |
- close(ndesc); |
|
1547 |
- if(!cli_leavetemps_flag) |
|
1548 |
- unlink(tempfile); |
|
1549 |
- free(tempfile); |
|
1550 |
- return CL_VIRUS; |
|
1551 |
- } |
|
1552 | 1458 |
|
1553 |
- close(ndesc); |
|
1554 |
- if(!cli_leavetemps_flag) |
|
1555 |
- unlink(tempfile); |
|
1556 |
- free(tempfile); |
|
1557 |
- free(exe_sections); |
|
1558 |
- return CL_CLEAN; |
|
1559 |
- |
|
1560 |
- case 0: /* We've got an unpacked buffer, no exe though */ |
|
1561 |
- cli_dbgmsg("FSG: Successfully decompressed\n"); |
|
1562 |
- close(ndesc); |
|
1563 |
- unlink(tempfile); |
|
1564 |
- free(tempfile); |
|
1565 |
- found = 0; |
|
1566 |
- upx_success = 1; |
|
1567 |
- break; /* Go and scan the buffer! */ |
|
1568 |
- |
|
1569 |
- default: /* Everything gone wrong */ |
|
1570 |
- cli_dbgmsg("FSG: Unpacking failed\n"); |
|
1571 |
- close(ndesc); |
|
1572 |
- unlink(tempfile); /* It's empty anyway */ |
|
1573 |
- free(tempfile); |
|
1574 |
- free(src); |
|
1575 |
- free(dest); |
|
1576 |
- break; |
|
1577 |
- } |
|
1459 |
+ while(found && (DCONF & PE_CONF_FSG) && epbuff[0] == '\xbe' && cli_readint32(epbuff + 1) - EC32(optional_hdr32.ImageBase) < min) { |
|
1578 | 1460 |
|
1579 |
- break; /* were done with 2 */ |
|
1580 |
- } |
|
1581 |
- } |
|
1461 |
+ /* FSG support - v. 1.33 (thx trog for the many samples) */ |
|
1582 | 1462 |
|
1583 |
- if(found && (DCONF & PE_CONF_FSG) && buff[0] == '\xbe' && cli_readint32(buff + 1) - EC32(optional_hdr32.ImageBase) < min) { |
|
1463 |
+ int sectcnt = 0; |
|
1464 |
+ char *support; |
|
1465 |
+ uint32_t newesi, newedi, newebx, oldep, gp, t; |
|
1466 |
+ struct cli_exe_section *sections; |
|
1584 | 1467 |
|
1585 |
- /* FSG support - v. 1.33 (thx trog for the many samples) */ |
|
1468 |
+ ssize = exe_sections[i + 1].rsz; |
|
1469 |
+ dsize = exe_sections[i].vsz; |
|
1586 | 1470 |
|
1587 |
- ssize = exe_sections[i + 1].rsz; |
|
1588 |
- dsize = exe_sections[i].vsz; |
|
1471 |
+ CLI_UNPSIZELIMITS("FSG", MAX(dsize, ssize)); |
|
1589 | 1472 |
|
1590 |
- while(found) { |
|
1591 |
- int sectcnt = 0; |
|
1592 |
- char *support; |
|
1593 |
- uint32_t newesi, newedi, newebx, oldep, gp, t; |
|
1594 |
- struct cli_exe_section *sections; |
|
1473 |
+ if(ssize <= 0x19 || dsize <= ssize) { |
|
1474 |
+ cli_dbgmsg("FSG: Size mismatch (ssize: %d, dsize: %d)\n", ssize, dsize); |
|
1475 |
+ free(exe_sections); |
|
1476 |
+ return CL_CLEAN; |
|
1477 |
+ } |
|
1595 | 1478 |
|
1479 |
+ if(!(gp = cli_rawaddr(cli_readint32(epbuff + 1) - EC32(optional_hdr32.ImageBase), NULL, 0 , &err, fsize, hdr_size)) && err ) { |
|
1480 |
+ cli_dbgmsg("FSG: Support data out of padding area\n"); |
|
1481 |
+ break; |
|
1482 |
+ } |
|
1596 | 1483 |
|
1597 |
- if(ctx->limits && ctx->limits->maxfilesize && (ssize > ctx->limits->maxfilesize || dsize > ctx->limits->maxfilesize)) { |
|
1598 |
- cli_dbgmsg("FSG: Sizes exceeded (ssize: %u, dsize: %u, max: %lu)\n", ssize, dsize, ctx->limits->maxfilesize); |
|
1599 |
- free(exe_sections); |
|
1600 |
- if(BLOCKMAX) { |
|
1601 |
- *ctx->virname = "PE.FSG.ExceededFileSize"; |
|
1602 |
- return CL_VIRUS; |
|
1603 |
- } else { |
|
1604 |
- return CL_CLEAN; |
|
1605 |
- } |
|
1606 |
- } |
|
1484 |
+ lseek(desc, gp, SEEK_SET); |
|
1485 |
+ gp = exe_sections[i + 1].raw - gp; |
|
1607 | 1486 |
|
1608 |
- if(ssize <= 0x19 || dsize <= ssize) { |
|
1609 |
- cli_dbgmsg("FSG: Size mismatch (ssize: %d, dsize: %d)\n", ssize, dsize); |
|
1610 |
- free(exe_sections); |
|
1611 |
- return CL_CLEAN; |
|
1612 |
- } |
|
1487 |
+ CLI_UNPSIZELIMITS("FSG", gp) |
|
1613 | 1488 |
|
1614 |
- if(!(gp = cli_rawaddr(cli_readint32(buff + 1) - EC32(optional_hdr32.ImageBase), NULL, 0 , &err, fsize, hdr_size)) && err ) { |
|
1615 |
- cli_dbgmsg("FSG: Support data out of padding area\n"); |
|
1616 |
- break; |
|
1617 |
- } |
|
1489 |
+ if((support = (char *) cli_malloc(gp)) == NULL) { |
|
1490 |
+ free(exe_sections); |
|
1491 |
+ return CL_EMEM; |
|
1492 |
+ } |
|
1618 | 1493 |
|
1619 |
- lseek(desc, gp, SEEK_SET); |
|
1620 |
- gp = exe_sections[i + 1].raw - gp; |
|
1494 |
+ if((int)cli_readn(desc, support, gp) != (int)gp) { |
|
1495 |
+ cli_dbgmsg("Can't read %d bytes from padding area\n", gp); |
|
1496 |
+ free(exe_sections); |
|
1497 |
+ free(support); |
|
1498 |
+ return CL_EIO; |
|
1499 |
+ } |
|
1621 | 1500 |
|
1622 |
- if(ctx->limits && ctx->limits->maxfilesize && (unsigned int) gp > ctx->limits->maxfilesize) { |
|
1623 |
- cli_dbgmsg("FSG: Buffer size exceeded (size: %d, max: %lu)\n", gp, ctx->limits->maxfilesize); |
|
1624 |
- free(exe_sections); |
|
1625 |
- if(BLOCKMAX) { |
|
1626 |
- *ctx->virname = "PE.FSG.ExceededFileSize"; |
|
1627 |
- return CL_VIRUS; |
|
1628 |
- } else { |
|
1629 |
- return CL_CLEAN; |
|
1630 |
- } |
|
1631 |
- } |
|
1501 |
+ /* newebx = cli_readint32(support) - EC32(optional_hdr32.ImageBase); Unused */ |
|
1502 |
+ newedi = cli_readint32(support + 4) - EC32(optional_hdr32.ImageBase); /* 1st dest */ |
|
1503 |
+ newesi = cli_readint32(support + 8) - EC32(optional_hdr32.ImageBase); /* Source */ |
|
1632 | 1504 |
|
1633 |
- if((support = (char *) cli_malloc(gp)) == NULL) { |
|
1634 |
- free(exe_sections); |
|
1635 |
- return CL_EMEM; |
|
1636 |
- } |
|
1505 |
+ if(newesi < exe_sections[i + 1].rva || newesi - exe_sections[i + 1].rva >= exe_sections[i + 1].rsz) { |
|
1506 |
+ cli_dbgmsg("FSG: Source buffer out of section bounds\n"); |
|
1507 |
+ free(support); |
|
1508 |
+ break; |
|
1509 |
+ } |
|
1637 | 1510 |
|
1638 |
- if((int)cli_readn(desc, support, gp) != (int)gp) { |
|
1639 |
- cli_dbgmsg("Can't read %d bytes from padding area\n", gp); |
|
1640 |
- free(exe_sections); |
|
1641 |
- free(support); |
|
1642 |
- return CL_EIO; |
|
1643 |
- } |
|
1511 |
+ if(newedi != exe_sections[i].rva) { |
|
1512 |
+ cli_dbgmsg("FSG: Bad destination (is %x should be %x)\n", newedi, exe_sections[i].rva); |
|
1513 |
+ free(support); |
|
1514 |
+ break; |
|
1515 |
+ } |
|
1644 | 1516 |
|
1645 |
- /* newebx = cli_readint32(support) - EC32(optional_hdr32.ImageBase); Unused */ |
|
1646 |
- newedi = cli_readint32(support + 4) - EC32(optional_hdr32.ImageBase); /* 1st dest */ |
|
1647 |
- newesi = cli_readint32(support + 8) - EC32(optional_hdr32.ImageBase); /* Source */ |
|
1517 |
+ /* Counting original sections */ |
|
1518 |
+ for(t = 12; t < gp - 4; t += 4) { |
|
1519 |
+ uint32_t rva = cli_readint32(support+t); |
|
1648 | 1520 |
|
1649 |
- if(newesi < exe_sections[i + 1].rva || newesi - exe_sections[i + 1].rva >= exe_sections[i + 1].rsz) { |
|
1650 |
- cli_dbgmsg("FSG: Source buffer out of section bounds\n"); |
|
1651 |
- free(support); |
|
1652 |
- break; |
|
1653 |
- } |
|
1521 |
+ if(!rva) |
|
1522 |
+ break; |
|
1654 | 1523 |
|
1655 |
- if(newedi != exe_sections[i].rva) { |
|
1656 |
- cli_dbgmsg("FSG: Bad destination (is %x should be %x)\n", newedi, exe_sections[i].rva); |
|
1657 |
- free(support); |
|
1658 |
- break; |
|
1659 |
- } |
|
1524 |
+ rva -= EC32(optional_hdr32.ImageBase)+1; |
|
1525 |
+ sectcnt++; |
|
1660 | 1526 |
|
1661 |
- /* Counting original sections */ |
|
1662 |
- for(t = 12; t < gp - 4; t += 4) { |
|
1663 |
- uint32_t rva = cli_readint32(support+t); |
|
1527 |
+ if(rva % 0x1000) cli_dbgmsg("FSG: Original section %d is misaligned\n", sectcnt); |
|
1664 | 1528 |
|
1665 |
- if(!rva) |
|
1666 |
- break; |
|
1529 |
+ if(rva < exe_sections[i].rva || rva - exe_sections[i].rva >= exe_sections[i].vsz) { |
|
1530 |
+ cli_dbgmsg("FSG: Original section %d is out of bounds\n", sectcnt); |
|
1531 |
+ break; |
|
1532 |
+ } |
|
1533 |
+ } |
|
1667 | 1534 |
|
1668 |
- rva -= EC32(optional_hdr32.ImageBase)+1; |
|
1669 |
- sectcnt++; |
|
1535 |
+ if(t >= gp - 4 || cli_readint32(support + t)) { |
|
1536 |
+ free(support); |
|
1537 |
+ break; |
|
1538 |
+ } |
|
1670 | 1539 |
|
1671 |
- if(rva % 0x1000) |
|
1672 |
- /* FIXME: really need to bother? */ |
|
1673 |
- cli_dbgmsg("FSG: Original section %d is misaligned\n", sectcnt); |
|
1540 |
+ if((sections = (struct cli_exe_section *) cli_malloc((sectcnt + 1) * sizeof(struct cli_exe_section))) == NULL) { |
|
1541 |
+ free(exe_sections); |
|
1542 |
+ free(support); |
|
1543 |
+ return CL_EMEM; |
|
1544 |
+ } |
|
1674 | 1545 |
|
1675 |
- if(rva < exe_sections[i].rva || rva - exe_sections[i].rva >= exe_sections[i].vsz) { |
|
1676 |
- cli_dbgmsg("FSG: Original section %d is out of bounds\n", sectcnt); |
|
1677 |
- break; |
|
1678 |
- } |
|
1679 |
- } |
|
1546 |
+ sections[0].rva = newedi; |
|
1547 |
+ for(t = 1; t <= (uint32_t)sectcnt; t++) |
|
1548 |
+ sections[t].rva = cli_readint32(support + 8 + t * 4) - 1 - EC32(optional_hdr32.ImageBase); |
|
1680 | 1549 |
|
1681 |
- if(t >= gp - 4 || cli_readint32(support + t)) { |
|
1682 |
- free(support); |
|
1683 |
- break; |
|
1684 |
- } |
|
1550 |
+ free(support); |
|
1685 | 1551 |
|
1686 |
- if((sections = (struct cli_exe_section *) cli_malloc((sectcnt + 1) * sizeof(struct cli_exe_section))) == NULL) { |
|
1687 |
- free(exe_sections); |
|
1688 |
- free(support); |
|
1689 |
- return CL_EMEM; |
|
1690 |
- } |
|
1552 |
+ if((src = (char *) cli_malloc(ssize)) == NULL) { |
|
1553 |
+ free(exe_sections); |
|
1554 |
+ free(sections); |
|
1555 |
+ return CL_EMEM; |
|
1556 |
+ } |
|
1691 | 1557 |
|
1692 |
- sections[0].rva = newedi; |
|
1693 |
- for(t = 1; t <= (uint32_t)sectcnt; t++) |
|
1694 |
- sections[t].rva = cli_readint32(support + 8 + t * 4) - 1 - EC32(optional_hdr32.ImageBase); |
|
1558 |
+ if(!cli_seeksect(desc, &exe_sections[i + 1]) || (unsigned int) cli_readn(desc, src, ssize) != ssize) { |
|
1559 |
+ cli_dbgmsg("Can't read raw data of section %d\n", i); |
|
1560 |
+ free(exe_sections); |
|
1561 |
+ free(sections); |
|
1562 |
+ free(src); |
|
1563 |
+ return CL_EIO; |
|
1564 |
+ } |
|
1695 | 1565 |
|
1696 |
- free(support); |
|
1566 |
+ if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) { |
|
1567 |
+ free(exe_sections); |
|
1568 |
+ free(src); |
|
1569 |
+ free(sections); |
|
1570 |
+ return CL_EMEM; |
|
1571 |
+ } |
|
1697 | 1572 |
|
1698 |
- if((src = (char *) cli_malloc(ssize)) == NULL) { |
|
1699 |
- free(exe_sections); |
|
1700 |
- free(sections); |
|
1701 |
- return CL_EMEM; |
|
1702 |
- } |
|
1573 |
+ oldep = vep + 161 + 6 + cli_readint32(epbuff+163); |
|
1574 |
+ cli_dbgmsg("FSG: found old EP @%x\n", oldep); |
|
1703 | 1575 |
|
1704 |
- lseek(desc, exe_sections[i + 1].raw, SEEK_SET); |
|
1705 |
- if((unsigned int) cli_readn(desc, src, ssize) != ssize) { |
|
1706 |
- cli_dbgmsg("Can't read raw data of section %d\n", i); |
|
1707 |
- free(exe_sections); |
|
1708 |
- free(sections); |
|
1709 |
- free(src); |
|
1710 |
- return CL_EIO; |
|
1711 |
- } |
|
1576 |
+ CLI_UNPTEMP("FSG",src,dest,sections,exe_sections); |
|
1577 |
+ CLI_UNPRESULTSFSG1("FSG",(unfsg_133(src + newesi - exe_sections[i + 1].rva, dest, ssize + exe_sections[i + 1].rva - newesi, dsize, sections, sectcnt, EC32(optional_hdr32.ImageBase), oldep, ndesc)),1,src,dest,sections); |
|
1578 |
+ break; /* were done with 1.33 */ |
|
1579 |
+ } |
|
1712 | 1580 |
|
1713 |
- if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) { |
|
1714 |
- free(exe_sections); |
|
1715 |
- free(src); |
|
1716 |
- free(sections); |
|
1717 |
- return CL_EMEM; |
|
1718 |
- } |
|
1719 | 1581 |
|
1720 |
- oldep = vep + 161 + 6 + cli_readint32(buff+163); |
|
1721 |
- cli_dbgmsg("FSG: found old EP @%x\n", oldep); |
|
1582 |
+ while(found && (DCONF & PE_CONF_FSG) && epbuff[0] == '\xbb' && cli_readint32(epbuff + 1) - EC32(optional_hdr32.ImageBase) < min && epbuff[5] == '\xbf' && epbuff[10] == '\xbe' && vep >= exe_sections[i + 1].rva && vep - exe_sections[i + 1].rva > exe_sections[i + 1].rva - 0xe0 ) { |
|
1722 | 1583 |
|
1723 |
- if(!(tempfile = cli_gentemp(NULL))) { |
|
1724 |
- free(exe_sections); |
|
1725 |
- free(src); |
|
1726 |
- free(dest); |
|
1727 |
- free(sections); |
|
1728 |
- return CL_EMEM; |
|
1729 |
- } |
|
1584 |
+ /* FSG support - v. 1.31 */ |
|
1730 | 1585 |
|
1731 |
- if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) { |
|
1732 |
- cli_dbgmsg("FSG: Can't create file %s\n", tempfile); |
|
1733 |
- free(tempfile); |
|
1734 |
- free(exe_sections); |
|
1735 |
- free(src); |
|
1736 |
- free(dest); |
|
1737 |
- free(sections); |
|
1738 |
- return CL_EIO; |
|
1739 |
- } |
|
1586 |
+ int sectcnt = 0; |
|
1587 |
+ uint32_t t; |
|
1588 |
+ uint32_t gp = cli_rawaddr(cli_readint32(epbuff+1) - EC32(optional_hdr32.ImageBase), NULL, 0 , &err, fsize, hdr_size); |
|
1589 |
+ char *support; |
|
1590 |
+ uint32_t newesi = cli_readint32(epbuff+11) - EC32(optional_hdr32.ImageBase); |
|
1591 |
+ uint32_t newedi = cli_readint32(epbuff+6) - EC32(optional_hdr32.ImageBase); |
|
1592 |
+ uint32_t oldep = vep - exe_sections[i + 1].rva; |
|
1593 |
+ struct cli_exe_section *sections; |
|
1740 | 1594 |
|
1741 |
- switch(unfsg_133(src + newesi - exe_sections[i + 1].rva, dest, ssize + exe_sections[i + 1].rva - newesi, dsize, sections, sectcnt, EC32(optional_hdr32.ImageBase), oldep, ndesc)) { |
|
1742 |
- case 1: /* Everything OK */ |
|
1743 |
- cli_dbgmsg("FSG: Unpacked and rebuilt executable saved in %s\n", tempfile); |
|
1744 |
- free(src); |
|
1745 |
- free(dest); |
|
1746 |
- free(sections); |
|
1747 |
- fsync(ndesc); |
|
1748 |
- lseek(ndesc, 0, SEEK_SET); |
|
1749 |
- |
|
1750 |
- cli_dbgmsg("***** Scanning rebuilt PE file *****\n"); |
|
1751 |
- if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) { |
|
1752 |
- free(exe_sections); |
|
1753 |
- close(ndesc); |
|
1754 |
- if(!cli_leavetemps_flag) |
|
1755 |
- unlink(tempfile); |
|
1756 |
- free(tempfile); |
|
1757 |
- return CL_VIRUS; |
|
1758 |
- } |
|
1595 |
+ ssize = exe_sections[i + 1].rsz; |
|
1596 |
+ dsize = exe_sections[i].vsz; |
|
1759 | 1597 |
|
1760 |
- close(ndesc); |
|
1761 |
- if(!cli_leavetemps_flag) |
|
1762 |
- unlink(tempfile); |
|
1763 |
- free(tempfile); |
|
1764 |
- free(exe_sections); |
|
1765 |
- return CL_CLEAN; |
|
1766 |
- |
|
1767 |
- case 0: /* We've got an unpacked buffer, no exe though */ |
|
1768 |
- cli_dbgmsg("FSG: Successfully decompressed\n"); |
|
1769 |
- close(ndesc); |
|
1770 |
- unlink(tempfile); |
|
1771 |
- free(tempfile); |
|
1772 |
- free(sections); |
|
1773 |
- found = 0; |
|
1774 |
- upx_success = 1; |
|
1775 |
- break; /* Go and scan the buffer! */ |
|
1776 |
- |
|
1777 |
- default: /* Everything gone wrong */ |
|
1778 |
- cli_dbgmsg("FSG: Unpacking failed\n"); |
|
1779 |
- close(ndesc); |
|
1780 |
- unlink(tempfile); /* It's empty anyway */ |
|
1781 |
- free(tempfile); |
|
1782 |
- free(src); |
|
1783 |
- free(dest); |
|
1784 |
- free(sections); |
|
1785 |
- break; |
|
1786 |
- } |
|
1787 | 1598 |
|
1788 |
- break; /* were done with 1.33 */ |
|
1789 |
- } |
|
1599 |
+ if(err) { |
|
1600 |
+ cli_dbgmsg("FSG: Support data out of padding area\n"); |
|
1601 |
+ break; |
|
1790 | 1602 |
} |
1791 | 1603 |
|
1792 |
- /* FIXME: easy 2 hack */ |
|
1793 |
- if(found && (DCONF & PE_CONF_FSG) && buff[0] == '\xbb' && cli_readint32(buff + 1) - EC32(optional_hdr32.ImageBase) < min && buff[5] == '\xbf' && buff[10] == '\xbe' && vep >= exe_sections[i + 1].rva && vep - exe_sections[i + 1].rva > exe_sections[i + 1].rva - 0xe0 ) { |
|
1794 |
- |
|
1795 |
- /* FSG support - v. 1.31 */ |
|
1604 |
+ if(newesi < exe_sections[i + 1].rva || newesi - exe_sections[i + 1].rva >= exe_sections[i + 1].raw) { |
|
1605 |
+ cli_dbgmsg("FSG: Source buffer out of section bounds\n"); |
|
1606 |
+ break; |
|
1607 |
+ } |
|
1796 | 1608 |
|
1797 |
- ssize = exe_sections[i + 1].rsz; |
|
1798 |
- dsize = exe_sections[i].vsz; |
|
1609 |
+ if(newedi != exe_sections[i].rva) { |
|
1610 |
+ cli_dbgmsg("FSG: Bad destination (is %x should be %x)\n", newedi, exe_sections[i].rva); |
|
1611 |
+ break; |
|
1612 |
+ } |
|
1799 | 1613 |
|
1800 |
- while(found) { |
|
1801 |
- int sectcnt = 0; |
|
1802 |
- uint32_t t; |
|
1803 |
- uint32_t gp = cli_rawaddr(cli_readint32(buff+1) - EC32(optional_hdr32.ImageBase), NULL, 0 , &err, fsize, hdr_size); |
|
1804 |
- char *support; |
|
1805 |
- uint32_t newesi = cli_readint32(buff+11) - EC32(optional_hdr32.ImageBase); |
|
1806 |
- uint32_t newedi = cli_readint32(buff+6) - EC32(optional_hdr32.ImageBase); |
|
1807 |
- uint32_t oldep = vep - exe_sections[i + 1].rva; |
|
1808 |
- struct cli_exe_section *sections; |
|
1809 |
- |
|
1810 |
- if(err) { |
|
1811 |
- cli_dbgmsg("FSG: Support data out of padding area\n"); |
|
1812 |
- break; |
|
1813 |
- } |
|
1614 |
+ CLI_UNPSIZELIMITS("FSG", MAX(dsize, ssize)); |
|
1814 | 1615 |
|
1815 |
- if(newesi < exe_sections[i + 1].rva || newesi - exe_sections[i + 1].rva >= exe_sections[i + 1].raw) { |
|
1816 |
- cli_dbgmsg("FSG: Source buffer out of section bounds\n"); |
|
1817 |
- break; |
|
1818 |
- } |
|
1616 |
+ if(ssize <= 0x19 || dsize <= ssize) { |
|
1617 |
+ cli_dbgmsg("FSG: Size mismatch (ssize: %d, dsize: %d)\n", ssize, dsize); |
|
1618 |
+ free(exe_sections); |
|
1619 |
+ return CL_CLEAN; |
|
1620 |
+ } |
|
1819 | 1621 |
|
1820 |
- if(newedi != exe_sections[i].rva) { |
|
1821 |
- cli_dbgmsg("FSG: Bad destination (is %x should be %x)\n", newedi, exe_sections[i].rva); |
|
1822 |
- break; |
|
1823 |
- } |
|
1622 |
+ lseek(desc, gp, SEEK_SET); |
|
1623 |
+ gp = exe_sections[i + 1].raw - gp; |
|
1824 | 1624 |
|
1825 |
- if(ctx->limits && ctx->limits->maxfilesize && (ssize > ctx->limits->maxfilesize || dsize > ctx->limits->maxfilesize)) { |
|
1826 |
- cli_dbgmsg("FSG: Sizes exceeded (ssize: %u, dsize: %u, max: %lu)\n", ssize, dsize, ctx->limits->maxfilesize); |
|
1827 |
- free(exe_sections); |
|
1828 |
- if(BLOCKMAX) { |
|
1829 |
- *ctx->virname = "PE.FSG.ExceededFileSize"; |
|
1830 |
- return CL_VIRUS; |
|
1831 |
- } else { |
|
1832 |
- return CL_CLEAN; |
|
1833 |
- } |
|
1834 |
- } |
|
1625 |
+ CLI_UNPSIZELIMITS("FSG", gp) |
|
1835 | 1626 |
|
1836 |
- if(ssize <= 0x19 || dsize <= ssize) { |
|
1837 |
- cli_dbgmsg("FSG: Size mismatch (ssize: %d, dsize: %d)\n", ssize, dsize); |
|
1838 |
- free(exe_sections); |
|
1839 |
- return CL_CLEAN; |
|
1840 |
- } |
|
1627 |
+ if((support = (char *) cli_malloc(gp)) == NULL) { |
|
1628 |
+ free(exe_sections); |
|
1629 |
+ return CL_EMEM; |
|
1630 |
+ } |
|
1841 | 1631 |
|
1842 |
- lseek(desc, gp, SEEK_SET); |
|
1843 |
- gp = exe_sections[i + 1].raw - gp; |
|
1632 |
+ if(cli_readn(desc, support, gp) != (int)gp) { |
|
1633 |
+ cli_dbgmsg("Can't read %d bytes from padding area\n", gp); |
|
1634 |
+ free(exe_sections); |
|
1635 |
+ free(support); |
|
1636 |
+ return CL_EIO; |
|
1637 |
+ } |
|
1844 | 1638 |
|
1845 |
- if(ctx->limits && ctx->limits->maxfilesize && gp > ctx->limits->maxfilesize) { |
|
1846 |
- cli_dbgmsg("FSG: Buffer size exceeded (size: %d, max: %lu)\n", gp, ctx->limits->maxfilesize); |
|
1847 |
- free(exe_sections); |
|
1848 |
- if(BLOCKMAX) { |
|
1849 |
- *ctx->virname = "PE.FSG.ExceededFileSize"; |
|
1850 |
- return CL_VIRUS; |
|
1851 |
- } else { |
|
1852 |
- return CL_CLEAN; |
|
1853 |
- } |
|
1854 |
- } |
|
1639 |
+ /* Counting original sections */ |
|
1640 |
+ for(t = 0; t < gp - 2; t += 2) { |
|
1641 |
+ uint32_t rva = support[t]|(support[t+1]<<8); |
|
1855 | 1642 |
|
1856 |
- if((support = (char *) cli_malloc(gp)) == NULL) { |
|
1857 |
- free(exe_sections); |
|
1858 |
- return CL_EMEM; |
|
1859 |
- } |
|
1643 |
+ if (rva == 2 || rva == 1) |
|
1644 |
+ break; |
|
1860 | 1645 |
|
1861 |
- if(cli_readn(desc, support, gp) != (int)gp) { |
|
1862 |
- cli_dbgmsg("Can't read %d bytes from padding area\n", gp); |
|
1863 |
- free(exe_sections); |
|
1864 |
- free(support); |
|
1865 |
- return CL_EIO; |
|
1866 |
- } |
|
1646 |
+ rva = ((rva-2)<<12) - EC32(optional_hdr32.ImageBase); |
|
1647 |
+ sectcnt++; |
|
1867 | 1648 |
|
1868 |
- /* Counting original sections */ |
|
1869 |
- for(t = 0; t < gp - 2; t += 2) { |
|
1870 |
- uint32_t rva = support[t]|(support[t+1]<<8); |
|
1871 |
- |
|
1872 |
- if (rva == 2 || rva == 1) |
|
1873 |
- break; |
|
1649 |
+ if(rva < exe_sections[i].rva || rva - exe_sections[i].rva >= exe_sections[i].vsz) { |
|
1650 |
+ cli_dbgmsg("FSG: Original section %d is out of bounds\n", sectcnt); |
|
1651 |
+ break; |
|
1652 |
+ } |
|
1653 |
+ } |
|
1874 | 1654 |
|
1875 |
- rva = ((rva-2)<<12) - EC32(optional_hdr32.ImageBase); |
|
1876 |
- sectcnt++; |
|
1655 |
+ if(t >= gp-10 || cli_readint32(support + t + 6) != 2) { |
|
1656 |
+ free(support); |
|
1657 |
+ break; |
|
1658 |
+ } |
|
1877 | 1659 |
|
1878 |
- if(rva < exe_sections[i].rva || rva - exe_sections[i].rva >= exe_sections[i].vsz) { |
|
1879 |
- cli_dbgmsg("FSG: Original section %d is out of bounds\n", sectcnt); |
|
1880 |
- break; |
|
1881 |
- } |
|
1882 |
- } |
|
1660 |
+ if((sections = (struct cli_exe_section *) cli_malloc((sectcnt + 1) * sizeof(struct cli_exe_section))) == NULL) { |
|
1661 |
+ free(exe_sections); |
|
1662 |
+ free(support); |
|
1663 |
+ return CL_EMEM; |
|
1664 |
+ } |
|
1883 | 1665 |
|
1884 |
- if(t >= gp-10 || cli_readint32(support + t + 6) != 2) { |
|
1885 |
- free(support); |
|
1886 |
- break; |
|
1887 |
- } |
|
1666 |
+ sections[0].rva = newedi; |
|
1667 |
+ for(t = 0; t <= (uint32_t)sectcnt - 1; t++) { |
|
1668 |
+ sections[t+1].rva = (((support[t*2]|(support[t*2+1]<<8))-2)<<12)-EC32(optional_hdr32.ImageBase); |
|
1669 |
+ } |
|
1888 | 1670 |
|
1889 |
- if((sections = (struct cli_exe_section *) cli_malloc((sectcnt + 1) * sizeof(struct cli_exe_section))) == NULL) { |
|
1890 |
- free(exe_sections); |
|
1891 |
- free(support); |
|
1892 |
- return CL_EMEM; |
|
1893 |
- } |
|
1671 |
+ free(support); |
|
1894 | 1672 |
|
1895 |
- sections[0].rva = newedi; |
|
1896 |
- for(t = 0; t <= (uint32_t)sectcnt - 1; t++) { |
|
1897 |
- sections[t+1].rva = (((support[t*2]|(support[t*2+1]<<8))-2)<<12)-EC32(optional_hdr32.ImageBase); |
|
1898 |
- } |
|
1673 |
+ if((src = (char *) cli_malloc(ssize)) == NULL) { |
|
1674 |
+ free(exe_sections); |
|
1675 |
+ free(sections); |
|
1676 |
+ return CL_EMEM; |
|
1677 |
+ } |
|
1899 | 1678 |
|
1900 |
- free(support); |
|
1679 |
+ if(!cli_seeksect(desc, &exe_sections[i + 1]) || (unsigned int) cli_readn(desc, src, ssize) != ssize) { |
|
1680 |
+ cli_dbgmsg("FSG: Can't read raw data of section %d\n", i); |
|
1681 |
+ free(exe_sections); |
|
1682 |
+ free(sections); |
|
1683 |
+ free(src); |
|
1684 |
+ return CL_EIO; |
|
1685 |
+ } |
|
1901 | 1686 |
|
1902 |
- if((src = (char *) cli_malloc(ssize)) == NULL) { |
|
1903 |
- free(exe_sections); |
|
1904 |
- free(sections); |
|
1905 |
- return CL_EMEM; |
|
1906 |
- } |
|
1687 |
+ if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) { |
|
1688 |
+ free(exe_sections); |
|
1689 |
+ free(src); |
|
1690 |
+ free(sections); |
|
1691 |
+ return CL_EMEM; |
|
1692 |
+ } |
|
1907 | 1693 |
|
1908 |
- lseek(desc, exe_sections[i + 1].raw, SEEK_SET); |
|
1909 |
- if((unsigned int) cli_readn(desc, src, ssize) != ssize) { |
|
1910 |
- cli_dbgmsg("FSG: Can't read raw data of section %d\n", i); |
|
1911 |
- free(exe_sections); |
|
1912 |
- free(sections); |
|
1913 |
- free(src); |
|
1914 |
- return CL_EIO; |
|
1915 |
- } |
|
1694 |
+ gp = 0xda + 6*(epbuff[16]=='\xe8'); |
|
1695 |
+ oldep = vep + gp + 6 + cli_readint32(src+gp+2+oldep); |
|
1696 |
+ cli_dbgmsg("FSG: found old EP @%x\n", oldep); |
|
1916 | 1697 |
|
1917 |
- if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) { |
|
1918 |
- free(exe_sections); |
|
1919 |
- free(src); |
|
1920 |
- free(sections); |
|
1921 |
- return CL_EMEM; |
|
1922 |
- } |
|
1698 |
+ CLI_UNPTEMP("FSG",src,dest,sections,exe_sections); |
|
1699 |
+ CLI_UNPRESULTSFSG1("FSG",(unfsg_133(src + newesi - exe_sections[i + 1].rva, dest, ssize + exe_sections[i + 1].rva - newesi, dsize, sections, sectcnt, EC32(optional_hdr32.ImageBase), oldep, ndesc)),1,src,dest,sections); |
|
1700 |
+ break; /* were done with 1.31 */ |
|
1701 |
+ } |
|
1923 | 1702 |
|
1924 |
- /* Better not increasing buff size any further, let's go the hard way */ |
|
1925 |
- gp = 0xda + 6*(buff[16]=='\xe8'); |
|
1926 |
- oldep = vep + gp + 6 + cli_readint32(src+gp+2+oldep); |
|
1927 |
- cli_dbgmsg("FSG: found old EP @%x\n", oldep); |
|
1928 | 1703 |
|
1929 |
- if(!(tempfile = cli_gentemp(NULL))) { |
|
1930 |
- free(exe_sections); |
|
1931 |
- free(src); |
|
1932 |
- free(dest); |
|
1933 |
- free(sections); |
|
1934 |
- return CL_EMEM; |
|
1935 |
- } |
|
1704 |
+ if(found && (DCONF & PE_CONF_UPX)) { |
|
1936 | 1705 |
|
1937 |
- if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) { |
|
1938 |
- cli_dbgmsg("FSG: Can't create file %s\n", tempfile); |
|
1939 |
- free(tempfile); |
|
1940 |
- free(exe_sections); |
|
1941 |
- free(src); |
|
1942 |
- free(dest); |
|
1943 |
- free(sections); |
|
1944 |
- return CL_EIO; |
|
1945 |
- } |
|
1706 |
+ /* UPX support */ |
|
1946 | 1707 |
|
1947 |
- switch(unfsg_133(src + newesi - exe_sections[i + 1].rva, dest, ssize + exe_sections[i + 1].rva - newesi, dsize, sections, sectcnt, EC32(optional_hdr32.ImageBase), oldep, ndesc)) { |
|
1948 |
- case 1: /* Everything OK */ |
|
1949 |
- cli_dbgmsg("FSG: Unpacked and rebuilt executable saved in %s\n", tempfile); |
|
1950 |
- free(src); |
|
1951 |
- free(dest); |
|
1952 |
- free(sections); |
|
1953 |
- fsync(ndesc); |
|
1954 |
- lseek(ndesc, 0, SEEK_SET); |
|
1955 |
- |
|
1956 |
- cli_dbgmsg("***** Scanning rebuilt PE file *****\n"); |
|
1957 |
- if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) { |
|
1958 |
- free(exe_sections); |
|
1959 |
- close(ndesc); |
|
1960 |
- if(!cli_leavetemps_flag) |
|
1961 |
- unlink(tempfile); |
|
1962 |
- free(tempfile); |
|
1963 |
- return CL_VIRUS; |
|
1964 |
- } |
|
1708 |
+ /* we assume (i + 1) is UPX1 */ |
|
1709 |
+ ssize = exe_sections[i + 1].rsz; |
|
1710 |
+ dsize = exe_sections[i].vsz + exe_sections[i + 1].vsz; |
|
1965 | 1711 |
|
1966 |
- close(ndesc); |
|
1967 |
- if(!cli_leavetemps_flag) |
|
1968 |
- unlink(tempfile); |
|
1969 |
- free(tempfile); |
|
1970 |
- free(exe_sections); |
|
1971 |
- return CL_CLEAN; |
|
1972 |
- |
|
1973 |
- case 0: /* We've got an unpacked buffer, no exe though */ |
|
1974 |
- cli_dbgmsg("FSG: FSG: Successfully decompressed\n"); |
|
1975 |
- close(ndesc); |
|
1976 |
- unlink(tempfile); |
|
1977 |
- free(tempfile); |
|
1978 |
- free(sections); |
|
1979 |
- found = 0; |
|
1980 |
- upx_success = 1; |
|
1981 |
- break; /* Go and scan the buffer! */ |
|
1982 |
- |
|
1983 |
- default: /* Everything gone wrong */ |
|
1984 |
- cli_dbgmsg("FSG: Unpacking failed\n"); |
|
1985 |
- close(ndesc); |
|
1986 |
- unlink(tempfile); /* It's empty anyway */ |
|
1987 |
- free(tempfile); |
|
1988 |
- free(src); |
|
1989 |
- free(dest); |
|
1990 |
- free(sections); |
|
1991 |
- break; |
|
1992 |
- } |
|
1712 |
+ CLI_UNPSIZELIMITS("UPX", MAX(dsize, ssize)); |
|
1993 | 1713 |
|
1994 |
- break; /* were done with 1.31 */ |
|
1995 |
- } |
|
1714 |
+ if(ssize <= 0x19 || dsize <= ssize || dsize > CLI_MAX_ALLOCATION ) { |
|
1715 |
+ cli_dbgmsg("UPX: Size mismatch or dsize too big (ssize: %d, dsize: %d)\n", ssize, dsize); |
|
1716 |
+ free(exe_sections); |
|
1717 |
+ return CL_CLEAN; |
|
1996 | 1718 |
} |
1997 | 1719 |
|
1720 |
+ if((src = (char *) cli_malloc(ssize)) == NULL) { |
|
1721 |
+ free(exe_sections); |
|
1722 |
+ return CL_EMEM; |
|
1723 |
+ } |
|
1998 | 1724 |
|
1999 |
- if(found && (DCONF & PE_CONF_UPX)) { |
|
2000 |
- |
|
2001 |
- /* UPX support */ |
|
2002 |
- |
|
2003 |
- /* we assume (i + 1) is UPX1 */ |
|
2004 |
- ssize = exe_sections[i + 1].rsz; |
|
2005 |
- dsize = exe_sections[i].vsz + exe_sections[i + 1].vsz; |
|
2006 |
- |
|
2007 |
- if(ctx->limits && ctx->limits->maxfilesize && (ssize > ctx->limits->maxfilesize || dsize > ctx->limits->maxfilesize)) { |
|
2008 |
- cli_dbgmsg("UPX: Sizes exceeded (ssize: %u, dsize: %u, max: %lu)\n", ssize, dsize , ctx->limits->maxfilesize); |
|
2009 |
- free(exe_sections); |
|
2010 |
- if(BLOCKMAX) { |
|
2011 |
- *ctx->virname = "PE.UPX.ExceededFileSize"; |
|
2012 |
- return CL_VIRUS; |
|
2013 |
- } else { |
|
2014 |
- return CL_CLEAN; |
|
2015 |
- } |
|
2016 |
- } |
|
2017 |
- |
|
2018 |
- if(ssize <= 0x19 || dsize <= ssize) { /* FIXME: What are reasonable values? */ |
|
2019 |
- cli_dbgmsg("UPX: Size mismatch (ssize: %d, dsize: %d)\n", ssize, dsize); |
|
2020 |
- free(exe_sections); |
|
2021 |
- return CL_CLEAN; |
|
2022 |
- } |
|
2023 |
- |
|
2024 |
- if((src = (char *) cli_malloc(ssize)) == NULL) { |
|
2025 |
- free(exe_sections); |
|
2026 |
- return CL_EMEM; |
|
2027 |
- } |
|
2028 |
- |
|
2029 |
- if(dsize > CLI_MAX_ALLOCATION) { |
|
2030 |
- cli_errmsg("UPX: Too big value of dsize\n"); |
|
2031 |
- free(exe_sections); |
|
2032 |
- free(src); |
|
2033 |
- return CL_EMEM; |
|
2034 |
- } |
|
1725 |
+ if((dest = (char *) cli_calloc(dsize + 8192, sizeof(char))) == NULL) { |
|
1726 |
+ free(exe_sections); |
|
1727 |
+ free(src); |
|
1728 |
+ return CL_EMEM; |
|
1729 |
+ } |
|
2035 | 1730 |
|
2036 |
- if((dest = (char *) cli_calloc(dsize + 8192, sizeof(char))) == NULL) { |
|
2037 |
- free(exe_sections); |
|
2038 |
- free(src); |
|
2039 |
- return CL_EMEM; |
|
2040 |
- } |
|
1731 |
+ if(!cli_seeksect(desc, &exe_sections[i + 1]) || (unsigned int) cli_readn(desc, src, ssize) != ssize) { |
|
1732 |
+ cli_dbgmsg("UPX: Can't read raw data of section %d\n", i+1); |
|
1733 |
+ free(exe_sections); |
|
1734 |
+ free(src); |
|
1735 |
+ free(dest); |
|
1736 |
+ return CL_EIO; |
|
1737 |
+ } |
|
2041 | 1738 |
|
2042 |
- lseek(desc, exe_sections[i + 1].raw, SEEK_SET); |
|
2043 |
- if((unsigned int) cli_readn(desc, src, ssize) != ssize) { |
|
2044 |
- cli_dbgmsg("UPX: Can't read raw data of section %d\n", i+1); |
|
2045 |
- free(exe_sections); |
|
2046 |
- free(src); |
|
2047 |
- free(dest); |
|
2048 |
- return CL_EIO; |
|
2049 |
- } |
|
1739 |
+ /* try to detect UPX code */ |
|
1740 |
+ if(cli_memstr(UPX_NRV2B, 24, epbuff + 0x69, 13) || cli_memstr(UPX_NRV2B, 24, epbuff + 0x69 + 8, 13)) { |
|
1741 |
+ cli_dbgmsg("UPX: Looks like a NRV2B decompression routine\n"); |
|
1742 |
+ upxfn = upx_inflate2b; |
|
1743 |
+ } else if(cli_memstr(UPX_NRV2D, 24, epbuff + 0x69, 13) || cli_memstr(UPX_NRV2D, 24, epbuff + 0x69 + 8, 13)) { |
|
1744 |
+ cli_dbgmsg("UPX: Looks like a NRV2D decompression routine\n"); |
|
1745 |
+ upxfn = upx_inflate2d; |
|
1746 |
+ } else if(cli_memstr(UPX_NRV2E, 24, epbuff + 0x69, 13) || cli_memstr(UPX_NRV2E, 24, epbuff + 0x69 + 8, 13)) { |
|
1747 |
+ cli_dbgmsg("UPX: Looks like a NRV2E decompression routine\n"); |
|
1748 |
+ upxfn = upx_inflate2e; |
|
1749 |
+ } |
|
2050 | 1750 |
|
2051 |
- /* try to detect UPX code */ |
|
1751 |
+ if(upxfn) { |
|
1752 |
+ int skew = cli_readint32(epbuff + 2) - EC32(optional_hdr32.ImageBase) - exe_sections[i + 1].rva; |
|
2052 | 1753 |
|
2053 |
- if(lseek(desc, ep, SEEK_SET) == -1) { |
|
2054 |
- cli_dbgmsg("UPX: lseek() failed\n"); |
|
2055 |
- free(exe_sections); |
|
2056 |
- free(src); |
|
2057 |
- free(dest); |
|
2058 |
- return CL_EIO; |
|
2059 |
- } |
|
1754 |
+ if(epbuff[1] != '\xbe' || skew <= 0 || skew > 0xfff) { /* FIXME: legit skews?? */ |
|
1755 |
+ skew = 0; |
|
1756 |
+ if(upxfn(src, ssize, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep) >= 0) |
|
1757 |
+ upx_success = 1; |
|
2060 | 1758 |
|
2061 |
- if(cli_readn(desc, buff, 126) != 126) { /* i.e. 0x69 + 13 + 8 */ |
|
2062 |
- cli_dbgmsg("UPX: Can't read 126 bytes at 0x%x (%d)\n", ep, ep); |
|
2063 |
- cli_dbgmsg("UPX: Broken or not UPX compressed file\n"); |
|
2064 |
- free(exe_sections); |
|
2065 |
- free(src); |
|
2066 |
- free(dest); |
|
2067 |
- return CL_CLEAN; |
|
2068 | 1759 |
} else { |
2069 |
- if(cli_memstr(UPX_NRV2B, 24, buff + 0x69, 13) || cli_memstr(UPX_NRV2B, 24, buff + 0x69 + 8, 13)) { |
|
2070 |
- cli_dbgmsg("UPX: Looks like a NRV2B decompression routine\n"); |
|
2071 |
- upxfn = upx_inflate2b; |
|
2072 |
- } else if(cli_memstr(UPX_NRV2D, 24, buff + 0x69, 13) || cli_memstr(UPX_NRV2D, 24, buff + 0x69 + 8, 13)) { |
|
2073 |
- cli_dbgmsg("UPX: Looks like a NRV2D decompression routine\n"); |
|
2074 |
- upxfn = upx_inflate2d; |
|
2075 |
- } else if(cli_memstr(UPX_NRV2E, 24, buff + 0x69, 13) || cli_memstr(UPX_NRV2E, 24, buff + 0x69 + 8, 13)) { |
|
2076 |
- cli_dbgmsg("UPX: Looks like a NRV2E decompression routine\n"); |
|
2077 |
- upxfn = upx_inflate2e; |
|
2078 |
- } |
|
1760 |
+ cli_dbgmsg("UPX: UPX1 seems skewed by %d bytes\n", skew); |
|
1761 |
+ if(upxfn(src + skew, ssize - skew, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep-skew) >= 0 || upxfn(src, ssize, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep) >= 0) |
|
1762 |
+ upx_success = 1; |
|
2079 | 1763 |
} |
2080 | 1764 |
|
2081 |
- if(upxfn) { |
|
2082 |
- int skew = cli_readint32(buff + 2) - EC32(optional_hdr32.ImageBase) - exe_sections[i + 1].rva; |
|
2083 |
- |
|
2084 |
- if(buff[1] != '\xbe' || skew <= 0 || skew > 0xfff) { /* FIXME: legit skews?? */ |
|
2085 |
- skew = 0; |
|
2086 |
- if(upxfn(src, ssize, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep) >= 0) |
|
2087 |
- upx_success = 1; |
|
2088 |
- |
|
2089 |
- } else { |
|
2090 |
- cli_dbgmsg("UPX: UPX1 seems skewed by %d bytes\n", skew); |
|
2091 |
- if(upxfn(src + skew, ssize - skew, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep-skew) >= 0 || upxfn(src, ssize, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep) >= 0) |
|
2092 |
- upx_success = 1; |
|
2093 |
- } |
|
2094 |
- |
|
2095 |
- if(upx_success) |
|
2096 |
- cli_dbgmsg("UPX: Successfully decompressed\n"); |
|
2097 |
- else |
|
2098 |
- cli_dbgmsg("UPX: Preferred decompressor failed\n"); |
|
2099 |
- } |
|
1765 |
+ if(upx_success) |
|
1766 |
+ cli_dbgmsg("UPX: Successfully decompressed\n"); |
|
1767 |
+ else |
|
1768 |
+ cli_dbgmsg("UPX: Preferred decompressor failed\n"); |
|
1769 |
+ } |
|
2100 | 1770 |
|
2101 |
- if(!upx_success && upxfn != upx_inflate2b) { |
|
2102 |
- if(upx_inflate2b(src, ssize, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep) == -1 && upx_inflate2b(src + 0x15, ssize - 0x15, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep - 0x15) == -1) { |
|
1771 |
+ if(!upx_success && upxfn != upx_inflate2b) { |
|
1772 |
+ if(upx_inflate2b(src, ssize, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep) == -1 && upx_inflate2b(src + 0x15, ssize - 0x15, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep - 0x15) == -1) { |
|
2103 | 1773 |
|
2104 |
- cli_dbgmsg("UPX: NRV2B decompressor failed\n"); |
|
2105 |
- } else { |
|
2106 |
- upx_success = 1; |
|
2107 |
- cli_dbgmsg("UPX: Successfully decompressed with NRV2B\n"); |
|
2108 |
- } |
|
1774 |
+ cli_dbgmsg("UPX: NRV2B decompressor failed\n"); |
|
1775 |
+ } else { |
|
1776 |
+ upx_success = 1; |
|
1777 |
+ cli_dbgmsg("UPX: Successfully decompressed with NRV2B\n"); |
|
2109 | 1778 |
} |
1779 |
+ } |
|
2110 | 1780 |
|
2111 |
- if(!upx_success && upxfn != upx_inflate2d) { |
|
2112 |
- if(upx_inflate2d(src, ssize, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep) == -1 && upx_inflate2d(src + 0x15, ssize - 0x15, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep - 0x15) == -1) { |
|
1781 |
+ if(!upx_success && upxfn != upx_inflate2d) { |
|
1782 |
+ if(upx_inflate2d(src, ssize, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep) == -1 && upx_inflate2d(src + 0x15, ssize - 0x15, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep - 0x15) == -1) { |
|
2113 | 1783 |
|
2114 |
- cli_dbgmsg("UPX: NRV2D decompressor failed\n"); |
|
2115 |
- } else { |
|
2116 |
- upx_success = 1; |
|
2117 |
- cli_dbgmsg("UPX: Successfully decompressed with NRV2D\n"); |
|
2118 |
- } |
|
2119 |
- } |
|
2120 |
- |
|
2121 |
- if(!upx_success && upxfn != upx_inflate2e) { |
|
2122 |
- if(upx_inflate2e(src, ssize, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep) == -1 && upx_inflate2e(src + 0x15, ssize - 0x15, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep - 0x15) == -1) { |
|
2123 |
- cli_dbgmsg("UPX: NRV2E decompressor failed\n"); |
|
2124 |
- } else { |
|
2125 |
- upx_success = 1; |
|
2126 |
- cli_dbgmsg("UPX: Successfully decompressed with NRV2E\n"); |
|
2127 |
- } |
|
1784 |
+ cli_dbgmsg("UPX: NRV2D decompressor failed\n"); |
|
1785 |
+ } else { |
|
1786 |
+ upx_success = 1; |
|
1787 |
+ cli_dbgmsg("UPX: Successfully decompressed with NRV2D\n"); |
|
2128 | 1788 |
} |
1789 |
+ } |
|
2129 | 1790 |
|
2130 |
- if(!upx_success) { |
|
2131 |
- cli_dbgmsg("UPX: All decompressors failed\n"); |
|
2132 |
- free(src); |
|
2133 |
- free(dest); |
|
1791 |
+ if(!upx_success && upxfn != upx_inflate2e) { |
|
1792 |
+ if(upx_inflate2e(src, ssize, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep) == -1 && upx_inflate2e(src + 0x15, ssize - 0x15, dest, &dsize, exe_sections[i].rva, exe_sections[i + 1].rva, vep - 0x15) == -1) { |
|
1793 |
+ cli_dbgmsg("UPX: NRV2E decompressor failed\n"); |
|
1794 |
+ } else { |
|
1795 |
+ upx_success = 1; |
|
1796 |
+ cli_dbgmsg("UPX: Successfully decompressed with NRV2E\n"); |
|
2134 | 1797 |
} |
2135 | 1798 |
} |
2136 | 1799 |
|
2137 |
- if(upx_success) { |
|
1800 |
+ if(!upx_success) { |
|
1801 |
+ cli_dbgmsg("UPX: All decompressors failed\n"); |
|
2138 | 1802 |
free(src); |
2139 |
- free(exe_sections); |
|
2140 |
- |
|
2141 |
- if(!(tempfile = cli_gentemp(NULL))) { |
|
2142 |
- free(dest); |
|
2143 |
- return CL_EMEM; |
|
2144 |
- } |
|
1803 |
+ free(dest); |
|
1804 |
+ } |
|
1805 |
+ } |
|
2145 | 1806 |
|
2146 |
- if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) { |
|
2147 |
- cli_dbgmsg("UPX/FSG: Can't create file %s\n", tempfile); |
|
2148 |
- free(tempfile); |
|
2149 |
- free(dest); |
|
2150 |
- return CL_EIO; |
|
2151 |
- } |
|
1807 |
+ if(upx_success) { |
|
1808 |
+ free(src); |
|
1809 |
+ free(exe_sections); |
|
2152 | 1810 |
|
2153 |
- if((unsigned int) write(ndesc, dest, dsize) != dsize) { |
|
2154 |
- cli_dbgmsg("UPX/FSG: Can't write %d bytes\n", dsize); |
|
2155 |
- free(tempfile); |
|
2156 |
- free(dest); |
|
2157 |
- close(ndesc); |
|
2158 |
- return CL_EIO; |
|
2159 |
- } |
|
1811 |
+ CLI_UNPTEMP("UPX/FSG",dest); |
|
2160 | 1812 |
|
1813 |
+ if((unsigned int) write(ndesc, dest, dsize) != dsize) { |
|
1814 |
+ cli_dbgmsg("UPX/FSG: Can't write %d bytes\n", dsize); |
|
1815 |
+ free(tempfile); |
|
2161 | 1816 |
free(dest); |
2162 |
- fsync(ndesc); |
|
2163 |
- lseek(ndesc, 0, SEEK_SET); |
|
1817 |
+ close(ndesc); |
|
1818 |
+ return CL_EIO; |
|
1819 |
+ } |
|
2164 | 1820 |
|
2165 |
- if(cli_leavetemps_flag) |
|
2166 |
- cli_dbgmsg("UPX/FSG: Decompressed data saved in %s\n", tempfile); |
|
1821 |
+ free(dest); |
|
1822 |
+ fsync(ndesc); |
|
1823 |
+ lseek(ndesc, 0, SEEK_SET); |
|
2167 | 1824 |
|
2168 |
- cli_dbgmsg("***** Scanning decompressed file *****\n"); |
|
2169 |
- if((ret = cli_magic_scandesc(ndesc, ctx)) == CL_VIRUS) { |
|
2170 |
- close(ndesc); |
|
2171 |
- if(!cli_leavetemps_flag) |
|
2172 |
- unlink(tempfile); |
|
2173 |
- free(tempfile); |
|
2174 |
- return CL_VIRUS; |
|
2175 |
- } |
|
1825 |
+ if(cli_leavetemps_flag) |
|
1826 |
+ cli_dbgmsg("UPX/FSG: Decompressed data saved in %s\n", tempfile); |
|
2176 | 1827 |
|
1828 |
+ cli_dbgmsg("***** Scanning decompressed file *****\n"); |
|
1829 |
+ if((ret = cli_magic_scandesc(ndesc, ctx)) == CL_VIRUS) { |
|
2177 | 1830 |
close(ndesc); |
2178 |
- if(!cli_leavetemps_flag) |
|
2179 |
- unlink(tempfile); |
|
1831 |
+ CLI_TMPUNLK(); |
|
2180 | 1832 |
free(tempfile); |
2181 |
- return ret; |
|
1833 |
+ return CL_VIRUS; |
|
2182 | 1834 |
} |
1835 |
+ |
|
1836 |
+ close(ndesc); |
|
1837 |
+ CLI_TMPUNLK(); |
|
1838 |
+ free(tempfile); |
|
1839 |
+ return ret; |
|
2183 | 1840 |
} |
2184 | 1841 |
|
2185 |
- /* Petite */ |
|
2186 | 1842 |
|
2187 |
- found = 2; |
|
1843 |
+ /* Petite */ |
|
2188 | 1844 |
|
2189 |
- lseek(desc, ep, SEEK_SET); |
|
2190 |
- memset(buff, 0, sizeof(buff)); |
|
2191 |
- if(cli_readn(desc, buff, 200) == -1) { |
|
2192 |
- cli_dbgmsg("cli_readn() failed\n"); |
|
1845 |
+ if(epsize<200) { |
|
2193 | 1846 |
free(exe_sections); |
2194 |
- return CL_EIO; |
|
1847 |
+ return CL_CLEAN; |
|
2195 | 1848 |
} |
2196 | 1849 |
|
2197 |
- if(buff[0] != '\xb8' || (uint32_t) cli_readint32(buff + 1) != exe_sections[nsections - 1].rva + EC32(optional_hdr32.ImageBase)) { |
|
2198 |
- if(nsections < 2 || buff[0] != '\xb8' || (uint32_t) cli_readint32(buff + 1) != exe_sections[nsections - 2].rva + EC32(optional_hdr32.ImageBase)) |
|
1850 |
+ found = 2; |
|
1851 |
+ |
|
1852 |
+ if(epbuff[0] != '\xb8' || (uint32_t) cli_readint32(epbuff + 1) != exe_sections[nsections - 1].rva + EC32(optional_hdr32.ImageBase)) { |
|
1853 |
+ if(nsections < 2 || epbuff[0] != '\xb8' || (uint32_t) cli_readint32(epbuff + 1) != exe_sections[nsections - 2].rva + EC32(optional_hdr32.ImageBase)) |
|
2199 | 1854 |
found = 0; |
2200 | 1855 |
else |
2201 | 1856 |
found = 1; |
2202 | 1857 |
} |
2203 | 1858 |
|
2204 |
- if((DCONF & PE_CONF_PETITE) && found) { |
|
1859 |
+ if(found && (DCONF & PE_CONF_PETITE)) { |
|
2205 | 1860 |
cli_dbgmsg("Petite: v2.%d compression detected\n", found); |
2206 | 1861 |
|
2207 |
- if(cli_readint32(buff + 0x80) == 0x163c988d) { |
|
1862 |
+ if(cli_readint32(epbuff + 0x80) == 0x163c988d) { |
|
2208 | 1863 |
cli_dbgmsg("Petite: level zero compression is not supported yet\n"); |
2209 | 1864 |
} else { |
2210 | 1865 |
dsize = max - min; |
2211 | 1866 |
|
2212 |
- if(ctx->limits && ctx->limits->maxfilesize && dsize > ctx->limits->maxfilesize) { |
|
2213 |
- cli_dbgmsg("Petite: Size exceeded (dsize: %u, max: %lu)\n", dsize, ctx->limits->maxfilesize); |
|
2214 |
- free(exe_sections); |
|
2215 |
- if(BLOCKMAX) { |
|
2216 |
- *ctx->virname = "PE.Petite.ExceededFileSize"; |
|
2217 |
- return CL_VIRUS; |
|
2218 |
- } else { |
|
2219 |
- return CL_CLEAN; |
|
2220 |
- } |
|
2221 |
- } |
|
1867 |
+ CLI_UNPSIZELIMITS("Petite", dsize); |
|
2222 | 1868 |
|
2223 | 1869 |
if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) { |
2224 | 1870 |
cli_dbgmsg("Petite: Can't allocate %d bytes\n", dsize); |
... | ... |
@@ -2228,9 +1773,7 @@ skip_upack_and_go_to_next_unpacker: |
2228 | 2228 |
|
2229 | 2229 |
for(i = 0 ; i < nsections; i++) { |
2230 | 2230 |
if(exe_sections[i].raw) { |
2231 |
- uint32_t offset = exe_sections[i].raw; |
|
2232 |
- |
|
2233 |
- if(lseek(desc, offset, SEEK_SET) == -1 || (unsigned int) cli_readn(desc, dest + exe_sections[i].rva - min, exe_sections[i].ursz) != exe_sections[i].ursz) { |
|
2231 |
+ if(!cli_seeksect(desc, &exe_sections[i]) || (unsigned int) cli_readn(desc, dest + exe_sections[i].rva - min, exe_sections[i].ursz) != exe_sections[i].ursz) { |
|
2234 | 2232 |
free(exe_sections); |
2235 | 2233 |
free(dest); |
2236 | 2234 |
return CL_EIO; |
... | ... |
@@ -2238,49 +1781,8 @@ skip_upack_and_go_to_next_unpacker: |
2238 | 2238 |
} |
2239 | 2239 |
} |
2240 | 2240 |
|
2241 |
- if(!(tempfile = cli_gentemp(NULL))) { |
|
2242 |
- free(dest); |
|
2243 |
- free(exe_sections); |
|
2244 |
- return CL_EMEM; |
|
2245 |
- } |
|
2246 |
- |
|
2247 |
- if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) { |
|
2248 |
- cli_dbgmsg("Petite: Can't create file %s\n", tempfile); |
|
2249 |
- free(tempfile); |
|
2250 |
- free(exe_sections); |
|
2251 |
- free(dest); |
|
2252 |
- return CL_EIO; |
|
2253 |
- } |
|
2254 |
- |
|
2255 |
- /* aCaB: Fixed to allow petite v2.1 unpacking (last section is a ghost) */ |
|
2256 |
- if (!petite_inflate2x_1to9(dest, min, max - min, exe_sections, |
|
2257 |
- nsections - (found == 1 ? 1 : 0), EC32(optional_hdr32.ImageBase), |
|
2258 |
- vep, ndesc, found, EC32(optional_hdr32.DataDirectory[2].VirtualAddress), |
|
2259 |
- EC32(optional_hdr32.DataDirectory[2].Size))) { |
|
2260 |
- cli_dbgmsg("Petite: Unpacked and rebuilt executable saved in %s\n", tempfile); |
|
2261 |
- cli_dbgmsg("***** Scanning rebuilt PE file *****\n"); |
|
2262 |
- free(dest); |
|
2263 |
- fsync(ndesc); |
|
2264 |
- lseek(ndesc, 0, SEEK_SET); |
|
2265 |
- if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) { |
|
2266 |
- free(exe_sections); |
|
2267 |
- close(ndesc); |
|
2268 |
- if(!cli_leavetemps_flag) { |
|
2269 |
- unlink(tempfile); |
|
2270 |
- } |
|
2271 |
- free(tempfile); |
|
2272 |
- return CL_VIRUS; |
|
2273 |
- } |
|
2274 |
- |
|
2275 |
- } else { |
|
2276 |
- cli_dbgmsg("Petite: Unpacking failed\n"); |
|
2277 |
- free(dest); |
|
2278 |
- } |
|
2279 |
- close(ndesc); |
|
2280 |
- if(!cli_leavetemps_flag) { |
|
2281 |
- unlink(tempfile); |
|
2282 |
- } |
|
2283 |
- free(tempfile); |
|
2241 |
+ CLI_UNPTEMP("Petite",dest,exe_sections); |
|
2242 |
+ CLI_UNPRESULTS("Petite",(petite_inflate2x_1to9(dest, min, max - min, exe_sections, nsections - (found == 1 ? 1 : 0), EC32(optional_hdr32.ImageBase),vep, ndesc, found, EC32(optional_hdr32.DataDirectory[2].VirtualAddress),EC32(optional_hdr32.DataDirectory[2].Size))),0,dest); |
|
2284 | 2243 |
} |
2285 | 2244 |
} |
2286 | 2245 |
|
... | ... |
@@ -2289,20 +1791,11 @@ skip_upack_and_go_to_next_unpacker: |
2289 | 2289 |
if((DCONF & PE_CONF_PESPIN) && nsections > 1 && |
2290 | 2290 |
vep >= exe_sections[nsections - 1].rva && |
2291 | 2291 |
vep < exe_sections[nsections - 1].rva + exe_sections[nsections - 1].rsz - 0x3217 - 4 && |
2292 |
- memcmp(buff+4, "\xe8\x00\x00\x00\x00\x8b\x1c\x24\x83\xc3", 10) == 0) { |
|
2292 |
+ memcmp(epbuff+4, "\xe8\x00\x00\x00\x00\x8b\x1c\x24\x83\xc3", 10) == 0) { |
|
2293 | 2293 |
|
2294 |
- char *spinned; |
|
2294 |
+ char *spinned; |
|
2295 | 2295 |
|
2296 |
- if(ctx->limits && ctx->limits->maxfilesize && fsize > ctx->limits->maxfilesize) { |
|
2297 |
- cli_dbgmsg("PEspin: Size exceeded (fsize: %u, max: %lu)\n", fsize, ctx->limits->maxfilesize); |
|
2298 |
- free(exe_sections); |
|
2299 |
- if(BLOCKMAX) { |
|
2300 |
- *ctx->virname = "PE.Pespin.ExceededFileSize"; |
|
2301 |
- return CL_VIRUS; |
|
2302 |
- } else { |
|
2303 |
- return CL_CLEAN; |
|
2304 |
- } |
|
2305 |
- } |
|
2296 |
+ CLI_UNPSIZELIMITS("PEspin", fsize); |
|
2306 | 2297 |
|
2307 | 2298 |
if((spinned = (char *) cli_malloc(fsize)) == NULL) { |
2308 | 2299 |
free(exe_sections); |
... | ... |
@@ -2317,61 +1810,8 @@ skip_upack_and_go_to_next_unpacker: |
2317 | 2317 |
return CL_EIO; |
2318 | 2318 |
} |
2319 | 2319 |
|
2320 |
- if(!(tempfile = cli_gentemp(NULL))) { |
|
2321 |
- free(spinned); |
|
2322 |
- free(exe_sections); |
|
2323 |
- return CL_EMEM; |
|
2324 |
- } |
|
2325 |
- |
|
2326 |
- if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) { |
|
2327 |
- cli_dbgmsg("PESpin: Can't create file %s\n", tempfile); |
|
2328 |
- free(tempfile); |
|
2329 |
- free(spinned); |
|
2330 |
- free(exe_sections); |
|
2331 |
- return CL_EIO; |
|
2332 |
- } |
|
2333 |
- |
|
2334 |
- switch(unspin(spinned, fsize, exe_sections, nsections - 1, vep, ndesc, ctx)) { |
|
2335 |
- case 0: |
|
2336 |
- free(spinned); |
|
2337 |
- if(cli_leavetemps_flag) |
|
2338 |
- cli_dbgmsg("PESpin: Unpacked and rebuilt executable saved in %s\n", tempfile); |
|
2339 |
- else |
|
2340 |
- cli_dbgmsg("PESpin: Unpacked and rebuilt executable\n"); |
|
2341 |
- fsync(ndesc); |
|
2342 |
- lseek(ndesc, 0, SEEK_SET); |
|
2343 |
- if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) { |
|
2344 |
- close(ndesc); |
|
2345 |
- if(!cli_leavetemps_flag) |
|
2346 |
- unlink(tempfile); |
|
2347 |
- free(tempfile); |
|
2348 |
- free(exe_sections); |
|
2349 |
- return CL_VIRUS; |
|
2350 |
- } |
|
2351 |
- close(ndesc); |
|
2352 |
- if(!cli_leavetemps_flag) |
|
2353 |
- unlink(tempfile); |
|
2354 |
- break; |
|
2355 |
- case 1: |
|
2356 |
- free(spinned); |
|
2357 |
- close(ndesc); |
|
2358 |
- unlink(tempfile); |
|
2359 |
- cli_dbgmsg("PESpin: Rebuilding failed\n"); |
|
2360 |
- break; |
|
2361 |
- case 2: |
|
2362 |
- free(spinned); |
|
2363 |
- close(ndesc); |
|
2364 |
- unlink(tempfile); |
|
2365 |
- cli_dbgmsg("PESpin: Size exceeded\n"); |
|
2366 |
- if(BLOCKMAX) { |
|
2367 |
- free(tempfile); |
|
2368 |
- free(exe_sections); |
|
2369 |
- *ctx->virname = "PE.Pespin.ExceededFileSize"; |
|
2370 |
- return CL_VIRUS; |
|
2371 |
- } |
|
2372 |
- } |
|
2373 |
- free(tempfile); |
|
2374 |
- |
|
2320 |
+ CLI_UNPTEMP("PESpin",spinned,exe_sections); |
|
2321 |
+ CLI_UNPRESULTS_("PEspin",SPINCASE(),(unspin(spinned, fsize, exe_sections, nsections - 1, vep, ndesc, ctx)),0,spinned); |
|
2375 | 2322 |
} |
2376 | 2323 |
|
2377 | 2324 |
|
... | ... |
@@ -2379,70 +1819,25 @@ skip_upack_and_go_to_next_unpacker: |
2379 | 2379 |
|
2380 | 2380 |
if((DCONF & PE_CONF_YC) && nsections > 1 && |
2381 | 2381 |
EC32(optional_hdr32.AddressOfEntryPoint) == exe_sections[nsections - 1].rva + 0x60 && |
2382 |
- memcmp(buff, "\x55\x8B\xEC\x53\x56\x57\x60\xE8\x00\x00\x00\x00\x5D\x81\xED\x6C\x28\x40\x00\xB9\x5D\x34\x40\x00\x81\xE9\xC6\x28\x40\x00\x8B\xD5\x81\xC2\xC6\x28\x40\x00\x8D\x3A\x8B\xF7\x33\xC0\xEB\x04\x90\xEB\x01\xC2\xAC", 51) == 0) { |
|
2382 |
+ memcmp(epbuff, "\x55\x8B\xEC\x53\x56\x57\x60\xE8\x00\x00\x00\x00\x5D\x81\xED\x6C\x28\x40\x00\xB9\x5D\x34\x40\x00\x81\xE9\xC6\x28\x40\x00\x8B\xD5\x81\xC2\xC6\x28\x40\x00\x8D\x3A\x8B\xF7\x33\xC0\xEB\x04\x90\xEB\x01\xC2\xAC", 51) == 0 && fsize >= exe_sections[nsections - 1].raw + 0xC6 + 0xb97) { |
|
2383 | 2383 |
|
2384 |
- char *spinned; |
|
2384 |
+ char *spinned; |
|
2385 | 2385 |
|
2386 |
- if ( fsize >= exe_sections[nsections - 1].raw + 0xC6 + 0xb97 ) { /* size check on yC sect */ |
|
2387 |
- if((spinned = (char *) cli_malloc(fsize)) == NULL) { |
|
2386 |
+ if((spinned = (char *) cli_malloc(fsize)) == NULL) { |
|
2388 | 2387 |
free(exe_sections); |
2389 | 2388 |
return CL_EMEM; |
2390 |
- } |
|
2389 |
+ } |
|
2391 | 2390 |
|
2392 |
- lseek(desc, 0, SEEK_SET); |
|
2393 |
- if((size_t) cli_readn(desc, spinned, fsize) != fsize) { |
|
2391 |
+ lseek(desc, 0, SEEK_SET); |
|
2392 |
+ if((size_t) cli_readn(desc, spinned, fsize) != fsize) { |
|
2394 | 2393 |
cli_dbgmsg("yC: Can't read %d bytes\n", fsize); |
2395 | 2394 |
free(spinned); |
2396 | 2395 |
free(exe_sections); |
2397 | 2396 |
return CL_EIO; |
2398 |
- } |
|
2399 |
- |
|
2400 |
- if(!(tempfile = cli_gentemp(NULL))) { |
|
2401 |
- free(spinned); |
|
2402 |
- free(exe_sections); |
|
2403 |
- return CL_EMEM; |
|
2404 |
- } |
|
2405 |
- |
|
2406 |
- if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) { |
|
2407 |
- cli_dbgmsg("yC: Can't create file %s\n", tempfile); |
|
2408 |
- free(tempfile); |
|
2409 |
- free(spinned); |
|
2410 |
- free(exe_sections); |
|
2411 |
- return CL_EIO; |
|
2412 |
- } |
|
2413 |
- |
|
2414 |
- if(!yc_decrypt(spinned, fsize, exe_sections, nsections-1, e_lfanew, ndesc)) { |
|
2415 |
- free(spinned); |
|
2416 |
- cli_dbgmsg("yC: Unpacked and rebuilt executable saved in %s\n", tempfile); |
|
2417 |
- fsync(ndesc); |
|
2418 |
- lseek(ndesc, 0, SEEK_SET); |
|
2419 |
- |
|
2420 |
- if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) { |
|
2421 |
- free(exe_sections); |
|
2422 |
- close(ndesc); |
|
2423 |
- if(!cli_leavetemps_flag) { |
|
2424 |
- unlink(tempfile); |
|
2425 |
- free(tempfile); |
|
2426 |
- } else { |
|
2427 |
- free(tempfile); |
|
2428 |
- } |
|
2429 |
- return CL_VIRUS; |
|
2430 |
- } |
|
2431 |
- |
|
2432 |
- } else { |
|
2433 |
- free(spinned); |
|
2434 |
- cli_dbgmsg("yC: Rebuilding failed\n"); |
|
2435 |
- } |
|
2436 |
- |
|
2437 |
- close(ndesc); |
|
2438 |
- if(!cli_leavetemps_flag) { |
|
2439 |
- unlink(tempfile); |
|
2440 |
- free(tempfile); |
|
2441 |
- } else { |
|
2442 |
- free(tempfile); |
|
2443 |
- } |
|
2444 |
- |
|
2445 | 2397 |
} |
2398 |
+ |
|
2399 |
+ CLI_UNPTEMP("yC",spinned,exe_sections); |
|
2400 |
+ CLI_UNPRESULTS("yC",(yc_decrypt(spinned, fsize, exe_sections, nsections-1, e_lfanew, ndesc)),0,spinned); |
|
2446 | 2401 |
} |
2447 | 2402 |
|
2448 | 2403 |
|
... | ... |
@@ -2452,154 +1847,121 @@ skip_upack_and_go_to_next_unpacker: |
2452 | 2452 |
exe_sections[nsections-1].raw>0x2b1 && |
2453 | 2453 |
vep == exe_sections[nsections - 1].rva && |
2454 | 2454 |
exe_sections[nsections - 1].rva + exe_sections[nsections - 1].rsz == max && |
2455 |
- memcmp(buff, "\x53\x55\x8b\xe8\x33\xdb\xeb", 7) == 0 && |
|
2456 |
- memcmp(buff+0x68, "\xe8\x00\x00\x00\x00\x58\x2d\x6d\x00\x00\x00\x50\x60\x33\xc9\x50\x58\x50\x50", 19) == 0) { |
|
2457 |
- uint32_t headsize=exe_sections[nsections - 1].raw; |
|
2458 |
- char *dest, *wwp; |
|
2455 |
+ memcmp(epbuff, "\x53\x55\x8b\xe8\x33\xdb\xeb", 7) == 0 && |
|
2456 |
+ memcmp(epbuff+0x68, "\xe8\x00\x00\x00\x00\x58\x2d\x6d\x00\x00\x00\x50\x60\x33\xc9\x50\x58\x50\x50", 19) == 0) { |
|
2457 |
+ uint32_t headsize=exe_sections[nsections - 1].raw; |
|
2458 |
+ char *dest, *wwp; |
|
2459 | 2459 |
|
2460 |
- for(i = 0 ; i < (unsigned int)nsections-1; i++) |
|
2461 |
- if (exe_sections[i].raw<headsize) headsize=exe_sections[i].raw; |
|
2460 |
+ for(i = 0 ; i < (unsigned int)nsections-1; i++) |
|
2461 |
+ if (exe_sections[i].raw<headsize) headsize=exe_sections[i].raw; |
|
2462 | 2462 |
|
2463 |
- dsize = max-min+headsize-exe_sections[nsections - 1].rsz; |
|
2463 |
+ dsize = max-min+headsize-exe_sections[nsections - 1].rsz; |
|
2464 | 2464 |
|
2465 |
- if(ctx->limits && ctx->limits->maxfilesize && dsize > ctx->limits->maxfilesize) { |
|
2466 |
- cli_dbgmsg("WWPack: Size exceeded (dsize: %u, max: %lu)\n", dsize, ctx->limits->maxfilesize); |
|
2467 |
- free(exe_sections); |
|
2468 |
- if(BLOCKMAX) { |
|
2469 |
- *ctx->virname = "PE.WWPack.ExceededFileSize"; |
|
2470 |
- return CL_VIRUS; |
|
2471 |
- } else { |
|
2472 |
- return CL_CLEAN; |
|
2473 |
- } |
|
2474 |
- } |
|
2465 |
+ CLI_UNPSIZELIMITS("WWPack", dsize); |
|
2475 | 2466 |
|
2476 |
- if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) { |
|
2477 |
- cli_dbgmsg("WWPack: Can't allocate %d bytes\n", dsize); |
|
2478 |
- free(exe_sections); |
|
2479 |
- return CL_EMEM; |
|
2480 |
- } |
|
2481 |
- |
|
2482 |
- lseek(desc, 0, SEEK_SET); |
|
2483 |
- if((size_t) cli_readn(desc, dest, headsize) != headsize) { |
|
2484 |
- cli_dbgmsg("WWPack: Can't read %d bytes from headers\n", headsize); |
|
2485 |
- free(dest); |
|
2486 |
- free(exe_sections); |
|
2487 |
- return CL_EIO; |
|
2488 |
- } |
|
2467 |
+ if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) { |
|
2468 |
+ cli_dbgmsg("WWPack: Can't allocate %d bytes\n", dsize); |
|
2469 |
+ free(exe_sections); |
|
2470 |
+ return CL_EMEM; |
|
2471 |
+ } |
|
2489 | 2472 |
|
2490 |
- for(i = 0 ; i < (unsigned int)nsections-1; i++) { |
|
2491 |
- if(exe_sections[i].rsz) { |
|
2492 |
- uint32_t offset = exe_sections[i].raw; |
|
2493 |
- |
|
2494 |
- if(lseek(desc, offset, SEEK_SET) == -1 || (unsigned int) cli_readn(desc, dest + headsize + exe_sections[i].rva - min, exe_sections[i].rsz) != exe_sections[i].rsz) { |
|
2473 |
+ lseek(desc, 0, SEEK_SET); |
|
2474 |
+ if((size_t) cli_readn(desc, dest, headsize) != headsize) { |
|
2475 |
+ cli_dbgmsg("WWPack: Can't read %d bytes from headers\n", headsize); |
|
2495 | 2476 |
free(dest); |
2496 | 2477 |
free(exe_sections); |
2497 | 2478 |
return CL_EIO; |
2498 |
- } |
|
2499 | 2479 |
} |
2500 |
- } |
|
2501 | 2480 |
|
2502 |
- if((wwp = (char *) cli_calloc(exe_sections[nsections - 1].rsz, sizeof(char))) == NULL) { |
|
2503 |
- cli_dbgmsg("WWPack: Can't allocate %d bytes\n", exe_sections[nsections - 1].rsz); |
|
2504 |
- free(dest); |
|
2505 |
- free(exe_sections); |
|
2506 |
- return CL_EMEM; |
|
2507 |
- } |
|
2481 |
+ for(i = 0 ; i < (unsigned int)nsections-1; i++) { |
|
2482 |
+ if(exe_sections[i].rsz) { |
|
2483 |
+ if(!cli_seeksect(desc, &exe_sections[i]) || (unsigned int) cli_readn(desc, dest + headsize + exe_sections[i].rva - min, exe_sections[i].rsz) != exe_sections[i].rsz) { |
|
2484 |
+ free(dest); |
|
2485 |
+ free(exe_sections); |
|
2486 |
+ return CL_EIO; |
|
2487 |
+ } |
|
2488 |
+ } |
|
2489 |
+ } |
|
2508 | 2490 |
|
2509 |
- lseek(desc, exe_sections[nsections - 1].raw, SEEK_SET); |
|
2510 |
- if((size_t) cli_readn(desc, wwp, exe_sections[nsections - 1].rsz) != exe_sections[nsections - 1].rsz) { |
|
2511 |
- cli_dbgmsg("WWPack: Can't read %d bytes from wwpack sect\n", exe_sections[nsections - 1].rsz); |
|
2512 |
- free(dest); |
|
2513 |
- free(wwp); |
|
2514 |
- free(exe_sections); |
|
2515 |
- return CL_EIO; |
|
2516 |
- } |
|
2491 |
+ if((wwp = (char *) cli_calloc(exe_sections[nsections - 1].rsz, sizeof(char))) == NULL) { |
|
2492 |
+ cli_dbgmsg("WWPack: Can't allocate %d bytes\n", exe_sections[nsections - 1].rsz); |
|
2493 |
+ free(dest); |
|
2494 |
+ free(exe_sections); |
|
2495 |
+ return CL_EMEM; |
|
2496 |
+ } |
|
2517 | 2497 |
|
2518 |
- if (!wwunpack(dest, dsize, headsize, min, exe_sections[nsections-1].rva, e_lfanew, wwp, exe_sections[nsections - 1].rsz, nsections-1)) { |
|
2498 |
+ if(!cli_seeksect(desc, &exe_sections[nsections - 1]) || (size_t) cli_readn(desc, wwp, exe_sections[nsections - 1].rsz) != exe_sections[nsections - 1].rsz) { |
|
2499 |
+ cli_dbgmsg("WWPack: Can't read %d bytes from wwpack sect\n", exe_sections[nsections - 1].rsz); |
|
2500 |
+ free(dest); |
|
2501 |
+ free(wwp); |
|
2502 |
+ free(exe_sections); |
|
2503 |
+ return CL_EIO; |
|
2504 |
+ } |
|
2505 |
+ |
|
2506 |
+ if (!wwunpack(dest, dsize, headsize, min, exe_sections[nsections-1].rva, e_lfanew, wwp, exe_sections[nsections - 1].rsz, nsections-1)) { |
|
2519 | 2507 |
|
2520 |
- free(wwp); |
|
2508 |
+ free(wwp); |
|
2521 | 2509 |
|
2522 |
- if(!(tempfile = cli_gentemp(NULL))) { |
|
2523 |
- free(dest); |
|
2524 |
- free(exe_sections); |
|
2525 |
- return CL_EMEM; |
|
2526 |
- } |
|
2510 |
+ CLI_UNPTEMP("WWPack",dest,exe_sections); |
|
2527 | 2511 |
|
2528 |
- if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) { |
|
2529 |
- cli_dbgmsg("WWPack: Can't create file %s\n", tempfile); |
|
2530 |
- free(tempfile); |
|
2531 |
- free(dest); |
|
2532 |
- free(exe_sections); |
|
2533 |
- return CL_EIO; |
|
2534 |
- } |
|
2512 |
+ if((unsigned int) write(ndesc, dest, dsize) != dsize) { |
|
2513 |
+ cli_dbgmsg("WWPack: Can't write %d bytes\n", dsize); |
|
2514 |
+ close(ndesc); |
|
2515 |
+ free(tempfile); |
|
2516 |
+ free(dest); |
|
2517 |
+ free(exe_sections); |
|
2518 |
+ return CL_EIO; |
|
2519 |
+ } |
|
2535 | 2520 |
|
2536 |
- if((unsigned int) write(ndesc, dest, dsize) != dsize) { |
|
2537 |
- cli_dbgmsg("WWPack: Can't write %d bytes\n", dsize); |
|
2538 |
- close(ndesc); |
|
2539 |
- free(tempfile); |
|
2540 |
- free(dest); |
|
2541 |
- free(exe_sections); |
|
2542 |
- return CL_EIO; |
|
2543 |
- } |
|
2521 |
+ free(dest); |
|
2522 |
+ if (cli_leavetemps_flag) |
|
2523 |
+ cli_dbgmsg("WWPack: Unpacked and rebuilt executable saved in %s\n", tempfile); |
|
2524 |
+ else |
|
2525 |
+ cli_dbgmsg("WWPack: Unpacked and rebuilt executable\n"); |
|
2544 | 2526 |
|
2545 |
- free(dest); |
|
2546 |
- if (cli_leavetemps_flag) |
|
2547 |
- cli_dbgmsg("WWPack: Unpacked and rebuilt executable saved in %s\n", tempfile); |
|
2548 |
- else |
|
2549 |
- cli_dbgmsg("WWPack: Unpacked and rebuilt executable\n"); |
|
2527 |
+ fsync(ndesc); |
|
2528 |
+ lseek(ndesc, 0, SEEK_SET); |
|
2550 | 2529 |
|
2551 |
- fsync(ndesc); |
|
2552 |
- lseek(ndesc, 0, SEEK_SET); |
|
2530 |
+ if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) { |
|
2531 |
+ free(exe_sections); |
|
2532 |
+ close(ndesc); |
|
2533 |
+ if(!cli_leavetemps_flag) |
|
2534 |
+ unlink(tempfile); |
|
2535 |
+ free(tempfile); |
|
2536 |
+ return CL_VIRUS; |
|
2537 |
+ } |
|
2553 | 2538 |
|
2554 |
- if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) { |
|
2555 |
- free(exe_sections); |
|
2556 |
- close(ndesc); |
|
2557 |
- if(!cli_leavetemps_flag) |
|
2558 |
- unlink(tempfile); |
|
2559 |
- free(tempfile); |
|
2560 |
- return CL_VIRUS; |
|
2539 |
+ close(ndesc); |
|
2540 |
+ if(!cli_leavetemps_flag) |
|
2541 |
+ unlink(tempfile); |
|
2542 |
+ free(tempfile); |
|
2543 |
+ } else { |
|
2544 |
+ free(wwp); |
|
2545 |
+ free(dest); |
|
2546 |
+ cli_dbgmsg("WWPpack: Decompression failed\n"); |
|
2561 | 2547 |
} |
2562 |
- |
|
2563 |
- close(ndesc); |
|
2564 |
- if(!cli_leavetemps_flag) |
|
2565 |
- unlink(tempfile); |
|
2566 |
- free(tempfile); |
|
2567 |
- } else { |
|
2568 |
- free(wwp); |
|
2569 |
- free(dest); |
|
2570 |
- cli_dbgmsg("WWPpack: Decompression failed\n"); |
|
2571 |
- } |
|
2572 | 2548 |
} |
2573 | 2549 |
|
2550 |
+ |
|
2574 | 2551 |
/* ASPACK support */ |
2575 |
- while((DCONF & PE_CONF_ASPACK) && ep+58+0x70e < fsize && !memcmp(buff,"\x60\xe8\x03\x00\x00\x00\xe9\xeb",8)) { |
|
2576 |
- char nbuff[6]; |
|
2552 |
+ while((DCONF & PE_CONF_ASPACK) && ep+58+0x70e < fsize && !memcmp(epbuff,"\x60\xe8\x03\x00\x00\x00\xe9\xeb",8)) { |
|
2577 | 2553 |
|
2578 |
- if(lseek(desc, ep+0x3b9, SEEK_SET) == -1) break; |
|
2579 |
- if(cli_readn(desc, nbuff, 6)!=6) break; |
|
2580 |
- if(memcmp(nbuff, "\x68\x00\x00\x00\x00\xc3",6)) break; |
|
2554 |
+ if(epsize<0x3bf || memcmp(epbuff+0x3b9, "\x68\x00\x00\x00\x00\xc3",6)) break; |
|
2581 | 2555 |
ssize = 0; |
2582 | 2556 |
for(i=0 ; i< nsections ; i++) |
2583 |
- if(ssize<exe_sections[i].rva+exe_sections[i].vsz) |
|
2584 |
- ssize=exe_sections[i].rva+exe_sections[i].vsz; |
|
2557 |
+ if(ssize<exe_sections[i].rva+exe_sections[i].vsz) |
|
2558 |
+ ssize=exe_sections[i].rva+exe_sections[i].vsz; |
|
2585 | 2559 |
if(!ssize) break; |
2586 |
- if(ctx->limits && ctx->limits->maxfilesize && ssize > ctx->limits->maxfilesize) { |
|
2587 |
- cli_dbgmsg("Pe.Aspack: Size exceeded\n"); |
|
2588 |
- free(exe_sections); |
|
2589 |
- if(BLOCKMAX) { |
|
2590 |
- *ctx->virname = "Pe.Aspack.ExceededFileSize"; |
|
2591 |
- return CL_VIRUS; |
|
2592 |
- } else { |
|
2593 |
- return CL_CLEAN; |
|
2594 |
- } |
|
2595 |
- } |
|
2560 |
+ |
|
2561 |
+ CLI_UNPSIZELIMITS("Aspack", ssize); |
|
2562 |
+ |
|
2596 | 2563 |
if(!(src=(char *)cli_calloc(ssize, sizeof(char)))) { |
2597 | 2564 |
free(exe_sections); |
2598 | 2565 |
return CL_EMEM; |
2599 | 2566 |
} |
2600 | 2567 |
for(i = 0 ; i < (unsigned int)nsections; i++) { |
2601 | 2568 |
if(!exe_sections[i].rsz) continue; |
2602 |
- if(lseek(desc, exe_sections[i].raw, SEEK_SET) == -1) break; |
|
2569 |
+ if(!cli_seeksect(desc, &exe_sections[i])) break; |
|
2603 | 2570 |
if(!CLI_ISCONTAINED(src, ssize, src+exe_sections[i].rva, exe_sections[i].rsz)) break; |
2604 | 2571 |
if(cli_readn(desc, src+exe_sections[i].rva, exe_sections[i].rsz)!=exe_sections[i].rsz) break; |
2605 | 2572 |
} |
... | ... |
@@ -2608,151 +1970,84 @@ skip_upack_and_go_to_next_unpacker: |
2608 | 2608 |
free(src); |
2609 | 2609 |
break; |
2610 | 2610 |
} |
2611 |
- if(!(tempfile = cli_gentemp(NULL))) { |
|
2612 |
- free(exe_sections); |
|
2613 |
- free(src); |
|
2614 |
- return CL_EMEM; |
|
2615 |
- } |
|
2616 |
- if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) { |
|
2617 |
- cli_dbgmsg("Aspack: Can't create file %s\n", tempfile); |
|
2618 |
- free(tempfile); |
|
2619 |
- free(exe_sections); |
|
2620 |
- free(src); |
|
2621 |
- return CL_EIO; |
|
2622 |
- } |
|
2623 |
- if (unaspack212((uint8_t *)src, ssize, exe_sections, nsections, vep-1, EC32(optional_hdr32.ImageBase), ndesc)) { |
|
2624 |
- free(src); |
|
2625 |
- cli_dbgmsg("Aspack: Dumped to %s\n", tempfile); |
|
2626 |
- fsync(ndesc); |
|
2627 |
- lseek(ndesc, 0, SEEK_SET); |
|
2628 |
- if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) { |
|
2629 |
- free(exe_sections); |
|
2630 |
- close(ndesc); |
|
2631 |
- if(!cli_leavetemps_flag) |
|
2632 |
- unlink(tempfile); |
|
2633 |
- free(tempfile); |
|
2634 |
- return CL_VIRUS; |
|
2635 |
- } |
|
2636 |
- } else { |
|
2637 |
- free(src); |
|
2638 |
- } |
|
2639 |
- |
|
2640 |
- close(ndesc); |
|
2641 |
- if(!cli_leavetemps_flag) |
|
2642 |
- unlink(tempfile); |
|
2643 |
- free(tempfile); |
|
2644 | 2611 |
|
2612 |
+ CLI_UNPTEMP("Aspack",src,exe_sections); |
|
2613 |
+ CLI_UNPRESULTS("Aspack",(unaspack212((uint8_t *)src, ssize, exe_sections, nsections, vep-1, EC32(optional_hdr32.ImageBase), ndesc)),1,src); |
|
2645 | 2614 |
break; |
2646 | 2615 |
} |
2647 | 2616 |
|
2648 | 2617 |
/* NsPack */ |
2649 | 2618 |
|
2650 | 2619 |
while (DCONF & PE_CONF_NSPACK) { |
2651 |
- uint32_t eprva = vep; |
|
2652 |
- uint32_t start_of_stuff, ssize, dsize, rep = ep; |
|
2653 |
- unsigned int nowinldr; |
|
2654 |
- char nbuff[24]; |
|
2655 |
- char *src=buff, *dest; |
|
2656 |
- |
|
2657 |
- if (*buff=='\xe9') { /* bitched headers */ |
|
2658 |
- eprva = cli_readint32(buff+1)+vep+5; |
|
2659 |
- if (!(rep = cli_rawaddr(eprva, exe_sections, nsections, &err, fsize, hdr_size)) && err) break; |
|
2660 |
- if (lseek(desc, rep, SEEK_SET)==-1) break; |
|
2661 |
- if (cli_readn(desc, nbuff, 24)!=24) break; |
|
2620 |
+ uint32_t eprva = vep; |
|
2621 |
+ uint32_t start_of_stuff, ssize, dsize, rep = ep; |
|
2622 |
+ unsigned int nowinldr; |
|
2623 |
+ char nbuff[24]; |
|
2624 |
+ char *src=buff, *dest; |
|
2625 |
+ |
|
2626 |
+ if (*epbuff=='\xe9') { /* bitched headers */ |
|
2627 |
+ eprva = cli_readint32(epbuff+1)+vep+5; |
|
2628 |
+ if (!(rep = cli_rawaddr(eprva, exe_sections, nsections, &err, fsize, hdr_size)) && err) break; |
|
2629 |
+ if (lseek(desc, rep, SEEK_SET)==-1) break; |
|
2630 |
+ if (cli_readn(desc, nbuff, 24)!=24) break; |
|
2631 |
+ src = nbuff; |
|
2632 |
+ } |
|
2633 |
+ |
|
2634 |
+ if (memcmp(src, "\x9c\x60\xe8\x00\x00\x00\x00\x5d\xb8\x07\x00\x00\x00", 13)) break; |
|
2635 |
+ |
|
2636 |
+ nowinldr = 0x54-cli_readint32(src+17); |
|
2637 |
+ cli_dbgmsg("NsPack: Found *start_of_stuff @delta-%x\n", nowinldr); |
|
2638 |
+ |
|
2639 |
+ if (lseek(desc, rep-nowinldr, SEEK_SET)==-1) break; |
|
2640 |
+ if (cli_readn(desc, nbuff, 4)!=4) break; |
|
2641 |
+ start_of_stuff=rep+cli_readint32(nbuff); |
|
2642 |
+ if (lseek(desc, start_of_stuff, SEEK_SET)==-1) break; |
|
2643 |
+ if (cli_readn(desc, nbuff, 20)!=20) break; |
|
2662 | 2644 |
src = nbuff; |
2663 |
- } |
|
2664 |
- |
|
2665 |
- if (memcmp(src, "\x9c\x60\xe8\x00\x00\x00\x00\x5d\xb8\x07\x00\x00\x00", 13)) break; |
|
2645 |
+ if (!cli_readint32(nbuff)) { |
|
2646 |
+ start_of_stuff+=4; /* FIXME: more to do */ |
|
2647 |
+ src+=4; |
|
2648 |
+ } |
|
2666 | 2649 |
|
2667 |
- nowinldr = 0x54-cli_readint32(src+17); |
|
2668 |
- cli_dbgmsg("NsPack: Found *start_of_stuff @delta-%x\n", nowinldr); |
|
2650 |
+ ssize = cli_readint32(src+5)|0xff; |
|
2651 |
+ dsize = cli_readint32(src+9); |
|
2669 | 2652 |
|
2670 |
- if (lseek(desc, rep-nowinldr, SEEK_SET)==-1) break; |
|
2671 |
- if (cli_readn(desc, nbuff, 4)!=4) break; |
|
2672 |
- start_of_stuff=rep+cli_readint32(nbuff); |
|
2673 |
- if (lseek(desc, start_of_stuff, SEEK_SET)==-1) break; |
|
2674 |
- if (cli_readn(desc, nbuff, 20)!=20) break; |
|
2675 |
- src = nbuff; |
|
2676 |
- if (!cli_readint32(nbuff)) { |
|
2677 |
- start_of_stuff+=4; /* FIXME: more to do */ |
|
2678 |
- src+=4; |
|
2679 |
- } |
|
2653 |
+ CLI_UNPSIZELIMITS("NsPack", MAX(ssize,dsize)); |
|
2680 | 2654 |
|
2681 |
- ssize = cli_readint32(src+5)|0xff; |
|
2682 |
- dsize = cli_readint32(src+9); |
|
2655 |
+ if ( !ssize || !dsize || dsize != exe_sections[0].vsz) break; |
|
2656 |
+ if (lseek(desc, start_of_stuff, SEEK_SET)==-1) break; |
|
2657 |
+ if (!(dest=cli_malloc(dsize))) break; |
|
2658 |
+ /* memset(dest, 0xfc, dsize); */ |
|
2683 | 2659 |
|
2684 |
- if(ctx->limits && ctx->limits->maxfilesize && (ssize > ctx->limits->maxfilesize || dsize > ctx->limits->maxfilesize)) { |
|
2685 |
- cli_dbgmsg("NsPack: Size exceeded\n"); |
|
2686 |
- free(exe_sections); |
|
2687 |
- if(BLOCKMAX) { |
|
2688 |
- *ctx->virname = "PE.NsPack.ExceededFileSize"; |
|
2689 |
- return CL_VIRUS; |
|
2690 |
- } else { |
|
2691 |
- return CL_CLEAN; |
|
2660 |
+ if (!(src=cli_malloc(ssize))) { |
|
2661 |
+ free(dest); |
|
2662 |
+ break; |
|
2692 | 2663 |
} |
2693 |
- } |
|
2664 |
+ /* memset(src, 0x00, ssize); */ |
|
2665 |
+ cli_readn(desc, src, ssize); |
|
2694 | 2666 |
|
2695 |
- if ( !ssize || !dsize || dsize != exe_sections[0].vsz) break; |
|
2696 |
- if (lseek(desc, start_of_stuff, SEEK_SET)==-1) break; |
|
2697 |
- if (!(dest=cli_malloc(dsize))) break; |
|
2698 |
- /* memset(dest, 0xfc, dsize); */ |
|
2667 |
+ eprva+=0x27a; |
|
2668 |
+ if (!(rep = cli_rawaddr(eprva, exe_sections, nsections, &err, fsize, hdr_size)) && err) { |
|
2669 |
+ free(dest); |
|
2670 |
+ free(src); |
|
2671 |
+ break; |
|
2672 |
+ } |
|
2673 |
+ if (lseek(desc, rep, SEEK_SET)==-1) { |
|
2674 |
+ free(dest); |
|
2675 |
+ free(src); |
|
2676 |
+ break; |
|
2677 |
+ } |
|
2678 |
+ if (cli_readn(desc, nbuff, 5)!=5) { |
|
2679 |
+ free(dest); |
|
2680 |
+ free(src); |
|
2681 |
+ break; |
|
2682 |
+ } |
|
2683 |
+ eprva=eprva+5+cli_readint32(nbuff+1); |
|
2684 |
+ cli_dbgmsg("NsPack: OEP = %08x\n", eprva); |
|
2699 | 2685 |
|
2700 |
- if (!(src=cli_malloc(ssize))) { |
|
2701 |
- free(dest); |
|
2686 |
+ CLI_UNPTEMP("NsPack",src,dest,exe_sections); |
|
2687 |
+ CLI_UNPRESULTS("NsPack",(unspack(src, dest, ctx, exe_sections[0].rva, EC32(optional_hdr32.ImageBase), eprva, ndesc)),0,src,dest); |
|
2702 | 2688 |
break; |
2703 |
- } |
|
2704 |
- /* memset(src, 0x00, ssize); */ |
|
2705 |
- cli_readn(desc, src, ssize); |
|
2706 |
- |
|
2707 |
- eprva+=0x27a; |
|
2708 |
- if (!(rep = cli_rawaddr(eprva, exe_sections, nsections, &err, fsize, hdr_size)) && err) break; |
|
2709 |
- if (lseek(desc, rep, SEEK_SET)==-1) break; |
|
2710 |
- if (cli_readn(desc, nbuff, 5)!=5) break; |
|
2711 |
- eprva=eprva+5+cli_readint32(nbuff+1); |
|
2712 |
- cli_dbgmsg("NsPack: OEP = %08x\n", eprva); |
|
2713 |
- |
|
2714 |
- if(!(tempfile = cli_gentemp(NULL))) { |
|
2715 |
- free(src); |
|
2716 |
- free(dest); |
|
2717 |
- free(exe_sections); |
|
2718 |
- return CL_EMEM; |
|
2719 |
- } |
|
2720 |
- |
|
2721 |
- if((ndesc = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU)) < 0) { |
|
2722 |
- cli_dbgmsg("NsPack: Can't create file %s\n", tempfile); |
|
2723 |
- free(tempfile); |
|
2724 |
- free(src); |
|
2725 |
- free(dest); |
|
2726 |
- free(exe_sections); |
|
2727 |
- return CL_EIO; |
|
2728 |
- } |
|
2729 |
- |
|
2730 |
- if (!unspack(src, dest, ctx, exe_sections[0].rva, EC32(optional_hdr32.ImageBase), eprva, ndesc)) { |
|
2731 |
- free(src); |
|
2732 |
- free(dest); |
|
2733 |
- if (cli_leavetemps_flag) |
|
2734 |
- cli_dbgmsg("NsPack: Unpacked and rebuilt executable saved in %s\n", tempfile); |
|
2735 |
- else |
|
2736 |
- cli_dbgmsg("NsPack: Unpacked and rebuilt executable\n"); |
|
2737 |
- fsync(ndesc); |
|
2738 |
- lseek(ndesc, 0, SEEK_SET); |
|
2739 |
- |
|
2740 |
- if(cli_magic_scandesc(ndesc, ctx) == CL_VIRUS) { |
|
2741 |
- free(exe_sections); |
|
2742 |
- close(ndesc); |
|
2743 |
- if(!cli_leavetemps_flag) unlink(tempfile); |
|
2744 |
- free(tempfile); |
|
2745 |
- return CL_VIRUS; |
|
2746 |
- } |
|
2747 |
- } else { |
|
2748 |
- free(src); |
|
2749 |
- free(dest); |
|
2750 |
- cli_dbgmsg("NsPack: Unpacking failed\n"); |
|
2751 |
- } |
|
2752 |
- close(ndesc); |
|
2753 |
- if(!cli_leavetemps_flag) unlink(tempfile); |
|
2754 |
- free(tempfile); |
|
2755 |
- break; |
|
2756 | 2689 |
} |
2757 | 2690 |
|
2758 | 2691 |
/* to be continued ... */ |