// // This program was written by Sang Cho, assistant professor at // the department of // computer science and engineering // chongju university // this program is based on the program pefile.c // which is written by Randy Kath(Microsoft Developmer Network Technology Group) // in june 12, 1993. // I have investigated P.E. file format as thoroughly as possible, // but I cannot claim that I am an expert yet, so some of its information // may give you wrong results. // // // // language used: djgpp // date of creation: September 28, 1997 // // date of first release: October 15, 1997 // // // you can contact me: e-mail address: sangcho@alpha94.chongju.ac.kr // hitel id: chokhas // phone number: (0431) 229-8491 +82-431-229-8491 // // // // Copyright (C) 1997. by Sang Cho. // // Permission is granted to make and distribute verbatim copies of this // program provided the copyright notice and this permission notice are // preserved on all copies. // // // File: pedump.c ( I included header file into source file. ) // // LICENSE // Sources released under GNU General Public License version 2 // or later by Mr. Sang Cho permission. // // REVISIONS // 2000-04-23 (ea) Initial adaptation to GCC/MinGW/ROS. // 2000-08-05 (ea) Initial raw adaptation done. // #include #include #include #include #include #include #include #ifndef bcopy #define bcopy(s,d,z) memcpy((d),(s),(z)) #endif typedef char CHAR; typedef short WCHAR; typedef short SHORT; typedef long LONG; typedef unsigned short USHORT; typedef unsigned long DWORD; typedef int BOOL; typedef unsigned char BYTE; typedef unsigned short WORD; typedef BYTE *PBYTE; typedef WORD *PWORD; typedef DWORD *PDWORD; typedef void *LPVOID; typedef int boolean; #define VOID void #define BOOLEAN boolean #ifndef NULL #define NULL 0 #endif #define FALSE 0 #define TRUE 1 #define CONST const #define LOWORD(l) ((WORD)(l)) #define WINAPI __stdcall // // Image Format // #define IMAGE_DOS_SIGNATURE 0x5A4D // MZ #define IMAGE_OS2_SIGNATURE 0x454E // NE #define IMAGE_OS2_SIGNATURE_LE 0x454C // LE #define IMAGE_VXD_SIGNATURE 0x454C // LE #define IMAGE_NT_SIGNATURE 0x00004550 // PE00 typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header WORD e_magic; // Magic number WORD e_cblp; // Bytes on last page of file WORD e_cp; // Pages in file WORD e_crlc; // Relocations WORD e_cparhdr; // Size of header in paragraphs WORD e_minalloc; // Minimum extra paragraphs needed WORD e_maxalloc; // Maximum extra paragraphs needed WORD e_ss; // Initial (relative) SS value WORD e_sp; // Initial SP value WORD e_csum; // Checksum WORD e_ip; // Initial IP value WORD e_cs; // Initial (relative) CS value WORD e_lfarlc; // File address of relocation table WORD e_ovno; // Overlay number WORD e_res[4]; // Reserved words WORD e_oemid; // OEM identifier (for e_oeminfo) WORD e_oeminfo; // OEM information; e_oemid specific WORD e_res2[10]; // Reserved words LONG e_lfanew; // File address of new exe header } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; // // File header format. // typedef struct _IMAGE_FILE_HEADER { WORD Machine; WORD NumberOfSections; DWORD TimeDateStamp; DWORD PointerToSymbolTable; DWORD NumberOfSymbols; WORD SizeOfOptionalHeader; WORD Characteristics; } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; #define IMAGE_SIZEOF_FILE_HEADER 20 #define IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file. #define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved externel references). #define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file. #define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file. #define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed. #define IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine. #define IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file #define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 // If Image is on removable media, copy and run from the swap file. #define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 // If Image is on Net, copy and run from the swap file. #define IMAGE_FILE_SYSTEM 0x1000 // System File. #define IMAGE_FILE_DLL 0x2000 // File is a DLL. #define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 // File should only be run on a UP machine #define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed. #define IMAGE_FILE_MACHINE_UNKNOWN 0 #define IMAGE_FILE_MACHINE_I386 0x14c // Intel 386. #define IMAGE_FILE_MACHINE_R3000 0x162 // MIPS little-endian, 0x160 big-endian #define IMAGE_FILE_MACHINE_R4000 0x166 // MIPS little-endian #define IMAGE_FILE_MACHINE_R10000 0x168 // MIPS little-endian #define IMAGE_FILE_MACHINE_ALPHA 0x184 // Alpha_AXP #define IMAGE_FILE_MACHINE_POWERPC 0x1F0 // IBM PowerPC Little-Endian // // Directory format. // typedef struct _IMAGE_DATA_DIRECTORY { DWORD VirtualAddress; DWORD Size; } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 // // Optional header format. // typedef struct _IMAGE_OPTIONAL_HEADER { // // Standard fields. // WORD Magic; BYTE MajorLinkerVersion; BYTE MinorLinkerVersion; DWORD SizeOfCode; DWORD SizeOfInitializedData; DWORD SizeOfUninitializedData; DWORD AddressOfEntryPoint; DWORD BaseOfCode; DWORD BaseOfData; // // NT additional fields. // DWORD ImageBase; DWORD SectionAlignment; DWORD FileAlignment; WORD MajorOperatingSystemVersion; WORD MinorOperatingSystemVersion; WORD MajorImageVersion; WORD MinorImageVersion; WORD MajorSubsystemVersion; WORD MinorSubsystemVersion; DWORD Win32VersionValue; DWORD SizeOfImage; DWORD SizeOfHeaders; DWORD CheckSum; WORD Subsystem; WORD DllCharacteristics; DWORD SizeOfStackReserve; DWORD SizeOfStackCommit; DWORD SizeOfHeapReserve; DWORD SizeOfHeapCommit; DWORD LoaderFlags; DWORD NumberOfRvaAndSizes; IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; } IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER; typedef struct _IMAGE_NT_HEADERS { DWORD Signature; IMAGE_FILE_HEADER FileHeader; IMAGE_OPTIONAL_HEADER OptionalHeader; } IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS; // Directory Entries #define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory #define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory #define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Resource Directory #define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory #define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory #define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Base Relocation Table #define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory #define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // Description String #define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // Machine Value (MIPS GP) #define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory #define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory #define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 // Bound Import Directory in headers #define IMAGE_DIRECTORY_ENTRY_IAT 12 // Import Address Table // // Section header format. // #define IMAGE_SIZEOF_SHORT_NAME 8 typedef struct _IMAGE_SECTION_HEADER { BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; union { DWORD PhysicalAddress; DWORD VirtualSize; } Misc; DWORD VirtualAddress; DWORD SizeOfRawData; DWORD PointerToRawData; DWORD PointerToRelocations; DWORD PointerToLinenumbers; WORD NumberOfRelocations; WORD NumberOfLinenumbers; DWORD Characteristics; } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; #define IMAGE_SIZEOF_SECTION_HEADER 40 // // Export Format // typedef struct _IMAGE_EXPORT_DIRECTORY { DWORD Characteristics; DWORD TimeDateStamp; WORD MajorVersion; WORD MinorVersion; DWORD Name; DWORD Base; DWORD NumberOfFunctions; DWORD NumberOfNames; PDWORD *AddressOfFunctions; PDWORD *AddressOfNames; PWORD *AddressOfNameOrdinals; } IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY; // // Import Format // typedef struct _IMAGE_IMPORT_BY_NAME { WORD Hint; BYTE Name[1]; } IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME; #define IMAGE_ORDINAL_FLAG 0x80000000 #define IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff) // // Resource Format. // // // Resource directory consists of two counts, following by a variable length // array of directory entries. The first count is the number of entries at // beginning of the array that have actual names associated with each entry. // The entries are in ascending order, case insensitive strings. The second // count is the number of entries that immediately follow the named entries. // This second count identifies the number of entries that have 16-bit integer // Ids as their name. These entries are also sorted in ascending order. // // This structure allows fast lookup by either name or number, but for any // given resource entry only one form of lookup is supported, not both. // This is consistant with the syntax of the .RC file and the .RES file. // // Predefined resource types ... there may be some more, but I don't have // the information yet. .....sang cho..... #define RT_NEWRESOURCE 0x2000 #define RT_ERROR 0x7fff #define RT_CURSOR 1 #define RT_BITMAP 2 #define RT_ICON 3 #define RT_MENU 4 #define RT_DIALOG 5 #define RT_STRING 6 #define RT_FONTDIR 7 #define RT_FONT 8 #define RT_ACCELERATORS 9 #define RT_RCDATA 10 #define RT_MESSAGETABLE 11 #define RT_GROUP_CURSOR 12 #define RT_GROUP_ICON 14 #define RT_VERSION 16 #define NEWBITMAP (RT_BITMAP|RT_NEWRESOURCE) #define NEWMENU (RT_MENU|RT_NEWRESOURCE) #define NEWDIALOG (RT_DIALOG|RT_NEWRESOURCE) typedef struct _IMAGE_RESOURCE_DIRECTORY { DWORD Characteristics; DWORD TimeDateStamp; WORD MajorVersion; WORD MinorVersion; WORD NumberOfNamedEntries; WORD NumberOfIdEntries; // IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[1]; } IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY; #define IMAGE_RESOURCE_NAME_IS_STRING 0x80000000 #define IMAGE_RESOURCE_DATA_IS_DIRECTORY 0x80000000 // // Each directory contains the 32-bit Name of the entry and an offset, // relative to the beginning of the resource directory of the data associated // with this directory entry. If the name of the entry is an actual text // string instead of an integer Id, then the high order bit of the name field // is set to one and the low order 31-bits are an offset, relative to the // beginning of the resource directory of the string, which is of type // IMAGE_RESOURCE_DIRECTORY_STRING. Otherwise the high bit is clear and the // low-order 16-bits are the integer Id that identify this resource directory // entry. If the directory entry is yet another resource directory (i.e. a // subdirectory), then the high order bit of the offset field will be // set to indicate this. Otherwise the high bit is clear and the offset // field points to a resource data entry. // typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY { DWORD Name; DWORD OffsetToData; } IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY; // // For resource directory entries that have actual string names, the Name // field of the directory entry points to an object of the following type. // All of these string objects are stored together after the last resource // directory entry and before the first resource data object. This minimizes // the impact of these variable length objects on the alignment of the fixed // size directory entry objects. // typedef struct _IMAGE_RESOURCE_DIRECTORY_STRING { WORD Length; CHAR NameString[1]; } IMAGE_RESOURCE_DIRECTORY_STRING, *PIMAGE_RESOURCE_DIRECTORY_STRING; typedef struct _IMAGE_RESOURCE_DIR_STRING_U { WORD Length; WCHAR NameString[1]; } IMAGE_RESOURCE_DIR_STRING_U, *PIMAGE_RESOURCE_DIR_STRING_U; // // Each resource data entry describes a leaf node in the resource directory // tree. It contains an offset, relative to the beginning of the resource // directory of the data for the resource, a size field that gives the number // of bytes of data at that offset, a CodePage that should be used when // decoding code point values within the resource data. Typically for new // applications the code page would be the unicode code page. // typedef struct _IMAGE_RESOURCE_DATA_ENTRY { DWORD OffsetToData; DWORD Size; DWORD CodePage; DWORD Reserved; } IMAGE_RESOURCE_DATA_ENTRY, *PIMAGE_RESOURCE_DATA_ENTRY; // Menu Resources ... added by .....sang cho.... // Menu resources are composed of a menu header followed by a sequential list // of menu items. There are two types of menu items: pop-ups and normal menu // itmes. The MENUITEM SEPARATOR is a special case of a normal menu item with // an empty name, zero ID, and zero flags. typedef struct _IMAGE_MENU_HEADER { WORD wVersion; // Currently zero WORD cbHeaderSize; // Also zero } IMAGE_MENU_HEADER, *PIMAGE_MENU_HEADER; typedef struct _IMAGE_POPUP_MENU_ITEM { WORD fItemFlags; WCHAR szItemText[1]; } IMAGE_POPUP_MENU_ITEM, *PIMAGE_POPUP_MENU_ITEM; typedef struct _IMAGE_NORMAL_MENU_ITEM { WORD fItemFlags; WORD wMenuID; WCHAR szItemText[1]; } IMAGE_NORMAL_MENU_ITEM, *PIMAGE_NORMAL_MENU_ITEM; #define GRAYED 0x0001 // GRAYED keyword #define INACTIVE 0x0002 // INACTIVE keyword #define BITMAP 0x0004 // BITMAP keyword #define OWNERDRAW 0x0100 // OWNERDRAW keyword #define CHECKED 0x0008 // CHECKED keyword #define POPUP 0x0010 // used internally #define MENUBARBREAK 0x0020 // MENUBARBREAK keyword #define MENUBREAK 0x0040 // MENUBREAK keyword #define ENDMENU 0x0080 // used internally // Dialog Box Resources .................. added by sang cho. // A dialog box is contained in a single resource and has a header and // a portion repeated for each control in the dialog box. // The item DWORD IStyle is a standard window style composed of flags found // in WINDOWS.H. // The default style for a dialog box is: // WS_POPUP | WS_BORDER | WS_SYSMENU // // The itme marked "Name or Ordinal" are : // If the first word is an 0xffff, the next two bytes contain an ordinal ID. // Otherwise, the first one or more WORDS contain a double-null-terminated string. // An empty string is represented by a single WORD zero in the first location. // // The WORD wPointSize and WCHAR szFontName entries are present if the FONT // statement was included for the dialog box. This can be detected by checking // the entry IStyle. If IStyle & DS_SETFONT ( which is 0x40), then these // entries will be present. typedef struct _IMAGE_DIALOG_BOX_HEADER1 { DWORD IStyle; DWORD IExtendedStyle; // New for Windows NT WORD nControls; // Number of Controls WORD x; WORD y; WORD cx; WORD cy; // N_OR_O MenuName; // Name or Ordinal ID // N_OR_O ClassName; // Name or Ordinal ID // WCHAR szCaption[]; // WORD wPointSize; // Only here if FONT set for dialog // WCHAR szFontName[]; // This too } IMAGE_DIALOG_HEADER, *PIMAGE_DIALOG_HEADER; typedef union _NAME_OR_ORDINAL { // Name or Ordinal ID struct _ORD_ID { WORD flgId; WORD Id; } ORD_ID; WCHAR szName[1]; } NAME_OR_ORDINAL, *PNAME_OR_ORDINAL; // The data for each control starts on a DWORD boundary (which may require // some padding from the previous control), and its format is as follows: typedef struct _IMAGE_CONTROL_DATA { DWORD IStyle; DWORD IExtendedStyle; WORD x; WORD y; WORD cx; WORD cy; WORD wId; // N_OR_O ClassId; // N_OR_O Text; // WORD nExtraStuff; } IMAGE_CONTROL_DATA, *PIMAGE_CONTROL_DATA; #define BUTTON 0x80 #define EDIT 0x81 #define STATIC 0x82 #define LISTBOX 0x83 #define SCROLLBAR 0x84 #define COMBOBOX 0x85 // The various statements used in a dialog script are all mapped to these // classes along with certain modifying styles. The values for these styles // can be found in WINDOWS.H. All dialog controls have the default styles // of WS_CHILD and WS_VISIBLE. A list of the default styles used follows: // // Statement Default Class Default Styles // CONTROL None WS_CHILD|WS_VISIBLE // LTEXT STATIC ES_LEFT // RTEXT STATIC ES_RIGHT // CTEXT STATIC ES_CENTER // LISTBOX LISTBOX WS_BORDER|LBS_NOTIFY // CHECKBOX BUTTON BS_CHECKBOX|WS_TABSTOP // PUSHBUTTON BUTTON BS_PUSHBUTTON|WS_TABSTOP // GROUPBOX BUTTON BS_GROUPBOX // DEFPUSHBUTTON BUTTON BS_DFPUSHBUTTON|WS_TABSTOP // RADIOBUTTON BUTTON BS_RADIOBUTTON // AUTOCHECKBOX BUTTON BS_AUTOCHECKBOX // AUTO3STATE BUTTON BS_AUTO3STATE // AUTORADIOBUTTON BUTTON BS_AUTORADIOBUTTON // PUSHBOX BUTTON BS_PUSHBOX // STATE3 BUTTON BS_3STATE // EDITTEXT EDIT ES_LEFT|WS_BORDER|WS_TABSTOP // COMBOBOX COMBOBOX None // ICON STATIC SS_ICON // SCROLLBAR SCROLLBAR None /// #define WS_OVERLAPPED 0x00000000L #define WS_POPUP 0x80000000L #define WS_CHILD 0x40000000L #define WS_CLIPSIBLINGS 0x04000000L #define WS_CLIPCHILDREN 0x02000000L #define WS_VISIBLE 0x10000000L #define WS_DISABLED 0x08000000L #define WS_MINIMIZE 0x20000000L #define WS_MAXIMIZE 0x01000000L #define WS_CAPTION 0x00C00000L #define WS_BORDER 0x00800000L #define WS_DLGFRAME 0x00400000L #define WS_VSCROLL 0x00200000L #define WS_HSCROLL 0x00100000L #define WS_SYSMENU 0x00080000L #define WS_THICKFRAME 0x00040000L #define WS_MINIMIZEBOX 0x00020000L #define WS_MAXIMIZEBOX 0x00010000L #define WS_GROUP 0x00020000L #define WS_TABSTOP 0x00010000L // other aliases #define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX) #define WS_POPUPWINDOW (WS_POPUP | WS_BORDER | WS_SYSMENU) #define WS_CHILDWINDOW (WS_CHILD) #define WS_TILED WS_OVERLAPPED #define WS_ICONIC WS_MINIMIZE #define WS_SIZEBOX WS_THICKFRAME #define WS_TILEDWINDOW WS_OVERLAPPEDWINDOW #define WS_EX_DLGMODALFRAME 0x00000001L #define WS_EX_NOPARENTNOTIFY 0x00000004L #define WS_EX_TOPMOST 0x00000008L #define WS_EX_ACCEPTFILES 0x00000010L #define WS_EX_TRANSPARENT 0x00000020L #define BS_PUSHBUTTON 0x00000000L #define BS_DEFPUSHBUTTON 0x00000001L #define BS_CHECKBOX 0x00000002L #define BS_AUTOCHECKBOX 0x00000003L #define BS_RADIOBUTTON 0x00000004L #define BS_3STATE 0x00000005L #define BS_AUTO3STATE 0x00000006L #define BS_GROUPBOX 0x00000007L #define BS_USERBUTTON 0x00000008L #define BS_AUTORADIOBUTTON 0x00000009L #define BS_OWNERDRAW 0x0000000BL #define BS_LEFTTEXT 0x00000020L #define ES_LEFT 0x00000000L #define ES_CENTER 0x00000001L #define ES_RIGHT 0x00000002L #define ES_MULTILINE 0x00000004L #define ES_UPPERCASE 0x00000008L #define ES_LOWERCASE 0x00000010L #define ES_PASSWORD 0x00000020L #define ES_AUTOVSCROLL 0x00000040L #define ES_AUTOHSCROLL 0x00000080L #define ES_NOHIDESEL 0x00000100L #define ES_OEMCONVERT 0x00000400L #define ES_READONLY 0x00000800L #define ES_WANTRETURN 0x00001000L #define LBS_NOTIFY 0x0001L #define LBS_SORT 0x0002L #define LBS_NOREDRAW 0x0004L #define LBS_MULTIPLESEL 0x0008L #define LBS_OWNERDRAWFIXED 0x0010L #define LBS_OWNERDRAWVARIABLE 0x0020L #define LBS_HASSTRINGS 0x0040L #define LBS_USETABSTOPS 0x0080L #define LBS_NOINTEGRALHEIGHT 0x0100L #define LBS_MULTICOLUMN 0x0200L #define LBS_WANTKEYBOARDINPUT 0x0400L #define LBS_EXTENDEDSEL 0x0800L #define LBS_DISABLENOSCROLL 0x1000L #define SS_LEFT 0x00000000L #define SS_CENTER 0x00000001L #define SS_RIGHT 0x00000002L #define SS_ICON 0x00000003L #define SS_BLACKRECT 0x00000004L #define SS_GRAYRECT 0x00000005L #define SS_WHITERECT 0x00000006L #define SS_BLACKFRAME 0x00000007L #define SS_GRAYFRAME 0x00000008L #define SS_WHITEFRAME 0x00000009L #define SS_SIMPLE 0x0000000BL #define SS_LEFTNOWORDWRAP 0x0000000CL #define SS_BITMAP 0x0000000EL // // Debug Format // typedef struct _IMAGE_DEBUG_DIRECTORY { DWORD Characteristics; DWORD TimeDateStamp; WORD MajorVersion; WORD MinorVersion; DWORD Type; DWORD SizeOfData; DWORD AddressOfRawData; DWORD PointerToRawData; } IMAGE_DEBUG_DIRECTORY, *PIMAGE_DEBUG_DIRECTORY; #define IMAGE_DEBUG_TYPE_UNKNOWN 0 #define IMAGE_DEBUG_TYPE_COFF 1 #define IMAGE_DEBUG_TYPE_CODEVIEW 2 #define IMAGE_DEBUG_TYPE_FPO 3 #define IMAGE_DEBUG_TYPE_MISC 4 #define IMAGE_DEBUG_TYPE_EXCEPTION 5 #define IMAGE_DEBUG_TYPE_FIXUP 6 #define IMAGE_DEBUG_TYPE_OMAP_TO_SRC 7 #define IMAGE_DEBUG_TYPE_OMAP_FROM_SRC 8 typedef struct _IMAGE_DEBUG_MISC { DWORD DataType; // type of misc data, see defines DWORD Length; // total length of record, rounded to four // byte multiple. BOOLEAN Unicode; // TRUE if data is unicode string BYTE Reserved[3]; BYTE Data[1]; // Actual data } IMAGE_DEBUG_MISC, *PIMAGE_DEBUG_MISC; // // Debugging information can be stripped from an image file and placed // in a separate .DBG file, whose file name part is the same as the // image file name part (e.g. symbols for CMD.EXE could be stripped // and placed in CMD.DBG). This is indicated by the IMAGE_FILE_DEBUG_STRIPPED // flag in the Characteristics field of the file header. The beginning of // the .DBG file contains the following structure which captures certain // information from the image file. This allows a debug to proceed even if // the original image file is not accessable. This header is followed by // zero of more IMAGE_SECTION_HEADER structures, followed by zero or more // IMAGE_DEBUG_DIRECTORY structures. The latter structures and those in // the image file contain file offsets relative to the beginning of the // .DBG file. // // If symbols have been stripped from an image, the IMAGE_DEBUG_MISC structure // is left in the image file, but not mapped. This allows a debugger to // compute the name of the .DBG file, from the name of the image in the // IMAGE_DEBUG_MISC structure. // typedef struct _IMAGE_SEPARATE_DEBUG_HEADER { WORD Signature; WORD Flags; WORD Machine; WORD Characteristics; DWORD TimeDateStamp; DWORD CheckSum; DWORD ImageBase; DWORD SizeOfImage; DWORD NumberOfSections; DWORD ExportedNamesSize; DWORD DebugDirectorySize; DWORD SectionAlignment; DWORD Reserved[2]; } IMAGE_SEPARATE_DEBUG_HEADER, *PIMAGE_SEPARATE_DEBUG_HEADER; #define IMAGE_SEPARATE_DEBUG_SIGNATURE 0x4944 #define IMAGE_SEPARATE_DEBUG_FLAGS_MASK 0x8000 #define IMAGE_SEPARATE_DEBUG_MISMATCH 0x8000 // when DBG was updated, the // old checksum didn't match. // // End Image Format // #define SIZE_OF_NT_SIGNATURE sizeof (DWORD) #define MAXRESOURCENAME 13 /* global macros to define header offsets into file */ /* offset to PE file signature */ #define NTSIGNATURE(a) ((LPVOID)((BYTE *)a + \ ((PIMAGE_DOS_HEADER)a)->e_lfanew)) /* DOS header identifies the NT PEFile signature dword the PEFILE header exists just after that dword */ #define PEFHDROFFSET(a) ((LPVOID)((BYTE *)a + \ ((PIMAGE_DOS_HEADER)a)->e_lfanew + \ SIZE_OF_NT_SIGNATURE)) /* PE optional header is immediately after PEFile header */ #define OPTHDROFFSET(a) ((LPVOID)((BYTE *)a + \ ((PIMAGE_DOS_HEADER)a)->e_lfanew + \ SIZE_OF_NT_SIGNATURE + \ sizeof (IMAGE_FILE_HEADER))) /* section headers are immediately after PE optional header */ #define SECHDROFFSET(a) ((LPVOID)((BYTE *)a + \ ((PIMAGE_DOS_HEADER)a)->e_lfanew + \ SIZE_OF_NT_SIGNATURE + \ sizeof (IMAGE_FILE_HEADER) + \ sizeof (IMAGE_OPTIONAL_HEADER))) typedef struct tagImportDirectory { DWORD dwRVAFunctionNameList; DWORD dwUseless1; DWORD dwUseless2; DWORD dwRVAModuleName; DWORD dwRVAFunctionAddressList; } IMAGE_IMPORT_MODULE_DIRECTORY, *PIMAGE_IMPORT_MODULE_DIRECTORY; /* global prototypes for functions in pefile.c */ /* PE file header info */ BOOL WINAPI GetDosHeader (LPVOID, PIMAGE_DOS_HEADER); DWORD WINAPI ImageFileType (LPVOID); BOOL WINAPI GetPEFileHeader (LPVOID, PIMAGE_FILE_HEADER); /* PE optional header info */ BOOL WINAPI GetPEOptionalHeader (LPVOID, PIMAGE_OPTIONAL_HEADER); LPVOID WINAPI GetModuleEntryPoint (LPVOID); int WINAPI NumOfSections (LPVOID); LPVOID WINAPI GetImageBase (LPVOID); LPVOID WINAPI ImageDirectoryOffset (LPVOID, DWORD); LPVOID WINAPI ImageDirectorySection (LPVOID, DWORD); /* PE section header info */ //int WINAPI GetSectionNames (LPVOID, HANDLE, char **); int WINAPI GetSectionNames (LPVOID, char **); BOOL WINAPI GetSectionHdrByName (LPVOID, PIMAGE_SECTION_HEADER, char *); // // structur to store string tokens // typedef struct _Str_P { char flag; // string_flag '@' or '%' or '#' char *pos; // starting postion of string int length; // length of string BOOL wasString; // if it were stringMode or not } Str_P; /* import section info */ int WINAPI GetImportModuleNames (LPVOID, char **); int WINAPI GetImportFunctionNamesByModule (LPVOID, char *, char **); // import function name reporting int WINAPI GetStringLength (char *); void WINAPI GetPreviousParamString (char *, char *); void WINAPI TranslateParameters (char **, char **, char **); BOOL WINAPI StringExpands (char **, char **, char **, Str_P *); char * WINAPI TranslateFunctionName (char *); /* export section info */ int WINAPI GetExportFunctionNames (LPVOID, char **); /* resource section info */ int WINAPI GetNumberOfResources (LPVOID); int WINAPI GetListOfResourceTypes (LPVOID, char **); int WINAPI MenuScan (int *, WORD **); int WINAPI MenuFill (char **, WORD **); void WINAPI StrangeMenuFill (char **, WORD **, int); int WINAPI GetContentsOfMenu (LPVOID, char **); int WINAPI PrintMenu (int, char **); int WINAPI PrintStrangeMenu (char **); int WINAPI dumpMenu (char **psz, int size); /* debug section info */ BOOL WINAPI IsDebugInfoStripped (LPVOID); int WINAPI RetrieveModuleName (LPVOID, char **); BOOL WINAPI IsDebugFile (LPVOID); BOOL WINAPI GetSeparateDebugHeader (LPVOID, PIMAGE_SEPARATE_DEBUG_HEADER); /********************************************************************** * NAME * * DESCRIPTION * Copy DOS header information to structure. * * ARGUMENTS */ BOOL WINAPI GetDosHeader ( LPVOID lpFile, PIMAGE_DOS_HEADER pHeader ) { /* * DOS header represents first structure * of bytes in PE image file. */ if ((WORD) IMAGE_DOS_SIGNATURE == *(WORD *) lpFile) { bcopy ( lpFile, (LPVOID) pHeader, sizeof (IMAGE_DOS_HEADER) ); return TRUE; } return FALSE; } /* return file signature */ DWORD WINAPI ImageFileType ( LPVOID lpFile) { /* dos file signature comes first */ if (*(USHORT *) lpFile == IMAGE_DOS_SIGNATURE) { /* determine location of PE File header from dos header */ if (LOWORD (*(DWORD *) NTSIGNATURE (lpFile)) == IMAGE_OS2_SIGNATURE || LOWORD (*(DWORD *) NTSIGNATURE (lpFile)) == IMAGE_OS2_SIGNATURE_LE) return (DWORD) LOWORD (*(DWORD *) NTSIGNATURE (lpFile)); else if (*(DWORD *) NTSIGNATURE (lpFile) == IMAGE_NT_SIGNATURE) return IMAGE_NT_SIGNATURE; else return IMAGE_DOS_SIGNATURE; } else /* unknown file type */ return 0; } /* copy file header information to structure */ BOOL WINAPI GetPEFileHeader ( LPVOID lpFile, PIMAGE_FILE_HEADER pHeader) { /* file header follows dos header */ if (ImageFileType (lpFile) == IMAGE_NT_SIGNATURE) bcopy (PEFHDROFFSET (lpFile), (LPVOID) pHeader, sizeof (IMAGE_FILE_HEADER)); else return FALSE; return TRUE; } /* copy optional header info to structure */ BOOL WINAPI GetPEOptionalHeader ( LPVOID lpFile, PIMAGE_OPTIONAL_HEADER pHeader) { /* optional header follows file header and dos header */ if (ImageFileType (lpFile) == IMAGE_NT_SIGNATURE) bcopy (OPTHDROFFSET (lpFile), (LPVOID) pHeader, sizeof (IMAGE_OPTIONAL_HEADER)); else return FALSE; return TRUE; } /* function returns the entry point for an exe module lpFile must be a memory mapped file pointer to the beginning of the image file */ LPVOID WINAPI GetModuleEntryPoint ( LPVOID lpFile) { PIMAGE_OPTIONAL_HEADER poh = (PIMAGE_OPTIONAL_HEADER) OPTHDROFFSET (lpFile); if (poh != NULL) return (LPVOID) (poh->AddressOfEntryPoint); else return NULL; } /* return the total number of sections in the module */ int WINAPI NumOfSections ( LPVOID lpFile) { /* number os sections is indicated in file header */ return ((int) ((PIMAGE_FILE_HEADER) PEFHDROFFSET (lpFile))->NumberOfSections); } /* retrieve entry point */ LPVOID WINAPI GetImageBase ( LPVOID lpFile) { PIMAGE_OPTIONAL_HEADER poh = (PIMAGE_OPTIONAL_HEADER) OPTHDROFFSET (lpFile); if (poh != NULL) return (LPVOID) (poh->ImageBase); else return NULL; } // // This function is written by sang cho // .. october 5, 1997 // /* function returns the actual address of given RVA, lpFile must be a memory mapped file pointer to the beginning of the image file */ LPVOID WINAPI GetActualAddress ( LPVOID lpFile, DWORD dwRVA) { // PIMAGE_OPTIONAL_HEADER poh = (PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET (lpFile); PIMAGE_SECTION_HEADER psh = (PIMAGE_SECTION_HEADER) SECHDROFFSET (lpFile); int nSections = NumOfSections (lpFile); int i = 0; if (dwRVA == 0) return NULL; if (dwRVA & 0x80000000) { //return (LPVOID)dwRVA; printf ("\n$$ what is going on $$"); exit (0); } /* locate section containing image directory */ while (i++ < nSections) { if (psh->VirtualAddress <= (DWORD) dwRVA && psh->VirtualAddress + psh->SizeOfRawData > (DWORD) dwRVA) break; psh++; } if (i > nSections) return NULL; /* return image import directory offset */ return (LPVOID) (((int) lpFile + (int) dwRVA - psh->VirtualAddress) + (int) psh->PointerToRawData); } // // This function is modified by sang cho // // /* return offset to specified IMAGE_DIRECTORY entry */ LPVOID WINAPI ImageDirectoryOffset ( LPVOID lpFile, DWORD dwIMAGE_DIRECTORY) { PIMAGE_OPTIONAL_HEADER poh = (PIMAGE_OPTIONAL_HEADER) OPTHDROFFSET (lpFile); PIMAGE_SECTION_HEADER psh = (PIMAGE_SECTION_HEADER) SECHDROFFSET (lpFile); int nSections = NumOfSections (lpFile); int i = 0; LPVOID VAImageDir; /* must be 0 thru (NumberOfRvaAndSizes-1) */ if (dwIMAGE_DIRECTORY >= poh->NumberOfRvaAndSizes) return NULL; /* locate specific image directory's relative virtual address */ VAImageDir = (LPVOID) poh->DataDirectory[dwIMAGE_DIRECTORY].VirtualAddress; if (VAImageDir == NULL) return NULL; /* locate section containing image directory */ while (i++ < nSections) { if (psh->VirtualAddress <= (DWORD) VAImageDir && psh->VirtualAddress + psh->SizeOfRawData > (DWORD) VAImageDir) break; psh++; } if (i > nSections) return NULL; /* return image import directory offset */ return (LPVOID) (((int) lpFile + (int) VAImageDir - psh->VirtualAddress) + (int) psh->PointerToRawData); } /* function retrieve names of all the sections in the file */ int WINAPI GetSectionNames ( LPVOID lpFile, char **pszSections) { int nSections = NumOfSections (lpFile); int i, nCnt = 0; PIMAGE_SECTION_HEADER psh; char *ps; if (ImageFileType (lpFile) != IMAGE_NT_SIGNATURE || (psh = (PIMAGE_SECTION_HEADER) SECHDROFFSET (lpFile)) == NULL) return 0; /* count the number of chars used in the section names */ for (i = 0; i < nSections; i++) nCnt += strlen ((char *)psh[i].Name) + 1; /* allocate space for all section names from heap */ ps = *pszSections = (char *) calloc (nCnt, 1); for (i = 0; i < nSections; i++) { strcpy (ps, (char *)psh[i].Name); ps += strlen ((char *)psh[i].Name) + 1; } return nCnt; } /* function gets the function header for a section identified by name */ BOOL WINAPI GetSectionHdrByName ( LPVOID lpFile, IMAGE_SECTION_HEADER * sh, char *szSection) { PIMAGE_SECTION_HEADER psh; int nSections = NumOfSections (lpFile); int i; if ((psh = (PIMAGE_SECTION_HEADER) SECHDROFFSET (lpFile)) != NULL) { /* find the section by name */ for (i = 0; i < nSections; i++) { if (!strcmp ((char *)psh->Name, szSection)) { /* copy data to header */ bcopy ((LPVOID) psh, (LPVOID) sh, sizeof (IMAGE_SECTION_HEADER)); return TRUE; } else psh++; } } return FALSE; } // // This function is modified by sang cho // // /* get import modules names separated by null terminators, return module count */ int WINAPI GetImportModuleNames ( LPVOID lpFile, char **pszModules) { PIMAGE_IMPORT_MODULE_DIRECTORY pid = (PIMAGE_IMPORT_MODULE_DIRECTORY) ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_IMPORT); // // sometimes there may be no section for idata or edata // instead rdata or data section may contain these sections .. // or even module names or function names are in different section. // so that's why we need to get actual address of RVAs each time. // ...................sang cho.................. // // PIMAGE_SECTION_HEADER psh = (PIMAGE_SECTION_HEADER) // ImageDirectorySection (lpFile, IMAGE_DIRECTORY_ENTRY_IMPORT); // BYTE *pData = (BYTE *)pid; // DWORD *pdw = (DWORD *)pid; int nCnt = 0, nSize = 0, i; char *pModule[1024]; /* hardcoded maximum number of modules?? */ char *psz; if (pid == NULL) return 0; // pData = (BYTE *)((int)lpFile + psh->PointerToRawData - psh->VirtualAddress); /* extract all import modules */ while (pid->dwRVAModuleName) { /* allocate temporary buffer for absolute string offsets */ //pModule[nCnt] = (char *)(pData + pid->dwRVAModuleName); pModule[nCnt] = (char *) GetActualAddress (lpFile, pid->dwRVAModuleName); nSize += strlen (pModule[nCnt]) + 1; /* increment to the next import directory entry */ pid++; nCnt++; } /* copy all strings to one chunk of memory */ *pszModules = (char *) calloc (nSize, 1); psz = *pszModules; for (i = 0; i < nCnt; i++) { strcpy (psz, pModule[i]); psz += strlen (psz) + 1; } return nCnt; } // // This function is rewritten by sang cho // // /* get import module function names separated by null terminators, return function count */ int WINAPI GetImportFunctionNamesByModule ( LPVOID lpFile, char *pszModule, char **pszFunctions) { PIMAGE_IMPORT_MODULE_DIRECTORY pid = (PIMAGE_IMPORT_MODULE_DIRECTORY) ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_IMPORT); // // sometimes there may be no section for idata or edata // instead rdata or data section may contain these sections .. // or even module names or function names are in different section. // so that's why we need to get actual address each time. // ...................sang cho.................. // //PIMAGE_SECTION_HEADER psh = (PIMAGE_SECTION_HEADER) //ImageDirectorySection (lpFile, IMAGE_DIRECTORY_ENTRY_IMPORT); //DWORD dwBase; int nCnt = 0, nSize = 0; int nnid = 0; int mnlength, i; DWORD dwFunctionName; DWORD dwFunctionAddress; char name[128]; char buff[256]; // enough for any string ?? char *psz; DWORD *pdw; //dwBase = (DWORD)((int)lpFile + psh->PointerToRawData - psh->VirtualAddress); /* find module's pid */ while (pid->dwRVAModuleName && strcmp (pszModule, (char *) GetActualAddress (lpFile, pid->dwRVAModuleName))) pid++; /* exit if the module is not found */ if (!pid->dwRVAModuleName) return 0; // I am doing this to get rid of .dll from module name strcpy (name, pszModule); mnlength = strlen (pszModule); for (i = 0; i < mnlength; i++) if (name[i] == '.') break; name[i] = 0; mnlength = i; /* count number of function names and length of strings */ dwFunctionName = pid->dwRVAFunctionNameList; // IMAGE_IMPORT_BY_NAME OR IMAGE_THUNK_DATA // modified by Sang Cho while (dwFunctionName && *(pdw = (DWORD *) GetActualAddress (lpFile, dwFunctionName))) { if ((*pdw) & 0x80000000) nSize += mnlength + 10 + 1 + 6; else nSize += strlen ((char *) GetActualAddress (lpFile, *pdw + 2)) + 1 + 6; dwFunctionName += 4; nCnt++; } /* allocate memory for function names */ *pszFunctions = (char *) calloc (nSize, 1); psz = *pszFunctions; // // I modified this part to store function address (4 bytes), // ord number (2 bytes), // and name strings (which was there originally) // so that's why there are 6 more bytes...... +6, or +4 and +2 etc. // these informations are used where they are needed. // ...........sang cho.................. // /* copy function names to mempry pointer */ dwFunctionName = pid->dwRVAFunctionNameList; dwFunctionAddress = pid->dwRVAFunctionAddressList; while (dwFunctionName && *(pdw = (DWORD *) GetActualAddress (lpFile, dwFunctionName))) { if ((*pdw) & 0x80000000) { *(int *) psz = (int) (*(DWORD *) GetActualAddress (lpFile, dwFunctionAddress)); psz += 4; *(short *) psz = *(short *) pdw; psz += 2; sprintf (buff, "%s:NoName%04d", name, nnid++); strcpy (psz, buff); psz += strlen (buff) + 1; } else { *(int *) psz = (int) (*(DWORD *) GetActualAddress (lpFile, dwFunctionAddress)); psz += 4; *(short *) psz = (*(short *) GetActualAddress (lpFile, *pdw)); psz += 2; strcpy (psz, (char *) GetActualAddress (lpFile, *pdw + 2)); psz += strlen ((char *) GetActualAddress (lpFile, *pdw + 2)) + 1; } dwFunctionName += 4; dwFunctionAddress += 4; } return nCnt; } // // This function is written by sang cho // October 6, 1997 // /* get numerically expressed string length */ int WINAPI GetStringLength ( char *psz) { if (!isdigit (*psz)) return 0; if (isdigit (*(psz + 1))) return (*psz - '0') * 10 + *(psz + 1) - '0'; else return *psz - '0'; } // // This function is written by sang cho // October 12, 1997 // /* translate parameter part of condensed name */ void WINAPI GetPreviousParamString ( char *xpin, // read-only source char *xpout) // translated result { int n = 0; char *pin, *pout; pin = xpin; pout = xpout; pin--; if (*pin == ',') pin--; else { printf ("\n **error PreviousParamString1 char = %c", *pin); exit (0); } while (*pin) { if (*pin == '>') n++; else if (*pin == '<') n--; else if (*pin == ')') n++; if (n > 0) { if (*pin == '(') n--; } else if (strchr (",(", *pin)) break; pin--; } //printf("\n ----- %s", pin); if (strchr (",(", *pin)) { pin++; } // printf("\n %s", pin); } else { printf ("\n **error PreviousParamString2"); exit (0); } n = xpin - pin - 1; strncpy (pout, pin, n); *(pout + n) = 0; } // // This function is written by sang cho // October 10, 1997 // /* translate parameter part of condensed name */ void WINAPI TranslateParameters ( char **ppin, // read-only source char **ppout, // translated result char **pps) // parameter stack { int i, n; char c; char name[128]; char *pin, *pout, *ps; //printf(" %c ", **in); pin = *ppin; pout = *ppout; ps = *pps; c = *pin; switch (c) { // types processing case 'b': strcpy (pout, "byte"); pout += 4; pin++; break; case 'c': strcpy (pout, "char"); pout += 4; pin++; break; case 'd': strcpy (pout, "double"); pout += 6; pin++; break; case 'f': strcpy (pout, "float"); pout += 5; pin++; break; case 'g': strcpy (pout, "long double"); pout += 11; pin++; break; case 'i': strcpy (pout, "int"); pout += 3; pin++; break; case 'l': strcpy (pout, "long"); pout += 4; pin++; break; case 's': strcpy (pout, "short"); pout += 5; pin++; break; case 'v': strcpy (pout, "void"); pout += 4; pin++; break; // postfix processing case 'M': case 'p': if (*(pin + 1) == 'p') { *ps++ = 'p'; pin += 2; } else { *ps++ = '*'; pin++; } *ppin = pin; *ppout = pout; *pps = ps; return; case 'q': *pout++ = '('; pin++; *ps++ = 'q'; *ppin = pin; *ppout = pout; *pps = ps; return; case 'r': if (*(pin + 1) == 'p') { *ps++ = 'r'; pin += 2; } else { *ps++ = '&'; pin++; } *ppin = pin; *ppout = pout; *pps = ps; return; // repeat processing case 't': if (isdigit (*(pin + 1))) { n = *(pin + 1) - '0'; pin++; pin++; GetPreviousParamString (pout, name); strcpy (pout, name); pout += strlen (name); for (i = 1; i < n; i++) { *pout++ = ','; strcpy (pout, name); pout += strlen (name); } } else pin++; break; // prefix processing case 'u': strcpy (pout, "u"); pout += 1; pin++; *ppin = pin; *ppout = pout; *pps = ps; return; case 'x': strcpy (pout, "const "); pout += 6; pin++; *ppin = pin; *ppout = pout; *pps = ps; return; case 'z': strcpy (pout, "static "); pout += 7; pin++; *ppin = pin; *ppout = pout; *pps = ps; return; default: strcpy (pout, "!1!"); pout += 3; *pout++ = *pin++; *ppin = pin; *ppout = pout; *pps = ps; return; } // need to process postfix finally c = *(ps - 1); if (strchr ("tqx", c)) { if (*(pin) && !strchr ("@$%", *(pin))) *pout++ = ','; *ppin = pin; *ppout = pout; *pps = ps; return; } switch (c) { case 'r': strcpy (pout, "*&"); pout += 2; ps--; break; case 'p': strcpy (pout, "**"); pout += 2; ps--; break; case '&': strcpy (pout, "&"); pout += 1; ps--; break; case '*': strcpy (pout, "*"); pout += 1; ps--; break; default: strcpy (pout, "!2!"); pout += 3; ps--; break; } if (*(pin) && !strchr ("@$%", *(pin))) *pout++ = ','; *ppin = pin; *ppout = pout; *pps = ps; } // // This function is written by sang cho // October 11, 1997 // /* translate parameter part of condensed name */ BOOL WINAPI StringExpands ( char **ppin, // read-only source char **ppout, // translated result char **pps, // parameter stack Str_P * pcstr) // currently stored string { // int n; // char c; char *pin, *pout, *ps; Str_P c_str; BOOL stringMode = TRUE; pin = *ppin; pout = *ppout; ps = *pps; c_str = *pcstr; if (strncmp (pin, "bctr", 4) == 0) { strncpy (pout, c_str.pos, c_str.length); pout += c_str.length; pin += 4; } else if (strncmp (pin, "bdtr", 4) == 0) { *pout++ = '~'; strncpy (pout, c_str.pos, c_str.length); pout += c_str.length; pin += 4; } else if (*pin == 'o') { strcpy (pout, "const "); pout += 6; pin++; stringMode = FALSE; } else if (*pin == 'q') { *pout++ = '('; pin++; *ps++ = 'q'; stringMode = FALSE; } else if (*pin == 't') { //if (*(ps-1) == 't') { *pout++ = ','; pin++; } // this also got me... //else october 12 .. sang { *pout++ = '<'; pin++; *ps++ = 't'; } stringMode = FALSE; } else if (strncmp (pin, "xq", 2) == 0) { *pout++ = '('; pin += 2; *ps++ = 'x'; *ps++ = 'q'; stringMode = FALSE; } else if (strncmp (pin, "bcall", 5) == 0) { strcpy (pout, "operator ()"); pout += 11; pin += 5; } else if (strncmp (pin, "bsubs", 5) == 0) { strcpy (pout, "operator []"); pout += 11; pin += 5; } else if (strncmp (pin, "bnwa", 4) == 0) { strcpy (pout, "operator new[]"); pout += 14; pin += 4; } else if (strncmp (pin, "bdla", 4) == 0) { strcpy (pout, "operator delete[]"); pout += 17; pin += 4; } else if (strncmp (pin, "bnew", 4) == 0) { strcpy (pout, "operator new"); pout += 12; pin += 4; } else if (strncmp (pin, "bdele", 5) == 0) { strcpy (pout, "operator delete"); pout += 15; pin += 5; } else if (strncmp (pin, "blsh", 4) == 0) { strcpy (pout, "operator <<"); pout += 11; pin += 4; } else if (strncmp (pin, "brsh", 4) == 0) { strcpy (pout, "operator >>"); pout += 11; pin += 4; } else if (strncmp (pin, "binc", 4) == 0) { strcpy (pout, "operator ++"); pout += 11; pin += 4; } else if (strncmp (pin, "bdec", 4) == 0) { strcpy (pout, "operator --"); pout += 11; pin += 4; } else if (strncmp (pin, "badd", 4) == 0) { strcpy (pout, "operator +"); pout += 10; pin += 4; } else if (strncmp (pin, "brplu", 5) == 0) { strcpy (pout, "operator +="); pout += 11; pin += 5; } else if (strncmp (pin, "bdiv", 4) == 0) { strcpy (pout, "operator /"); pout += 10; pin += 4; } else if (strncmp (pin, "brdiv", 5) == 0) { strcpy (pout, "operator /="); pout += 11; pin += 5; } else if (strncmp (pin, "bmul", 4) == 0) { strcpy (pout, "operator *"); pout += 10; pin += 4; } else if (strncmp (pin, "brmul", 5) == 0) { strcpy (pout, "operator *="); pout += 11; pin += 5; } else if (strncmp (pin, "basg", 4) == 0) { strcpy (pout, "operator ="); pout += 10; pin += 4; } else if (strncmp (pin, "beql", 4) == 0) { strcpy (pout, "operator =="); pout += 11; pin += 4; } else if (strncmp (pin, "bneq", 4) == 0) { strcpy (pout, "operator !="); pout += 11; pin += 4; } else if (strncmp (pin, "bor", 3) == 0) { strcpy (pout, "operator |"); pout += 10; pin += 3; } else if (strncmp (pin, "bror", 4) == 0) { strcpy (pout, "operator |="); pout += 11; pin += 4; } else if (strncmp (pin, "bcmp", 4) == 0) { strcpy (pout, "operator ~"); pout += 10; pin += 4; } else if (strncmp (pin, "bnot", 4) == 0) { strcpy (pout, "operator !"); pout += 10; pin += 4; } else if (strncmp (pin, "band", 4) == 0) { strcpy (pout, "operator &"); pout += 10; pin += 4; } else if (strncmp (pin, "brand", 5) == 0) { strcpy (pout, "operator &="); pout += 11; pin += 5; } else if (strncmp (pin, "bxor", 4) == 0) { strcpy (pout, "operator ^"); pout += 10; pin += 4; } else if (strncmp (pin, "brxor", 5) == 0) { strcpy (pout, "operator ^="); pout += 11; pin += 5; } else { strcpy (pout, "!$$$!"); pout += 5; } *ppin = pin; *ppout = pout; *pps = ps; return stringMode; } // end of '$' processing //---------------------------------------------------------------------- // structure to store string tokens //---------------------------------------------------------------------- //typedef struct _Str_P { // char flag; // string_flag '@' or '%' or '#' // char *pos; // starting postion of string // int length; // length of string // BOOL wasString; // if it were stringMode or not //} Str_P; //---------------------------------------------------------------------- // // I think I knocked it down finally. But who knows? // october 12, 1997 ... sang // // well I have to rewrite whole part of TranslateFunctionName.. // this time I am a little bit more experienced than 5 days ago. // or am i??? anyway i use stacks instead of recurcive calls // and i hope this will take care of every symptoms i have experienced.. // october 10, 1997 .... sang // It took a lot of time for me to figure out what is all about.... // but still some prefixes like z (static) // -- or some types like b (byte) ,g (long double) ,s (short) -- // -- or postfix like M ( * ) // -- or $or ( & ) which is pretty wierd. .. added.. october 12 // -- also $t business is quite tricky too. (templates) // there may be a lot of things undiscovered yet.... // I am not so sure my interpretation is correct or not // If I am wrong please let me know. // october 8, 1997 .... sang // // // This function is written by sang cho // October 5, 1997 // /* translate condesed import function name */ char * WINAPI TranslateFunctionName ( char *psz) { int i, /*j,*/ n; char c = 0; char cc; static char buff[512]; // result of translation int is = 0; char pStack[32]; // parameter processing stack Str_P sStack[32]; // String processing stack Str_P tok; // String token Str_P c_str; // current string int iend = 0; char *endTab[8]; // end of string position check char *ps; char *pin, *pout; BOOL stringMode = TRUE; if (*psz != '@') return psz; pin = psz; pout = buff; ps = pStack; //................................................................ // serious users may need to run the following code. // so I may need to include some flag options... // If you want to know about how translation is done, // you can just revive following line and you can see it. // october 6, 1997 ... sang cho //printf ("\n................................... %s", psz); // for debugging... //pa = pb = pout; pin++; tok.flag = 'A'; tok.pos = pout; tok.length = 0; tok.wasString = stringMode; sStack[is++] = tok; // initialize sStack with dummy marker while (*pin) { while (*pin) { c = *pin; //--------------------------------------------- // check for the end of number specified string //--------------------------------------------- if (iend > 0) { for (i = 0; i < iend; i++) if (pin == endTab[i]) break; if (i < iend) { // move the end of endTab to ith position endTab[i] = endTab[iend - 1]; iend--; // get top of the string stack tok = sStack[is - 1]; // I am expecting '#' token from stack if (tok.flag != '#') { printf ("\n**some serious error1** %c is = %d char = %c", tok.flag, is, *pin); exit (0); } // pop '#' token I am happy now. else { //if (c) //printf("\n pop # token ... current char = %c", c); //else printf("\n pop percent token..next char = NULL"); is--; } stringMode = tok.wasString; if (!stringMode) { // need to process postfix finally cc = *(ps - 1); if (strchr ("qtx", cc)) { if (!strchr ("@$%", c)) *pout++ = ','; } else { switch (cc) { case 'r': strcpy (pout, "*&"); pout += 2; ps--; break; case 'p': strcpy (pout, "**"); pout += 2; ps--; break; case '&': strcpy (pout, "&"); pout += 1; ps--; break; case '*': strcpy (pout, "*"); pout += 1; ps--; break; default: strcpy (pout, "!3!"); pout += 3; ps--; break; } if (!strchr ("@$%", c)) *pout++ = ','; } } // string mode restored... else; } else; // do nothing.. } //------------------------------------------------ // special control symbol processing: //------------------------------------------------ if (strchr ("@$%", c)) break; //--------------------------------------------------------------- // string part processing : no '$' met yet // or inside of '%' block // or inside of '#' block (numbered string) //--------------------------------------------------------------- else if (stringMode) *pout++ = *pin++; //else if (is > 1) *pout++ = *pin++; //------------------------------------------------ // parameter part processing: '$' met //------------------------------------------------ else // parameter processing { if (!isdigit (c)) TranslateParameters (&pin, &pout, &ps); else // number specified string processing { n = GetStringLength (pin); if (n < 10) pin++; else pin += 2; // push '#' token //if (*pin) //printf("\n push # token .. char = %c", *pin); //else printf("\n push percent token..next char = NULL"); tok.flag = '#'; tok.pos = pout; tok.length = 0; tok.wasString = stringMode; sStack[is++] = tok; // mark end of input string endTab[iend++] = pin + n; stringMode = TRUE; } } } // end of inner while loop // // beginning of new string or end of string ( quotation mark ) // if (c == '%') { pin++; // anyway we have to proceed... tok = sStack[is - 1]; // get top of the sStack if (tok.flag == '%') { // pop '%' token and set c_str //if (*pin) //printf("\n pop percent token..next char = %c", *pin); //else printf("\n pop percent token..next char = NULL"); is--; c_str = tok; c_str.length = pout - c_str.pos; if (*(ps - 1) == 't') { *pout++ = '>'; ps--; stringMode = tok.wasString; } else { printf ("\n**some string error3** stack = %c", *(ps - 1)); exit (0); } } else if (tok.flag == 'A' || tok.flag == '#') { // push '%' token //if (*pin) //printf("\n push percent token..next char = %c", *pin); //else printf("\n push percent token..next char = NULL"); tok.flag = '%'; tok.pos = pout; tok.length = 0; tok.wasString = stringMode; sStack[is++] = tok; } else { printf ("\n**some string error5**"); exit (0); } } // // sometimes we need string to use as constructor name or destructor name // else if (c == '@') // get string from previous marker upto here. { pin++; tok = sStack[is - 1]; c_str.flag = 'S'; c_str.pos = tok.pos; c_str.length = pout - tok.pos; c_str.wasString = stringMode; *pout++ = ':'; *pout++ = ':'; } // // we need to take care of parameter control sequence // else if (c == '$') // need to precess template or parameter part { pin++; if (stringMode) stringMode = StringExpands (&pin, &pout, &ps, &c_str); else { // template parameter mode I guess "$t" if (is > 1) { if (*pin == 't') pin++; else { printf ("\nMYGOODNESS1 %c", *pin); exit (0); } //ps--; //if (*ps == 't') *pout++ = '>'; //else { printf("\nMYGOODNESS2"); exit(0);} *pout++ = ','; //pin++; ..this almost blowed me.... } // real parameter mode I guess // unexpected case is found ... humm what can I do... else { // this is newly found twist.. it really hurts. if (ps <= pStack) { if (*pin == 'q') { *ps++ = 'q'; *pout++ = '('; pin++; } else { printf ("\n** I GIVEUP ***"); exit (0); } continue; } ps--; while (*ps != 'q') { if (*ps == '*') *pout++ = '*'; else if (*ps == '&') *pout++ = '&'; else if (*ps == 'p') { *pout++ = '*'; *pout++ = '*'; } else if (*ps == 'r') { *pout++ = '*'; *pout++ = '&'; } else { printf ("\n*** SOMETHING IS WRONG1*** char= %c", *pin); exit (0); } ps--; } *pout++ = ')'; ps--; while (*ps != 'q') { if (*ps == '*') *pout++ = '*'; else if (*ps == '&') *pout++ = '&'; else if (*ps == 'p') { *pout++ = '*'; *pout++ = '*'; } else if (*ps == 'r') { *pout++ = '*'; *pout++ = '&'; } else { printf ("\n*** SOMETHING IS WRONG2***"); exit (0); } ps--; } ps++; *pout++ = ','; } } } // end of '$' processing } // end of outer while loop // // need to process remaining parameter stack // while (ps > pStack) { ps--; switch (*ps) { case 't': *pout++ = '>'; break; case 'q': *pout++ = ')'; break; case 'x': strcpy (pout, " const"); pout += 6; break; case 'r': strcpy (pout, "*&"); pout += 2; break; case 'p': strcpy (pout, "**"); pout += 2; break; case '&': *pout++ = '&'; break; case '*': *pout++ = '*'; break; default: strcpy (pout, "!4!"); pout += 3; *pout++ = *ps; } } *pout = 0; return buff; } // // This function is written by sang cho // // /* get exported function names separated by null terminators, return count of functions */ int WINAPI GetExportFunctionNames ( LPVOID lpFile, char **pszFunctions) { //PIMAGE_SECTION_HEADER psh; PIMAGE_EXPORT_DIRECTORY ped; //DWORD dwBase; DWORD imageBase; //=========================== char *pfns[8192] = {NULL,}; // maximum number of functions //============================= char buff[256]; // enough for any string ?? char *psz = NULL; //=============================== DWORD *pdwAddress; DWORD *pdw1; DWORD *pdwNames; WORD *pwOrd; int i, nCnt = 0, ntmp = 0; int enid = 0, ordBase = 1; // usally ordBase is 1.... int enames = 0; /* get section header and pointer to data directory for .edata section */ ped = (PIMAGE_EXPORT_DIRECTORY) ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_EXPORT); if (ped == NULL) return 0; // // sometimes there may be no section for idata or edata // instead rdata or data section may contain these sections .. // or even module names or function names are in different section. // so that's why we need to get actual address each time. // ...................sang cho.................. // //psh = (PIMAGE_SECTION_HEADER) //ImageDirectorySection(lpFile, IMAGE_DIRECTORY_ENTRY_EXPORT); //if (psh == NULL) return 0; //dwBase = (DWORD)((int)lpFile + psh->PointerToRawData - psh->VirtualAddress); /* determine the offset of the export function names */ pdwAddress = (DWORD *) GetActualAddress (lpFile, (DWORD) ped->AddressOfFunctions); imageBase = (DWORD) GetImageBase (lpFile); ordBase = ped->Base; if (ped->NumberOfNames > 0) { pdwNames = (DWORD *) GetActualAddress (lpFile, (DWORD) ped->AddressOfNames); pwOrd = (WORD *) GetActualAddress (lpFile, (DWORD) ped->AddressOfNameOrdinals); pdw1 = pdwAddress; /* figure out how much memory to allocate for all strings */ for (i = 0; i < (int) ped->NumberOfNames; i++) { nCnt += strlen ((char *) GetActualAddress (lpFile, *(DWORD *) pdwNames)) + 1 + 6; pdwNames++; } // get the number of unnamed functions for (i = 0; i < (int) ped->NumberOfFunctions; i++) if (*pdw1++) ntmp++; // add memory required to show unnamed functions. if (ntmp > (int) ped->NumberOfNames) nCnt += 18 * (ntmp - (int) ped->NumberOfNames); /* allocate memory for function names */ *pszFunctions = (char *) calloc (nCnt, 1); pdwNames = (DWORD *) GetActualAddress (lpFile, (DWORD) ped->AddressOfNames); /* copy string pointer to buffer */ for (i = 0; i < (int) ped->NumberOfNames; i++) { pfns[(int) (*pwOrd) + ordBase] = (char *) GetActualAddress (lpFile, *(DWORD *) pdwNames); pdwNames++; pwOrd++; } psz = *pszFunctions; } for (i = ordBase; i < (int) ped->NumberOfFunctions + ordBase; i++) { if (*pdwAddress > 0) { *(DWORD *) psz = imageBase + *pdwAddress; psz += 4; *(WORD *) psz = (WORD) (i); psz += 2; if (pfns[i]) { strcpy (psz, pfns[i]); psz += strlen (psz) + 1; } else { sprintf (buff, "ExpFn%04d()", enid++); strcpy (psz, buff); psz += 12; } enames++; } pdwAddress++; } return enames; } /* determine the total number of resources in the section */ int WINAPI GetNumberOfResources ( LPVOID lpFile) { PIMAGE_RESOURCE_DIRECTORY prdRoot, prdType; PIMAGE_RESOURCE_DIRECTORY_ENTRY prde; int nCnt = 0, i; /* get root directory of resource tree */ if ((prdRoot = (PIMAGE_RESOURCE_DIRECTORY) ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_RESOURCE)) == NULL) return 0; /* set pointer to first resource type entry */ prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ((DWORD) prdRoot + sizeof (IMAGE_RESOURCE_DIRECTORY)); /* loop through all resource directory entry types */ for (i = 0; i < prdRoot->NumberOfIdEntries; i++) { /* locate directory or each resource type */ prdType = (PIMAGE_RESOURCE_DIRECTORY) ((int) prdRoot + (int) prde->OffsetToData); /* mask off most significant bit of the data offset */ prdType = (PIMAGE_RESOURCE_DIRECTORY) ((DWORD) prdType ^ 0x80000000); /* increment count of name'd and ID'd resources in directory */ nCnt += prdType->NumberOfNamedEntries + prdType->NumberOfIdEntries; /* increment to next entry */ prde++; } return nCnt; } // // This function is rewritten by sang cho // // /* name each type of resource in the section */ int WINAPI GetListOfResourceTypes ( LPVOID lpFile, char **pszResTypes) { PIMAGE_RESOURCE_DIRECTORY prdRoot; PIMAGE_RESOURCE_DIRECTORY_ENTRY prde; char *pMem; char buff[32]; int nCnt, i; DWORD prdeName; /* get root directory of resource tree */ if ((prdRoot = (PIMAGE_RESOURCE_DIRECTORY) ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_RESOURCE)) == NULL) return 0; /* allocate enuff space to cover all types */ nCnt = prdRoot->NumberOfIdEntries * (MAXRESOURCENAME + 1); *pszResTypes = (char *) calloc (nCnt, 1); if ((pMem = *pszResTypes) == NULL) return 0; /* set pointer to first resource type entry */ prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ((DWORD) prdRoot + sizeof (IMAGE_RESOURCE_DIRECTORY)); /* loop through all resource directory entry types */ for (i = 0; i < prdRoot->NumberOfIdEntries; i++) { prdeName = prde->Name; //if (LoadString (hDll, prde->Name, pMem, MAXRESOURCENAME)) // pMem += strlen (pMem) + 1; // // modified by ...................................Sang Cho.. // I can't user M/S provied funcitons here so I have to figure out // how to do above functions. But I can settle down with the following // code, which works pretty good for me. // if (prdeName == 1) { strcpy (pMem, "RT_CURSOR"); pMem += 10; } else if (prdeName == 2) { strcpy (pMem, "RT_BITMAP"); pMem += 10; } else if (prdeName == 3) { strcpy (pMem, "RT_ICON "); pMem += 10; } else if (prdeName == 4) { strcpy (pMem, "RT_MENU "); pMem += 10; } else if (prdeName == 5) { strcpy (pMem, "RT_DIALOG"); pMem += 10; } else if (prdeName == 6) { strcpy (pMem, "RT_STRING"); pMem += 10; } else if (prdeName == 7) { strcpy (pMem, "RT_FONTDIR"); pMem += 11; } else if (prdeName == 8) { strcpy (pMem, "RT_FONT "); pMem += 10; } else if (prdeName == 9) { strcpy (pMem, "RT_ACCELERATORS"); pMem += 16; } else if (prdeName == 10) { strcpy (pMem, "RT_RCDATA"); pMem += 10; } else if (prdeName == 11) { strcpy (pMem, "RT_MESSAGETABLE"); pMem += 16; } else if (prdeName == 12) { strcpy (pMem, "RT_GROUP_CURSOR"); pMem += 16; } else if (prdeName == 14) { strcpy (pMem, "RT_GROUP_ICON "); pMem += 16; } else if (prdeName == 16) { strcpy (pMem, "RT_VERSION"); pMem += 11; } else if (prdeName == 17) { strcpy (pMem, "RT_DLGINCLUDE "); pMem += 16; } else if (prdeName == 19) { strcpy (pMem, "RT_PLUGPLAY "); pMem += 16; } else if (prdeName == 20) { strcpy (pMem, "RT_VXD "); pMem += 10; } else if (prdeName == 21) { strcpy (pMem, "RT_ANICURSOR "); pMem += 16; } else if (prdeName == 22) { strcpy (pMem, "RT_ANIICON"); pMem += 11; } else if (prdeName == 0x2002) { strcpy (pMem, "RT_NEWBITMAP"); pMem += 13; } else if (prdeName == 0x2004) { strcpy (pMem, "RT_NEWMENU"); pMem += 11; } else if (prdeName == 0x2005) { strcpy (pMem, "RT_NEWDIALOG"); pMem += 13; } else if (prdeName == 0x7fff) { strcpy (pMem, "RT_ERROR "); pMem += 10; } else { sprintf (buff, "RT_UNKNOWN:%08lX", prdeName); strcpy (pMem, buff); pMem += 20; } prde++; } return prdRoot->NumberOfIdEntries; } // // This function is written by sang cho // October 12, 1997 // /* copy menu information */ void WINAPI StrangeMenuFill ( char **psz, // results WORD ** pMenu, // read-only int size) { WORD *pwd; WORD *ptr, *pmax; pwd = *pMenu; pmax = (WORD *) ((DWORD) pwd + size); ptr = (WORD *) (*psz); while (pwd < pmax) { *ptr++ = *pwd++; } *psz = (char *) ptr; *pMenu = pwd; } // // This function is written by sang cho // October 1, 1997 // /* obtain menu information */ int WINAPI MenuScan ( int *len, WORD ** pMenu) { //int num = 0; //int ndetails; WORD *pwd; WORD flag, flag1; WORD id, ispopup; pwd = *pMenu; flag = *pwd; // so difficult to correctly code this so let's try this pwd++; (*len) += 2; // flag store if ((flag & 0x0010) == 0) { ispopup = flag; id = *pwd; pwd++; (*len) += 2; // id store } else { ispopup = flag; } while (*pwd) { (*len)++; pwd++; } (*len)++; // name and null character pwd++; // skip double null if ((flag & 0x0010) == 0) // normal node: done { *pMenu = pwd; return (int) flag; } // popup node: need to go on... while (1) { *pMenu = pwd; flag1 = (WORD) MenuScan (len, pMenu); pwd = *pMenu; if (flag1 & 0x0080) break; } // fill # of details to num above //(*len) += 2; *pMenu = pwd; return flag; } // // This function is written by sang cho // October 2, 1997 // /* copy menu information */ int WINAPI MenuFill ( char **psz, WORD ** pMenu) { //int num = 0; //int ndetails; char *ptr/*, *pTemp*/; WORD *pwd; WORD flag, flag1; WORD id/*, ispopup*/; ptr = *psz; pwd = *pMenu; //flag = (*(PIMAGE_POPUP_MENU_ITEM *)pwd)->fItemFlags; flag = *pwd; // so difficult to correctly code this so let's try this pwd++; if ((flag & 0x0010) == 0) { *(WORD *) ptr = flag; // flag store ptr += 2; *(WORD *) ptr = id = *pwd; // id store ptr += 2; pwd++; } else { *(WORD *) ptr = flag; // flag store ptr += 2; } while (*pwd) // name extract { *ptr = *(char *) pwd; ptr++; pwd++; } //name and null character *ptr = 0; ptr++; pwd++; // skip double null if ((flag & 0x0010) == 0) // normal node: done { *pMenu = pwd; *psz = ptr; return (int) flag; } //pTemp = ptr; //ptr += 2; // popup node: need to go on... while (1) { //num++; *pMenu = pwd; *psz = ptr; flag1 = (WORD) MenuFill (psz, pMenu); pwd = *pMenu; ptr = *psz; if (flag1 & 0x0080) break; } // fill # of details to num above //*(WORD *)pTemp = (WORD)num; *pMenu = pwd; *psz = ptr; return flag; } // //============================================================================== // The following program is based on preorder-tree-traversal. // once you understand how to traverse..... // the rest is pretty straight forward. // still we need to scan it first and fill it next time. // and finally we can print it. // // This function is written by sang cho // September 29, 1997 // revised october 2, 1997 // revised october 12, 1997 // .............................................................................. // ------------------------------------------------------------------------------ // I use same structure - which is used in P.E. programs - for my reporting. // So, my structure is as follows: // # of menu name is stored else where ( in directory I suppose ) // supermenuname null terminated string, only ascii is considered. // flag tells : node is a leaf or a internal node. // popupname null terminated string // // flag normal menu flag (leaf node) // id normal menu id // name normal menu name // or or // flag popup menu flag (internal node) // popupname popup menu name // // flag it may folows // id normal menu id // name normal menu name // or or // flag popup menu // popupname popup menu name // ......... // it goes on like this, // but usually, it only goes a few steps,... // ------------------------------------------------------------------------------ /* scan menu and copy menu */ int WINAPI GetContentsOfMenu ( LPVOID lpFile, char **pszResTypes) { PIMAGE_RESOURCE_DIRECTORY prdType, prdName, prdLanguage; PIMAGE_RESOURCE_DIRECTORY_ENTRY prde, prde1; PIMAGE_RESOURCE_DIR_STRING_U pMenuName; PIMAGE_RESOURCE_DATA_ENTRY prData; //PIMAGE_SECTION_HEADER psh = (PIMAGE_SECTION_HEADER) //ImageDirectorySection (lpFile, IMAGE_DIRECTORY_ENTRY_RESOURCE); PIMAGE_MENU_HEADER pMenuHeader; //PIMAGE_POPUP_MENU_ITEM pPopup; WORD* pPopup; //PIMAGE_NORMAL_MENU_ITEM pNormal; char buff[32]; int /*nCnt = 0,*/ i, j; //int num = 0; int size; int sLength, nMenus; WORD flag; WORD *pwd; //DWORD prdeName; //DWORD dwBase; obsolete char *pMem/*, *pTemp*/; //BOOL isStrange = FALSE; /* get root directory of resource tree */ if ((prdType = (PIMAGE_RESOURCE_DIRECTORY) ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_RESOURCE)) == NULL) return 0; /* set pointer to first resource type entry */ prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ((DWORD) prdType + sizeof (IMAGE_RESOURCE_DIRECTORY)); for (i = 0; i < prdType->NumberOfIdEntries; i++) { if (prde->Name == RT_MENU) break; prde++; } if (prde->Name != RT_MENU) return 0; prdName = (PIMAGE_RESOURCE_DIRECTORY) ((DWORD) prdType + (prde->OffsetToData ^ 0x80000000)); if (prdName == NULL) return 0; prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ((DWORD) prdName + sizeof (IMAGE_RESOURCE_DIRECTORY)); // sometimes previous code tells you lots of things hidden underneath // I wish I could save all the revisions I made ... but again .... sigh. // october 12, 1997 sang //dwBase = (DWORD)((int)lpFile + psh->PointerToRawData - psh->VirtualAddress); nMenus = prdName->NumberOfNamedEntries + prdName->NumberOfIdEntries; sLength = 0; for (i = 0; i < prdName->NumberOfNamedEntries; i++) { pMenuName = (PIMAGE_RESOURCE_DIR_STRING_U) ((DWORD) prdType + (prde->Name ^ 0x80000000)); sLength += pMenuName->Length + 1; prdLanguage = (PIMAGE_RESOURCE_DIRECTORY) ((DWORD) prdType + (prde->OffsetToData ^ 0x80000000)); if (prdLanguage == NULL) continue; prde1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ((DWORD) prdLanguage + sizeof (IMAGE_RESOURCE_DIRECTORY)); prData = (PIMAGE_RESOURCE_DATA_ENTRY) ((DWORD) prdType + prde1->OffsetToData); if (prData == NULL) continue; pMenuHeader = (PIMAGE_MENU_HEADER) GetActualAddress (lpFile, prData->OffsetToData); // // normally wVersion and cbHeaderSize should be zero // but if it is not then nothing is known to us... // so let's do our best ... namely guessing .... and trying .... // ... and suffering ... // it gave me many sleepless (not exactly but I like to say this) nights. // // strange case if (pMenuHeader->wVersion | pMenuHeader->cbHeaderSize) { //isStrange = TRUE; pwd = (WORD *) ((DWORD) pMenuHeader + 16); size = prData->Size; // expect to return the length needed to report. // sixteen more bytes to do something sLength += 16 + size; //StrangeMenuScan (&sLength, &pwd, size); } // normal case else { pPopup = (WORD*) ((DWORD) pMenuHeader + sizeof (IMAGE_MENU_HEADER)); while (1) { flag = (WORD) MenuScan (&sLength, (WORD **) (&pPopup)); if (flag & 0x0080) break; } } prde++; } for (i = 0; i < prdName->NumberOfIdEntries; i++) { sLength += 12; prdLanguage = (PIMAGE_RESOURCE_DIRECTORY) ((DWORD) prdType + (prde->OffsetToData ^ 0x80000000)); if (prdLanguage == NULL) continue; prde1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ((DWORD) prdLanguage + sizeof (IMAGE_RESOURCE_DIRECTORY)); prData = (PIMAGE_RESOURCE_DATA_ENTRY) ((DWORD) prdType + prde1->OffsetToData); if (prData == NULL) continue; pMenuHeader = (PIMAGE_MENU_HEADER) GetActualAddress (lpFile, prData->OffsetToData); // strange case if (pMenuHeader->wVersion | pMenuHeader->cbHeaderSize) { pwd = (WORD *) ((DWORD) pMenuHeader + 16); size = prData->Size; // expect to return the length needed to report. // sixteen more bytes to do something sLength += 16 + size; //StrangeMenuScan (&sLength, &pwd, size); } // normal case else { pPopup = (WORD*) ((DWORD) pMenuHeader + sizeof (IMAGE_MENU_HEADER)); while (1) { flag = (WORD) MenuScan (&sLength, (WORD **) (&pPopup)); if (flag & 0x0080) break; } } prde++; } // // allocate memory for menu names // *pszResTypes = (char *) calloc (sLength, 1); pMem = *pszResTypes; // // and start all over again // prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ((DWORD) prdName + sizeof (IMAGE_RESOURCE_DIRECTORY)); for (i = 0; i < prdName->NumberOfNamedEntries; i++) { pMenuName = (PIMAGE_RESOURCE_DIR_STRING_U) ((DWORD) prdType + (prde->Name ^ 0x80000000)); for (j = 0; j < pMenuName->Length; j++) *pMem++ = (char) (pMenuName->NameString[j]); *pMem = 0; pMem++; prdLanguage = (PIMAGE_RESOURCE_DIRECTORY) ((DWORD) prdType + (prde->OffsetToData ^ 0x80000000)); if (prdLanguage == NULL) continue; prde1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ((DWORD) prdLanguage + sizeof (IMAGE_RESOURCE_DIRECTORY)); prData = (PIMAGE_RESOURCE_DATA_ENTRY) ((DWORD) prdType + prde1->OffsetToData); if (prData == NULL) continue; pMenuHeader = (PIMAGE_MENU_HEADER) GetActualAddress (lpFile, prData->OffsetToData); // strange case if (pMenuHeader->wVersion | pMenuHeader->cbHeaderSize) { pwd = (WORD *) ((DWORD) pMenuHeader); size = prData->Size; strcpy (pMem, ":::::::::::"); pMem += 12; *(int *) pMem = size; pMem += 4; StrangeMenuFill (&pMem, &pwd, size); } // normal case else { pPopup = (WORD*) ((DWORD) pMenuHeader + sizeof (IMAGE_MENU_HEADER)); while (1) { flag = (WORD) MenuFill (&pMem, (WORD **) (&pPopup)); if (flag & 0x0080) break; } } prde++; } for (i = 0; i < prdName->NumberOfIdEntries; i++) { sprintf (buff, "MenuId_%04lX", (prde->Name)); strcpy (pMem, buff); pMem += strlen (buff) + 1; prdLanguage = (PIMAGE_RESOURCE_DIRECTORY) ((DWORD) prdType + (prde->OffsetToData ^ 0x80000000)); if (prdLanguage == NULL) continue; prde1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ((DWORD) prdLanguage + sizeof (IMAGE_RESOURCE_DIRECTORY)); prData = (PIMAGE_RESOURCE_DATA_ENTRY) ((DWORD) prdType + prde1->OffsetToData); if (prData == NULL) continue; pMenuHeader = (PIMAGE_MENU_HEADER) GetActualAddress (lpFile, prData->OffsetToData); // strange case if (pMenuHeader->wVersion | pMenuHeader->cbHeaderSize) { pwd = (WORD *) ((DWORD) pMenuHeader); size = prData->Size; strcpy (pMem, ":::::::::::"); pMem += 12; *(int *) pMem = size; pMem += 4; StrangeMenuFill (&pMem, &pwd, size); } // normal case else { pPopup = (WORD*) ((DWORD) pMenuHeader + sizeof (IMAGE_MENU_HEADER)); while (1) { flag = (WORD) MenuFill (&pMem, (WORD **) (&pPopup)); if (flag & 0x0080) break; } } prde++; } return nMenus; } // // This function is written by sang cho // October 12, 1997 // /* print contents of menu */ int WINAPI PrintStrangeMenu ( char **psz) { //int i, j, k, l; int num; //WORD flag1, flag2; //char buff[128]; char *ptr, *pmax; //return dumpMenu (psz, size); ptr = *psz; if (strncmp (ptr, ":::::::::::", 11) != 0) { printf ("\n#### I don't know why!!!"); dumpMenu (psz, 1024); exit (0); } ptr += 12; num = *(int *) ptr; ptr += 4; pmax = ptr + num; *psz = ptr; return dumpMenu (psz, num); // I will write some code later... } // // This function is written by sang cho // October 2, 1997 // /* print contents of menu */ int WINAPI PrintMenu ( int indent, char **psz) { int /*i, */ j, k, l; WORD id /*, num */ ; WORD flag; char buff[128]; char *ptr; ptr = *psz; //num = *(WORD *)ptr; //ptr += 2; while (1) { flag = *(WORD *) ptr; if (flag & 0x0010) // flag == popup { printf ("\n\n"); for (j = 0; j < indent; j++) printf (" "); ptr += 2; printf ("%s {Popup}\n", ptr); ptr += strlen (ptr) + 1; *psz = ptr; PrintMenu (indent + 5, psz); ptr = *psz; } else // ispopup == 0 { printf ("\n"); for (j = 0; j < indent; j++) printf (" "); ptr += 2; id = *(WORD *) ptr; ptr += 2; strcpy (buff, ptr); l = strlen (ptr); ptr += l + 1; if (strchr (buff, 0x09) != NULL) { for (k = 0; k < l; k++) if (buff[k] == 0x09) break; for (j = 0; j < l - k; j++) buff[31 - j] = buff[l - j]; for (j = k; j < 32 + k - l; j++) buff[j] = 32; } if (strchr (buff, 0x08) != NULL) { for (k = 0; k < l; k++) if (buff[k] == 0x08) break; for (j = 0; j < l - k; j++) buff[31 - j] = buff[l - j]; for (j = k; j < 32 + k - l; j++) buff[j] = 32; } printf ("%s", buff); l = strlen (buff); for (j = l; j < 32; j++) printf (" "); printf ("[ID=%04Xh]", id); *psz = ptr; } if (flag & 0x0080) break; } return 0; } // // This function is written by sang cho // October 2, 1997 // /* the format of menu is not known so I'll do my best */ int WINAPI dumpMenu ( char **psz, int size) { int i, j, k, n, l, c; char buff[32]; char *ptr, *pmax; ptr = *psz; pmax = ptr + size; for (i = 0; i < (size / 16) + 1; i++) { n = 0; for (j = 0; j < 16; j++) { c = (int) (*ptr); if (c < 0) c += 256; buff[j] = c; printf ("%02X", c); ptr++; if (ptr >= pmax) break; n++; if (n % 4 == 0) printf (" "); } n++; if (n % 4 == 0) printf (" "); l = j; j++; for (; j < 16; j++) { n++; if (n % 4 == 0) printf (" "); else printf (" "); } printf (" "); for (k = 0; k < l; k++) if (isprint (c = buff[k])) printf ("%c", c); else printf ("."); printf ("\n"); if (ptr >= pmax) break; } *psz = ptr; return 0; } // // This function is written by sang cho // October 13, 1997 // /* scan dialog box and copy dialog box */ int WINAPI GetContentsOfDialog ( LPVOID lpFile, char **pszResTypes) { PIMAGE_RESOURCE_DIRECTORY prdType, prdName, prdLanguage; PIMAGE_RESOURCE_DIRECTORY_ENTRY prde, prde1; PIMAGE_RESOURCE_DIR_STRING_U pDialogName; PIMAGE_RESOURCE_DATA_ENTRY prData; PIMAGE_DIALOG_HEADER pDialogHeader; //PIMAGE_CONTROL_DATA pControlData; char buff[32]; int /*nCnt = 0,*/ i, j; //int num = 0; int size; int sLength, nDialogs; //WORD flag; WORD *pwd; //DWORD prdeName; char *pMem/*, *pTemp*/; //BOOL isStrange = FALSE; /* get root directory of resource tree */ if ((prdType = (PIMAGE_RESOURCE_DIRECTORY) ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_RESOURCE)) == NULL) return 0; /* set pointer to first resource type entry */ prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ((DWORD) prdType + sizeof (IMAGE_RESOURCE_DIRECTORY)); for (i = 0; i < prdType->NumberOfIdEntries; i++) { if (prde->Name == RT_DIALOG) break; prde++; } if (prde->Name != RT_DIALOG) return 0; prdName = (PIMAGE_RESOURCE_DIRECTORY) ((DWORD) prdType + (prde->OffsetToData ^ 0x80000000)); if (prdName == NULL) return 0; prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ((DWORD) prdName + sizeof (IMAGE_RESOURCE_DIRECTORY)); nDialogs = prdName->NumberOfNamedEntries + prdName->NumberOfIdEntries; sLength = 0; for (i = 0; i < prdName->NumberOfNamedEntries; i++) { pDialogName = (PIMAGE_RESOURCE_DIR_STRING_U) ((DWORD) prdType + (prde->Name ^ 0x80000000)); sLength += pDialogName->Length + 1; prdLanguage = (PIMAGE_RESOURCE_DIRECTORY) ((DWORD) prdType + (prde->OffsetToData ^ 0x80000000)); if (prdLanguage == NULL) continue; prde1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ((DWORD) prdLanguage + sizeof (IMAGE_RESOURCE_DIRECTORY)); prData = (PIMAGE_RESOURCE_DATA_ENTRY) ((DWORD) prdType + prde1->OffsetToData); if (prData == NULL) continue; size = prData->Size; sLength += 4 + size; prde++; } for (i = 0; i < prdName->NumberOfIdEntries; i++) { sLength += 14; prdLanguage = (PIMAGE_RESOURCE_DIRECTORY) ((DWORD) prdType + (prde->OffsetToData ^ 0x80000000)); if (prdLanguage == NULL) continue; prde1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ((DWORD) prdLanguage + sizeof (IMAGE_RESOURCE_DIRECTORY)); prData = (PIMAGE_RESOURCE_DATA_ENTRY) ((DWORD) prdType + prde1->OffsetToData); if (prData == NULL) continue; size = prData->Size; sLength += 4 + size; prde++; } // // allocate memory for menu names // *pszResTypes = (char *) calloc (sLength, 1); pMem = *pszResTypes; // // and start all over again // prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ((DWORD) prdName + sizeof (IMAGE_RESOURCE_DIRECTORY)); for (i = 0; i < prdName->NumberOfNamedEntries; i++) { pDialogName = (PIMAGE_RESOURCE_DIR_STRING_U) ((DWORD) prdType + (prde->Name ^ 0x80000000)); for (j = 0; j < pDialogName->Length; j++) *pMem++ = (char) (pDialogName->NameString[j]); *pMem = 0; pMem++; prdLanguage = (PIMAGE_RESOURCE_DIRECTORY) ((DWORD) prdType + (prde->OffsetToData ^ 0x80000000)); if (prdLanguage == NULL) continue; prde1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ((DWORD) prdLanguage + sizeof (IMAGE_RESOURCE_DIRECTORY)); prData = (PIMAGE_RESOURCE_DATA_ENTRY) ((DWORD) prdType + prde1->OffsetToData); if (prData == NULL) continue; pDialogHeader = (PIMAGE_DIALOG_HEADER) GetActualAddress (lpFile, prData->OffsetToData); pwd = (WORD *) ((DWORD) pDialogHeader); size = prData->Size; *(int *) pMem = size; pMem += 4; StrangeMenuFill (&pMem, &pwd, size); prde++; } for (i = 0; i < prdName->NumberOfIdEntries; i++) { sprintf (buff, "DialogId_%04lX", (prde->Name)); strcpy (pMem, buff); pMem += strlen (buff) + 1; prdLanguage = (PIMAGE_RESOURCE_DIRECTORY) ((DWORD) prdType + (prde->OffsetToData ^ 0x80000000)); if (prdLanguage == NULL) { printf ("\nprdLanguage = NULL"); exit (0); } prde1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ((DWORD) prdLanguage + sizeof (IMAGE_RESOURCE_DIRECTORY)); prData = (PIMAGE_RESOURCE_DATA_ENTRY) ((DWORD) prdType + prde1->OffsetToData); if (prData == NULL) { printf ("\nprData = NULL"); exit (0); } pDialogHeader = (PIMAGE_DIALOG_HEADER) GetActualAddress (lpFile, prData->OffsetToData); pwd = (WORD *) ((DWORD) pDialogHeader); size = prData->Size; *(int *) pMem = size; pMem += 4; StrangeMenuFill (&pMem, &pwd, size); prde++; } return nDialogs; } // // This function is written by sang cho // October 14, 1997 // /* print contents of dialog */ void WINAPI PrintNameOrOrdinal ( char **psz) { char *ptr; ptr = *psz; if (*(WORD *) ptr == 0xFFFF) { ptr += 2; printf ("%04X", *(WORD *) ptr); ptr += 2; } else { printf ("%c", '"'); while (*(WORD *) ptr) { printf ("%c", *ptr); ptr += 2; } ptr += 2; printf ("%c", '"'); } *psz = ptr; } // // This function is written by sang cho // October 14, 1997 // /* print contents of dialog */ void WINAPI PrintDialog ( char **psz) { int i/*, j, k, l, n, c*/; int num, size; DWORD flag; WORD class; //char buff[32]; char *ptr, *pmax; BOOL isStrange = FALSE; ptr = *psz; size = *(int *) ptr; ptr += 4; pmax = ptr + size; // IStype of Dialog Header flag = *(DWORD *) ptr; // // check if flag is right or not // it has been observed that some dialog information is strange // and extra work is needed to fix that ... so let's try something // if ((flag & 0xFFFF0000) == 0xFFFF0000) { flag = *(DWORD *) (ptr + 12); num = *(short *) (ptr + 16); isStrange = TRUE; ptr += 26; } else { num = *(short *) (ptr + 8); ptr += 18; } printf (", # of Controls=%03d, Caption:%c", num, '"'); // Menu name if (*(WORD *) ptr == 0xFFFF) ptr += 4; // ordinal else { while (*(WORD *) ptr) ptr += 2; ptr += 2; } // name // Class name if (*(WORD *) ptr == 0xFFFF) ptr += 4; // ordinal else { while (*(WORD *) ptr) ptr += 2; ptr += 2; } // name // Caption while (*(WORD *) ptr) { printf ("%c", *ptr); ptr += 2; } ptr += 2; printf ("%c", '"'); // FONT present if (flag & 0x00000040) { if (isStrange) ptr += 6; else ptr += 2; // FONT size while (*(WORD *) ptr) ptr += 2; // WCHARs ptr += 2; // double null } // strange case adjust if (isStrange) ptr += 8; // DWORD padding if ((ptr - *psz) % 4) ptr += 4 - ((ptr - *psz) % 4); // start reporting .. finally for (i = 0; i < num; i++) { flag = *(DWORD *) ptr; if (isStrange) ptr += 14; else ptr += 16; printf ("\n Control::%03d - ID:", i + 1); // Control ID printf ("%04X, Class:", *(WORD *) ptr); ptr += 2; // Control Class if (*(WORD *) ptr == 0xFFFF) { ptr += 2; class = *(WORD *) ptr; ptr += 2; switch (class) { case 0x80: printf ("BUTTON "); break; case 0x81: printf ("EDIT "); break; case 0x82: printf ("STATIC "); break; case 0x83: printf ("LISTBOX "); break; case 0x84: printf ("SCROLLBAR"); break; case 0x85: printf ("COMBOBOX "); break; default: printf ("%04X ", class); break; } } else PrintNameOrOrdinal (&ptr); printf (" Text:"); // Text PrintNameOrOrdinal (&ptr); // nExtraStuff ptr += 2; // strange case adjust if (isStrange) ptr += 8; // DWORD padding if ((ptr - *psz) % 4) ptr += 4 - ((ptr - *psz) % 4); } /* ptr = *psz; printf("\n"); for (i=0; i<(size/16)+1; i++) { n = 0; for (j=0; j<16; j++) { c = (int)(*ptr); if (c<0) c+=256; buff[j] = c; printf ("%02X",c); ptr++; if (ptr >= pmax) break; n++; if (n%4 == 0) printf (" "); } n++; if (n%4 == 0) printf (" "); l = j; j++; for (; j<16; j++) { n++; if (n%4 == 0) printf (" "); else printf (" "); } printf (" "); for (k=0; k= pmax) break; } */ *psz = pmax; } /* function indicates whether debug info has been stripped from file */ BOOL WINAPI IsDebugInfoStripped ( LPVOID lpFile) { PIMAGE_FILE_HEADER pfh; pfh = (PIMAGE_FILE_HEADER) PEFHDROFFSET (lpFile); return (pfh->Characteristics & IMAGE_FILE_DEBUG_STRIPPED); } /* retrieve the module name from the debug misc. structure */ int WINAPI RetrieveModuleName ( LPVOID lpFile, char **pszModule) { PIMAGE_DEBUG_DIRECTORY pdd; PIMAGE_DEBUG_MISC pdm = NULL; int nCnt; if (!(pdd = (PIMAGE_DEBUG_DIRECTORY) ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_DEBUG))) return 0; while (pdd->SizeOfData) { if (pdd->Type == IMAGE_DEBUG_TYPE_MISC) { pdm = (PIMAGE_DEBUG_MISC) ((DWORD) pdd->PointerToRawData + (DWORD) lpFile); *pszModule = (char *) calloc ((nCnt = (strlen ((char *)pdm->Data))) + 1, 1); // may need some unicode business here...above bcopy (pdm->Data, *pszModule, nCnt); break; } pdd++; } if (pdm != NULL) return nCnt; else return 0; } /* determine if this is a valid debug file */ BOOL WINAPI IsDebugFile ( LPVOID lpFile) { PIMAGE_SEPARATE_DEBUG_HEADER psdh; psdh = (PIMAGE_SEPARATE_DEBUG_HEADER) lpFile; return (psdh->Signature == IMAGE_SEPARATE_DEBUG_SIGNATURE); } /* copy separate debug header structure from debug file */ BOOL WINAPI GetSeparateDebugHeader ( LPVOID lpFile, PIMAGE_SEPARATE_DEBUG_HEADER psdh) { PIMAGE_SEPARATE_DEBUG_HEADER pdh; pdh = (PIMAGE_SEPARATE_DEBUG_HEADER) lpFile; if (pdh->Signature == IMAGE_SEPARATE_DEBUG_SIGNATURE) { bcopy ((LPVOID) pdh, (LPVOID) psdh, sizeof (IMAGE_SEPARATE_DEBUG_HEADER)); return TRUE; } return FALSE; } // // I tried to immitate the output of w32dasm disassembler. // which is a pretty good program. // but I am disappointed with this program and I myself // am writting a disassembler. // This PEdump program is a byproduct of that project. // so enjoy this program and I hope we will have a little more // knowledge on windows programming world. // .... sang cho #define MAXSECTIONNUMBER 16 #define MAXNAMESTRNUMBER 40 int main ( int argc, char **argv ) { DWORD fileType; LPVOID lpFile; FILE *my_fp; IMAGE_DOS_HEADER dosHdr; PIMAGE_FILE_HEADER pfh; PIMAGE_OPTIONAL_HEADER poh; PIMAGE_SECTION_HEADER psh; //IMAGE_SECTION_HEADER idsh; IMAGE_SECTION_HEADER shdr[MAXSECTIONNUMBER]; //PIMAGE_IMPORT_MODULE_DIRECTORY pid; int nSections; // number of sections int nResources; // number of resources int nMenus; // number of menus int nDialogs; // number of dialogs int nImportedModules; // number of imported modules int nFunctions; // number of functions in the imported module int nExportedFunctions; // number of exported funcions int imageBase; int entryPoint; int i, j, /*k,*/ n; //int mnsize; //int nCnt; //int nSize; int fsize; char *pnstr; char *pst; char *piNameBuff; // import module name buffer char *pfNameBuff; // import functions in the module name buffer char *peNameBuff; // export function name buffer char *pmNameBuff; // menu name buffer char *pdNameBuff; // dialog name buffer /* * Check user arguments. */ if (2 == argc) { my_fp = fopen (argv[1], "rb"); if (my_fp == NULL) { printf ( "%s: can not open input file \"%s\".\n", argv[0], argv[1] ); exit (0); } } else { printf ( "%s - PE/COFF file dumper\n" "Copyright (c) 1993 Randy Kath (MSDN Technology Group)\n" "Copyright (c) 1997 Sang Cho (CS & Engineering - Chongju University)\n" "Copyright (c) 2000 Emanuele Aliberti (ReactOS Development Team)\n\n", argv[0] ); printf ( "usage: %s input_file_name\n", argv[0] ); exit (0); } /* * Get input file's size. */ /* argv [0], */ fseek (my_fp, 0L, SEEK_END); fsize = ftell (my_fp); rewind (my_fp); /* * Buffer the file in memory. */ lpFile = (void *) calloc (fsize, 1); if (lpFile == NULL) { printf ( "%s: can not allocate memory.\n", argv[0] ); fclose(my_fp); exit (0); } /* * --- Start of report --- */ printf ("\n\nDump of file: %s\n\n", argv[1]); n = fread (lpFile, fsize, 1, my_fp); fclose(my_fp); if (n == -1) { printf ( "%s: failed to read the file \"%s\".\n", argv[0], argv[1] ); free(lpFile); exit (0); } GetDosHeader (lpFile, &dosHdr); if ((WORD) IMAGE_DOS_SIGNATURE == dosHdr.e_magic) { if ((dosHdr.e_lfanew > 4096) || (dosHdr.e_lfanew < 64) ) { printf ( "%s: This file is not in PE format; it looks like in DOS format.\n", argv[0] ); free(lpFile); exit (0); } } else { printf ( "%s: This doesn't look like an executable file (magic = 0x%04x).\n", argv[0], dosHdr.e_magic ); free(lpFile); exit (0); } fileType = ImageFileType (lpFile); if (fileType != IMAGE_NT_SIGNATURE) { printf ( "%s: This file is not in PE format (magic = 0x%08lx).\n", argv[0], fileType ); free(lpFile); exit (0); } //===================================== // now we can really start processing //===================================== pfh = (PIMAGE_FILE_HEADER) PEFHDROFFSET (lpFile); poh = (PIMAGE_OPTIONAL_HEADER) OPTHDROFFSET (lpFile); psh = (PIMAGE_SECTION_HEADER) SECHDROFFSET (lpFile); nSections = pfh->NumberOfSections; imageBase = poh->ImageBase; entryPoint = poh->AddressOfEntryPoint; if (psh == NULL) { free(lpFile); return 0; } /* store section headers */ for (i = 0; i < nSections; i++ ) { shdr[i] = *psh++; } /* * Get Code offset and size, * Data offset and size. */ for (i = 0; i < nSections; i++ ) { if (poh->BaseOfCode == shdr[i].VirtualAddress) { printf ( "Code Offset = %08lX, Code Size = %08lX \n", shdr[i].PointerToRawData, shdr[i].SizeOfRawData ); } if (((shdr[i].Characteristics) & 0xC0000040) == 0xC0000040) { printf ( "Data Offset = %08lX, Data Size = %08lX \n", shdr[i].PointerToRawData, shdr[i].SizeOfRawData ); break; } } printf ("\n"); printf ( "Number of Objects = %04d (dec), Imagebase = %08Xh \n", nSections, imageBase ); /* * Object name alignment. */ for (i = 0; i < nSections; i++ ) { for (j = 0; j < 7; j++ ) { if (shdr[i].Name[j] == 0) { shdr[i].Name[j] = 32; } } shdr[i].Name[7] = 0; } for (i = 0; i < nSections; i++) printf ("\n Object%02d: %8s RVA: %08lX Offset: %08lX Size: %08lX Flags: %08lX ", i + 1, shdr[i].Name, shdr[i].VirtualAddress, shdr[i].PointerToRawData, shdr[i].SizeOfRawData, shdr[i].Characteristics); /* * Get List of Resources. */ nResources = GetListOfResourceTypes (lpFile, &pnstr); pst = pnstr; printf ("\n"); printf ("\n+++++++++++++++++++ RESOURCE INFORMATION +++++++++++++++++++"); printf ("\n"); if (nResources == 0) printf ("\n There are no Resources in This Application.\n"); else { printf ("\nNumber of Resource Types = %4d (decimal)\n", nResources); for (i = 0; i < nResources; i++) { printf ("\n Resource Type %03d: %s", i + 1, pst); pst += strlen ((char *) (pst)) + 1; } free ((void *) pnstr); printf ("\n"); printf ("\n+++++++++++++++++++ MENU INFORMATION +++++++++++++++++++"); printf ("\n"); nMenus = GetContentsOfMenu (lpFile, &pmNameBuff); if (nMenus == 0) { printf ("\n There are no Menus in This Application.\n"); } else { pst = pmNameBuff; printf ("\nNumber of Menus = %4d (decimal)", nMenus); //dumpMenu(&pst, 8096); for (i = 0; i < nMenus; i++) { // menu ID print printf ("\n\n%s", pst); pst += strlen (pst) + 1; printf ("\n-------------"); if (strncmp (pst, ":::::::::::", 11) == 0) { printf ("\n"); PrintStrangeMenu (&pst); } else { PrintMenu (6, &pst); } //else PrintStrangeMenu(&pst); } free ((void *) pmNameBuff); printf ("\n"); } printf ("\n"); printf ("\n+++++++++++++++++ DIALOG INFORMATION +++++++++++++++++++"); printf ("\n"); nDialogs = GetContentsOfDialog (lpFile, &pdNameBuff); if (nDialogs == 0) { printf ("\n There are no Dialogs in This Application.\n"); } else { pst = pdNameBuff; printf ("\nNumber of Dialogs = %4d (decimal)", nDialogs); printf ("\n"); for (i = 0; i < nDialogs; i++) { // Dialog ID print printf ("\nName: %s", pst); pst += strlen (pst) + 1; PrintDialog (&pst); } free ((void *) pdNameBuff); printf ("\n"); } } printf ("\n+++++++++++++++++++ IMPORTED FUNCTIONS +++++++++++++++++++"); nImportedModules = GetImportModuleNames (lpFile, &piNameBuff); if (nImportedModules == 0) { printf ("\n There are no imported Functions in This Application.\n"); } else { pnstr = piNameBuff; printf ("\nNumber of Imported Modules = %4d (decimal)\n", nImportedModules); for (i = 0; i < nImportedModules; i++) { printf ("\n Import Module %03d: %s", i + 1, pnstr); pnstr += strlen ((char *) (pnstr)) + 1; } printf ("\n"); printf ("\n+++++++++++++++++++ IMPORT MODULE DETAILS +++++++++++++++++"); pnstr = piNameBuff; for (i = 0; i < nImportedModules; i++) { printf ("\n\n Import Module %03d: %s \n", i + 1, pnstr); nFunctions = GetImportFunctionNamesByModule (lpFile, pnstr, &pfNameBuff); pnstr += strlen ((char *) (pnstr)) + 1; pst = pfNameBuff; for (j = 0; j < nFunctions; j++) { printf ("\nAddr:%08X hint(%04X) Name: %s", (*(int *) pst), (*(short *) (pst + 4)), //(pst+6)); TranslateFunctionName (pst + 6)); pst += strlen ((char *) (pst + 6)) + 1 + 6; } free ((void *) pfNameBuff); } free ((void *) piNameBuff); } printf ("\n"); printf ("\n+++++++++++++++++++ EXPORTED FUNCTIONS +++++++++++++++++++"); nExportedFunctions = GetExportFunctionNames (lpFile, &peNameBuff); printf ("\nNumber of Exported Functions = %4d (decimal)\n", nExportedFunctions); if (nExportedFunctions > 0) { pst = peNameBuff; for (i = 0; i < nExportedFunctions; i++) { printf ("\nAddr:%08X Ord:%4d (%04Xh) Name: %s", (*(int *) pst), (*(WORD *) (pst + 4)), (*(WORD *) (pst + 4)), //(pst+6)); TranslateFunctionName (pst + 6)); pst += strlen ((char *) (pst + 6)) + 6 + 1; } free ((void *) peNameBuff); } free ((void *) lpFile); return 0; } /* EOF */