Advertisement
Guest User

pefile.cpp

a guest
Oct 24th, 2010
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 27.23 KB | None | 0 0
  1. #include "pefile.h"
  2.  
  3. // Konstruktoren
  4. PEFile::PEFile(void)
  5. {
  6.  
  7. }
  8.  
  9. PEFile::PEFile(const char *filename)
  10. {
  11.     // Einlesen der über filename übergebenen Datei
  12.     this->szFilename = new char[strlen(filename)+1];
  13.     strncpy(this->szFilename, filename, strlen(filename));
  14.     this->szFilename[strlen(filename)] = 0;
  15.     FILE *fd = fopen(this->szFilename, "rb");
  16.     if(fd == 0)
  17.         fireError("Die Datei <%s> konnte nicht geoeffnet werden", this->szFilename);
  18.     fseek(fd, 0, SEEK_END);
  19.     this->dwFileSize = ftell(fd);
  20.     fseek(fd, 0, SEEK_SET);
  21.     this->pbRawData = new BYTE[this->dwFileSize];
  22.     fread(this->pbRawData, 1, this->dwFileSize, fd);
  23.     fclose(fd);
  24.     this->gatherInformations(UPDATE_ALL);
  25. }
  26.  
  27. // Destruktor
  28. PEFile::~PEFile()
  29. {
  30.     delete this->szFilename;
  31.     delete this->pbRawData;
  32.     delete this->ppSectionHeader;
  33. }
  34.  
  35. // Private Methoden
  36. DWORD PEFile::roNthSectionHeader(DWORD n)
  37. {
  38.     return this->pImageDOSHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS) + (n * sizeof(IMAGE_SECTION_HEADER));
  39. }
  40.  
  41. void PEFile::gatherInformations(__in DWORD fUpdates)
  42. {
  43.     // Speichern des DOS- und der NT-Header in den entsprechenden Eigenschaften
  44.     this->pImageDOSHeader = (IMAGE_DOS_HEADER *) &this->pbRawData[0];
  45.     this->pImageNTHeaders = (IMAGE_NT_HEADERS *) &this->pbRawData[this->pImageDOSHeader->e_lfanew];
  46.  
  47.     // Ermitteln der physikalischen Adressen der Section Header
  48.     this->dwNumberOfSections = this->pImageNTHeaders->FileHeader.NumberOfSections;
  49.     this->ppSectionHeader = new IMAGE_SECTION_HEADER *[this->dwNumberOfSections];
  50.     for(DWORD n = 0; n < this->dwNumberOfSections; n++)
  51.         this->ppSectionHeader[n] = (IMAGE_SECTION_HEADER *) &this->pbRawData[this->roNthSectionHeader(n)];
  52.  
  53.     // Untersuchen der PE-Datei auf die Anzahl der Section Header die
  54.     // zwischen dem Ende der Header und dem Anfang der Daten passen
  55.     this->dwNumberOfSectionHeaderFitInCave = SectionHeaderFitBetween(this->roNthSectionHeader(this->dwNumberOfSections), this->pImageNTHeaders->OptionalHeader.SizeOfHeaders);
  56.    
  57.     // Ermitteln von Informationen über den OEP
  58.     this->dwSectionOfOEP = this->getSectionIdByRVA(this->pImageNTHeaders->OptionalHeader.AddressOfEntryPoint);
  59.     this->roOEP = this->getRawOffsetByRVA(this->pImageNTHeaders->OptionalHeader.AddressOfEntryPoint);
  60.  
  61.     // Ermitteln, der Anzahl an RelocationBlocks
  62.     DWORD dwSizeIBR = this->pImageNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
  63.     this->roIBR = this->getRawOffsetByRVA(this->pImageNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
  64.     if(dwSizeIBR != 0x00000000 && this->roIBR != 0x00000000)
  65.     {
  66.         DWORD roRelocBlock = this->roIBR;
  67.         int iRelocBlockCounter = 0;
  68.         DWORD dwCountBytes = 0;
  69.         do
  70.         {
  71.             DWORD dwSizeRelocBlock = ReadDWORD(roRelocBlock + sizeof(DWORD));
  72.             roRelocBlock += dwSizeRelocBlock;
  73.             dwCountBytes += dwSizeRelocBlock;
  74.             if(dwCountBytes <= dwSizeIBR)
  75.                 iRelocBlockCounter++;
  76.         } while(dwCountBytes < dwSizeIBR);
  77.         if(dwCountBytes == dwSizeIBR)
  78.             this->dwNumRelocBlocks = iRelocBlockCounter;
  79.         else
  80.             this->dwNumRelocBlocks = 0, fireError("Die im IMAGE_DATA_DIRECTORY angegebene Groeße (%d Byte) der RelocTable ist falsch (%d Byte)", dwSizeIBR, dwCountBytes);
  81.     }
  82.     else
  83.         this->dwNumRelocBlocks = 0;
  84.    
  85.     this->dwFreeBytesAfterRelocs = 0;
  86.     DWORD roEndOfReloc = this->getRawOffsetByRVA(this->pImageNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress + this->pImageNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size);
  87.     if(roEndOfReloc == 0)       // Es ist keine RelocTable vorhanden, also wird einfach eine gemacht
  88.     {
  89.         addSection(".reloc", 0x200, 0x42000040);
  90.         this->pImageNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = this->getSectionHeaderByName(".reloc")->VirtualAddress;
  91.         roEndOfReloc = this->getSectionHeaderByName(".reloc")->PointerToRawData;
  92.        
  93.     }
  94.     DWORD dwProbablyFreeBytes = BytesBetween(this->ppSectionHeader[this->getSectionIdByRawOffset(roEndOfReloc)]->SizeOfRawData, this->ppSectionHeader[this->getSectionIdByRawOffset(roEndOfReloc)]->Misc.VirtualSize);
  95.     for(DWORD i = 0; i < dwProbablyFreeBytes; i++)
  96.     {
  97.         if(ReadBYTE(roEndOfReloc + i ) == 0x00)
  98.             this->dwFreeBytesAfterRelocs++;
  99.         else
  100.             break;
  101.     }
  102.    
  103.     // Eintragen aller Codecaves an Enden von Sections
  104.     this->CaveArr = this->findCodeCaves(&this->dwNumCodeCaves);
  105.  
  106.     // ImportDir
  107.     DWORD dwImportDirSize = this->pImageNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
  108.     this->roImportDir = this->getRawOffsetByRVA(this->pImageNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
  109.     if(dwImportDirSize)
  110.         this->dwNumImportDescriptors = (dwImportDirSize / sizeof(IMAGE_IMPORT_DESCRIPTOR)) - 1;
  111.     else
  112.         this->dwNumImportDescriptors = 0;
  113.  
  114.     DWORD dwImpByNameCounter = 0;
  115.     if(this->dwNumImportDescriptors)
  116.     {
  117.         this->dwNumImportsModule = new DWORD[this->dwNumImportDescriptors];
  118.         IMAGE_IMPORT_DESCRIPTOR *iidArr = (IMAGE_IMPORT_DESCRIPTOR *) &this->pbRawData[this->roImportDir];
  119.         for(DWORD i = 0; i < this->dwNumImportDescriptors; i++)
  120.         {
  121.             if(iidArr[i].FirstThunk == 0x00000000)
  122.                 break;
  123.             //fireDebug("Name der DLL: %s, Adresse des OTD Arrays: 0x%08x", (char *) &this->pbRawData[this->getRawOffsetByRVA(iidArr[i].Name)], this->getRawOffsetByRVA(iidArr[i].FirstThunk));
  124.             IMAGE_THUNK_DATA32 *itd32Arr = (IMAGE_THUNK_DATA32 *) &this->pbRawData[this->getRawOffsetByRVA(iidArr[i].FirstThunk)];
  125.             for(this->dwNumImportsModule[i] = 0; itd32Arr[this->dwNumImportsModule[i]].u1.Function != 0x00000000; this->dwNumImportsModule[i]++);
  126.         }
  127.     }
  128. }
  129.  
  130. // Caves
  131. CODE_CAVE *PEFile::findCodeCaves(__in DWORD *iNumCodeCaves)
  132. {
  133.     int iCountCodeCave = 0;
  134.     CODE_CAVE *ccbuffer = new CODE_CAVE[this->dwNumberOfSections];
  135.     IMAGE_SECTION_HEADER *pNthHeader;
  136.     for(DWORD n = 0; n < this->dwNumberOfSections; n++)
  137.     {
  138.         pNthHeader = this->ppSectionHeader[n];
  139.         if(Align(pNthHeader->Misc.VirtualSize, this->pImageNTHeaders->OptionalHeader.FileAlignment) >= pNthHeader->Misc.VirtualSize
  140.             && pNthHeader->Misc.VirtualSize != 0x0000
  141.             && pNthHeader->PointerToRawData != 0x0000)
  142.         {
  143.             DWORD dwCaveSize = BytesBetween(Align(pNthHeader->Misc.VirtualSize, this->pImageNTHeaders->OptionalHeader.FileAlignment), pNthHeader->Misc.VirtualSize);
  144.             DWORD RawOffset = pNthHeader->PointerToRawData + pNthHeader->Misc.VirtualSize;
  145.             bool empty = true;
  146.             for(DWORD i = 0; i < dwCaveSize; i++)
  147.             {
  148.                 if(*((BYTE *) &this->pbRawData[RawOffset] + i))
  149.                 {
  150.                     empty = false;
  151.                     break;
  152.                 }
  153.             }
  154.             if(!empty)
  155.                 continue;
  156.             ccbuffer[iCountCodeCave].RawOffset = RawOffset;
  157.             ccbuffer[iCountCodeCave].dwCaveSize = dwCaveSize;
  158.             iCountCodeCave++;
  159.         }
  160.     }
  161.     CODE_CAVE *codecaves = new CODE_CAVE[iCountCodeCave];
  162.     memcpy(codecaves, ccbuffer, iCountCodeCave * sizeof(CODE_CAVE));
  163.     *iNumCodeCaves = iCountCodeCave;
  164.     delete ccbuffer;
  165.     return codecaves;
  166. }
  167.  
  168. CODE_CAVE *PEFile::findNullPatterns(__in DWORD iMinPatternSize, __out DWORD *iNumNullPatterns)
  169. {
  170.     CODE_CAVE *codecaves;
  171.     DWORD dwNumCodeCaves = 0;
  172.     DWORD *dwNumCCInSection = new DWORD[this->dwNumberOfSections];
  173.     CODE_CAVE **pccbuffer = new CODE_CAVE *[this->dwNumberOfSections];
  174.     for(DWORD n = 0; n < this->dwNumberOfSections; n++)
  175.     {
  176.         pccbuffer[n] = this->findNullPatternsInSection(iMinPatternSize, n, &dwNumCCInSection[n]);
  177.         dwNumCodeCaves += dwNumCCInSection[n];
  178.     }
  179.     codecaves = new CODE_CAVE[dwNumCodeCaves];
  180.     int index = 0;
  181.     for(DWORD n = 0; n < this->dwNumberOfSections; n++)
  182.     {
  183.         memcpy(codecaves + index, pccbuffer[n], dwNumCCInSection[n] * sizeof(CODE_CAVE));
  184.         index += dwNumCCInSection[n];
  185.     }
  186.     *iNumNullPatterns = dwNumCodeCaves;
  187.     return codecaves;
  188. }
  189.  
  190. CODE_CAVE *PEFile::findNullPatternsInSection(DWORD dwMinPatternSize, DWORD dwSectionID, __out DWORD *dwNumNullPatterns)
  191. {
  192.     if(dwSectionID < 0 || dwSectionID >= this->dwNumberOfSections || this->ppSectionHeader[dwSectionID]->PointerToRawData == 0x00000000)
  193.         return (CODE_CAVE *) NULL;
  194.    
  195.     //Variablen
  196.     IMAGE_SECTION_HEADER *ish = this->ppSectionHeader[dwSectionID];
  197.     DWORD dwRawSize = Align(ish->SizeOfRawData, this->pImageNTHeaders->OptionalHeader.FileAlignment);
  198.     DWORD rvaStartOffset = ish->PointerToRawData;
  199.     DWORD dwMaxCodeCaves = dwRawSize / (dwMinPatternSize + 1);
  200.     CODE_CAVE *ccbuffer = new CODE_CAVE[dwMaxCodeCaves];
  201.     DWORD dwCountCodeCaves = 0;
  202.     DWORD dwByteCounter = 0;
  203.     for(DWORD i = 0; i < dwRawSize; i++)
  204.     {
  205.         if(*((BYTE *) &this->pbRawData[rvaStartOffset + i]) == 0x00)
  206.             dwByteCounter++;
  207.         else if(dwByteCounter)
  208.         {
  209.             if(dwByteCounter >= dwMinPatternSize)
  210.             {
  211.                 ccbuffer[dwCountCodeCaves].RawOffset = rvaStartOffset + (i - dwByteCounter);
  212.                 ccbuffer[dwCountCodeCaves].dwCaveSize = dwByteCounter;
  213.                 dwCountCodeCaves++;
  214.             }
  215.             dwByteCounter = 0;
  216.         }
  217.     }
  218.     if(dwByteCounter >= dwMinPatternSize)
  219.     {
  220.         ccbuffer[dwCountCodeCaves].RawOffset = rvaStartOffset + (dwRawSize - dwByteCounter);
  221.         ccbuffer[dwCountCodeCaves].dwCaveSize = dwByteCounter;
  222.         dwCountCodeCaves++;
  223.     }
  224.     CODE_CAVE *codecaves = new CODE_CAVE[dwCountCodeCaves];
  225.     memcpy(codecaves, ccbuffer, dwCountCodeCaves * sizeof(CODE_CAVE));
  226.     delete ccbuffer;
  227.     *dwNumNullPatterns = dwCountCodeCaves;
  228.     return codecaves;
  229. }
  230.  
  231. // Zurrück ans Zeichbrett :D
  232. bool PEFile::createCodecave(__in DWORD roCaveStart, __in DWORD dwCaveSize)
  233. {
  234.     // Entweder will jemand in die Header schreiben oder über das Ziel hinaus schießen
  235.     if(roCaveStart < this->pImageNTHeaders->OptionalHeader.SizeOfHeaders || roCaveStart >= this->dwFileSize)
  236.         return false;
  237.     // Vars
  238.     DWORD dwNewFileSize;
  239.     DWORD dwSectionOfCaveStart = this->getSectionIdByRawOffset(roCaveStart);
  240.     bool bSectionendHasCave = false;
  241.     CODE_CAVE *ccAffectedSection;
  242.     // Gucken ob sich das zu erzeugende Cave in einer Section befindet, welche ein Cave an ihrem Ende hat
  243.     for(DWORD i = 0; i <  this->dwNumCodeCaves; i++)
  244.         if(this->getSectionIdByRawOffset(this->CaveArr[i].RawOffset) == dwSectionOfCaveStart)
  245.             bSectionendHasCave = true, ccAffectedSection = &this->CaveArr[i];
  246.     if(bSectionendHasCave)
  247.     {
  248.         DWORD dwNewVirtualSize = this->ppSectionHeader[dwSectionOfCaveStart]->Misc.VirtualSize + dwCaveSize;
  249.         DWORD dwNewRawSize = Align(dwNewVirtualSize, this->pImageNTHeaders->OptionalHeader.FileAlignment);
  250.         // Ermitteln der neuen Dateigröße und ggf. der Anzahl an Bytes, um die die nachfolgenden Sections verschoben werden müssen
  251.         DWORD dwDeltaFollowingSections = 0;
  252.         if(ccAffectedSection->dwCaveSize < dwCaveSize)
  253.             dwDeltaFollowingSections = Align(dwCaveSize - ccAffectedSection->dwCaveSize, this->pImageNTHeaders->OptionalHeader.FileAlignment);
  254.         dwNewFileSize = this->dwFileSize + dwDeltaFollowingSections;
  255.         // Schreiben der notwendigen Relocations
  256.         RELOC_INTERVAL relIntervalAffectedSection = {roCaveStart, this->ppSectionHeader[dwSectionOfCaveStart]->PointerToRawData + dwNewRawSize, dwCaveSize};
  257.         this->writeRelocationsForRawOffsetInterval(relIntervalAffectedSection);
  258.         // Neue Parameter
  259.         this->pImageNTHeaders->OptionalHeader.AddressOfEntryPoint = this->getRVAByRawOffset(this->roOEP + dwCaveSize);
  260.         this->ppSectionHeader[dwSectionOfCaveStart]->SizeOfRawData = dwNewRawSize;
  261.         this->ppSectionHeader[dwSectionOfCaveStart]->Misc.VirtualSize = dwNewVirtualSize;
  262.         // Kopieren der ursprünglichen Daten und Einfügen des Caves
  263.         BYTE *buffer = new BYTE[dwNewFileSize];
  264.         memcpy(buffer, this->pbRawData, roCaveStart);
  265.         for(DWORD i = 0; i < dwCaveSize; i++)
  266.             buffer[roCaveStart + i] = 0x00;
  267.         memcpy(
  268.             &buffer[roCaveStart + dwCaveSize],
  269.             &this->pbRawData[roCaveStart],
  270.             ccAffectedSection->RawOffset - roCaveStart
  271.             );
  272.         for(DWORD i = 0; i < (dwNewRawSize - dwNewVirtualSize); i++)
  273.             buffer[ccAffectedSection->RawOffset + dwCaveSize + i] = 0x00;
  274.         memcpy(
  275.             &buffer[this->ppSectionHeader[dwSectionOfCaveStart]->PointerToRawData + dwNewRawSize],
  276.             &this->pbRawData[ccAffectedSection->RawOffset + ccAffectedSection->dwCaveSize],
  277.             this->dwFileSize - (ccAffectedSection->RawOffset + ccAffectedSection->dwCaveSize)
  278.             );
  279.         if(dwDeltaFollowingSections)
  280.             (void) 0;
  281.         delete this->pbRawData;
  282.         this->pbRawData = buffer;
  283.         this->dwFileSize = dwNewFileSize;
  284.         return true;
  285.     }
  286.     else
  287.     {
  288.         (void) 0;
  289.     }
  290. }
  291.  
  292. // Relocations
  293. bool PEFile::switchSections(__in DWORD dwSec1, __in DWORD dwSec2)
  294. {
  295.     if(dwSec1 >= this->dwNumberOfSections || dwSec2 >= this->dwNumberOfSections)
  296.         return false;
  297.     if(dwSec1 == dwSec2)
  298.         return true;
  299.     IMAGE_SECTION_HEADER ishFirst;
  300.     IMAGE_SECTION_HEADER ishSecond;
  301.     ((this->ppSectionHeader[dwSec1]->PointerToRawData < this->ppSectionHeader[dwSec2]->PointerToRawData)
  302.         ? (ishFirst = *this->ppSectionHeader[dwSec1], ishSecond = *this->ppSectionHeader[dwSec2])
  303.         : (ishFirst = *this->ppSectionHeader[dwSec2], ishSecond = *this->ppSectionHeader[dwSec1])
  304.     );
  305.  
  306.     this->switchSectionHeader(dwSec1, dwSec2);
  307.    
  308.     DWORD dwWrittenBytes = 0;
  309.     BYTE *buffer = new BYTE[this->dwFileSize];
  310.     memcpy(
  311.         buffer,
  312.         this->pbRawData,
  313.         ishFirst.PointerToRawData
  314.     );
  315.     dwWrittenBytes += ishFirst.PointerToRawData;
  316.     memcpy(
  317.         &buffer[dwWrittenBytes],
  318.         &this->pbRawData[ishSecond.PointerToRawData],
  319.         ishSecond.SizeOfRawData
  320.     );
  321.     dwWrittenBytes += ishSecond.SizeOfRawData;
  322.     memcpy(
  323.         &buffer[dwWrittenBytes],
  324.         &this->pbRawData[ishFirst.PointerToRawData + ishFirst.SizeOfRawData],
  325.         BytesBetween(ishSecond.PointerToRawData, ishFirst.PointerToRawData + ishFirst.SizeOfRawData)
  326.     );
  327.     dwWrittenBytes += BytesBetween(ishSecond.PointerToRawData, ishFirst.PointerToRawData + ishFirst.SizeOfRawData);
  328.     memcpy(
  329.         &buffer[dwWrittenBytes],
  330.         &this->pbRawData[ishFirst.PointerToRawData],
  331.         ishFirst.SizeOfRawData
  332.     );
  333.     dwWrittenBytes += ishFirst.SizeOfRawData;
  334.     memcpy(
  335.         &buffer[dwWrittenBytes],
  336.         &this->pbRawData[ishSecond.PointerToRawData + ishSecond.SizeOfRawData],
  337.         this->dwFileSize - dwWrittenBytes
  338.     );
  339.     dwWrittenBytes += this->dwFileSize - dwWrittenBytes;
  340.     delete this->pbRawData;
  341.     this->pbRawData = buffer;
  342.     //this->gatherInformations();
  343.     return true;
  344. }
  345.  
  346. bool PEFile::switchSectionHeader(__in DWORD dwSec1, __in DWORD dwSec2)
  347. {
  348.     if(dwSec1 >= this->dwNumberOfSections || dwSec2 >= this->dwNumberOfSections)
  349.     return false;
  350.     if(dwSec1 == dwSec2)
  351.         return true;
  352.    
  353.     IMAGE_SECTION_HEADER ishFirst;
  354.     IMAGE_SECTION_HEADER ishSecond;
  355.     ((this->ppSectionHeader[dwSec1]->PointerToRawData < this->ppSectionHeader[dwSec2]->PointerToRawData)
  356.         ? (ishFirst = *this->ppSectionHeader[dwSec1], ishSecond = *this->ppSectionHeader[dwSec2])
  357.         : (ishFirst = *this->ppSectionHeader[dwSec2], ishSecond = *this->ppSectionHeader[dwSec1])
  358.     );
  359.  
  360.     int iRawSizeDelta = ishSecond.SizeOfRawData - ishFirst.SizeOfRawData;
  361.  
  362.     if(iRawSizeDelta)
  363.         for(DWORD i = 0; i < this->dwNumberOfSections; i++)
  364.             if(Min(dwSec1, dwSec2) < i && i <= Max(dwSec1, dwSec2))
  365.                 this->ppSectionHeader[i]->PointerToRawData += iRawSizeDelta;
  366.    
  367.     IMAGE_SECTION_HEADER temp = *this->ppSectionHeader[dwSec1];
  368.     *this->ppSectionHeader[dwSec1] = *this->ppSectionHeader[dwSec2];
  369.     *this->ppSectionHeader[dwSec2] = temp;
  370.     this->ppSectionHeader[dwSec2]->PointerToRawData = this->ppSectionHeader[dwSec1]->PointerToRawData;
  371.     this->ppSectionHeader[dwSec1]->PointerToRawData = temp.PointerToRawData;
  372.    
  373.     return true;
  374. }
  375.  
  376. bool PEFile::writeAllRelocations(__in DWORD dwDelta)
  377. {
  378.     if(this->dwNumRelocBlocks == 0)
  379.         return true;
  380.     DWORD roRelocBlock = this->roIBR;
  381.     DWORD dwRelocBlockSize = ReadDWORD(roIBR + sizeof(DWORD));
  382.     DWORD dwNumRelocs;
  383.     for(DWORD i = 0; i < this->dwNumRelocBlocks; i++)
  384.     {
  385.         dwNumRelocs = (dwRelocBlockSize - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);
  386.         for(DWORD j = 0; j < dwNumRelocs; j++)
  387.         {
  388.             DWORD roBaseReloc = roRelocBlock + sizeof(IMAGE_BASE_RELOCATION) + j * sizeof(WORD);
  389.             WORD wBaseReloc = ReadWORD(roBaseReloc);
  390.             if((wBaseReloc >> 12) & IMAGE_REL_BASED_HIGHLOW)
  391.             {
  392.                 DWORD roRelocElem = this->getRawOffsetByRVA(ReadDWORD(roRelocBlock)) + (wBaseReloc & 0x0FFF);
  393.                 DWORD dwRelocElem = ReadDWORD(roRelocElem) + dwDelta;
  394.                 WriteDWORD(roRelocElem, dwRelocElem);
  395.             }
  396.             WriteWORD(roBaseReloc, (wBaseReloc & 0xF000) | ((wBaseReloc & 0x0FFF) + dwDelta));
  397.            
  398.         }
  399.         roRelocBlock += dwRelocBlockSize;
  400.         dwRelocBlockSize = ReadDWORD(roRelocBlock + sizeof(DWORD));
  401.     }
  402.     return true;
  403. }
  404.  
  405. bool PEFile::writeRelocationsForRawOffsetInterval(__in RELOC_INTERVAL relInterval)
  406. {
  407.     if(this->dwNumRelocBlocks == 0)
  408.         return true;
  409.     if(relInterval.roLowBoundary < relInterval.roLowBoundary
  410.         || relInterval.dwDelta == 0
  411.         || relInterval.roLowBoundary < this->pImageNTHeaders->OptionalHeader.SizeOfHeaders
  412.         || relInterval.roHighBoundary >= this->dwFileSize
  413.     )
  414.         return false;
  415.    
  416.     DWORD roRelocBlock = this->roIBR;
  417.     DWORD dwRelocBlockSize = ReadDWORD(roIBR + sizeof(DWORD));
  418.     DWORD dwNumRelocs;
  419.     for(DWORD i = 0; i < this->dwNumRelocBlocks; i++)
  420.     {
  421.         dwNumRelocs = (dwRelocBlockSize - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);
  422.         for(DWORD j = 0; j < dwNumRelocs; j++)
  423.         {
  424.             DWORD roBaseReloc = roRelocBlock + sizeof(IMAGE_BASE_RELOCATION) + j * sizeof(WORD);
  425.             WORD wBaseReloc = ReadWORD(roBaseReloc);
  426.             DWORD roRelocElem = this->getRawOffsetByRVA(ReadDWORD(roRelocBlock)) + (wBaseReloc & 0x0FFF);
  427.             DWORD dwRelocElem = ReadDWORD(roRelocElem);
  428.             if((wBaseReloc >> 12) & IMAGE_REL_BASED_HIGHLOW)
  429.                 if(InInterval(this->getRawOffsetByRVA(dwRelocElem - this->pImageNTHeaders->OptionalHeader.ImageBase), sizeof(DWORD), relInterval))
  430.                     WriteDWORD(roRelocElem, dwRelocElem + relInterval.dwDelta);
  431.             if(InInterval(roRelocElem, sizeof(WORD), relInterval))
  432.                 WriteWORD(roBaseReloc, (wBaseReloc & 0xF000) | ((wBaseReloc & 0x0FFF) + relInterval.dwDelta));
  433.         }
  434.         roRelocBlock += dwRelocBlockSize;
  435.         dwRelocBlockSize = ReadDWORD(roRelocBlock + sizeof(DWORD));
  436.     }
  437.     return true;
  438. }
  439.  
  440. bool PEFile::addRelocation(__in DWORD rvaRelocEntry, __in BYTE bRelocType)
  441. {
  442.     DWORD roNextIBR = this->roIBR;
  443.     DWORD dwAffectedIBR;
  444.     DWORD dwWrittenBytes = 0;
  445.     for(dwAffectedIBR = 0; dwAffectedIBR < this->dwNumRelocBlocks; dwAffectedIBR++)
  446.     {
  447.         if(ReadDWORD(roNextIBR) <= rvaRelocEntry && rvaRelocEntry <= ReadDWORD(roNextIBR) + 0xFFF)
  448.             break;
  449.         else
  450.             roNextIBR += ReadDWORD(roNextIBR + sizeof(DWORD));
  451.     }
  452.     if(dwAffectedIBR == this->dwNumRelocBlocks)
  453.     {
  454.         if(this->dwFreeBytesAfterRelocs >= 2*sizeof(DWORD) + sizeof(WORD))
  455.         {
  456.             roNextIBR = this->getRawOffsetByRVA(this->pImageNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress + this->pImageNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size);
  457.             WriteDWORD(roNextIBR, rvaRelocEntry & 0xFFFFF000);
  458.             WriteDWORD(roNextIBR + sizeof(DWORD), 2 * sizeof(DWORD) + sizeof(WORD));
  459.             WriteWORD(roNextIBR + 2 * sizeof(DWORD), ((WORD) bRelocType << 12) | (rvaRelocEntry & 0x00000FFF));
  460.             dwWrittenBytes += 2 * sizeof(DWORD) + sizeof(WORD);
  461.             this->dwFreeBytesAfterRelocs -= 2 * sizeof(DWORD) + sizeof(WORD);
  462.             this->dwNumRelocBlocks++;
  463.         }
  464.         else return false;
  465.     }
  466.     else
  467.     {
  468.         printf("0x%08x\n", roNextIBR);
  469.         if(dwAffectedIBR == this->dwNumRelocBlocks - 1 && this->dwFreeBytesAfterRelocs >= + sizeof(WORD))           // Man befindet sich im letzten RelocEntry
  470.         {
  471.             DWORD dwExistingRelocs =  (ReadDWORD(roNextIBR + sizeof(DWORD)) - 2 * sizeof(DWORD)) / sizeof(WORD);
  472.             WriteDWORD(roNextIBR + sizeof(DWORD), ReadDWORD(roNextIBR + sizeof(DWORD)) +  sizeof(WORD));
  473.             WriteWORD(roNextIBR + 2*sizeof(DWORD)+ dwExistingRelocs * sizeof(WORD), ((WORD) bRelocType << 12) | (rvaRelocEntry & 0x00000FFF));
  474.             dwWrittenBytes += sizeof(WORD);
  475.         }
  476.     }
  477.     this->pImageNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size += dwWrittenBytes;
  478.     return true;
  479. }
  480.  
  481. // Injections
  482. int PEFile::addSection(__in const char *sSecName, __in DWORD dwVirtualSize, __in DWORD dwCharacteristics)
  483. {
  484.     // Kein Platz für einen neuen Header
  485.     if(!this->dwNumberOfSectionHeaderFitInCave)
  486.         return -1;
  487.     DWORD dwSecId = this->dwNumberOfSections;
  488.    
  489.     // Festlegen der neuen SectionHeader Parameter
  490.     IMAGE_SECTION_HEADER *ishNew = (IMAGE_SECTION_HEADER *) &this->pbRawData[this->roNthSectionHeader(dwSecId)];
  491.     memcpy(&ishNew->Name, sSecName, Min(strlen(sSecName), 8));
  492.     ishNew->Misc.VirtualSize = dwVirtualSize;
  493.     ishNew->Characteristics = dwCharacteristics;
  494.     ishNew->SizeOfRawData = Align(dwVirtualSize, this->pImageNTHeaders->OptionalHeader.FileAlignment);
  495.     ishNew->PointerToRawData = this->ppSectionHeader[dwSecId - 1]->PointerToRawData + this->ppSectionHeader[dwSecId - 1]->SizeOfRawData;
  496.     ishNew->VirtualAddress = this->ppSectionHeader[dwSecId - 1]->VirtualAddress + Align(this->ppSectionHeader[dwSecId - 1]->SizeOfRawData, this->pImageNTHeaders->OptionalHeader.SectionAlignment);
  497.     // Sonstige zu verändernde Header
  498.     this->pImageNTHeaders->OptionalHeader.SizeOfImage += Align(dwVirtualSize, this->pImageNTHeaders->OptionalHeader.SectionAlignment);
  499.     this->pImageNTHeaders->FileHeader.NumberOfSections++;
  500.    
  501.     // Speichern der neuen Daten und updaten der Informationen
  502.     BYTE *buffer = new BYTE[this->dwFileSize + ishNew->SizeOfRawData];
  503.     memcpy(buffer, this->pbRawData, this->dwFileSize);
  504.     for(DWORD i = 0; i < ishNew->SizeOfRawData; i++)
  505.         buffer[ishNew->PointerToRawData + i] = 0x00;
  506.     delete this->pbRawData;
  507.     this->pbRawData = buffer;
  508.     this->dwFileSize += ishNew->SizeOfRawData;
  509.     this->dwNumberOfSections++;
  510.     this->gatherInformations(UPDATE_ALL);
  511.     return dwSecId;
  512. }
  513.  
  514. int PEFile::insertCode(__in const char *secName, __in BYTE *data, __in DWORD size, __in DWORD fSettings)
  515. {
  516.     if(this->dwNumberOfSectionHeaderFitInCave < 1)
  517.         fireError("Es ist kein Platz fuer eine weitere Section");
  518.     // Überprüfen ob sich Daten bei der Addresse des neuen SectionHeaders befinden
  519.     IMAGE_SECTION_HEADER *ishNew = (IMAGE_SECTION_HEADER *) &this->pbRawData[this->roNthSectionHeader(this->dwNumberOfSections)];
  520.     for(DWORD i = 0; i < sizeof(IMAGE_SECTION_HEADER); i++)
  521.         if(*((BYTE *) ishNew + i))
  522.             fireError("Es befinden sich Daten im vermeintlichen Cave");
  523.    
  524.     this->CaveArr = this->findCodeCaves(&this->dwNumCodeCaves);
  525.     // Setzen des SectionHeaders
  526.     strncpy((char *) ishNew->Name, secName, 8);
  527.     ishNew->Misc.VirtualSize = size;
  528.     return 0;
  529. }
  530.  
  531. bool PEFile::deleteSectionById(DWORD dwSecId)
  532. {
  533.     IMAGE_SECTION_HEADER *ish = this->getSectionHeaderById(dwSecId);
  534.     IMAGE_SECTION_HEADER *ishLastSec = this->getSectionHeaderById(this->dwNumberOfSections - 1);
  535.     DWORD dwBytesAfterSection = (ishLastSec->PointerToRawData + ishLastSec->SizeOfRawData) - (ish->PointerToRawData + ish->SizeOfRawData);
  536.    
  537.     this->pImageNTHeaders->FileHeader.NumberOfSections--;
  538.     this->pImageNTHeaders->OptionalHeader.SizeOfImage -= Align(ish->Misc.VirtualSize, this->pImageNTHeaders->OptionalHeader.SectionAlignment);
  539.    
  540.     memcpy(&this->pbRawData[ish->PointerToRawData], &this->pbRawData[ish->PointerToRawData + ish->SizeOfRawData], dwBytesAfterSection);
  541.     this->dwFileSize -= ish->SizeOfRawData;
  542.     DWORD dwNumSecAfter = (this->dwNumberOfSections - 1) - dwSecId;
  543.     for(DWORD i = 0; i < dwNumSecAfter; i++)
  544.         this->switchSectionHeader(dwSecId + i, dwSecId + i + 1);
  545.     for(DWORD i = 0; i < sizeof(IMAGE_SECTION_HEADER); i++)
  546.         *((BYTE *)this->ppSectionHeader[this->dwNumberOfSections - 1] + i) = 0x00;
  547.    
  548.     this->dwNumberOfSections--;
  549.     return true;
  550. }
  551.  
  552. // Get'ter
  553. DWORD PEFile::getSectionIdByName(__in const char *name)
  554. {
  555.     BYTE *buffer[IMAGE_SIZEOF_SHORT_NAME];
  556.     if(strlen(name) < IMAGE_SIZEOF_SHORT_NAME)
  557.     {
  558.         memcpy(buffer, name, strlen(name));
  559.         for(DWORD i = strlen(name); i < IMAGE_SIZEOF_SHORT_NAME; i++)
  560.             buffer[i] = 0x00;
  561.     }
  562.     for(DWORD n = 0; n < this->dwNumberOfSections; n++)
  563.         if(memcmp(this->ppSectionHeader[n]->Name, name, IMAGE_SIZEOF_SHORT_NAME) == 0)
  564.             return n;
  565.     return -1;
  566. }
  567.  
  568. DWORD PEFile::getSectionIdByRVA(__in DWORD dwRVA)
  569. {
  570.     for(DWORD n = 0; n < this->dwNumberOfSections; n++)
  571.         if(this->ppSectionHeader[n]->VirtualAddress != 0x00000000 && this->ppSectionHeader[n]->VirtualAddress <= dwRVA && dwRVA < this->ppSectionHeader[n]->VirtualAddress + Align(this->ppSectionHeader[n]->Misc.VirtualSize, this->pImageNTHeaders->OptionalHeader.SectionAlignment))
  572.             return n;
  573.     return -1;
  574. }
  575.  
  576. DWORD PEFile::getSectionIdByRawOffset(__in DWORD dwOffset)
  577. {
  578.     for(DWORD n = 0; n < this->dwNumberOfSections; n++)
  579.         if(this->ppSectionHeader[n]->PointerToRawData != 0x00000000 && this->ppSectionHeader[n]->PointerToRawData <= dwOffset && dwOffset < this->ppSectionHeader[n]->PointerToRawData + this->ppSectionHeader[n]->SizeOfRawData)
  580.             return n;
  581.     return -1;
  582. }
  583.  
  584. DWORD PEFile::getRawOffsetOfSectionEnd(__in DWORD dwSectionId)
  585. {
  586.     if(dwSectionId < 0 || dwSectionId > this->dwNumberOfSections -1)
  587.         return 0x00000000;
  588.     return this->ppSectionHeader[dwSectionId]->PointerToRawData + Align(this->ppSectionHeader[dwSectionId]->Misc.VirtualSize, this->pImageNTHeaders->OptionalHeader.FileAlignment);
  589. }
  590.  
  591. DWORD PEFile::getRawOffsetByRVA(__in DWORD dwRVA)
  592. {
  593.     if(dwRVA == 0x00000000)
  594.         return 0x00000000;
  595.     int iSectionId = this->getSectionIdByRVA(dwRVA);
  596.     if(iSectionId == -1)
  597.         return 0x00000000;
  598.     DWORD dwSectionRVA = this->ppSectionHeader[iSectionId]->VirtualAddress;
  599.     DWORD dwSectionRawOffset = this->ppSectionHeader[iSectionId]->PointerToRawData;
  600.     int iDelta = BytesBetween(dwSectionRVA, dwRVA);
  601.     return dwSectionRawOffset + iDelta;
  602. }
  603.  
  604. DWORD PEFile::getRVAByRawOffset(__in DWORD dwRO)
  605. {
  606.     if(dwRO == 0x00000000)
  607.         return 0x00000000;
  608.     int iSectionId = this->getSectionIdByRawOffset(dwRO);
  609.     DWORD dwSectionRVA = this->ppSectionHeader[iSectionId]->VirtualAddress;
  610.     DWORD dwSectionRawOffset = this->ppSectionHeader[iSectionId]->PointerToRawData;
  611.     int iDelta = BytesBetween(dwSectionRawOffset, dwRO);
  612.     return dwSectionRVA + iDelta;
  613. }
  614.  
  615. IMAGE_NT_HEADERS *PEFile::getNTHeaders(void) { return this->pImageNTHeaders; }
  616.  
  617. BYTE *PEFile::getPointerToDataByRO(__in DWORD dwRO) { return &this->pbRawData[dwRO]; }
  618.  
  619. IMAGE_SECTION_HEADER *PEFile::getSectionHeaderById(__in DWORD dwID) { return this->ppSectionHeader[dwID]; }
  620.  
  621. IMAGE_SECTION_HEADER *PEFile::getSectionHeaderByRO(__in DWORD dwRO) { return this->ppSectionHeader[this->getSectionIdByRawOffset(dwRO)]; }
  622.  
  623. IMAGE_SECTION_HEADER *PEFile::getSectionHeaderByName(__in const char *sSecName) {return this->ppSectionHeader[this->getSectionIdByName(sSecName)]; }
  624.  
  625. DWORD PEFile::getNumberOfSections() { return this->dwNumberOfSections; }
  626.  
  627. DWORD PEFile::getFileSize() { return this->dwFileSize; }
  628.  
  629. CODE_CAVE *PEFile::getSecEndCCByName(__in const char *SecName)
  630. {
  631.     DWORD dwSecId = this->getSectionIdByName(SecName);
  632.     if(dwSecId == -1)
  633.         return NULL;
  634.     for(DWORD i = 0; i < this->dwNumCodeCaves; i++)
  635.         if(this->getSectionIdByRawOffset(this->CaveArr[i].RawOffset) == dwSecId)
  636.             return &CaveArr[i];
  637.     return NULL;
  638. }
  639.  
  640. // Setter
  641. void PEFile::setFileSize(DWORD dwFileSize) { this->dwFileSize = dwFileSize; }
  642.  
  643. // Output
  644. bool PEFile::writePEFile(const char *outputFilename)
  645. {
  646.     HANDLE hFile = CreateFileA(outputFilename, GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, NULL, NULL);
  647.     if (!hFile)
  648.         return false;
  649.     DWORD dWritten = 0;
  650.     if (!WriteFile(hFile, this->pbRawData, this->dwFileSize, &dWritten, 0))
  651.         return false;
  652.     if (dWritten != this->dwFileSize)
  653.         return false;
  654.     CloseHandle(hFile);
  655.     return true;
  656. }
  657.  
  658. // Prints
  659. void fireError(const char *format, ...)
  660. {
  661.     char buffer[500];
  662.     va_list argumentlist;
  663.     va_start(argumentlist, format);
  664.     vsnprintf(buffer, sizeof(buffer) - 1, format, argumentlist);
  665.     va_end(argumentlist);
  666.     fprintf(stderr, "[Error] %s\n", buffer);
  667.     exit(0);
  668. }
  669.  
  670. void fireDebug(const char *format, ...)
  671. {
  672.     char buffer[500];
  673.     va_list argumentlist;
  674.     va_start(argumentlist, format);
  675.     vsnprintf(buffer, sizeof(buffer) - 1, format, argumentlist);
  676.     va_end(argumentlist);
  677.     printf("[Debug] %s\n", buffer);
  678. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement