emitWin.C

Go to the documentation of this file.
00001 /*
00002  * See the dyninst/COPYRIGHT file for copyright information.
00003  * 
00004  * We provide the Paradyn Tools (below described as "Paradyn")
00005  * on an AS IS basis, and do not warrant its validity or performance.
00006  * We reserve the right to update, modify, or discontinue this
00007  * software at any time.  We shall have no obligation to supply such
00008  * updates or modifications or any other form of support to you.
00009  * 
00010  * By your use of Paradyn, you understand and agree that we (or any
00011  * other person or entity with proprietary rights in Paradyn) are
00012  * under no obligation to provide either maintenance services,
00013  * update services, notices of latent defects, or correction of
00014  * defects for Paradyn.
00015  * 
00016  * This library is free software; you can redistribute it and/or
00017  * modify it under the terms of the GNU Lesser General Public
00018  * License as published by the Free Software Foundation; either
00019  * version 2.1 of the License, or (at your option) any later version.
00020  * 
00021  * This library is distributed in the hope that it will be useful,
00022  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00024  * Lesser General Public License for more details.
00025  * 
00026  * You should have received a copy of the GNU Lesser General Public
00027  * License along with this library; if not, write to the Free Software
00028  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00029  */
00030 
00031 #include <algorithm>
00032 #include "../common/h/parseauxv.h"
00033 #include "Object.h"
00034 #include "Object-nt.h"
00035 #include "emitWin.h"
00036 #include "Symtab.h"
00037 #include <iostream>
00038 #include <dbghelp.h>
00039 
00040 
00041 using namespace Dyninst;
00042 using namespace Dyninst::SymtabAPI;
00043 using namespace std;
00044 
00045 
00046 emitWin::emitWin(PCHAR baseaddress, Object *o_nt, void (*err_func)(const char *)){
00047     base_addr =  baseaddress;
00048     obj_nt = o_nt;
00049     err_func_ = err_func;
00050 }
00051 
00052 PIMAGE_SECTION_HEADER emitWin::CreateSecHeader(unsigned int size, PIMAGE_SECTION_HEADER preSecHdr){
00053     DWORD mem_offset, mem_size, disk_offset, disk_size;
00054     PIMAGE_NT_HEADERS pNTHeader = obj_nt -> GetImageHeader();
00055    
00056     disk_size=PEAlign(size,pNTHeader -> OptionalHeader.FileAlignment);
00057     mem_size=PEAlign(disk_size, pNTHeader->OptionalHeader.SectionAlignment);
00058 
00059     disk_offset=PEAlign(preSecHdr->PointerToRawData+preSecHdr->SizeOfRawData,
00060                 pNTHeader->OptionalHeader.FileAlignment);
00061 
00062     mem_offset=PEAlign(preSecHdr->VirtualAddress+preSecHdr->Misc.VirtualSize,
00063                 pNTHeader->OptionalHeader.SectionAlignment);
00064     PIMAGE_SECTION_HEADER newSecHdr=new IMAGE_SECTION_HEADER;  
00065     memset(newSecHdr,0,(size_t)sizeof(IMAGE_SECTION_HEADER));
00066   
00067     newSecHdr->PointerToRawData=disk_offset;
00068     newSecHdr->VirtualAddress=mem_offset;
00069 
00070     newSecHdr->SizeOfRawData=disk_size;
00071     newSecHdr->Misc.VirtualSize=mem_size;
00072     newSecHdr->Characteristics=0xC0000040;
00073     return newSecHdr;
00074 }
00075 
00076 bool emitWin::AlignSection(PIMAGE_SECTION_HEADER p){
00077     return true;
00078 }
00079 
00080 // based on the dyninst section being the last section
00081 static Region *getDyninstSection(Symtab *st)
00082 {
00083    vector<Region*> regs;
00084    st->getAllRegions(regs);
00085    return regs.back();
00086 }
00087 
00088 static Offset copy_ILT_or_ALT(unsigned int idtIdx, 
00089                              vector<pair<string,IMAGE_IMPORT_DESCRIPTOR> > &idt, 
00090                              const vector<void*> &iltEntries, 
00091                              const unsigned char *ptrDyn,
00092                              Offset secOff, 
00093                              Offset ptrToWrite,
00094                              int addrWidth,
00095                              bool isILT)
00096 {
00097    assert(idtIdx < idt.size());
00098    if (isILT) {
00099       idt[idtIdx].second.OriginalFirstThunk = secOff + ptrToWrite;
00100    } else {
00101       idt[idtIdx].second.FirstThunk = secOff + ptrToWrite;;
00102    }
00103    idtIdx++;
00104 
00105    for (vector<void*>::const_iterator eit = iltEntries.begin();
00106         eit != iltEntries.end(); 
00107         eit++)
00108    {
00109       if (0 == (*eit) && idtIdx < idt.size()) {
00110          if (isILT) {
00111             idt[idtIdx].second.OriginalFirstThunk = secOff + ptrToWrite + addrWidth;
00112          } else {
00113             idt[idtIdx].second.FirstThunk = secOff + ptrToWrite + addrWidth;
00114          }
00115          idtIdx++;
00116       }
00117       memcpy((void*)(ptrDyn + ptrToWrite), &(*eit), addrWidth);
00118       ptrToWrite += addrWidth;
00119    }
00120    return ptrToWrite;
00121 }
00122 
00123 
00124 /* Things that need to change:
00125  *
00126  * Tables
00127  *  - Move import descriptor table even if we're not adding new libraries 
00128       (orig. ILT, IAT, HNT tables are full, must point to additional entries)
00129  *  - Add extra import lookup table entries (per-lib ILT's are NULL terminated)
00130  *  - Add extra Hint/Name table entries (1 table for whole binary, but can split)
00131  *  - Add extra import address table entries (can't move original entries)
00132  *  - Add extra library names (duplicates are OK)
00133  * PE Header
00134  *  - fix Import (descriptor) table pointer
00135  *  - fix Import address table pointer
00136  */
00137 bool emitWin::writeImpTable(Symtab* obj)
00138 {
00139    bool ret = true; 
00140 
00141    // populate Import descriptor table with existing entries
00142    vector<pair<string,IMAGE_IMPORT_DESCRIPTOR> > & idt = obj_nt->getImportDescriptorTable();
00143    int origIDTSize = idt.size();
00144 
00145    //get the dyninst section
00146    Region *dynSec = getDyninstSection(obj);
00147    assert(dynSec);
00148 
00149    std::map<string, map<Offset, string> > & ref = obj_nt->getRefs();
00150 
00151    // for each new library in ref, create new IDT entry,
00152    // for each new function in ref, create new HNT entry
00153    map<string, map<string, WORD> > hnt;
00154    for(map<string, map<Offset, string> >::iterator lit=ref.begin(); 
00155        lit != ref.end(); 
00156        lit++)
00157    {
00158       // add IDT entry
00159       IMAGE_IMPORT_DESCRIPTOR newID;
00160       newID.FirstThunk = NULL;       // IAT offset,      don't know yet
00161       newID.ForwarderChain=0;
00162       newID.Name = NULL;             // lib name offset, don't know yet
00163       newID.OriginalFirstThunk=NULL; // ILT offset,      don't know yet
00164       newID.TimeDateStamp=0;
00165       idt.push_back(std::pair<string, IMAGE_IMPORT_DESCRIPTOR>(lit->first, newID));
00166 
00167       hnt[lit->first]; // add hnt entry for the library if needed 
00168       map<string, map<string, WORD> >::iterator libHNT = hnt.find(lit->first);
00169 
00170       // for each new function in ref, create new HNT entry
00171       for(map<Offset, string>::iterator fit = lit->second.begin(); 
00172           fit != lit->second.end(); 
00173           fit++)
00174       {
00175          if (libHNT->second.end() == libHNT->second.find(fit->second)) {
00176             // add missing HNT entry
00177             (libHNT->second)[fit->second] = 0; // index hint = 0
00178          }
00179       }
00180    }
00181 
00182    //create space to hold the .dyninst section and updated import table
00183    unsigned int numImports = 0;
00184    // calculate hint/name table, number of import funcs, the concatenated length of lib names
00185    unsigned int hntSize = 0;
00186    unsigned int libNameSize = 0;
00187    for (map<string, map<string, WORD> >::iterator hit = hnt.begin();
00188         hit != hnt.end();
00189         hit++)
00190    {
00191       numImports += hit->second.size();
00192       libNameSize += hit->first.size() + 1;
00193       for (map<string, WORD>::iterator fit = hit->second.begin();
00194            fit != hit->second.end();
00195            fit++)
00196       {
00197          int nameLen = fit->first.size();
00198          hntSize += 2 + nameLen + 1 + ((nameLen+1) % 2); // hint + nameLen + '\0' + padding
00199       }
00200    }
00201    unsigned int idtSize = sizeof(IMAGE_IMPORT_DESCRIPTOR) * (idt.size() + 1);
00202    unsigned int iltSize = (numImports + hnt.size()) * obj->getAddressWidth();
00203    unsigned int iatSize = iltSize;
00204    unsigned int secSize = dynSec->getDiskSize() + idtSize + iltSize + hntSize + iatSize + libNameSize;
00205    unsigned char* ptrDyn = (unsigned char*) GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT, secSize);
00206 
00207    // initialize the new .dyninst section
00208    Offset ptrToWrite = 0;
00209 
00210    // a. copy the existing section, set dynSec data pointer
00211    memcpy(ptrDyn + ptrToWrite,
00212           dynSec->getPtrToRawData(), 
00213           dynSec->getDiskSize());
00214    ptrToWrite += dynSec->getDiskSize();
00215    dynSec->setPtrToRawData(ptrDyn, secSize);
00216 
00217    // b. copy the HNT, set (ILT/IAT)->HNT pointers
00218    assert(sizeof(void*) == obj->getAddressWidth());
00219    vector<void*> iltEntries;
00220    for (map<string, map<string, WORD> >::iterator hit = hnt.begin();
00221         hit != hnt.end();
00222         hit++)
00223    {
00224       for (map<string, WORD>::iterator fit = hit->second.begin();
00225            fit != hit->second.end();
00226            fit++)
00227       {
00228          // set ILT pointer
00229          iltEntries.push_back((void*)(dynSec->getMemOffset() + ptrToWrite));
00230 
00231          // copy hint
00232          memcpy(ptrDyn + ptrToWrite,
00233                 &(fit->second), 
00234                 2);
00235          ptrToWrite += 2;
00236 
00237          // copy func name
00238          int nameLen = fit->first.size() + 1; // include the ending \0
00239          memcpy(ptrDyn + ptrToWrite,
00240                 fit->first.c_str(), 
00241                 nameLen);
00242          ptrToWrite += nameLen;
00243 
00244          // copy padding
00245          int padLen = nameLen % 2;
00246          if (padLen) { // padLen is 0 or 1, write if 1
00247             ptrDyn[ptrToWrite] = '\0';
00248             ptrToWrite += padLen;
00249          }
00250       }
00251 
00252       // add null entry to close library ILT
00253       iltEntries.push_back(0);
00254    }
00255 
00256    // c. copy the ILT, set IDT pointers
00257    ptrToWrite = copy_ILT_or_ALT(origIDTSize, 
00258                                 idt, 
00259                                 iltEntries, 
00260                                 ptrDyn,
00261                                 dynSec->getMemOffset(), 
00262                                 ptrToWrite, 
00263                                 obj->getAddressWidth(), 
00264                                 true); 
00265 
00266    // d. copy the IAT (identical to ILT), set IDT pointers
00267    Offset iatOffset = dynSec->getMemOffset() + ptrToWrite;
00268    ptrToWrite = copy_ILT_or_ALT(origIDTSize, 
00269                                 idt, 
00270                                 iltEntries, 
00271                                 ptrDyn,
00272                                 dynSec->getMemOffset(), 
00273                                 ptrToWrite, 
00274                                 obj->getAddressWidth(), 
00275                                 false); 
00276    assert(iatSize == (dynSec->getMemOffset() + ptrToWrite - iatOffset));
00277 
00278    // e. create list of library names, set IDT pointers
00279    for (int idtIdx = origIDTSize; idtIdx  != idt.size(); idtIdx++) {
00280       idt[idtIdx].second.Name = dynSec->getMemOffset() + ptrToWrite;
00281       int nameLen = idt[idtIdx].first.size() + 1; // include terminating \0
00282       memcpy(ptrDyn + ptrToWrite,
00283              idt[idtIdx].first.c_str(), 
00284              nameLen);
00285       ptrToWrite += nameLen;
00286    }
00287 
00288    // f. copy the null-terminated IDT
00289    Offset idtOffset = dynSec->getMemOffset() + ptrToWrite;
00290    for (vector<pair<string,IMAGE_IMPORT_DESCRIPTOR> >::iterator dit = idt.begin(); 
00291         dit != idt.end();
00292         dit++)
00293    {
00294       memcpy(ptrDyn + ptrToWrite,
00295              (void*)& dit->second, 
00296              sizeof(IMAGE_IMPORT_DESCRIPTOR));
00297       ptrToWrite += sizeof(IMAGE_IMPORT_DESCRIPTOR);
00298    }
00299    memset(ptrDyn + ptrToWrite, 0, sizeof(IMAGE_IMPORT_DESCRIPTOR));
00300    ptrToWrite += sizeof(IMAGE_IMPORT_DESCRIPTOR);
00301    assert(idtSize == (dynSec->getMemOffset() + ptrToWrite - idtOffset));
00302 
00303    assert(ptrToWrite == secSize);
00304 
00305    // fix PE header import descriptor table address & size
00306    if (obj_nt->getPEHdr()->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_IMPORT) {
00307       obj_nt->getPEHdr()->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = idtOffset;
00308       obj_nt->getPEHdr()->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = idtSize;
00309    } else {
00310       ret = false;
00311    }
00312 
00313    return ret;
00314 } // end writeImpTable
00315 
00316 
00317 bool emitWin::driver(Symtab *obj, std::string fName){
00318     //if external references exist, write the import info.
00319     if(!obj_nt->getRefs().empty())
00320         writeImpTable(obj);
00321 
00322     Offset MoveAheadOffset=0;
00323     //get the number of new added sections
00324     std::vector<Region *> newregs;
00325     if(!obj -> getAllNewRegions(newregs)){
00326         log_winerror(err_func_, "No new section added, no need to drive");
00327         printf("No new section added, no need to drive\n");
00328         return false;
00329     }
00330     //printf("number of new added sections is %d\n",newregs.size());
00331 
00332     unsigned int n1 = NumOfAllowedSecInSectionTable();
00333     
00334     if(newregs.size() > n1){
00335         //no enough space in section table for new sections
00336         //need to use space in Dos Stub Area
00337         unsigned int n2= NumOfAllowedSecInDosHeader();
00338         if(newregs.size() > n1+n2){
00339             //can not accommandate all new sections even if steal all space in Dos Stub.
00340             log_winerror(err_func_, "no way to insert all new added sections, abort.\n");
00341             printf("no way to insert all new added sections, abort.\n");
00342             return false;
00343         }
00344         //need to move into Dos Stub Area
00345         isMoveAhead = true;
00346         //put n1 new section headers in section table, rest in dos stub
00347         MoveAheadOffset = SizeOfSecHeader*(newregs.size() - n1);
00348         //printf("move ahead in %lu bytes\n", MoveAheadOffset);
00349 
00350     }
00351     //there is enough space in section header table for new added sections
00352     //no need to steal space in Dos Stub Area
00353     else 
00354         isMoveAhead = false;
00355 
00356     //get the set of regions which include new added sections.
00357     std::vector<Region *> regs;
00358     if(!(obj -> getAllRegions(regs))) {
00359         printf("Failed to get regions.\n");
00360         log_winerror(err_func_, "Failed to get regions.\n");
00361         return false;
00362     }
00363 
00364     IMAGE_DOS_HEADER DosHeader;
00365     memcpy(&DosHeader, base_addr, sizeof(IMAGE_DOS_HEADER));
00366     DWORD peHdrOffset = DosHeader.e_lfanew;
00367     DWORD dwDosStufOffset = sizeof(IMAGE_DOS_HEADER);
00368     PIMAGE_NT_HEADERS NTHeader=new IMAGE_NT_HEADERS;
00369 
00370     memcpy(NTHeader, base_addr + DosHeader.e_lfanew, sizeof(IMAGE_NT_HEADERS));
00371     assert(NTHeader->Signature == IMAGE_NT_SIGNATURE);
00372    
00373     //vector of section headers
00374     //including the new added sections
00375     std::vector<PIMAGE_SECTION_HEADER> secHdrs;
00376     PIMAGE_NT_HEADERS pehdr = obj_nt->GetImageHeader();
00377    
00378     //pointer of 1st section header
00379     PIMAGE_SECTION_HEADER pScnHdr = (PIMAGE_SECTION_HEADER)(((char*)pehdr) +
00380                                  sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) +
00381                                  pehdr->FileHeader.SizeOfOptionalHeader);
00382 
00383     //first, the original sections
00384     for(unsigned int i=0; i<NTHeader->FileHeader.NumberOfSections; i++){
00385         PIMAGE_SECTION_HEADER p=new IMAGE_SECTION_HEADER;
00386         memcpy(p,pScnHdr, sizeof(IMAGE_SECTION_HEADER));
00387         //printf("%d, name: %s, disk_off:%x\n",i, (const char*)p->Name, p->PointerToRawData);
00388         secHdrs.push_back(p);
00389         //AlignSection(p);
00390         pScnHdr++;
00391     }
00392     //then, create section header for new added sections
00393     PIMAGE_SECTION_HEADER pre = secHdrs[secHdrs.size()-1];
00394     for(unsigned int i=0; i<newregs.size(); i++){
00395         PIMAGE_SECTION_HEADER p = CreateSecHeader(newregs[i]->getDiskSize(), pre);
00396         if((size_t)strlen(newregs[i]->getRegionName().c_str())> 8)
00397             memcpy(p->Name, newregs[i]->getRegionName().c_str(),8);
00398         else
00399             memcpy(p->Name, newregs[i]->getRegionName().c_str(),
00400             (size_t)strlen(newregs[i]->getRegionName().c_str()));
00401         secHdrs.push_back(p);
00402         pre = p;
00403     }
00404     
00405     //printf("size of sec headers:%d\n", secHdrs.size());
00406     for(unsigned int i=0; i<secHdrs.size(); i++){
00407         printf("%s, diskOff=%x, diskSize=%x, memoff=%x, memsize=%x\n", 
00408                (const char*)secHdrs[i]->Name,secHdrs[i]->PointerToRawData, 
00409                secHdrs[i]->SizeOfRawData, secHdrs[i]->VirtualAddress, 
00410                secHdrs[i]->Misc.VirtualSize);
00411     }
00412 
00413     //resize the last section to fit label and trap table pointer
00414     PIMAGE_SECTION_HEADER lastSec = secHdrs[secHdrs.size()-1];
00415     const int REWRITE_LABEL_SIZE = obj->getAddressWidth() + 16;
00416     if (obj->getObject()->trapHeader()) {
00417         lastSec->SizeOfRawData = PEAlign(
00418             lastSec->SizeOfRawData + REWRITE_LABEL_SIZE, 
00419             pehdr->OptionalHeader.FileAlignment);
00420         lastSec->Misc.VirtualSize = PEAlign(
00421             lastSec->SizeOfRawData + REWRITE_LABEL_SIZE, 
00422             pehdr->OptionalHeader.SectionAlignment);
00423     }
00424 
00425     //calculate size of file
00426     DWORD dwFileSize = lastSec->PointerToRawData + lastSec->SizeOfRawData;
00427     //printf("size of file=%x", dwFileSize);
00428 
00429     //open a file to write the image to disk
00430     HANDLE hFile = CreateFileA(fName.c_str(),GENERIC_WRITE,
00431                                FILE_SHARE_WRITE | FILE_SHARE_READ, NULL,
00432                                CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
00433 
00434     if(hFile == INVALID_HANDLE_VALUE){
00435         log_winerror(err_func_, "Failed to open a file to write.\n");
00436         printf("Failed to open a file to write.\n");
00437         return false;
00438     }
00439 
00440     PCHAR pMem = (char*)GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT,dwFileSize);
00441     if(pMem == NULL){
00442         log_winerror(err_func_, "Failed to allocate memory space for written file\n");
00443         printf("Failed to allocate memory space for written file\n");
00444         return false;
00445     }
00446 
00447     // start to wrtie the file
00448     Offset writeOffset = 0;
00449     //retrieve the dos header from exe image
00450     memcpy(pMem,&DosHeader,sizeof(IMAGE_DOS_HEADER));
00451     writeOffset += sizeof(IMAGE_DOS_HEADER);
00452 
00453     //if move ahead, do adjustment for the pe pointer
00454     if(isMoveAhead)
00455         ((PIMAGE_DOS_HEADER)pMem)->e_lfanew -= MoveAheadOffset;
00456 
00457     //write the dos stub
00458     PCHAR dosStub = base_addr + sizeof(IMAGE_DOS_HEADER);
00459     if(isMoveAhead){
00460         memcpy(pMem+writeOffset, dosStub, peHdrOffset-sizeof(IMAGE_DOS_HEADER)-MoveAheadOffset);
00461         writeOffset+=peHdrOffset-sizeof(IMAGE_DOS_HEADER)-MoveAheadOffset;
00462     }
00463     else{
00464         memcpy(pMem+writeOffset, dosStub, peHdrOffset-sizeof(IMAGE_DOS_HEADER));
00465         writeOffset += peHdrOffset-sizeof(IMAGE_DOS_HEADER);
00466     }
00467    
00468     //write the PE file header
00469    
00470     //write NT header
00471     NTHeader->FileHeader.NumberOfSections = regs.size();
00472     //update SizeOfImage
00473     NTHeader->OptionalHeader.SizeOfImage = secHdrs[secHdrs.size()-1]->VirtualAddress + 
00474         secHdrs[secHdrs.size()-1]->Misc.VirtualSize;
00475 
00476     //if move the import descriptor table, update its address
00477     if(!obj_nt->getRefs().empty() && NTHeader->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_IMPORT) {
00478        Offset newOff = obj_nt->getPEHdr()->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
00479        Offset newSize = obj_nt->getPEHdr()->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
00480         NTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = newOff;
00481         NTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = newSize;
00482         printf("new import descriptor table address: %lu size: %lu\n", newOff, newSize);
00483     }
00484     //if move the import address table, update its address
00485     if(!obj_nt->getRefs().empty() && NTHeader->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_IAT) {
00486        Offset newOff = obj_nt->getPEHdr()->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress;
00487        Offset newSize = obj_nt->getPEHdr()->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size;
00488         NTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = newOff;
00489         NTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size = newSize;
00490         printf("new import address table address: %lu size: %lu\n", newOff, newSize);
00491     }
00492 
00493     memcpy(pMem+writeOffset, NTHeader,sizeof(IMAGE_NT_HEADERS));
00494     //if bound import table is not empty, update its virtual address
00495     if(bit_addr != 0){
00496         assert(NTHeader->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_IMPORT);
00497         PIMAGE_NT_HEADERS newpeHdr = (PIMAGE_NT_HEADERS)((void *)(pMem+writeOffset));
00498         PIMAGE_OPTIONAL_HEADER newoptHdr = (PIMAGE_OPTIONAL_HEADER)&newpeHdr -> OptionalHeader;
00499         printf("old address: 0x%x\n", newoptHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress);
00500         newoptHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress+=sizeof(IMAGE_SECTION_HEADER);
00501         printf("new address: 0x%x\n", newoptHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress);
00502     }
00503     writeOffset += sizeof(IMAGE_NT_HEADERS);
00504 
00505     //write section header table and section
00506     //DWORD dwFirstSectionHeaderOffset = peHdrOffset + sizeof(IMAGE_NT_HEADERS);
00507     DWORD dwFirstSectionHeaderOffset = writeOffset;
00508     unsigned int numSecns = secHdrs.size();
00509     for(unsigned int i=0; i<numSecns; i++){
00510         memcpy(pMem+dwFirstSectionHeaderOffset + i*sizeof(IMAGE_SECTION_HEADER),secHdrs[i],
00511             sizeof(IMAGE_SECTION_HEADER));
00512         memcpy(pMem+secHdrs[i]->PointerToRawData, regs[i]->getPtrToRawData(),regs[i]->getDiskSize());
00513     }
00514 
00515     // copy trap-table header & DYNINST_REWRITE to end of last section
00516     Address trapHead = obj->getObject()->trapHeader();
00517     Address writeTarg = (Address) (pMem 
00518         + lastSec->PointerToRawData 
00519         + lastSec->SizeOfRawData 
00520         - REWRITE_LABEL_SIZE);
00521     memcpy((void*)writeTarg, (void*) &trapHead, obj->getAddressWidth());
00522     memcpy((void*)(writeTarg + obj->getAddressWidth()), "DYNINST_REWRITE", 16);
00523 
00524     //write bound import table info
00525     if(bit_addr != 0){
00526         memcpy(pMem+dwFirstSectionHeaderOffset + secHdrs.size()*sizeof(IMAGE_SECTION_HEADER),
00527             (char*)(base_addr+bit_addr), bit_size);
00528     }   
00529 
00530     //move the file pointer to beginning to write
00531     DWORD dwByteWritten =0;
00532     SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
00533     WriteFile(hFile, pMem, dwFileSize,&dwByteWritten, NULL);
00534     // ------ FORCE CALCULATED FILE SIZE ------
00535     SetFilePointer(hFile,dwFileSize,NULL,FILE_BEGIN);
00536     SetEndOfFile(hFile);
00537     CloseHandle(hFile);
00538 
00539     GlobalFree(pMem);
00540 
00541     return true;
00542 }
00543 
00544 
00545 /*In windows PE file, there are two alignments:
00546  1. SectionAlignment: the alignment of section in memory
00547  2. FileAlignment: the alignment of section in disk
00548  */
00549 //this function is used to calculated the aligned address given dwAddr.
00550 //which is applicable for either case.
00551 Offset emitWin::PEAlign(Offset dwAddr,Offset dwAlign)
00552 {   
00553     return(((dwAddr + dwAlign - 1) / dwAlign) * dwAlign);
00554 }
00555 
00556 //This function is used to calculate the maximum number of sections allowed to insert
00557 //for the section header table, the usable space includes the usused space plus the dos stub area if any.
00558 unsigned int emitWin::NumOfTotalAllowedSec(){
00559     unsigned int unusedSpaces = 0;
00560    
00561     //get the PE header pointer;
00562     PIMAGE_NT_HEADERS peHdrs = obj_nt -> GetImageHeader();
00563     //if no phdr, the
00564     if(peHdrs){
00565    
00566     }
00567 
00568     return unusedSpaces;
00569 }
00570 
00571 //to calculate the number of entries that can be inserted into section header table
00572 //because of the fileAlignment, there could be unused space in section header table
00573 unsigned int emitWin::NumOfAllowedSecInSectionTable(){
00574 
00575     //get base address of mapped file
00576     PIMAGE_NT_HEADERS peHdr = obj_nt -> GetImageHeader();
00577     IMAGE_OPTIONAL_HEADER optHdr = peHdr -> OptionalHeader;
00578 
00579     unsigned int NumOfDataDir = optHdr.NumberOfRvaAndSizes;
00580     //printf("NumOfDataDir: %lu\n", NumOfDataDir);
00581     assert( NumOfDataDir == 16);
00582 
00583     //retrieve information on bound import table
00584     //which is 12th entry (IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT) in data directory
00585     //Note: bound import table is right after section header table and before sections
00586     IMAGE_DATA_DIRECTORY bit = optHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT];
00587     bit_addr = bit.VirtualAddress;
00588     bit_size = bit.Size;
00589 
00590     //printf("bound import table:0x%x, 0x%x\n", bit_addr, bit_size);
00591 
00592     //calculate the size of space between section header table and section
00593     PIMAGE_SECTION_HEADER pScnHdr = (PIMAGE_SECTION_HEADER)(((char*)peHdr) +
00594                                  sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) +
00595                                  peHdr->FileHeader.SizeOfOptionalHeader); //pointer of 1st section header
00596     unsigned int nSections = peHdr->FileHeader.NumberOfSections;
00597 
00598     DWORD dwFirstSectionHeaderOffset = ((PIMAGE_DOS_HEADER)base_addr)->e_lfanew + sizeof(IMAGE_NT_HEADERS);
00599 
00600     DWORD dwStuffSize = pScnHdr ->PointerToRawData - (dwFirstSectionHeaderOffset + nSections*sizeof(IMAGE_SECTION_HEADER));
00601 
00602     unsigned int ret = (dwStuffSize - bit_size)/SizeOfSecHeader;
00603     //printf("extra section headers: %lu\n", ret);
00604     return ret;
00605 
00606 }
00607 
00608 //to calculate the number of entries that can be inserted into Dos Stub area
00609 //we don't care the Dos Stub, so just steal the space in that area for the additional section header
00610 unsigned int emitWin::NumOfAllowedSecInDosHeader(){
00611      //get base address of mapped file
00612     PIMAGE_NT_HEADERS peHdr = obj_nt -> GetImageHeader();
00613     //size of dos stub area
00614     unsigned int size = (char*)peHdr - (base_addr+sizeof(IMAGE_DOS_HEADER));
00615     unsigned int ret = size/SizeOfSecHeader;
00616     //printf("extra section headers in dos stub: %lu\n", ret);
00617     return ret;
00618 }
00619 
00620 void emitWin::log_winerror(void (*err_func)(const char *), const char* msg) {
00621     err_func(msg);
00622 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 12 Jul 2013 for SymtabAPI by  doxygen 1.6.1