⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pe_sections.idc

📁 加密解密2配套光盘,内有加密解密第二版书内提及的软件.
💻 IDC
📖 第 1 页 / 共 5 页
字号:
#include <idc.idc>

/*
// File:
//   pe_sections.idc
//
// Created by:
//   Atli Gudmundsson (agudmundsson@symantec.com)
//
// Purpose:
//   parses the input file and if it is a PE executable does the following:
//   - Loads and creates a HEADER section that corresponds to the PE file header.
//   - Creates the MZ and PE header structures at the correct place in the header.
//     - All fields in the structures, that contain a non zero offset, are resolved.
//   - Creates the PE section structures at the correct place in the header.
//   - Loads and creates all possible sections.
//   - Creates table data structures.  Those currently recognizes are:
//
//     - the export table.
//     - the import table.
//     - the resource table (bare format).
//     - the debug table.
//     - the relocs table.
//     - the tls table.
//     - the bound import table
//
// Note:
//   Be sure to uncheck the 'Make imports section' option, when loading the file for the first time.
//   Otherwise most of the data in the import section will be invisible.
//
//   Can be unchecked by default from IDA.CFG by specifying PE_MAKE_IDATA = NO.
//
// Usage:
//   Just run the script ;).
//
// Fixes/additions
//   amg - ??-06-1999 - 1st version.
//   amg - 06-03-2000 - a total rewrite, merging two scripts (pe_header.idc --> pe_section.idc),
//                      also added some comments.
//   amg - 07-03-2000 - added xrefs in to the structures (see above) so that you can now travel
//                      from one structure to the next (e.g. from the MZ header to the PE header)
//                      This doesn't work for versions less than or equal to v4.02, but it
//                      won't cause any errors either...
//   amg - 01-08-2000 - added an #ifdef because of function incompatability between new and old 
//                      versions of IDA.
//   amg - 01-08-2000 - a major rewrite.  The script now loads all sections possible.
//   amg - 06-08-2000 - added some information messages.
//   amg - 06-08-2000 - the script now recognizes when a previously loaded section is interfering
//                      with the loading of another section and tries to fix that.
//   amg - 21-08-2000 - added information about the entry (what it is and in which section)
//   amg - 21-08-2000 - added more information messages.
//   amg - 29-08-2000 - some bug fixes.
//   amg - 30-08-2000 - added support for parsing the header tables.
//   amg - 18-09-2000 - resource table added (bare format).
//   amg - 18-09-2000 - some bug fixes.
//   amg - 21-09-2000 - fixed a minor overside when I was optimizing the script last time ;)
//                      I forgot to enforce the loading of the HEADER section, silly me :)
//                      anyway, fixed.
//   amg - 21-09-2000 - added a coooool banner that is displayed in the message output.
//   amg - 25-09-2000 - we now force the creation of all structures, overstepping some problems
//                      where IDA has already declared a data element in the middle of the structure.
//   amg - 25-09-2000 - the TimeStamp function ULDateToStr() now supports times stamps with the high bit set.
//   amg - 25-09-2000 - the script now recognizes when there is no entrypoint in the file.
//   amg - 26-09-2000 - the script now parses the relocs tables correctly, even though some of the
//                      page entries look broken.
//   amg - 09-10-2000 - if the header physical size is too small then we just use the virtual size instead.
//   amg - 09-10-2000 - names are now created correctly, when requested (overlapping datastructures are destroyed).
//   amg - 17-10-2000 - we can now see where each section ends in the file.
//   amg - 02-11-2000 - export ordinal comments are now correct (base added)
//   amg - 03-11-2000 - we now create all structures, always.  Helps debugging apps.
//   amg - 03-11-2000 - tls table added.
//   amg - 05-11-2000 - minor fixes:
//                       - to the date function (ULDateToStr()).
//                       - to the export handling.
//   amg - 06-11-2000 - minor enhancement:
//                       - to the import handling (zero terminated entries).
//   amg - 09-11-2000 - added some minor comments to the section flags.
//   amg - 10-11-2000 - the script now:
//                       - skips a particular table if the user presses No.
//                       - stops parsing tables if the user presses Esc/Cancel.
//   amg - 10-11-2000 - fixed the TLS parsing code, we no longer assume we have a callbacks array pointer.
//   amg - 10-11-2000 - added better support for user termination requests, when parsing individual tables.
//   amg - 14-11-2000 - the script now handles correctly invalid reloc tables, in regard to when finding empty entries in the table.
//   amg - 15-11-2000 - the script now displays a message when ever it detects extra data after the image.
//   amg - 21-11-2000 - the script now uses a custom Dword() function (LEDword()) since the old one returns 0xff in
//                      those bytes which would reference into undefined segment memory.
//   amg - 21-11-2000 - we now display a warning if the TLS contains callbacks.
//   amg - 28-11-2000 - fixed the physical size, when loading sections, it is now adjusted to the file alignment.
//   amg - 14-12-2000 - we now use GetInputFilePath() instead of GetInputFile(), to get the location of the original file.
//   amg - 18-12-2000 - major modifications (to support the PE_DLLS.IDC script):
//                      - added a NO_MAIN ifdef so that the script can be called from another script.
//                      - added a prefix variable (called DLL_name) to all functions.
//   amg - 15-01-2001 - added some error checking, regarding section creation. (more is needed though)
//   amg - 28-02-2001 - fixed some bugs
//                      - a most embarrassing bug... forgot a return in the LEWord() function.
//                      - the above fix exposed another bug in the doResourceTable() function... fixed.
//   amg - 28-02-2001 - the script now creates a function and a name on all exports which have no name,
//                      this allows the script to work better with the PE_DLLS.IDC script.
//   amg - 01-03-2001 - the script no longer gives the user the option of selecting which tables to load,
//                      all tables are loaded by default.
//   amg - 06-03-2001 - the script no longer tries to make forwarder entries in the export table into functions,
//                      instead it makes them into strings.
//   amg - 25-04-2001 - the script now supports 'strange' section values, such as when the first section in the
//                      section table is realy the last section in the file.
//   amg - 25-04-2001 - IDA may occasionaly change the default string type from ASCII to something else (such as
//                      PASCAL), this would play havoc with the strings created by the script.  The script now
//                      bypasses this behaviour, with out affecting IDA.
//   amg - 01-05-2001 - re-enabled the asking of whether to load all tables (see change at 01-03-2001), but this time it is
//                      #ifdefed (Should help when analyzing weird script errors)
//   amg - 01-05-2001 - adjusted the import parsing code so that it would actualy terminate the import directory correctly.
//   amg - 02-05-2001 - the script is no longer fooled by sections which have a very high RVA (2G+), when determining the
//                      header virtual size.
//   amg - 02-05-2001 - the script now conforms to IDAs way of things when creating section names (replacing spaces with '_')
//   amg - 22-05-2001 - the script now behaves correctly when creating sections with ":" in the name, leaving them in there.
//                      note: this bug would not allow the pe_dlls.idc script to recognize already loaded DLLs (sections)
//   amg - 28-05-2001 - bugfix: if all sections vSizes were zero then the HEADER size would be 0x7fffffff.
//   amg - 14-06-2001 - bugfix: if phyAddr was 0 and phySize was not then the section was loaded with the header data.
//                              - windows actualy takes phyAddr == 0 to mean that phySize is also 0
//                              - additional research revealed that windows truncates phyAddr to a 200h boundary.
//                                this means that if (0 < phyAddr < 200h) and (phySize != 0) then the section will be
//                                loaded with the header data.
//   amg - 14-06-2001 - interface: minor adjustments to the output of the script (made it more understandable (hopefully ;))
//   amg - 22-07-2001 - bound import table now included.
//   amg - 04-08-2001 - PE2 format now supported (PE32+ if you will :).
//                      note: due to IDA limitations the image base is handled as a 32-bit value (high 32-bits are ignored)
//   amg - 04-08-2001 - debug directory now supported.
//   amg - 07-08-2001 - bugfix: bound import table seems to be constructed of {DWORD, WORD, WORD} nibbles
//   amg - 19-08-2001 - bugfix: Native subsystem now behaves correctly in regards to non-sector aligned sections
//   amg - 28-08-2001 - bugfix: some runtime packers pack the export table.  This would cause the script to go into a very long loop.
//   amg - 02-09-2001 - bugfix: the script now asks the user what it should do when it encounters files with weird section offsets.
//   amg - 02-09-2001 - interface: image flags will now be different for multivalue flags (reversing all bits when cleared)
//   amg - 12-10-2001 - interface: image flags will now be of the following form: mask - bits - info
//   amg - 14-10-2001 - interface: if the script encounters a HEADER section it will ask the user if he wants to refresh the section data.
//   amg - 14-10-2001 - interface: the script now detects if there is a .reloc section but no relocs and asks if it should try to parse
//                      it for relocs.
//   amg - 14-10-2001 - bugfix: the script is now fully PE2 compliant (any future bugs aside ;)
//   amg - 28-10-2001 - bugfix: in Windows 00000000 as an EP is valid, but only if the image is a non-DLL
//   amg - 28-10-2001 - interface: image flags will now be of the following form: mask - bit state - info
//                        you can see I'm having trouble with this one (what do you think is the best one so far ? :)
//   amg - 26-11-2001 - bugfix: Windows does not care about the size field of the resource table
//   amg - 26-11-2001 - bugfix: TLS code now correctly displays the TLS directory (instead of most of the time leaving it undefined)
//   amg - 28-11-2001 - bugfix: offset values are now taken into account when adjusting section sizes to alignment values
//   amg - 04-02-2002 - interface: we now add the correct name of an export as a comment (in the export table) if needed.
//   amg - 12-03-2002 - minor structural change: doPEtables is now handled with in the LoadSections function
//   amg - 12-03-2002 - bugfix: the header structures (MZ, PE) are now created after everything else is done.
//                              otherwise some tables might actually 'destroy' them...
//   amg - 05-04-2002 - enhancement: changed name of ULDToStr() to ULDateToStr()
//                                   created ULDosDateToStr()
//   amg - 05-04-2002 - enhancement: we now display Borlands [DOS] time along with Microsoft time for the timestamp field in the pe header.
//   amg - 17-05-2002 - enhancement: loading of the image is now in a seperate function (i.e. EXEload()), to better support secondary scripts
//                                   that want to use this one (e.g. the pe_dlls.idc script).
//   amg - 13-07-2002 - bugfix:
//                        - introduced a define for the DLL name seperator (used in pe_dlls.idc as well).
//                        - we now display the VA for the entry point correctly in PE2 images.
//                        - we now, correctly, recognize an EP==0 in the HEADER section.
//                        - better reporting of strangely terminated relocs
//   amg - 13-07-2002 - enhancement:
//                        - we now resolve DLL address collisions (when called from pe_dlls.idc),
//                          loading the second DLL at a different (free) location.
//                        - we now apply fixups to all relocated DLLs (most common relocs are supported).
//   amg - 15-07-2002 - bugfix:
//                        - IDA prefixes sections names with an underscore '_' if it starts with a number, section creation now recognizes this.
//                        - we now recognize a corrupted section count field (too high a value).
//   amg - 15-07-2002 - bugfix:
//                        - addition of image base to 64-bit relocations is now applied correctly (detecting any carry).
//
*/

