How to detect the types of executable files

How to detect the types of executable files

type

  {
  IMAGE_DOS_HEADER:
    DOS .EXE header.
  }
  IMAGE_DOS_HEADER = packed record
    e_magic   : Word;               // Magic number ("MZ")
    e_cblp    : Word;               // Bytes on last page of file
    e_cp      : Word;               // Pages in file
    e_crlc    : Word;               // Relocations
    e_cparhdr : Word;               // Size of header in paragraphs
    e_minalloc: Word;               // Minimum extra paragraphs needed
    e_maxalloc: Word;               // Maximum extra paragraphs needed
    e_ss      : Word;               // Initial (relative) SS value
    e_sp      : Word;               // Initial SP value
    e_csum    : Word;               // Checksum
    e_ip      : Word;               // Initial IP value
    e_cs      : Word;               // Initial (relative) CS value
    e_lfarlc  : Word;               // Address of relocation table
    e_ovno    : Word;               // Overlay number
    e_res     : packed array [0..3] of Word;  // Reserved words
    e_oemid   : Word;               // OEM identifier (for e_oeminfo)
    e_oeminfo : Word;               // OEM info; e_oemid specific
    e_res2    : packed array [0..9] of Word;  // Reserved words
    e_lfanew  : Longint;            // File address of new exe header
  end;

  {
  TExeFileKind:
    The kinds of files recognised.
  }
  TExeFileKind = (
    fkUnknown,  // unknown file kind: not an executable
    fkError,    // error file kind: used for files that don‘t exist
    fkDOS,      // DOS executable
    fkExe32,    // 32 bit executable
    fkExe16,    // 16 bit executable
    fkDLL32,    // 32 bit DLL
    fkDLL16,    // 16 bit DLL
    fkVXD       // virtual device driver
  );

function ExeType(const FileName: string): TExeFileKind;
  {Examines given file and returns a code that indicates the type of
  executable file it is (or if it isn‘t an executable)}
const
  cDOSRelocOffset = $18;  // offset of "pointer" to DOS relocation table
  cWinHeaderOffset = $3C; // offset of "pointer" to windows header in file
  cNEAppTypeOffset = $0D; // offset in NE windows header of app type field
  cDOSMagic = $5A4D;      // magic number for a DOS executable
  cNEMagic = $454E;       // magic number for a NE executable (Win 16)
  cPEMagic = $4550;       // magic nunber for a PE executable (Win 32)
  cLEMagic = $454C;       // magic number for a Virtual Device Driver
  cNEDLLFlag = $80        // flag in NE app type field indicating a DLL
var
  FS: TFileStream;              // stream to executable file
  WinMagic: Word;               // word containing PE or NE magic numbers
  HdrOffset: LongInt;           // offset of windows header in exec file
  ImgHdrPE: IMAGE_FILE_HEADER;  // PE file header record
  DOSHeader: IMAGE_DOS_HEADER;  // DOS header
  AppFlagsNE: Byte;             // byte defining DLLs in NE format
  DOSFileSize: Integer;         // size of DOS file
