| 1 | /* $Id: pe2lx.h,v 1.16 2003-03-31 02:53:32 bird Exp $
 | 
|---|
| 2 |  *
 | 
|---|
| 3 |  * Pe2Lx class declarations. Ring 0 and Ring 3
 | 
|---|
| 4 |  *
 | 
|---|
| 5 |  * Copyright (c) 1998-2000 knut st. osmundsen (knut.stange.osmundsen@mynd.no)
 | 
|---|
| 6 |  *
 | 
|---|
| 7 |  * Project Odin Software License can be found in LICENSE.TXT
 | 
|---|
| 8 |  *
 | 
|---|
| 9 |  */
 | 
|---|
| 10 | #ifndef _PE2LX_H_
 | 
|---|
| 11 | #define _PE2LX_H_
 | 
|---|
| 12 | 
 | 
|---|
| 13 | 
 | 
|---|
| 14 | /*******************************************************************************
 | 
|---|
| 15 | *   Defined Constants And Macros                                               *
 | 
|---|
| 16 | *******************************************************************************/
 | 
|---|
| 17 | /*
 | 
|---|
| 18 |  * BufferedRVAReader config
 | 
|---|
| 19 |  */
 | 
|---|
| 20 | #define BUFFEREDRVAREADER_BUFFERSIZE PAGESIZE   /* reader code assumes this size... */
 | 
|---|
| 21 | 
 | 
|---|
| 22 | 
 | 
|---|
| 23 | 
 | 
|---|
| 24 | /*******************************************************************************
 | 
|---|
| 25 | *   Structures and Typedefs                                                    *
 | 
|---|
| 26 | *******************************************************************************/
 | 
|---|
| 27 | /**
 | 
|---|
| 28 |  * LXObject is use to store objects in the virtual LX file.
 | 
|---|
| 29 |  */
 | 
|---|
| 30 | typedef struct LXObject
 | 
|---|
| 31 | {
 | 
|---|
| 32 |     ULONG ulRVA;                /* Object relative virtual address  */
 | 
|---|
| 33 |     ULONG cbPhysical;           /* Physical size        */
 | 
|---|
| 34 |     ULONG cbVirtual;            /* Virtual size         */
 | 
|---|
| 35 |     ULONG flFlags;              /* LX flags!            */
 | 
|---|
| 36 |     struct
 | 
|---|
| 37 |     {
 | 
|---|
| 38 |         ULONG offTIBFix : 30;   /* TIBfix offset (from the object start) */
 | 
|---|
| 39 |         ULONG fTIBFixObject : 1;/* Set: The object contains the tibfix. Clear: not tib fix object. */
 | 
|---|
| 40 |         ULONG fStackObject : 1; /* Set: The object is the stack object. Clear: not the stack object. */
 | 
|---|
| 41 |     } Misc;
 | 
|---|
| 42 |     ULONG offPEFile;            /* section offset into real PE file. */
 | 
|---|
| 43 |     ULONG offLXFile;            /* object offset into virtual LX file. */
 | 
|---|
| 44 | } LXOBJECT, *PLXOBJECT;
 | 
|---|
| 45 | typedef const LXOBJECT *PCLXOBJECT;
 | 
|---|
| 46 | 
 | 
|---|
| 47 | 
 | 
|---|
| 48 | 
 | 
|---|
| 49 | /**
 | 
|---|
| 50 |  * Pe2Lx class. Reads a PE executable image and creates a virtual LX file which
 | 
|---|
| 51 |  * can be read from and (RING3) dumped to file.
 | 
|---|
| 52 |  *
 | 
|---|
| 53 |  * @author      knut st. osmundsen
 | 
|---|
| 54 |  * @approval    knut st. osmundsen
 | 
|---|
| 55 |  */
 | 
|---|
| 56 | class Pe2Lx : public ModuleBase
 | 