// Uncomment the following line to allow the user to choose which tables to parse (good for script debugging).
// #define DEBUG_ASK_TABLES

#define MZ_HEADER_STRUCTURE_NAME  "S_MZ_HEADER"
#define PE_HEADER_STRUCTURE_NAME  "S_PE_HEADER"
#define PE_SECTION_STRUCTURE_NAME "S_PE_SECTION"

#define PE_HEADER_SECTION_NAME    "HEADER"
#define DLL_SEPERATOR             "_"

// The following define is no longer supported:
//
//#define IDA_IS_OLD
//
//   comment the above line if you are using v3.85+
// uncomment the above line if you are using pre v3.85

#ifndef NO_MAIN

static main(void)
{
  return EXEload();
}

#endif

static EXEload(void)
{
  auto fhandle;
  auto MZ_signature, PE_signature;
  auto current;
  auto PEoffset, imageBase;

  auto error;

  error = 0;

  Message("-------------------------------------------------------------------------------\n\n");
  Message("  The PE header parser script.\n  Created by Atli Gudmundsson <agudmundsson@symantec.com>\n");
  Message("\n");

  current = GetInputFilePath();
  fhandle = fopen(current, "rb");

  while(fhandle == 0)
  {
#ifdef IDA_IS_OLD
    current = AskFile(current, "Please find the file for me");
#else
    current = AskFile(-1, current, "Please find the file for me");
#endif
    if(current == 0)
    {
      error = -1;
      break;
    }

    fhandle = fopen(current, "rb");
  }

  // fhandle contains a valid handle to an open file.

  while(!error)
  {
    if(MySeek(fhandle, 0, 0) != 0)
    {
      error = -1;
      break;
    }

    MZ_signature = readshort(fhandle, 0);

    if((MZ_signature != 0x4d5a) && (MZ_signature != 0x5a4d))
    {
      WarningMessage("This is not an MZ executable!");
      error = -1;
      break;
    }

    MySeek(fhandle, 0x3c, 0);
    PEoffset = readlong(fhandle, 0);

    MySeek(fhandle, PEoffset, 0);
    PE_signature = readlong(fhandle, 0);

    if(PE_signature == 0x4550)
    {
      imageBase = LoadSections(fhandle, PEoffset, "");
      if(imageBase == -1)
      {
        error = -1;
      }

      break;
    }
    else
    {
      WarningMessage("This is not a PE executable!");
      error = -1;
      break;
    }
  }

  fclose(fhandle);

  if(!error)
  {
    return imageBase;
  }
  else
  {
    return BADADDR;
  }
}

