... | ... |
@@ -176,7 +176,7 @@ struct macho_fat_arch |
176 | 176 |
if(DETECT_BROKEN) { \ |
177 | 177 |
if(ctx->virname) \ |
178 | 178 |
*ctx->virname = "Broken.Executable"; \ |
179 |
- return cli_checkfp(fd, ctx) ? CL_CLEAN : CL_VIRUS; \ |
|
179 |
+ return cli_checkfp(map->fd, ctx) ? CL_CLEAN : CL_VIRUS; \ |
|
180 | 180 |
} \ |
181 | 181 |
return CL_EFORMAT |
182 | 182 |
|
... | ... |
@@ -201,7 +201,7 @@ static uint32_t cli_rawaddr(uint32_t vaddr, struct cli_exe_section *sects, uint1 |
201 | 201 |
return vaddr - sects[i].rva + sects[i].raw; |
202 | 202 |
} |
203 | 203 |
|
204 |
-int cli_scanmacho(int fd, cli_ctx *ctx, struct cli_exe_info *fileinfo) |
|
204 |
+int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo) |
|
205 | 205 |
{ |
206 | 206 |
struct macho_hdr hdr; |
207 | 207 |
struct macho_load_cmd load_cmd; |
... | ... |
@@ -213,14 +213,17 @@ int cli_scanmacho(int fd, cli_ctx *ctx, struct cli_exe_info *fileinfo) |
213 | 213 |
unsigned int arch = 0, ep = 0, err; |
214 | 214 |
struct cli_exe_section *sections = NULL; |
215 | 215 |
char name[16]; |
216 |
+ struct F_MAP *map = *ctx->fmap; |
|
217 |
+ ssize_t at; |
|
216 | 218 |
|
217 | 219 |
if(fileinfo) |
218 | 220 |
matcher = 1; |
219 | 221 |
|
220 |
- if(read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { |
|
222 |
+ if(fmap_readn(map, &hdr, 0, sizeof(hdr)) != sizeof(hdr)) { |
|
221 | 223 |
cli_dbgmsg("cli_scanmacho: Can't read header\n"); |
222 | 224 |
return matcher ? -1 : CL_EFORMAT; |
223 | 225 |
} |
226 |
+ at = sizeof(hdr); |
|
224 | 227 |
|
225 | 228 |
if(hdr.magic == 0xfeedface) { |
226 | 229 |
conv = 0; |
... | ... |
@@ -311,7 +314,7 @@ int cli_scanmacho(int fd, cli_ctx *ctx, struct cli_exe_info *fileinfo) |
311 | 311 |
} |
312 | 312 |
|
313 | 313 |
if(m64) |
314 |
- lseek(fd, 4, SEEK_CUR); |
|
314 |
+ at += 4; |
|
315 | 315 |
|
316 | 316 |
hdr.ncmds = EC32(hdr.ncmds, conv); |
317 | 317 |
if(!hdr.ncmds || hdr.ncmds > 1024) { |
... | ... |
@@ -320,11 +323,12 @@ int cli_scanmacho(int fd, cli_ctx *ctx, struct cli_exe_info *fileinfo) |
320 | 320 |
} |
321 | 321 |
|
322 | 322 |
for(i = 0; i < hdr.ncmds; i++) { |
323 |
- if(read(fd, &load_cmd, sizeof(load_cmd)) != sizeof(load_cmd)) { |
|
323 |
+ if(fmap_readn(map, &load_cmd, at, sizeof(load_cmd)) != sizeof(load_cmd)) { |
|
324 | 324 |
cli_dbgmsg("cli_scanmacho: Can't read load command\n"); |
325 | 325 |
free(sections); |
326 | 326 |
RETURN_BROKEN; |
327 | 327 |
} |
328 |
+ at += sizeof(load_cmd); |
|
328 | 329 |
/* |
329 | 330 |
if((m64 && EC32(load_cmd.cmdsize, conv) % 8) || (!m64 && EC32(load_cmd.cmdsize, conv) % 4)) { |
330 | 331 |
cli_dbgmsg("cli_scanmacho: Invalid command size (%u)\n", EC32(load_cmd.cmdsize, conv)); |
... | ... |
@@ -335,19 +339,21 @@ int cli_scanmacho(int fd, cli_ctx *ctx, struct cli_exe_info *fileinfo) |
335 | 335 |
load_cmd.cmd = EC32(load_cmd.cmd, conv); |
336 | 336 |
if((m64 && load_cmd.cmd == 0x19) || (!m64 && load_cmd.cmd == 0x01)) { /* LC_SEGMENT */ |
337 | 337 |
if(m64) { |
338 |
- if(read(fd, &segment_cmd64, sizeof(segment_cmd64)) != sizeof(segment_cmd64)) { |
|
338 |
+ if(fmap_readn(map, &segment_cmd64, at, sizeof(segment_cmd64)) != sizeof(segment_cmd64)) { |
|
339 | 339 |
cli_dbgmsg("cli_scanmacho: Can't read segment command\n"); |
340 | 340 |
free(sections); |
341 | 341 |
RETURN_BROKEN; |
342 | 342 |
} |
343 |
+ at += sizeof(segment_cmd64); |
|
343 | 344 |
nsects = EC32(segment_cmd64.nsects, conv); |
344 | 345 |
strncpy(name, segment_cmd64.segname, 16); |
345 | 346 |
} else { |
346 |
- if(read(fd, &segment_cmd, sizeof(segment_cmd)) != sizeof(segment_cmd)) { |
|
347 |
+ if(fmap_readn(map, &segment_cmd, at, sizeof(segment_cmd)) != sizeof(segment_cmd)) { |
|
347 | 348 |
cli_dbgmsg("cli_scanmacho: Can't read segment command\n"); |
348 | 349 |
free(sections); |
349 | 350 |
RETURN_BROKEN; |
350 | 351 |
} |
352 |
+ at += sizeof(segment_cmd); |
|
351 | 353 |
nsects = EC32(segment_cmd.nsects, conv); |
352 | 354 |
strncpy(name, segment_cmd.segname, 16); |
353 | 355 |
} |
... | ... |
@@ -374,11 +380,12 @@ int cli_scanmacho(int fd, cli_ctx *ctx, struct cli_exe_info *fileinfo) |
374 | 374 |
|
375 | 375 |
for(j = 0; j < nsects; j++) { |
376 | 376 |
if(m64) { |
377 |
- if(read(fd, §ion64, sizeof(section64)) != sizeof(section64)) { |
|
377 |
+ if(fmap_readn(map, §ion64, at, sizeof(section64)) != sizeof(section64)) { |
|
378 | 378 |
cli_dbgmsg("cli_scanmacho: Can't read section\n"); |
379 | 379 |
free(sections); |
380 | 380 |
RETURN_BROKEN; |
381 | 381 |
} |
382 |
+ at += sizeof(section64); |
|
382 | 383 |
sections[sect].rva = EC64(section64.addr, conv); |
383 | 384 |
sections[sect].vsz = EC64(section64.size, conv); |
384 | 385 |
sections[sect].raw = EC32(section64.offset, conv); |
... | ... |
@@ -386,11 +393,12 @@ int cli_scanmacho(int fd, cli_ctx *ctx, struct cli_exe_info *fileinfo) |
386 | 386 |
sections[sect].rsz = sections[sect].vsz + (section64.align - (sections[sect].vsz % section64.align)) % section64.align; /* most likely we can assume it's the same as .vsz */ |
387 | 387 |
strncpy(name, section64.sectname, 16); |
388 | 388 |
} else { |
389 |
- if(read(fd, §ion, sizeof(section)) != sizeof(section)) { |
|
389 |
+ if(fmap_readn(map, §ion, at, sizeof(section)) != sizeof(section)) { |
|
390 | 390 |
cli_dbgmsg("cli_scanmacho: Can't read section\n"); |
391 | 391 |
free(sections); |
392 | 392 |
RETURN_BROKEN; |
393 | 393 |
} |
394 |
+ at += sizeof(section); |
|
394 | 395 |
sections[sect].rva = EC32(section.addr, conv); |
395 | 396 |
sections[sect].vsz = EC32(section.size, conv); |
396 | 397 |
sections[sect].raw = EC32(section.offset, conv); |
... | ... |
@@ -414,17 +422,18 @@ int cli_scanmacho(int fd, cli_ctx *ctx, struct cli_exe_info *fileinfo) |
414 | 414 |
cli_dbgmsg("MACHO: ------------------\n"); |
415 | 415 |
|
416 | 416 |
} else if(arch && (load_cmd.cmd == 0x4 || load_cmd.cmd == 0x5)) { /* LC_(UNIX)THREAD */ |
417 |
- lseek(fd, 8, SEEK_CUR); |
|
417 |
+ at += 8; |
|
418 | 418 |
switch(arch) { |
419 | 419 |
case 1: /* x86 */ |
420 | 420 |
{ |
421 | 421 |
struct macho_thread_state_x86 thread_state_x86; |
422 | 422 |
|
423 |
- if(read(fd, &thread_state_x86, sizeof(thread_state_x86)) != sizeof(thread_state_x86)) { |
|
423 |
+ if(fmap_readn(map, &thread_state_x86, at, sizeof(thread_state_x86)) != sizeof(thread_state_x86)) { |
|
424 | 424 |
cli_dbgmsg("cli_scanmacho: Can't read thread_state_x86\n"); |
425 | 425 |
free(sections); |
426 | 426 |
RETURN_BROKEN; |
427 | 427 |
} |
428 |
+ at += sizeof(thread_state_x86); |
|
428 | 429 |
break; |
429 | 430 |
} |
430 | 431 |
|
... | ... |
@@ -432,11 +441,12 @@ int cli_scanmacho(int fd, cli_ctx *ctx, struct cli_exe_info *fileinfo) |
432 | 432 |
{ |
433 | 433 |
struct macho_thread_state_ppc thread_state_ppc; |
434 | 434 |
|
435 |
- if(read(fd, &thread_state_ppc, sizeof(thread_state_ppc)) != sizeof(thread_state_ppc)) { |
|
435 |
+ if(fmap_readn(map, &thread_state_ppc, at, sizeof(thread_state_ppc)) != sizeof(thread_state_ppc)) { |
|
436 | 436 |
cli_dbgmsg("cli_scanmacho: Can't read thread_state_ppc\n"); |
437 | 437 |
free(sections); |
438 | 438 |
RETURN_BROKEN; |
439 | 439 |
} |
440 |
+ at += sizeof(thread_state_ppc); |
|
440 | 441 |
ep = EC32(thread_state_ppc.srr0, conv); |
441 | 442 |
break; |
442 | 443 |
} |
... | ... |
@@ -445,11 +455,12 @@ int cli_scanmacho(int fd, cli_ctx *ctx, struct cli_exe_info *fileinfo) |
445 | 445 |
{ |
446 | 446 |
struct macho_thread_state_ppc64 thread_state_ppc64; |
447 | 447 |
|
448 |
- if(read(fd, &thread_state_ppc64, sizeof(thread_state_ppc64)) != sizeof(thread_state_ppc64)) { |
|
448 |
+ if(fmap_readn(map, &thread_state_ppc64, at, sizeof(thread_state_ppc64)) != sizeof(thread_state_ppc64)) { |
|
449 | 449 |
cli_dbgmsg("cli_scanmacho: Can't read thread_state_ppc64\n"); |
450 | 450 |
free(sections); |
451 | 451 |
RETURN_BROKEN; |
452 | 452 |
} |
453 |
+ at += sizeof(thread_state_ppc64); |
|
453 | 454 |
ep = EC64(thread_state_ppc64.srr0, conv); |
454 | 455 |
break; |
455 | 456 |
} |
... | ... |
@@ -460,7 +471,7 @@ int cli_scanmacho(int fd, cli_ctx *ctx, struct cli_exe_info *fileinfo) |
460 | 460 |
} |
461 | 461 |
} else { |
462 | 462 |
if(EC32(load_cmd.cmdsize, conv) > sizeof(load_cmd)) |
463 |
- lseek(fd, EC32(load_cmd.cmdsize, conv) - sizeof(load_cmd), SEEK_CUR); |
|
463 |
+ at += EC32(load_cmd.cmdsize, conv) - sizeof(load_cmd); |
|
464 | 464 |
} |
465 | 465 |
} |
466 | 466 |
|
... | ... |
@@ -492,10 +503,12 @@ int cli_scanmacho(int fd, cli_ctx *ctx, struct cli_exe_info *fileinfo) |
492 | 492 |
|
493 | 493 |
int cli_machoheader(struct F_MAP *map, struct cli_exe_info *fileinfo) |
494 | 494 |
{ |
495 |
- return cli_scanmacho(map->fd, NULL, fileinfo); |
|
495 |
+ cli_ctx ctx; |
|
496 |
+ ctx.fmap = ↦ |
|
497 |
+ return cli_scanmacho(&ctx, fileinfo); |
|
496 | 498 |
} |
497 | 499 |
|
498 |
-int cli_scanmacho_unibin(int fd, cli_ctx *ctx) |
|
500 |
+int cli_scanmacho_unibin(cli_ctx *ctx) |
|
499 | 501 |
{ |
500 | 502 |
struct macho_fat_header fat_header; |
501 | 503 |
struct macho_fat_arch fat_arch; |
... | ... |
@@ -503,16 +516,14 @@ int cli_scanmacho_unibin(int fd, cli_ctx *ctx) |
503 | 503 |
int ret = CL_CLEAN; |
504 | 504 |
struct stat sb; |
505 | 505 |
off_t pos; |
506 |
+ struct F_MAP *map = *ctx->fmap; |
|
507 |
+ ssize_t at; |
|
506 | 508 |
|
507 |
- if(fstat(fd, &sb) == -1) { |
|
508 |
- cli_dbgmsg("cli_scanmacho_unibin: fstat failed for fd %d\n", fd); |
|
509 |
- return CL_ESTAT; |
|
510 |
- } |
|
511 |
- |
|
512 |
- if(read(fd, &fat_header, sizeof(fat_header)) != sizeof(fat_header)) { |
|
509 |
+ if(fmap_readn(map, &fat_header, 0, sizeof(fat_header)) != sizeof(fat_header)) { |
|
513 | 510 |
cli_dbgmsg("cli_scanmacho_unibin: Can't read fat_header\n"); |
514 | 511 |
return CL_EFORMAT; |
515 | 512 |
} |
513 |
+ at = sizeof(fat_header); |
|
516 | 514 |
|
517 | 515 |
if(fat_header.magic == 0xcafebabe) { |
518 | 516 |
conv = 0; |
... | ... |
@@ -533,18 +544,17 @@ int cli_scanmacho_unibin(int fd, cli_ctx *ctx) |
533 | 533 |
} |
534 | 534 |
cli_dbgmsg("UNIBIN: Number of architectures: %u\n", (unsigned int) fat_header.nfats); |
535 | 535 |
for(i = 0; i < fat_header.nfats; i++) { |
536 |
- if(read(fd, &fat_arch, sizeof(fat_arch)) != sizeof(fat_arch)) { |
|
536 |
+ if(fmap_readn(map, &fat_arch, at, sizeof(fat_arch)) != sizeof(fat_arch)) { |
|
537 | 537 |
cli_dbgmsg("cli_scanmacho_unibin: Can't read fat_arch\n"); |
538 | 538 |
RETURN_BROKEN; |
539 | 539 |
} |
540 |
- pos = lseek(fd, 0, SEEK_CUR); |
|
540 |
+ at += sizeof(fat_arch); |
|
541 | 541 |
fat_arch.offset = EC32(fat_arch.offset, conv); |
542 | 542 |
fat_arch.size = EC32(fat_arch.size, conv); |
543 | 543 |
cli_dbgmsg("UNIBIN: Binary %u of %u\n", i + 1, fat_header.nfats); |
544 | 544 |
cli_dbgmsg("UNIBIN: File offset: %u\n", fat_arch.offset); |
545 | 545 |
cli_dbgmsg("UNIBIN: File size: %u\n", fat_arch.size); |
546 |
- ret = cli_dumpscan(fd, fat_arch.offset, fat_arch.size, ctx); |
|
547 |
- lseek(fd, pos, SEEK_SET); |
|
546 |
+ ret = cli_dumpscan(map->fd, fat_arch.offset, fat_arch.size, ctx); |
|
548 | 547 |
if(ret == CL_VIRUS) |
549 | 548 |
break; |
550 | 549 |
} |
... | ... |
@@ -25,8 +25,8 @@ |
25 | 25 |
#include "execs.h" |
26 | 26 |
#include "fmap.h" |
27 | 27 |
|
28 |
-int cli_scanmacho(int fd, cli_ctx *ctx, struct cli_exe_info *fileinfo); |
|
28 |
+int cli_scanmacho(cli_ctx *ctx, struct cli_exe_info *fileinfo); |
|
29 | 29 |
int cli_machoheader(struct F_MAP *map, struct cli_exe_info *fileinfo); |
30 |
-int cli_scanmacho_unibin(int fd, cli_ctx *ctx); |
|
30 |
+int cli_scanmacho_unibin(cli_ctx *ctx); |
|
31 | 31 |
|
32 | 32 |
#endif |
... | ... |
@@ -2075,12 +2075,12 @@ int cli_magic_scandesc(int desc, cli_ctx *ctx) |
2075 | 2075 |
|
2076 | 2076 |
case CL_TYPE_MACHO: |
2077 | 2077 |
if(ctx->dconf->macho) |
2078 |
- ret = cli_scanmacho(desc, ctx, NULL); |
|
2078 |
+ ret = cli_scanmacho(ctx, NULL); |
|
2079 | 2079 |
break; |
2080 | 2080 |
|
2081 | 2081 |
case CL_TYPE_MACHO_UNIBIN: |
2082 | 2082 |
if(ctx->dconf->macho) |
2083 |
- ret = cli_scanmacho_unibin(desc, ctx); |
|
2083 |
+ ret = cli_scanmacho_unibin(ctx); |
|
2084 | 2084 |
break; |
2085 | 2085 |
|
2086 | 2086 |
case CL_TYPE_SIS: |