begin
  try
    // Open stream onto file: raises exception if can‘t be read
    FS := TFileStream.Create(FileName, fmOpenRead + fmShareDenyNone);
    try
      // Assume unkown file
      Result := fkUnknown;
      // Any exec file is at least size of DOS header long
      if FS.Size < SizeOf(DOSHeader) then
        Exit;
      FS.ReadBuffer(DOSHeader, SizeOf(DOSHeader));
      // DOS files begin with "MZ"
      if DOSHeader.e_magic <> cDOSMagic then
        Exit;
      // DOS files have length >= size indicated at offset $02 and $04
      // (offset $02 indicates length of file mod 512 and offset $04
      // indicates no. of 512 pages in file)
      if (DOSHeader.e_cblp = 0) then
        DOSFileSize := DOSHeader.e_cp * 512
      else
        DOSFileSize := (DOSHeader.e_cp - 1) * 512 + DOSHeader.e_cblp;
      if FS.Size <  DOSFileSize then
        Exit;
      // DOS file relocation offset must be within DOS file size.
      if DOSHeader.e_lfarlc > DOSFileSize then
        Exit;
      // We assume we have an executable file: assume its a DOS program
      Result := fkDOS;
      // Try to find offset of Windows program header
      if FS.Size <= cWinHeaderOffset + SizeOf(LongInt) then
        // file too small for windows header "pointer": it‘s a DOS file
        Exit;
      // read it
      FS.Position := cWinHeaderOffset;
      FS.ReadBuffer(HdrOffset, SizeOf(LongInt));
      // Now try to read first word of Windows program header
      if FS.Size <= HdrOffset + SizeOf(Word) then
        // file too small to contain header: it‘s a DOS file
        Exit;
      FS.Position := HdrOffset;
      // This word should be NE, PE or LE per file type: check which
      FS.ReadBuffer(WinMagic, SizeOf(Word));
      case WinMagic of
        cPEMagic:
        begin
          // 32 bit Windows application: now check whether app or DLL
          if FS.Size < HdrOffset + SizeOf(LongWord) + SizeOf(ImgHdrPE) then
            // file not large enough for image header: assume DOS
            Exit;
          // read Windows image header
          FS.Position := HdrOffset + SizeOf(LongWord);
          FS.ReadBuffer(ImgHdrPE, SizeOf(ImgHdrPE));
          if (ImgHdrPE.Characteristics and IMAGE_FILE_DLL)
            = IMAGE_FILE_DLL then
            // characteristics indicate a 32 bit DLL
            Result := fkDLL32
          else
            // characteristics indicate a 32 bit application
            Result := fkExe32;
        end;
        cNEMagic:
        begin
          // We have 16 bit Windows executable: check whether app or DLL
          if FS.Size <= HdrOffset + cNEAppTypeOffset
            + SizeOf(AppFlagsNE) then
            // app flags field would be beyond EOF: assume DOS
            Exit;
          // read app flags byte
          FS.Position := HdrOffset + cNEAppTypeOffset;
          FS.ReadBuffer(AppFlagsNE, SizeOf(AppFlagsNE));
          if (AppFlagsNE and cNEDLLFlag) = cNEDLLFlag then
            // app flags indicate DLL
            Result := fkDLL16
          else
            // app flags indicate program
            Result := fkExe16;
        end;
        cLEMagic:
          // We have a Virtual Device Driver
          Result := fkVXD;
        else
          // DOS application
          {Do nothing - DOS result already set};
      end;
    finally
      FS.Free;
    end;
  except
    // Exception raised in function => error result
    Result := fkError;
  end;
end;
时间: 2024-10-13 03:59:37

How to detect the types of executable files的相关文章

Files and Directories

Files and Directories Introduction In the previous chapter we coveredthe basic functions that perform I/O. The discussion centered on I/O for regular files-opening a file, and reading or writing a file. We'll now look at additionalfeatures of the fil

The Portable Executable File Format from Top to Bottom(每个结构体都非常清楚)

The Portable Executable File Format from Top to Bottom Randy KathMicrosoft Developer Network Technology Group Created: June 12, 1993 Click to open or copy the files in the EXEVIEW sample application for this technical article. Click to open or copy t

Autotools Mythbuster

Preface Diego Elio?"Flameeyes"?Pettenò Author and Publisher?<[email protected]> SRC=https://autotools.io/index.html David J.?"user99"?Cozatt Miscellaneous Editing?<[email protected]> Copyright ? 2009-2013 Diego Elio Pettenò

YASM User Manual

This document is the user manual for the Yasm assembler. It is intended as both an introduction and a general-purpose reference for all Yasm users. 1.?Introduction Yasm is a BSD-licensed assembler that is designed from the ground up to allow for mult

OPENVPN搭建与配置

Content-type: text/html; charset=UTF-8 openvpn Section: Maintenance Commands (8)Updated: 17 November 2008Index Return to Main Contents NAME openvpn - secure IP tunnel daemon. SYNOPSIS openvpn [ options ... ] INTRODUCTION OpenVPN is an open source VPN

Dr.memory

Run Dr.memory on visual c++ 2013 Title: Dr. Memory Command: C:\Program Files (x86)\Dr. Memory\bin\drmemory.exe Arguments: -visual_studio -- $(TargetPath) Initial Directory: $(TargetDir) set arguments-light -no_midchunk_inheritance_ok -no_check_gdi -n

PE打补丁技术大全

Downloads PE Viewer PE Maker - Step 1 - Add new Section. PE Maker - Step 2 - Travel towards OEP. PE Maker - Step 3 - Support Import Table. PE Maker - Step 4 - Support DLL and OCX. PE Maker - Step 5 - Final work. CALC.EXE - test file Contents 0. Prefa

Code Complete阅读笔记(二)

2015-03-06   328   Unusual Data Types    ——You can carry this technique to extremes,putting all the variables in your program into one big,juicy variable and then passingit everywhere.Careful programmers avoid bundling data any more than is logically

PostgreSQL源码安装文档

This document describes the installation of PostgreSQL using the source    code distribution. (If you are installing a pre-packaged distribution,    such as an RPM or Debian package, ignore this document and read the    packager's instructions instea