... | ... |
@@ -876,6 +876,17 @@ static void handle_pdfname(struct pdf_struct *pdf, struct pdf_obj *obj, |
876 | 876 |
static char *pdf_readstring(const char *q0, int len, const char *key, unsigned *slen); |
877 | 877 |
static int pdf_readint(const char *q0, int len, const char *key); |
878 | 878 |
static const char *pdf_getdict(const char *q0, int* len, const char *key); |
879 |
+ |
|
880 |
+static void pdf_parse_trailer(struct pdf_struct *pdf, const char *s, long length) |
|
881 |
+{ |
|
882 |
+ char *newID; |
|
883 |
+ newID = pdf_readstring(s, length, "/ID", &pdf->fileIDlen); |
|
884 |
+ if (newID) { |
|
885 |
+ free(pdf->fileID); |
|
886 |
+ pdf->fileID = newID; |
|
887 |
+ } |
|
888 |
+} |
|
889 |
+ |
|
879 | 890 |
static void pdf_parseobj(struct pdf_struct *pdf, struct pdf_obj *obj) |
880 | 891 |
{ |
881 | 892 |
/* enough to hold common pdf names, we don't need all the names */ |
... | ... |
@@ -960,9 +971,9 @@ static void pdf_parseobj(struct pdf_struct *pdf, struct pdf_obj *obj) |
960 | 960 |
if (trailer < 0) trailer = 0; |
961 | 961 |
q2 = pdf->map + trailer; |
962 | 962 |
cli_dbgmsg("cli_pdf: looking for trailer in linearized pdf: %ld - %ld\n", trailer, trailer_end); |
963 |
- pdf->fileID = pdf_readstring(q2, trailer_end - trailer, "/ID", &pdf->fileIDlen); |
|
963 |
+ pdf_parse_trailer(pdf, q2, trailer_end - trailer); |
|
964 | 964 |
if (pdf->fileID) |
965 |
- cli_dbgmsg("found fileID\n"); |
|
965 |
+ cli_dbgmsg("cli_pdf: found fileID\n"); |
|
966 | 966 |
} |
967 | 967 |
} |
968 | 968 |
if (objstate == STATE_LAUNCHACTION) |
... | ... |
@@ -1281,7 +1292,7 @@ static void check_user_password(struct pdf_struct *pdf, int R, const char *O, |
1281 | 1281 |
if (!pdf->key) |
1282 | 1282 |
return; |
1283 | 1283 |
memcpy(pdf->key, result, pdf->keylen); |
1284 |
- dbg_printhex("md5", result, 32); |
|
1284 |
+ dbg_printhex("md5", result, 16); |
|
1285 | 1285 |
dbg_printhex("Candidate encryption key", pdf->key, pdf->keylen); |
1286 | 1286 |
|
1287 | 1287 |
/* 7.6.3.3 Algorithm 6 */ |
... | ... |
@@ -1521,7 +1532,7 @@ int cli_pdf(const char *dir, cli_ctx *ctx, off_t offset) |
1521 | 1521 |
pdf.flags |= 1 << ENCRYPTED_PDF; |
1522 | 1522 |
cli_dbgmsg("cli_pdf: encrypted pdf found, stream will probably fail to decompress!\n"); |
1523 | 1523 |
pdf_parse_encrypt(&pdf, enc, eof - enc); |
1524 |
- pdf.fileID = pdf_readstring(eofmap, bytesleft, "/ID", &pdf.fileIDlen); |
|
1524 |
+ pdf_parse_trailer(&pdf, eofmap, bytesleft); |
|
1525 | 1525 |
} |
1526 | 1526 |
q += 9; |
1527 | 1527 |
while (q < eof && (*q == ' ' || *q == '\n' || *q == '\r')) { q++; } |
... | ... |
@@ -1553,7 +1564,7 @@ int cli_pdf(const char *dir, cli_ctx *ctx, off_t offset) |
1553 | 1553 |
/* parse PDF and find obj offsets */ |
1554 | 1554 |
while ((rc = pdf_findobj(&pdf)) > 0) { |
1555 | 1555 |
struct pdf_obj *obj = &pdf.objs[pdf.nobjs-1]; |
1556 |
- cli_dbgmsg("found %d %d obj @%ld\n", obj->id >> 8, obj->id&0xff, obj->start + offset); |
|
1556 |
+ cli_dbgmsg("cli_pdf: found %d %d obj @%ld\n", obj->id >> 8, obj->id&0xff, obj->start + offset); |
|
1557 | 1557 |
} |
1558 | 1558 |
if (pdf.nobjs) |
1559 | 1559 |
pdf.nobjs--; |
... | ... |
@@ -2276,7 +2287,7 @@ ascii85decode(const char *buf, off_t len, unsigned char *output) |
2276 | 2276 |
} |
2277 | 2277 |
} else if(byte == 'z') { |
2278 | 2278 |
if(quintet) { |
2279 |
- cli_dbgmsg("ascii85decode: unexpected 'z'\n"); |
|
2279 |
+ cli_dbgmsg("cli_pdf: ascii85decode: unexpected 'z'\n"); |
|
2280 | 2280 |
return -1; |
2281 | 2281 |
} |
2282 | 2282 |
*output++ = '\0'; |
... | ... |
@@ -2285,12 +2296,12 @@ ascii85decode(const char *buf, off_t len, unsigned char *output) |
2285 | 2285 |
*output++ = '\0'; |
2286 | 2286 |
ret += 4; |
2287 | 2287 |
} else if(byte == EOF) { |
2288 |
- cli_dbgmsg("ascii85decode: quintet %d\n", quintet); |
|
2288 |
+ cli_dbgmsg("cli_pdf: ascii85decode: quintet %d\n", quintet); |
|
2289 | 2289 |
if(quintet) { |
2290 | 2290 |
int i; |
2291 | 2291 |
|
2292 | 2292 |
if(quintet == 1) { |
2293 |
- cli_dbgmsg("ascii85Decode: only 1 byte in last quintet\n"); |
|
2293 |
+ cli_dbgmsg("cli_pdf: ascii85Decode: only 1 byte in last quintet\n"); |
|
2294 | 2294 |
return -1; |
2295 | 2295 |
} |
2296 | 2296 |
for(i = quintet; i < 5; i++) |
... | ... |
@@ -2304,7 +2315,7 @@ ascii85decode(const char *buf, off_t len, unsigned char *output) |
2304 | 2304 |
} |
2305 | 2305 |
break; |
2306 | 2306 |
} else if(!isspace(byte)) { |
2307 |
- cli_dbgmsg("ascii85Decode: invalid character 0x%x, len %lu\n", |
|
2307 |
+ cli_dbgmsg("cli_pdf: ascii85Decode: invalid character 0x%x, len %lu\n", |
|
2308 | 2308 |
byte & 0xFF, (unsigned long)len); |
2309 | 2309 |
return -1; |
2310 | 2310 |
} |
... | ... |
@@ -2085,23 +2085,23 @@ int cli_scanpe(cli_ctx *ctx) |
2085 | 2085 |
!memcmp(epbuff+0x63+offset, "\xaa\xe2\xcc", 3) && |
2086 | 2086 |
(fsize >= exe_sections[nsections-1].raw + 0xC6 + ecx + offset)) { |
2087 | 2087 |
|
2088 |
- char *spinned; |
|
2088 |
+ char *spinned; |
|
2089 | 2089 |
|
2090 |
- if((spinned = (char *) cli_malloc(fsize)) == NULL) { |
|
2091 |
- free(exe_sections); |
|
2092 |
- return CL_EMEM; |
|
2093 |
- } |
|
2090 |
+ if((spinned = (char *) cli_malloc(fsize)) == NULL) { |
|
2091 |
+ free(exe_sections); |
|
2092 |
+ return CL_EMEM; |
|
2093 |
+ } |
|
2094 | 2094 |
|
2095 |
- if((size_t) fmap_readn(map, spinned, 0, fsize) != fsize) { |
|
2096 |
- cli_dbgmsg("yC: Can't read %lu bytes\n", (unsigned long)fsize); |
|
2097 |
- free(spinned); |
|
2098 |
- free(exe_sections); |
|
2099 |
- return CL_EREAD; |
|
2100 |
- } |
|
2095 |
+ if((size_t) fmap_readn(map, spinned, 0, fsize) != fsize) { |
|
2096 |
+ cli_dbgmsg("yC: Can't read %lu bytes\n", (unsigned long)fsize); |
|
2097 |
+ free(spinned); |
|
2098 |
+ free(exe_sections); |
|
2099 |
+ return CL_EREAD; |
|
2100 |
+ } |
|
2101 | 2101 |
|
2102 |
- cli_dbgmsg("%d,%d,%d,%d\n", nsections-1, e_lfanew, ecx, offset); |
|
2103 |
- CLI_UNPTEMP("yC",(spinned,exe_sections,0)); |
|
2104 |
- CLI_UNPRESULTS("yC",(yc_decrypt(spinned, fsize, exe_sections, nsections-1, e_lfanew, ndesc, ecx, offset)),0,(spinned,0)); |
|
2102 |
+ cli_dbgmsg("%d,%d,%d,%d\n", nsections-1, e_lfanew, ecx, offset); |
|
2103 |
+ CLI_UNPTEMP("yC",(spinned,exe_sections,0)); |
|
2104 |
+ CLI_UNPRESULTS("yC",(yc_decrypt(spinned, fsize, exe_sections, nsections-1, e_lfanew, ndesc, ecx, offset)),0,(spinned,0)); |
|
2105 | 2105 |
} |
2106 | 2106 |
} |
2107 | 2107 |
|
... | ... |
@@ -40,7 +40,7 @@ |
40 | 40 |
/* ========================================================================== */ |
41 | 41 |
/* "Emulates" the poly decryptors */ |
42 | 42 |
|
43 |
-static int yc_poly_emulator(char* decryptor_offset, char* code, unsigned int ecx) |
|
43 |
+static int yc_poly_emulator(char* decryptor_offset, char* code, unsigned int ecx, uint32_t max_emu) |
|
44 | 44 |
{ |
45 | 45 |
|
46 | 46 |
/* |
... | ... |
@@ -64,7 +64,7 @@ static int yc_poly_emulator(char* decryptor_offset, char* code, unsigned int ecx |
64 | 64 |
unsigned char cl = ecx & 0xff; |
65 | 65 |
unsigned int j,i; |
66 | 66 |
|
67 |
- for(i=0;i<ecx;i++) /* Byte looper - Decrypts every byte and write it back */ |
|
67 |
+ for(i=0;i<ecx&&i<max_emu;i++) /* Byte looper - Decrypts every byte and write it back */ |
|
68 | 68 |
{ |
69 | 69 |
al = code[i]; |
70 | 70 |
|
... | ... |
@@ -168,7 +168,7 @@ int yc_decrypt(char *fbuf, unsigned int filesize, struct cli_exe_section *sectio |
168 | 168 |
unsigned int i; |
169 | 169 |
struct pe_image_file_hdr *pe = (struct pe_image_file_hdr*) (fbuf + peoffset); |
170 | 170 |
char *sname = (char *)pe + EC16(pe->SizeOfOptionalHeader) + 0x18; |
171 |
- |
|
171 |
+ uint32_t max_emu; |
|
172 | 172 |
/* |
173 | 173 |
|
174 | 174 |
First layer (decryptor of the section decryptor) in last section |
... | ... |
@@ -180,7 +180,7 @@ int yc_decrypt(char *fbuf, unsigned int filesize, struct cli_exe_section *sectio |
180 | 180 |
*/ |
181 | 181 |
cli_dbgmsg("yC: offset: %x, length: %x\n", offset, ecx); |
182 | 182 |
cli_dbgmsg("yC: decrypting decryptor on sect %d\n", sectcount); |
183 |
- if (yc_poly_emulator(fbuf + ycsect + 0x93, fbuf + ycsect + 0xc6, ecx)) |
|
183 |
+ if (yc_poly_emulator(fbuf + ycsect + 0x93, fbuf + ycsect + 0xc6, ecx, ecx)) |
|
184 | 184 |
return 1; |
185 | 185 |
filesize-=sections[sectcount].ursz; |
186 | 186 |
|
... | ... |
@@ -190,31 +190,38 @@ int yc_decrypt(char *fbuf, unsigned int filesize, struct cli_exe_section *sectio |
190 | 190 |
|
191 | 191 |
Start offset for analyze: Start of yC Section + 0x457 |
192 | 192 |
End offset for analyze: Start of yC Section + 0x487 |
193 |
- Lenght to decrypt - ECX = Raw Size of Section |
|
193 |
+ Length to decrypt - ECX = Raw Size of Section |
|
194 | 194 |
|
195 | 195 |
*/ |
196 | 196 |
|
197 | 197 |
|
198 | 198 |
/* Loop through all sections and decrypt them... */ |
199 |
- for(i=0;i<sectcount;i++) |
|
200 |
- { |
|
201 |
- uint32_t name = (uint32_t) cli_readint32(sname+i*0x28); |
|
202 |
- if (!sections[i].raw || |
|
203 |
- !sections[i].rsz || |
|
204 |
- name == 0x63727372 || /* rsrc */ |
|
205 |
- name == 0x7273722E || /* .rsr */ |
|
206 |
- name == 0x6F6C6572 || /* relo */ |
|
207 |
- name == 0x6C65722E || /* .rel */ |
|
208 |
- name == 0x6164652E || /* .eda */ |
|
209 |
- name == 0x6164722E || /* .rda */ |
|
210 |
- name == 0x6164692E || /* .ida */ |
|
211 |
- name == 0x736C742E || /* .tls */ |
|
212 |
- (name&0xffff) == 0x4379 /* yC */ |
|
199 |
+ for(i=0;i<sectcount;i++) { |
|
200 |
+ uint32_t name = (uint32_t) cli_readint32(sname+i*0x28); |
|
201 |
+ if (!sections[i].raw || |
|
202 |
+ !sections[i].rsz || |
|
203 |
+ name == 0x63727372 || /* rsrc */ |
|
204 |
+ name == 0x7273722E || /* .rsr */ |
|
205 |
+ name == 0x6F6C6572 || /* relo */ |
|
206 |
+ name == 0x6C65722E || /* .rel */ |
|
207 |
+ name == 0x6164652E || /* .eda */ |
|
208 |
+ name == 0x6164722E || /* .rda */ |
|
209 |
+ name == 0x6164692E || /* .ida */ |
|
210 |
+ name == 0x736C742E || /* .tls */ |
|
211 |
+ (name&0xffff) == 0x4379 /* yC */ |
|
213 | 212 |
) continue; |
214 |
- cli_dbgmsg("yC: decrypting sect%d\n",i); |
|
215 |
- if (yc_poly_emulator(fbuf + ycsect + (offset == -0x18 ? 0x3ea : 0x457), fbuf + sections[i].raw, sections[i].ursz)) |
|
216 |
- return 1; |
|
213 |
+ cli_dbgmsg("yC: decrypting sect%d\n",i); |
|
214 |
+ max_emu = filesize - sections[i].raw; |
|
215 |
+ if (max_emu > filesize) { |
|
216 |
+ cli_dbgmsg("yC: bad emulation length limit %u\n", max_emu); |
|
217 |
+ return 1; |
|
217 | 218 |
} |
219 |
+ if (yc_poly_emulator(fbuf + ycsect + (offset == -0x18 ? 0x3ea : 0x457), |
|
220 |
+ fbuf + sections[i].raw, |
|
221 |
+ sections[i].ursz, |
|
222 |
+ max_emu)) |
|
223 |
+ return 1; |
|
224 |
+ } |
|
218 | 225 |
|
219 | 226 |
/* Remove yC section */ |
220 | 227 |
pe->NumberOfSections=EC16(sectcount); |