static WarningMessage(outString)
{
  Message(outString + "\n");
  Warning(outString);
}

static CleanSectName(sect_name)
{
  auto retval;

  retval = "";

  if(sect_name != "")
  {
    auto i, str_len;

    str_len = strlen(sect_name);
    i = 0;

    do
    {
      auto letter, sub_str;

      sub_str = substr(sect_name, i, i+1);

      if((sub_str != ":") && (sub_str != ".") && ((sub_str < "0") || ((sub_str > "9") && (sub_str < "A") || (sub_str > "Z") && ((sub_str < "a") || (sub_str > "z")))))
      {
        sub_str = "_";
      }

      retval = retval + sub_str;

      i++;
    }
    while(i != str_len);
  }

  return retval;
}

/*
// Function:
//   CreateSection
// Purpose:
//   Creates a virtual section, expanding or adjusting already existing sections
//   as needed.
// Input:
//   SectionName
//   SectionStart  - VA of the start of the section
//   vSize         - the requested virtual size of the section
//   phyAddr       - offset of this sections physical block, in the file
//   phySize       - size of this sections physical block, in the file
//   loadData      - specifies wether the function should actually read the data from the file.
// Returns:
//   nothing
// Notes:
//   The function also prints messages that tell the user if anything unusual happend.
*/
static CreateSection(fhandle, SectionName, SectionStart, vSize, phyAddr, phySize, loadData)
{
  auto SectionBase;
  auto question, answer;

  SectionName = CleanSectName(SectionName);

#if defined(DEBUG_THIS)
  Message(form("%s: [%08X, %08X] --> [%08X, %08X]\n", SectionName, phyAddr, phySize, SectionStart, vSize));
#endif

  SectionBase = SectionStart;

  if(vSize != 0)
  {
    auto SectionEnd;

    SectionEnd = SectionStart + vSize;

    while(SectionStart < SectionEnd)
    {
      if(SegStart(SectionStart) != BADADDR)
      {
        // A section, at the specified address, already exists.

        if((SegName(SectionStart) == SectionName) || (SegName(SectionStart) == "_" + SectionName)) // if name starts with a number then IDA prefixes it with an '_'
        {
          // A section with the given name already exists at this address.

          if(SegEnd(SectionStart) >= SectionEnd)
          {
            // cool, nothing more needed

            Message("  %s (%.8X - %.8X) section already exists.\n", SegName(SectionStart), SegStart(SectionStart), SegEnd(SectionStart));

            if((SegStart(SectionStart) != SectionStart) || (SegEnd(SectionStart) != SectionEnd))
            {
              Message("  and already spans the addresses (%.8X - %.8X).\n", SectionStart, SectionEnd);
            }

            SectionStart = SectionEnd;
            break;
          }
          else
          {
            // must expand the section upwards.

            SegBounds(SectionStart, SegStart(SectionStart), SectionEnd, 1);
            SegRename(SectionStart, SectionName);

            Message("  %s section found at %.8X, expanded to (%.8X - %.8X).\n", SectionName, SectionStart, SegStart(SectionStart), SegEnd(SectionStart));
          }
        }
        else
        {
          // An unknown section, at the specified address, already exists.
          Message("  %s (%.8X - %.8X) section already spans the address %.8X.\n", SegName(SectionStart), SegStart(SectionStart), SegEnd(SectionStart), SectionStart);
          Message("  %s created at the next available address.\n", SectionName);

          SectionStart = SegEnd(SectionStart);
          continue;
        }
      }
      else
      {
        // no section has this start address in itself.

        SegCreate(SectionStart, SectionEnd, 0, 1, saRelPara, scPub);
        SegRename(SectionStart, SectionName);
      }

      // SectionStart is always inside a section at this point
      // SegEnd(SectionStart) == SectionEnd OR SegEnd(SectionStart) is inside a section

      if(SegEnd(SectionStart) < SectionEnd)
      {
        auto temp;

        // hmmm, unable to do the entire segment
        // must have another segment interfering

        temp = SegEnd(SectionStart);

        if(SegName(temp) == SectionName)
        {
          // they have the same names, so let's merge them

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -