ipv8吧 关注:14贴子:170
  • 12回复贴,共1

通过一个kriz病毒查Pe文件

只看楼主收藏回复

通过一个kriz病毒查Pe文件头部的IPv8里回话层和表示层的理论调查!
#传说中的PE文件查
int cli_scanpe(int desc, cli_ctx *ctx)
{
uint16_t e_magic; /* DOS signature ("MZ") */
uint16_t nsections;
uint32_t e_lfanew; /* address of new exe header */
uint32_t ep, vep; /* entry point (raw, virtual) */
uint8_t polipos = 0;
time_t timestamp;
struct pe_image_file_hdr file_hdr;
union {
struct pe_image_optional_hdr64 opt64;
struct pe_image_optional_hdr32 opt32;
} pe_opt;
struct pe_image_section_hdr *section_hdr;
struct stat sb;
char sname[9], buff[4096], epbuff[4096], *tempfile;
uint32_t epsize;
ssize_t bytes;
unsigned int i, found, upx_success = 0, min = 0, max = 0, err;
unsigned int ssize = 0, dsize = 0, dll = 0, pe_plus = 0;
int (*upxfn)(char *, uint32_t, char *, uint32_t *, uint32_t, uint32_t, uint32_t) = NULL;
char *src = NULL, *dest = NULL;
int ndesc, ret = CL_CLEAN, upack = 0, native=0;
size_t fsize;
uint32_t valign, falign, hdr_size, j;
struct cli_exe_section *exe_sections;
struct cli_matcher *md5_sect;
char timestr[32];
if(!ctx) {
cli_errmsg("cli_scanpe: ctx == NULL\n");
return CL_ENULLARG;
}
//读取DOS头,既是MZ
if(cli_readn(desc, &e_magic, sizeof(e_magic)) != sizeof(e_magic)) {
cli_dbgmsg("Can't read DOS signature\n");
return CL_CLEAN;
}
//EC16功能:前后16位数据互换
//因为IMAGE_DOS_SIGNATURE是0x5a4d,既是ZM
if(EC16(e_magic) != IMAGE_DOS_SIGNATURE && EC16(e_magic) != IMAGE_DOS_SIGNATURE_OLD) {
cli_dbgmsg("Invalid DOS signature\n");
return CL_CLEAN;
}
//再跳过58bytes就到达0x3c位置,PE头偏移数据
lseek(desc, 58, SEEK_CUR); /* skip to the end of the DOS header */
//读取PE文件头的文件偏移地址
if(cli_readn(desc, &e_lfanew, sizeof(e_lfanew)) != sizeof(e_lfanew)) {
cli_dbgmsg("Can't read new header address\n");
/* truncated header? */
//根据设置,判断是否要归类到病毒
if(DETECT_BROKEN) {
if(ctx->virname)
*ctx->virname = "Broken.Executable";
return CL_VIRUS;
}
return CL_CLEAN;
}
//EC32功能:高低地址翻转
//设置为正常顺序
e_lfanew = EC32(e_lfanew);
cli_dbgmsg("e_lfanew == %d\n", e_lfanew);
if(!e_lfanew) {
cli_dbgmsg("Not a PE file\n");
return CL_CLEAN;
}
//跳到PE文件头位置
if(lseek(desc, e_lfanew, SEEK_SET) < 0) {
/* probably not a PE file */
cli_dbgmsg("Can't lseek to e_lfanew\n");
return CL_CLEAN;
}
//读取镜像文件头
if(cli_readn(desc, &file_hdr, sizeof(struct pe_image_file_hdr)) != sizeof(struct pe_image_file_hdr)) {
/* bad information in e_lfanew - probably not a PE file */
cli_dbgmsg("Can't read file header\n");
return CL_CLEAN;
}
//判断PE签名是否为00EP
if(EC32(file_hdr.Magic) != IMAGE_NT_SIGNATURE) {
cli_dbgmsg("Invalid PE signature (probably NE file)\n");
return CL_CLEAN;
}
//文件属性为0x2000既是DLL文件
//文件属性为0x01则是普通EXE文件
if(EC16(file_hdr.Characteristics) & 0x2000) {
cli_dbgmsg("File type: DLL\n");
dll = 1;
} else if(EC16(file_hdr.Characteristics) & 0x01) {
cli_dbgmsg("File type: Executable\n");
}
//判断该PE文件的目标CPU 类型
switch(EC16(file_hdr.Machine)) {
case 0x0:
cli_dbgmsg("Machine type: Unknown\n");
break;
case 0x14c:
cli_dbgmsg("Machine type: 80386\n");
break;
case 0x14d:
cli_dbgmsg("Machine type: 80486\n");
break;
case 0x14e:
cli_dbgmsg("Machine type: 80586\n");
break;
case 0x160:
cli_dbgmsg("Machine type: R30000 (big-endian)\n");
break;
case 0x162:
cli_dbgmsg("Machine type: R3000\n");
break;
case 0x166:
cli_dbgmsg("Machine type: R4000\n");
break;
case 0x168:
cli_dbgmsg("Machine type: R10000\n");
break;
case 0x184:
cli_dbgmsg("Machine type: DEC Alpha AXP\n");
break;
case 0x284:
cli_dbgmsg("Machine type: DEC Alpha AXP 64bit\n");
break;
case 0x1f0:
cli_dbgmsg("Machine type: PowerPC\n");
break;
case 0x200:
cli_dbgmsg("Machine type: IA64\n");
break;
case 0x268:
cli_dbgmsg("Machine type: M68k\n");
break;
case 0x266:
cli_dbgmsg("Machine type: MIPS16\n");
break;
case 0x366:
cli_dbgmsg("Machine type: MIPS+FPU\n");
break;
case 0x466:
cli_dbgmsg("Machine type: MIPS16+FPU\n");
break;
case 0x1a2:
cli_dbgmsg("Machine type: Hitachi SH3\n");
break;
case 0x1a3:
cli_dbgmsg("Machine type: Hitachi SH3-DSP\n");
break;
case 0x1a4:
cli_dbgmsg("Machine type: Hitachi SH3-E\n");
break;
case 0x1a6:
cli_dbgmsg("Machine type: Hitachi SH4\n");
break;
case 0x1a8:
cli_dbgmsg("Machine type: Hitachi SH5\n");
break;
case 0x1c0:
cli_dbgmsg("Machine type: ARM\n");
break;
case 0x1c2:
cli_dbgmsg("Machine type: THUMB\n");
break;
case 0x1d3:
cli_dbgmsg("Machine type: AM33\n");
break;
case 0x520:
cli_dbgmsg("Machine type: Infineon TriCore\n");
break;
case 0xcef:
cli_dbgmsg("Machine type: CEF\n");
break;
case 0xebc:
cli_dbgmsg("Machine type: EFI Byte Code\n");
break;
case 0x9041:
cli_dbgmsg("Machine type: M32R\n");
break;
case 0xc0ee:
cli_dbgmsg("Machine type: CEE\n");
break;


来自Android客户端1楼2017-08-31 10:55回复
    续上...
    case 0x8664:
    cli_dbgmsg("Machine type: AMD64\n");
    break;
    default:
    cli_warnmsg("Unknown machine type in PE header (0x%x)\n", EC16(file_hdr.Machine));
    }
    //获取块的数目
    nsections = EC16(file_hdr.NumberOfSections);
    if(nsections < 1 || nsections > 96) {
    if(DETECT_BROKEN) {
    if(ctx->virname)
    *ctx->virname = "Broken.Executable";
    return CL_VIRUS;
    }
    if(nsections)
    cli_warnmsg("PE file contains %d sections\n", nsections);
    else
    cli_warnmsg("PE file contains no sections\n");
    return CL_CLEAN;
    }
    cli_dbgmsg("NumberOfSections: %d\n", nsections);
    //获取文件创建时间
    //自1970/1/1 用GMT计算的秒数
    timestamp = (time_t) EC32(file_hdr.TimeDateStamp);
    cli_dbgmsg("TimeDateStamp: %s", cli_ctime(×tamp, timestr, sizeof(timestr)));
    //读取可选镜像文件头大小
    cli_dbgmsg("SizeOfOptionalHeader: %x\n", EC16(file_hdr.SizeOfOptionalHeader));
    //可选镜像文件头太小
    if (EC16(file_hdr.SizeOfOptionalHeader) < sizeof(struct pe_image_optional_hdr32)) {
    cli_dbgmsg("SizeOfOptionalHeader too small\n");
    if(DETECT_BROKEN) {
    if(ctx->virname)
    *ctx->virname = "Broken.Executable";
    return CL_VIRUS;
    }
    return CL_CLEAN;
    }
    //读取可选镜像文件头数据
    if(cli_readn(desc, &optional_hdr32, sizeof(struct pe_image_optional_hdr32)) != sizeof(struct pe_image_optional_hdr32)) {
    cli_dbgmsg("Can't read optional file header\n");
    if(DETECT_BROKEN) {
    if(ctx->virname)
    *ctx->virname = "Broken.Executable";
    return CL_VIRUS;
    }
    return CL_CLEAN;
    }
    //读取可选镜像文件头标志,判断是32位还是64位
    //ROM映像0x107
    //普通可执行的映像0x10b
    //PE32+是0x20b
    /* This will be a chicken and egg problem until we drop 9x */
    if(EC32(optional_hdr64.Magic)==PE32P_SIGNATURE) {
    //再判断读取可选镜像文件头大小是否正确
    if(EC16(file_hdr.SizeOfOptionalHeader)!=sizeof(struct pe_image_optional_hdr64)) {
    /* FIXME: need to play around a bit more with xp64 */
    cli_dbgmsg("Incorrect SizeOfOptionalHeader for PE32+\n");
    if(DETECT_BROKEN) {
    if(ctx->virname)
    *ctx->virnam


    来自Android客户端2楼2017-08-31 10:57
    回复
      续上...
      [i + 1].rsz));
      /* allocate needed buffer */
      if (!(src = cli_calloc (ssize + dsize, sizeof(char)))) {
      free(exe_sections);
      return CL_EMEM;
      }
      if (exe_sections[i + 1].rsz < offdiff + 12 || exe_sections[i + 1].rsz > ssize) {
      cli_dbgmsg("MEW: Size mismatch: %08x\n", exe_sections[i + 1].rsz);
      free(src);
      break;
      }
      if((bytes = read(desc, src + dsize, exe_sections[i + 1].rsz)) != exe_sections[i + 1].rsz) {
      cli_dbgmsg("MEW: Can't read %d bytes [read: %lu]\n", exe_sections[i + 1].rsz, (unsigned long)bytes);
      free(exe_sections);
      free(src);
      return CL_EIO;
      }
      cli_dbgmsg("MEW: %u (%08x) bytes read\n", (unsigned int)bytes, (unsigned int)bytes);
      /* count offset to lzma proc, if lzma used, 0xe8 -> call */
      if (buff[0x7b] == '\xe8') {
      if (!CLI_ISCONTAINED(exe_sections[1].rva, exe_sections[1].vsz, cli_readint32(buff + 0x7c) + fileoffset + 0x80, 4)) {
      cli_dbgmsg("MEW: lzma proc out of bounds!\n");
      free(src);
      break; /* to next unpacker in chain */
      }
      uselzma = cli_readint32(buff + 0x7c) - (exe_sections[0].rva - fileoffset - 0x80);
      } else {
      uselzma = 0;
      }
      CLI_UNPTEMP("MEW",(src,exe_sections,0));
      CLI_UNPRESULTS("MEW",(unmew11(src, offdiff, ssize, dsize, EC32(optional_hdr32.ImageBase), exe_sections[0].rva, uselzma, ndesc)),1,(src,0));
      break;
      }
      }
      if(epsize<168) {
      free(exe_sections);
      return CL_CLEAN;
      }
      if (found || upack) {
      /* Check EP for UPX vs. FSG vs. Upack */
      /* Upack 0.39 produces 2 types of executables
      * 3 sections: | 2 sections (one empty, I don't chech found if !upack, since it's in OR above):
      * mov esi, value | pusha
      * lodsd | call $+0x9
      * push eax |
      *
      * Upack 1.1/1.2 Beta produces [based on 2 samples (sUx) provided by aCaB]:
      * 2 sections
      * mov esi, value
      * loads
      * mov edi, eax
      *
      * Upack unknown [sample 0297729]
      * 3 sections


      来自Android客户端4楼2017-08-31 11:02
      回复
        * mov esi, value
        * push [esi]
        * jmp
        *
        */
        /* upack 0.39-3s + sample 0151477*/
        while(((upack && nsections == 3) && /* 3 sections */
        ((
        epbuff[0] == '\xbe' && cli_readint32(epbuff + 1) - EC32(optional_hdr32.ImageBase) > min && /* mov esi */
        epbuff[5] == '\xad' && epbuff[6] == '\x50' /* lodsd; push eax */
        )
        ||
        /* based on 0297729 sample from aCaB */
        (epbuff[0] == '\xbe' && cli_readint32(epbuff + 1) - EC32(optional_hdr32.ImageBase) > min && /* mov esi */
        epbuff[5] == '\xff' && epbuff[6] == '\x36' /* push [esi] */
        )
        ))
        ||
        ((!upack && nsections == 2) && /* 2 sections */
        (( /* upack 0.39-2s */
        epbuff[0] == '\x60' && epbuff[1] == '\xe8' && cli_readint32(epbuff+2) == 0x9 /* pusha; call+9 */
        )
        ||
        ( /* upack 1.1/1.2, based on 2 samples */
        epbuff[0] == '\xbe' && cli_readint32(epbuff+1) - EC32(optional_hdr32.ImageBase) < min && /* mov esi */
        cli_readint32(epbuff + 1) - EC32(optional_hdr32.ImageBase) > 0 &&
        epbuff[5] == '\xad' && epbuff[6] == '\x8b' && epbuff[7] == '\xf8' /* loads; mov edi, eax */
        )
        ))
        ) {
        uint32_t vma, off;
        int a,b,c;
        cli_dbgmsg("Upack characteristics found.\n");
        a = exe_sections[0].vsz;
        b = exe_sections[1].vsz;
        if (upack) {
        cli_dbgmsg("Upack: var set\n");
        c = exe_sections[2].vsz;
        ssize = exe_sections[0].ursz + exe_sections[0].uraw;
        off = exe_sections[0].rva;
        vma = EC32(optional_hdr32.ImageBase) + exe_sections[0].rva;
        } else {
        cli_dbgmsg("Upack: var NOT set\n");
        c = exe_sections[1].rva;
        ssize = exe_sections[1].uraw;
        off = 0;
        vma = exe_sections[1].rva - exe_sections[1].uraw;
        }
        dsize = a+b+c;
        CLI_UNPSIZELIMITS("Upack", MAX(MAX(dsize, ssize), exe_sections[1].ursz));
        if (!CLI_ISCONTAINED(0, dsize, exe_sections[1].rva - off, exe_sections[1].ursz) || (upack && !CLI_ISCONTAINED(0, dsize, exe_sections[2].rva - exe_sections[0].rva, ssize))


        来自Android客户端5楼2017-08-31 11:04
        回复
          || ssize > dsize) {
          cli_dbgmsg("Upack: probably malformed pe-header, skipping to next unpacker\n");
          break;
          }
          if((dest = (char *) cli_calloc(dsize, sizeof(char))) == NULL) {
          free(exe_sections);
          return CL_EMEM;
          }
          lseek(desc, 0, SEEK_SET);
          if(read(desc, dest, ssize) != ssize) {
          cli_dbgmsg("Upack: Can't read raw data of section 0\n");
          free(dest);
          break;
          }
          if(upack) memmove(dest + exe_sections[2].rva - exe_sections[0].rva, dest, ssize);
          lseek(desc, exe_sections[1].uraw, SEEK_SET);
          if(read(desc, dest + exe_sections[1].rva - off, exe_sections[1].ursz) != exe_sections[1].ursz) {
          cli_dbgmsg("Upack: Can't read raw data of section 1\n");
          free(dest);
          break;
          }
          CLI_UNPTEMP("Upack",(dest,exe_sections,0));
          CLI_UNPRESULTS("Upack",(unupack(upack, dest, dsize, epbuff, vma, ep, EC32(optional_hdr32.ImageBase), exe_sections[0].rva, ndesc)),1,(dest,0));
          break;
          }
          }
          while(found && (DCONF & PE_CONF_FSG) && epbuff[0] == '\x87' && epbuff[1] == '\x25') {
          /* FSG v2.0 support - thanks to aCaB ! */
          uint32_t newesi, newedi, newebx, newedx;
          ssize = exe_sections[i + 1].rsz;
          dsize = exe_sections[i].vsz;
          CLI_UNPSIZELIMITS("FSG", MAX(dsize, ssize));
          if(ssize <= 0x19 || dsize <= ssize) {
          cli_dbgmsg("FSG: Size mismatch (ssize: %d, dsize: %d)\n", ssize, dsize);
          free(exe_sections);
          return CL_CLEAN;
          }
          newedx = cli_readint32(epbuff + 2) - EC32(optional_hdr32.ImageBase);
          if(!CLI_ISCONTAINED(exe_sections[i + 1].rva, exe_sections[i + 1].rsz, newedx, 4)) {
          cli_dbgmsg("FSG: xchg out of bounds (%x), giving up\n", newedx);
          break;
          }
          if((src = (char *) cli_malloc(ssize)) == NULL) {
          free(exe_sections);
          return CL_EMEM;
          }
          if(!cli_seeksect(desc, &exe_sections[i + 1]) || (unsigned int) cli_readn(desc, src, ssize) != ssize) {
          cli_dbgmsg("Can't read raw data of section %d\n", i + 1);
          free(exe_sections);
          free(src);
          retur


          来自Android客户端6楼2017-08-31 11:07
          回复
            CL_EMEM;
            }
            CLI_UNPTEMP("FSG",(src,dest,exe_sections,0));
            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,0));
            break;
            }
            while(found && (DCONF & PE_CONF_FSG) && epbuff[0] == '\xbe' && cli_readint32(epbuff + 1) - EC32(optional_hdr32.ImageBase) < min) {
            /* FSG support - v. 1.33 (thx trog for the many samples) */
            int sectcnt = 0;
            char *support;
            uint32_t newesi, newedi, oldep, gp, t;
            struct cli_exe_section *sections;
            ssize = exe_sections[i + 1].rsz;
            dsize = exe_sections[i].vsz;
            CLI_UNPSIZELIMITS("FSG", MAX(dsize, ssize));
            if(ssize <= 0x19 || dsize <= ssize) {
            cli_dbgmsg("FSG: Size mismatch (ssize: %d, dsize: %d)\n", ssize, dsize);
            free(exe_sections);
            return CL_CLEAN;
            }
            if(!(gp = cli_rawaddr(cli_readint32(epbuff + 1) - EC32(optional_hdr32.ImageBase), NULL, 0 , &err, fsize, hdr_size)) && err ) {
            cli_dbgmsg("FSG: Support data out of padding area\n");
            break;
            }
            lseek(desc, gp, SEEK_SET);
            gp = exe_sections[i + 1].raw - gp;
            CLI_UNPSIZELIMITS("FSG", gp)
            if((support = (char *) cli_malloc(gp)) == NULL) {
            free(exe_sections);
            return CL_EMEM;
            }
            if((int)cli_readn(desc, support, gp) != (int)gp) {
            cli_dbgmsg("Can't read %d bytes from padding area\n", gp);
            free(exe_sections);
            free(support);
            return CL_EIO;
            }
            /* newebx = cli_readint32(support) - EC32(optional_hdr32.ImageBase); Unused */
            newedi = cli_readint32(support + 4) - EC32(optional_hdr32.ImageBase); /* 1st dest */
            newesi = cli_readint32(support + 8) - EC32(optional_hdr32.ImageBase); /* Source */
            if(newesi < exe_sections[i + 1].rva || newesi - exe_sections[i + 1].rva >= exe_sections[i + 1].rsz) {
            cli_dbgmsg("FSG: Source buffer out of section bounds\n");
            free(support);
            break;
            }
            if(newedi != exe_sections[i].rva) {
            cli_dbgmsg("FSG: Bad destination (is %x should b


            来自Android客户端7楼2017-08-31 11:07
            收起回复
              以上片段可参考…


              来自Android客户端8楼2017-08-31 11:09
              回复