|---|
| 57 | {
 | 
|---|
| 58 | public:
 | 
|---|
| 59 |     /** @cat Constructor/Destructor */
 | 
|---|
| 60 |     Pe2Lx(SFN hFile);
 | 
|---|
| 61 |     ~Pe2Lx();
 | 
|---|
| 62 | 
 | 
|---|
| 63 |     /** @cat Public Main methods */
 | 
|---|
| 64 |     ULONG  init(PCSZ pszFilename);
 | 
|---|
| 65 |     ULONG  read(ULONG offLXFile, PVOID pvBuffer, ULONG cbToRead, ULONG flFlags, PMTE pMTE);
 | 
|---|
| 66 |     ULONG  applyFixups(PMTE pMTE, ULONG iObject, ULONG iPageTable, PVOID pvPage,
 | 
|---|
| 67 |                        ULONG ulPageAddress, PVOID pvPTDA); /*(ldrEnum32bitRelRecs)*/
 | 
|---|
| 68 |     ULONG  applyFixupsDelta(PVOID pvPage, ULONG ulDelta, ULONG ulRVAPage);
 | 
|---|
| 69 | 
 | 
|---|
| 70 |     ULONG  openPath(PCHAR pachFilename, USHORT cchFilename, ldrlv_t *pLdrLv, PULONG pful, ULONG lLibPath); /* (ldrOpenPath) */
 | 
|---|
| 71 |     static ULONG  openPath2(PCHAR pachFilename, ULONG cchFilename, ldrlv_t *pLdrLv, PULONG pful, ULONG lLibPath, BOOL fOdin32PathValid);
 | 
|---|
| 72 |     #ifndef RING0
 | 
|---|
| 73 |     ULONG  testApplyFixups();
 | 
|---|
| 74 |     ULONG  writeFile(PCSZ pszLXFilename);
 | 
|---|
| 75 |     #endif
 | 
|---|
| 76 | 
 | 
|---|
| 77 |     /** @cat public query methods */
 | 
|---|
| 78 |     BOOL    isExe();
 | 
|---|
| 79 |     BOOL    isDll();
 | 
|---|
| 80 |     static SFN  getKernel32SFN()        {   return sfnKernel32;   }
 | 
|---|
| 81 |     static VOID setKernel32SFN(SFN sfn) {   sfnKernel32 = sfn;    }
 | 
|---|
| 82 |     static VOID invalidateOdin32Path();
 | 
|---|
| 83 |     static LONG getLoadedModuleCount()  {   return cLoadedModules;}
 | 
|---|
| 84 | 
 | 
|---|
| 85 |     /** @cat public Helper methods */
 | 
|---|
| 86 |     ULONG  querySizeOfLxFile();
 | 
|---|
| 87 |     VOID   dumpVirtualLxFile();
 | 
|---|
| 88 | 
 | 
|---|
| 89 | private:
 | 
|---|
| 90 |     /** @cat conversion methods */
 | 
|---|
| 91 |     ULONG       makeObjectTable();
 | 
|---|
| 92 |     ULONG       makeObjectPageTable();
 | 
|---|
| 93 |     ULONG       makeFixups();
 | 
|---|
| 94 |     ULONG       makeExports();
 | 
|---|
| 95 | 
 | 
|---|
| 96 |     /** @cat conversion helper(s) */
 | 
|---|
| 97 |     ULONG       loadNtHeaders();
 | 
|---|
| 98 |     VOID        releaseNtHeaders();
 | 
|---|
| 99 |     ULONG       loadBaseRelocations();
 | 
|---|
| 100 | 
 | 
|---|
| 101 |     /** @cat init() helper methods - may only be called at init time! */
 | 
|---|
| 102 |     ULONG       addObject(ULONG ulRVA, ULONG cbPhysical, ULONG cbVirtual, ULONG flFlags, ULONG offPEFile);
 | 
|---|
| 103 |     ULONG       addTIBFixObject();
 | 
|---|
| 104 |     ULONG       addStackObject(ULONG cbStack);
 | 
|---|
| 105 | 
 | 
|---|
| 106 |     /** @cat PE helper methods */
 | 
|---|
| 107 | 
 | 
|---|
| 108 |     /** @cat Fixups Helpers - calls allowed from makeFixups only! */
 | 
|---|
| 109 |     ULONG       initFixups();
 | 
|---|
| 110 |     ULONG       addPageFixupEntry(BOOL fLast = FALSE);
 | 
|---|
| 111 |     ULONG       add32OffsetFixup(WORD offSource, ULONG ulTarget);
 | 
|---|
| 112 |     ULONG       add32OrdImportFixup(WORD offSource, ULONG ulModuleOrdinal, ULONG ulFunctionOrdinal, PCSZ pszModuleName);
 | 
|---|
| 113 |     ULONG       add32NameImportFixup(WORD offSource, ULONG ulModuleOrdinal, PCSZ pszFnName, PCSZ pszModuleName);
 | 
|---|
| 114 |     ULONG       addModule(PCSZ pszModuleName, PULONG pulModuleOrdinal);
 | 
|---|
| 115 |     ULONG       addImportFunctionName(PCSZ pszFnName, PULONG poffFnName);
 | 
|---|
| 116 |     VOID        finalizeFixups();
 | 
|---|
| 117 |     VOID        finalizeImportNames();
 | 
|---|
| 118 | 
 | 
|---|
| 119 |     /** @cat Entry table / Resident nametable helpers */
 | 
|---|
| 120 |     ULONG       initEntry();
 | 
|---|
| 121 |     ULONG       addResName(ULONG ulOrdinal, PCSZ pszName, ULONG cchName);
 | 
|---|
| 122 |     ULONG       addEntry(ULONG ulOrdinal, ULONG ulRVA);
 | 
|---|
| 123 |     ULONG       addForwarderEntry(ULONG ulOrdinal, PCSZ pszDllName, PCSZ pszFnNameOrOrd);
 | 
|---|
| 124 |     ULONG       addLastEntry();
 | 
|---|
| 125 |     VOID        finalizeExports();
 | 
|---|
| 126 | 
 | 
|---|
| 127 |     /** @cat Misc helpers */
 | 
|---|
| 128 |     ULONG       getCountOfPages();
 | 
|---|
| 129 |     ULONG       queryObjectAndOffset(ULONG ulRVA, PULONG pulObject, PULONG poffObject);
 | 
|---|
| 130 |     ULONG       readAtRVA(ULONG ulRVA, PVOID pvBuffer, ULONG cbBuffer);
 | 
|---|
| 131 | 
 | 
|---|
| 132 |     /** @cat static helpers */
 | 
|---|
| 133 |     static PCSZ queryOdin32ModuleName(PCSZ pszWin32ModuleName);
 | 
|---|
| 134 |     static BOOL initOdin32Path();
 | 
|---|
| 135 |     static BOOL setOdin32Path(const char *psz);
 | 
|---|
| 136 |     #ifndef RING0
 | 
|---|
| 137 |     static BOOL isCustomDllExcluded(PCSZ pszModuleName);
 | 
|---|
| 138 |     #endif
 | 
|---|
| 139 | 
 | 
|---|
| 140 |     /** @cat static dump methods */
 | 
|---|
| 141 |     static VOID dumpNtHeaders(PIMAGE_NT_HEADERS pNtHdrs);
 | 
|---|
| 142 |     static VOID dumpSectionHeader(PIMAGE_SECTION_HEADER pSection);
 | 
|---|
| 143 | 
 | 
|---|
| 144 | 
 | 
|---|
| 145 | private:
 | 
|---|
| 146 |     /** @cat private data members - allways present.  */
 | 
|---|
| 147 |     BOOL        fAllInOneObject;        /* The All-in-object fix will be or is applied. */
 | 
|---|
| 148 |     PLXOBJECT   paObjects;              /* Pointer to object array. */
 | 
|---|
| 149 |     USHORT      cObjects;               /* Count of elements in the object array. */
 | 
|---|
| 150 |     USHORT      cObjectsAllocated;      /* Size of the object array.  */
 | 
|---|
| 151 | 
 | 
|---|
| 152 |     /**
 | 
|---|
| 153 |      * @cat LX structures
 | 
|---|
| 154 |      */
 | 
|---|
| 155 |     struct e32_exe     LXHdr;           /* Lxheader */
 | 
|---|
| 156 | 
 | 
|---|
| 157 |     struct o32_obj    *paObjTab;        /* Pointer to object table - if null check cObjects > 0 and generate it using makeObjectTable */
 | 
|---|
| 158 |     struct o32_map    *paObjPageTab;    /* Pointer to object page table - if null check cObjects > 0 and generate it using makeObjectPageTable */
 | 
|---|
| 159 | 
 | 
|---|
| 160 |     PCHAR              pachResNameTable; /* Pointer to resident name table. */
 | 
|---|
| 161 |     ULONG              offCurResName;    /* Offset of the next entry in the resident name table. */
 | 
|---|
| 162 |     ULONG              cchRNTAllocated;  /* Count of char allocated for the resident name table. */
 | 
|---|
| 163 | 
 | 
|---|
| 164 |     struct b32_bundle *pEntryBundles;       /* Pointer to entry bundles. (exports) */
 | 
|---|
| 165 |     ULONG              offCurEntryBundle;   /* Offset of the next bundle. */
 | 
|---|
| 166 |     ULONG              offLastEntryBundle;  /* Offset of the last entry bundle. */
 | 
|---|
| 167 |     ULONG              ulLastOrdinal;       /* Ordinal number of last entry which was added. */
 | 
|---|
| 168 |     ULONG              cbEBAllocated;       /* Count of bytes allocate for entry bundles. */
 | 
|---|
| 169 |     BOOL               fForwarders;         /* Set if forwarders are present. */
 | 
|---|
| 170 | 
 | 
|---|
| 171 |     PULONG             paulFixupPageTable;  /* Pointer to fixup pagetable. If null generate it using makeFixups. */
 | 
|---|
| 172 |     ULONG              cFixupPTEntries;     /* Number of entries in the fixup page table. */
 | 
|---|
| 173 |     ULONG              cFPTEAllocated;      /* Number of page table entries allocated. */
 | 
|---|
| 174 | 
 | 
|---|
| 175 |     PVOID              pFixupRecords;       /* Pointer to fixup records. If null generate it using makeFixups. */
 | 
|---|
| 176 |     ULONG              offCurFixupRec;      /* Offset of next fixup. */
 | 
|---|
| 177 |     ULONG              cbFRAllocated;       /* Count of bytes allocated for Fixup records. */
 | 
|---|
| 178 | 
 | 
|---|
| 179 |     PVOID              pvCrossPageFixup;    /* Pointer to cross page fixup. */
 | 
|---|
| 180 |     ULONG              cbCrossPageFixup;    /* Fixup size in bytes. */
 | 
|---|
| 181 | 
 | 
|---|
| 182 |     PCHAR              pachImpModuleNames;  /* Pointer to list of module names. */
 | 
|---|
| 183 |     ULONG              offCurImpModuleName; /* Offset of next modulename. */
 | 
|---|
| 184 |     ULONG              cchIMNAllocated;     /* Count of chars allocated for pachImpModuleNames. */
 | 
|---|
| 185 | 
 | 
|---|
| 186 |     PCHAR              pachImpFunctionNames;  /* Pointer to list of function names. */
 | 
|---|
| 187 |     ULONG              offCurImpFunctionName; /* Offset of next functionname. */
 | 
|---|
| 188 |     ULONG              cchIFNAllocated;       /* Count of chars allocated for pachImpFunctionNames. */
 | 
|---|
| 189 | 
 | 
|---|
| 190 |     /**
 | 
|---|
| 191 |      * @cat PE structues
 | 
|---|
| 192 |      */
 | 
|---|
| 193 |     ULONG                   offNtHeaders;   /* Fileoffset of the PE\0\0 signature. */
 | 
|---|
| 194 |     PIMAGE_NT_HEADERS       pNtHdrs;        /* Pointer to NT-Headers. If null load it using loadNtHeaders. */
 | 
|---|
| 195 |     ULONG                   ulImageBase;    /* Image base address. */
 | 
|---|
| 196 |     PIMAGE_BASE_RELOCATION  pBaseRelocs;    /* Baserelocations. */
 | 
|---|
| 197 |     ULONG                   cbBaseRelocs;   /* Size of baserelocations. */
 | 
|---|
| 198 |     ULONG                   fApplyFixups;   /* TRUE: apply fixups, FALSE: do not apply fixups, ~0=check if need to apply fixups */
 | 
|---|
| 199 |     ULONG                   fDeltaOnly;     /* TRUE: apply fixups only as deltas. FALSE: needs to calculate target address... */
 | 
|---|
| 200 | 
 | 
|---|
| 201 |     /**
 | 
|---|
| 202 |      * @cat static data.
 | 
|---|
| 203 |      */
 | 
|---|
| 204 |     static struct LieListEntry              /* Dll Name lie table. */
 | 
|---|
| 205 |     {
 | 
|---|
| 206 |         PCSZ pszWin32Name;                  /* Win32 dll name. */
 | 
|---|
| 207 |         PCSZ pszOdin32Name;                 /* Odin32 dll name. */
 | 
|---|
| 208 |     } paLieList[];
 | 
|---|
| 209 | 
 | 
|---|
| 210 |     static struct PeCharacteristicsToLxFlags/* section characteristics to object flags */
 | 
|---|
| 211 |     {
 | 
|---|
| 212 |         unsigned int Characteristics;       /* set of section characteristics */
 | 
|---|
| 213 |         ULONG flFlags;                      /* equivalent object flags */
 | 
|---|
| 214 |     } paSecChars2Flags[];
 | 
|---|
| 215 | 
 | 
|---|
| 216 |     static LONG             cLoadedModules; /* Count of existing objects. Updated by constructor and destructor. */
 | 
|---|
| 217 |     static const char *     pszOdin32Path;  /* Odin32 base path (include a slash). */
 | 
|---|
| 218 |     static ULONG            cchOdin32Path;  /* Odin32 base path length. */
 | 
|---|
| 219 |     static SFN              sfnKernel32;    /* Odin32 Kernel32 filehandle. */
 | 
|---|
| 220 | };
 | 
|---|
| 221 | 
 | 
|---|
| 222 | 
 | 
|---|
| 223 | /**
 | 
|---|
| 224 |  * BufferedRVARead - read at RVA with buffering.
 | 
|---|
| 225 |  * @author      knut st. osmundsen
 | 
|---|
| 226 |  * @approval    knut st. osmundsen
 | 
|---|
| 227 |  */
 | 
|---|
| 228 | class BufferedRVARead
 | 
|---|
| 229 | {
 | 
|---|
| 230 | public:
 | 
|---|
| 231 |     BufferedRVARead(SFN hFile, ULONG cObjects, PCLXOBJECT paObjects);
 | 
|---|
| 232 | #if 0
 | 
|---|
| 233 |     ULONG readAtRVA(ULONG ulRVA, PVOID pvBuffer, ULONG cbBuffer)
 | 
|---|
| 234 | #else
 | 
|---|
| 235 |     /**
 | 
|---|
| 236 |      * Reads a chunk of data at the spcified RVA.
 | 
|---|
| 237 |      * @returns   NO_ERROR on success.
 | 
|---|
| 238 |      *            ERROR_INVALID_PARAMETER
 | 
|---|
| 239 |      *            <Whatever rc ReadAt returns>
 | 
|---|
| 240 |      * @param     ulRVA     RVA to read from. Within the filesize.
 | 
|---|
| 241 |      * @param     pvBuffer  Pointer to output buffer. pvBuffer > 64KB
 | 
|---|
| 242 |      * @param     cbBuffer  Number of bytes to read. 0 < cbBuffer > 256MB
 | 
|---|
| 243 |      * @status    completely
 | 
|---|
| 244 |      * @author    knut st. osmundsen
 | 
|---|
| 245 |      */
 | 
|---|
| 246 |     inline ULONG readAtRVA(ULONG ulRVA, PVOID pvBuffer, ULONG cbBuffer)
 | 
|---|
| 247 |     {
 | 
|---|
| 248 |         /*
 | 
|---|
| 249 |          * five cases:
 | 
|---|
| 250 |          *  1) entire area is within the buffer.
 | 
|---|
| 251 |          *  2) start of area is within the buffer.
 | 
|---|
| 252 |          *  3) end of area is within the buffer.
 | 
|---|
| 253 |          *  4) the area is larger than the buffer, covering it.
 | 
|---|
| 254 |          *  5) the area is outside the buffer.
 | 
|---|
| 255 |          *
 | 
|---|
| 256 |          * these are optimal: 1, 2, and 5.
 | 
|---|
| 257 |          * The request is allways process from start to end. This will make case 3 and 4 less effecient.
 | 
|---|
| 258 |          */
 | 
|---|
| 259 |         #ifdef DEBUG
 | 
|---|
| 260 |         if (ulRVA == ~0UL || (ULONG)pvBuffer < 0x10000UL || cbBuffer == 0UL || cbBuffer >= 0x10000000UL)
 | 
|---|
| 261 |             return ERROR_INVALID_PARAMETER;
 | 
|---|
| 262 |         #endif
 | 
|---|
| 263 | 
 | 
|---|
| 264 |         do
 | 
|---|
| 265 |         {
 | 
|---|
| 266 |             if (ulRVA >= this->ulRVA && ulRVA < this->ulRVA + sizeof(achBuffer))
 | 
|---|
| 267 |             {   /* in buffer */
 | 
|---|
| 268 |                 register ULONG cbRead = sizeof(achBuffer) - (ulRVA - this->ulRVA);
 | 
|---|
| 269 |                 cbRead = min(cbRead, cbBuffer);
 | 
|---|
| 270 |                 memcpy(pvBuffer, &achBuffer[ulRVA - this->ulRVA], (size_t)cbRead);
 | 
|---|
| 271 |                 if (cbBuffer == cbRead)
 | 
|---|
| 272 |                     return NO_ERROR;
 | 
|---|
| 273 |                 cbBuffer -= cbRead;
 | 
|---|
| 274 |                 pvBuffer = (PVOID)((ULONG)pvBuffer + cbRead);
 | 
|---|
| 275 |                 ulRVA += cbRead;
 | 
|---|
| 276 |             }
 | 
|---|
| 277 |             else
 | 
|---|
| 278 |             {   /* not in buffer, then read it into the buffer! */
 | 
|---|
| 279 |                 APIRET rc = readToBuffer(ulRVA);
 | 
|---|
| 280 |                 if (rc != NO_ERROR)
 | 
|---|
| 281 |                     return rc;
 | 
|---|
| 282 |             }
 | 
|---|
| 283 |         } while (cbBuffer != 0UL);
 | 
|---|
| 284 | 
 | 
|---|
| 285 |         return NO_ERROR;
 | 
|---|
| 286 |     }
 | 
|---|
| 287 | #endif
 | 
|---|
| 288 | 
 | 
|---|
| 289 |     ULONG dupString(ULONG ulRVA, PSZ *ppsz);
 | 
|---|
| 290 |     BufferedRVARead & operator =(BufferedRVARead &SrcObj);
 | 
|---|
| 291 | 
 | 
|---|
| 292 | private:
 | 
|---|
| 293 |     ULONG readToBuffer(ULONG ulRVA);
 | 
|---|
| 294 | 
 | 
|---|
| 295 | private:
 | 
|---|
| 296 |     SFN   hFile;                /* Filehandle. */
 | 
|---|
| 297 |     ULONG cObjects;             /* Count of objects */
 | 
|---|
| 298 |     PCLXOBJECT paObjects;       /* Pointer to a readonly array of objects. */
 | 
|---|
| 299 |     ULONG ulRVA;                /* RVA for the buffer start */
 | 
|---|
| 300 |     CHAR  achBuffer[BUFFEREDRVAREADER_BUFFERSIZE];  /* Buffer. NOTE! Code assumes that it is a page. */
 | 
|---|
| 301 | };
 | 
|---|
| 302 | 
 | 
|---|
| 303 | #endif
 | 
|---|