Advertisement
Guest User

ImportRebuild.cpp

a guest
Nov 29th, 2012
237
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 22.27 KB | None | 0 0
  1. //
  2. //from Scylla Imports Reconstruction
  3. //
  4. #include "ImportRebuild.h"
  5.  
  6. #include "Scylla.h"
  7. #include "StringConversion.h"
  8.  
  9. //#define DEBUG_COMMENTS
  10.  
  11. ImportRebuild::ImportRebuild()
  12. {
  13.     imageData = NULL;
  14.     sizeOfFile = 0;
  15.  
  16.     pDosStub = NULL;
  17.  
  18.     pOverlay = NULL;
  19.     sizeOfOverlay = 0;
  20.  
  21.     pImportDescriptor = NULL;
  22.     pThunkData = NULL;
  23.     pImportByName = NULL;
  24.  
  25.     numberOfImportDescriptors = 0;
  26.     sizeOfImportSection = 0;
  27.     sizeOfApiAndModuleNames = 0;
  28.     importSectionIndex = 0;
  29. }
  30.  
  31. ImportRebuild::~ImportRebuild()
  32. {
  33.     delete [] pDosStub;
  34.     delete [] imageData;
  35.  
  36.     for (size_t i = 0; i < vecSectionData.size(); i++)
  37.     {
  38.         delete [] vecSectionData[i];
  39.     }
  40.  
  41.     delete [] pOverlay;
  42. }
  43.  
  44. bool ImportRebuild::splitTargetFile()
  45. {
  46.     PIMAGE_SECTION_HEADER pSecHeader = 0;
  47.     BYTE * data = 0;
  48.     DWORD alignment = 0;
  49.  
  50.     DosHeader = *(IMAGE_DOS_HEADER*)imageData;
  51.  
  52.     if (DosHeader.e_magic != IMAGE_DOS_SIGNATURE)
  53.     {
  54.         return false;
  55.     }
  56.  
  57.     NTHeader = *(IMAGE_NT_HEADERS*)(imageData + DosHeader.e_lfanew);
  58.  
  59.     if (NTHeader.Signature != IMAGE_NT_SIGNATURE)
  60.     {
  61.         return false;
  62.     }
  63.  
  64.     if (DosHeader.e_lfanew > sizeof(IMAGE_DOS_HEADER))
  65.     {
  66.         size_t sizeOfStub = DosHeader.e_lfanew - sizeof(IMAGE_DOS_HEADER);
  67.         pDosStub = new BYTE[sizeOfStub];
  68.         CopyMemory(pDosStub, imageData + sizeof(IMAGE_DOS_HEADER), sizeOfStub);
  69.     }
  70.  
  71.     pSecHeader = IMAGE_FIRST_SECTION((IMAGE_NT_HEADERS*)(imageData + DosHeader.e_lfanew));
  72.  
  73.     for (WORD i = 0; i < NTHeader.FileHeader.NumberOfSections; i++)
  74.     {
  75.         const DWORD SECTION_SIZE_MAX = 300000000;
  76.         DWORD sizeOfSection = pSecHeader->SizeOfRawData;
  77.  
  78.         if (sizeOfSection > SECTION_SIZE_MAX)
  79.         {
  80.             sizeOfSection = SECTION_SIZE_MAX;
  81.         }
  82.  
  83.         //TODO better use section alignment because it is better?
  84.         alignment = alignValue(sizeOfSection, NTHeader.OptionalHeader.SectionAlignment);
  85.         data = new BYTE[alignment];
  86.  
  87.         ZeroMemory(data, alignment);
  88.         CopyMemory(data, imageData + pSecHeader->PointerToRawData, sizeOfSection);
  89.  
  90.         vecSectionData.push_back(data);
  91.         vecSectionHeaders.push_back(*pSecHeader);
  92.  
  93.         pSecHeader++;
  94.     }
  95.  
  96.     if(NTHeader.FileHeader.NumberOfSections > 0) // ??
  97.     {
  98.         const IMAGE_SECTION_HEADER* pLastSec = &(*vecSectionHeaders.rbegin());
  99.         DWORD calcSize = pLastSec->PointerToRawData + pLastSec->SizeOfRawData;
  100.         if (calcSize < sizeOfFile)
  101.         {
  102.             sizeOfOverlay = sizeOfFile - calcSize;
  103.             pOverlay = new BYTE[sizeOfOverlay];
  104.             memcpy(pOverlay, imageData + calcSize, sizeOfOverlay);
  105.         }
  106.     }
  107.  
  108.     delete [] imageData;
  109.     imageData = 0;
  110.  
  111.     return true;
  112. }
  113.  
  114. bool ImportRebuild::alignSectionHeaders()
  115. {
  116.     for (WORD i = 0; i < vecSectionHeaders.size(); i++)
  117.     {
  118.         vecSectionHeaders[i].VirtualAddress = alignValue(vecSectionHeaders[i].VirtualAddress, NTHeader.OptionalHeader.SectionAlignment);
  119.         vecSectionHeaders[i].Misc.VirtualSize = alignValue(vecSectionHeaders[i].Misc.VirtualSize, NTHeader.OptionalHeader.SectionAlignment);
  120.  
  121.         vecSectionHeaders[i].PointerToRawData = alignValue(vecSectionHeaders[i].PointerToRawData, NTHeader.OptionalHeader.FileAlignment);
  122.         vecSectionHeaders[i].SizeOfRawData = alignValue(vecSectionHeaders[i].SizeOfRawData, NTHeader.OptionalHeader.FileAlignment);
  123.     }
  124.  
  125.     return true;
  126. }
  127.  
  128. bool ImportRebuild::saveNewFile(const WCHAR * filepath)
  129. {
  130.     DWORD fileOffset = 0;
  131.     DWORD dwWriteSize = 0;
  132.     size_t i = 0;
  133.  
  134.     if (vecSectionHeaders.size() != vecSectionData.size())
  135.     {
  136.         return false;
  137.     }
  138.  
  139.     HANDLE hFile = CreateFile(filepath, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, 0,CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  140.  
  141.     if(hFile == INVALID_HANDLE_VALUE)
  142.     {
  143. #ifdef DEBUG_COMMENTS
  144.         Scylla::debugLog.log(L"saveNewFile :: INVALID_HANDLE_VALUE %u", GetLastError());
  145. #endif
  146.  
  147.         return false;
  148.     }
  149.  
  150.     //alignSectionHeaders();
  151.     updatePeHeader();
  152.  
  153.     fileOffset = 0;
  154.     dwWriteSize = sizeof(IMAGE_DOS_HEADER);
  155.     ProcessAccessHelp::writeMemoryToFile(hFile, fileOffset, dwWriteSize, &DosHeader);
  156.  
  157.     fileOffset += dwWriteSize;
  158.     dwWriteSize = DosHeader.e_lfanew - sizeof(IMAGE_DOS_HEADER);
  159.     ProcessAccessHelp::writeMemoryToFile(hFile, fileOffset, dwWriteSize, pDosStub);
  160.  
  161.     fileOffset += dwWriteSize;
  162.     dwWriteSize = sizeof(IMAGE_NT_HEADERS);
  163.     ProcessAccessHelp::writeMemoryToFile(hFile, fileOffset, dwWriteSize, &NTHeader);
  164.  
  165.     fileOffset += dwWriteSize;
  166.     dwWriteSize = sizeof(IMAGE_SECTION_HEADER);
  167.  
  168.     for (i = 0; i < vecSectionHeaders.size(); i++)
  169.     {
  170.         if (!ProcessAccessHelp::writeMemoryToFile(hFile, fileOffset, dwWriteSize, &vecSectionHeaders[i]))
  171.         {
  172. #ifdef DEBUG_COMMENTS
  173.             Scylla::debugLog.log(L"saveNewFile :: writeMemoryToFile failed offset %X size %X", fileOffset, dwWriteSize);
  174. #endif
  175.             CloseHandle(hFile);
  176.             return false;
  177.         }
  178.         fileOffset += dwWriteSize;
  179.     }
  180.  
  181.     for (i = 0; i < vecSectionHeaders.size(); i++)
  182.     {
  183.         dwWriteSize = vecSectionHeaders[i].PointerToRawData - fileOffset;
  184.  
  185.         if (dwWriteSize)
  186.         {
  187.             if (!writeZeroMemoryToFile(hFile, fileOffset, dwWriteSize))
  188.             {
  189. #ifdef DEBUG_COMMENTS
  190.                 Scylla::debugLog.log(L"saveNewFile :: writeZeroMemoryToFile failed offset %X size %X", fileOffset, dwWriteSize);
  191. #endif
  192.                 CloseHandle(hFile);
  193.                 return false;
  194.             }
  195.             fileOffset += dwWriteSize;
  196.         }
  197.  
  198.         dwWriteSize = vecSectionHeaders[i].SizeOfRawData;
  199.  
  200.         ProcessAccessHelp::writeMemoryToFile(hFile, fileOffset, dwWriteSize, vecSectionData[i]);
  201.         fileOffset += dwWriteSize;
  202.     }
  203.  
  204.     if(pOverlay)
  205.     {
  206.         ProcessAccessHelp::writeMemoryToFile(hFile, fileOffset, (DWORD)sizeOfOverlay, pOverlay);
  207.         fileOffset += (DWORD)sizeOfOverlay;
  208.     }
  209.  
  210.     CloseHandle(hFile);
  211.     return true;
  212. }
  213.  
  214. bool ImportRebuild::writeZeroMemoryToFile(HANDLE hFile, DWORD fileOffset, DWORD size)
  215. {
  216.     bool retValue = false;
  217.     PVOID zeromemory = calloc(size, 1);
  218.  
  219.     if (zeromemory)
  220.     {
  221.         retValue = ProcessAccessHelp::writeMemoryToFile(hFile, fileOffset, size, zeromemory);
  222.         free(zeromemory);
  223.     }
  224.     else
  225.     {
  226.         retValue = false;
  227.     }
  228.  
  229.     return retValue;
  230. }
  231.  
  232. bool ImportRebuild::addNewSection(char * sectionName, DWORD sectionSize, BYTE * sectionData)
  233. {
  234.     BYTE * newBuffer = 0;
  235.     IMAGE_SECTION_HEADER pNewSection = {0};
  236.     size_t lastSectionIndex = vecSectionHeaders.size() - 1;
  237.     size_t nameLength = strlen(sectionName);
  238.  
  239.     if (nameLength > IMAGE_SIZEOF_SHORT_NAME)
  240.     {
  241. #ifdef DEBUG_COMMENTS
  242.         Scylla::debugLog.log(L"addNewSection :: sectionname is too long %d", nameLength);
  243. #endif
  244.         return false;
  245.     }
  246.  
  247.     memcpy_s(pNewSection.Name, IMAGE_SIZEOF_SHORT_NAME, sectionName, nameLength);
  248.  
  249.     pNewSection.SizeOfRawData = alignValue(sectionSize, NTHeader.OptionalHeader.FileAlignment);
  250.     pNewSection.Misc.VirtualSize = alignValue(sectionSize, NTHeader.OptionalHeader.SectionAlignment);
  251.  
  252.     pNewSection.PointerToRawData = alignValue(vecSectionHeaders[lastSectionIndex].PointerToRawData + vecSectionHeaders[lastSectionIndex].SizeOfRawData, NTHeader.OptionalHeader.FileAlignment);
  253.     pNewSection.VirtualAddress = alignValue(vecSectionHeaders[lastSectionIndex].VirtualAddress + vecSectionHeaders[lastSectionIndex].Misc.VirtualSize, NTHeader.OptionalHeader.SectionAlignment);
  254.  
  255.     pNewSection.Characteristics = IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE|IMAGE_SCN_CNT_CODE|IMAGE_SCN_CNT_INITIALIZED_DATA;
  256.  
  257.     vecSectionHeaders.push_back(pNewSection);
  258.  
  259.     if ( (sectionSize != pNewSection.SizeOfRawData) || (sectionData == 0) )
  260.     {
  261.         newBuffer = new BYTE[pNewSection.SizeOfRawData];
  262.         ZeroMemory(newBuffer, pNewSection.SizeOfRawData);
  263.  
  264.         if (sectionData)
  265.         {
  266.             CopyMemory(newBuffer, sectionData, sectionSize);
  267.         }
  268.        
  269.     }
  270.     else
  271.     {
  272.         newBuffer = sectionData;
  273.     }
  274.  
  275.     vecSectionData.push_back(newBuffer);
  276.  
  277.     return true;
  278. }
  279.  
  280. bool ImportRebuild::loadTargetFile(const WCHAR * filepath)
  281. {
  282.     HANDLE hTargetFile = INVALID_HANDLE_VALUE;
  283.     DWORD fileSize = 0;
  284.     bool retValue = false;
  285.  
  286.     hTargetFile = CreateFile(filepath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  287.  
  288.     if(hTargetFile == INVALID_HANDLE_VALUE)
  289.     {
  290. #ifdef DEBUG_COMMENTS
  291.         Scylla::debugLog.log(L"loadTargetFile :: INVALID_HANDLE_VALUE %u", GetLastError());
  292. #endif
  293.  
  294.         return false;
  295.     }
  296.  
  297.     fileSize = (DWORD)ProcessAccessHelp::getFileSize(hTargetFile);
  298.  
  299.     if (!fileSize)
  300.     {
  301.         CloseHandle(hTargetFile);
  302.         hTargetFile = 0;
  303.         return false;
  304.     }
  305.  
  306.     imageData = new BYTE[fileSize];
  307.  
  308.     if (!imageData)
  309.     {
  310.         retValue = false;
  311.     }
  312.     else
  313.     {
  314.         sizeOfFile = fileSize;
  315.         retValue = ProcessAccessHelp::readMemoryFromFile(hTargetFile, 0, fileSize, imageData);
  316.     }
  317.  
  318.     CloseHandle(hTargetFile);
  319.     hTargetFile = 0;
  320.  
  321.     return retValue;
  322. }
  323.  
  324. DWORD ImportRebuild::alignValue(DWORD badValue, DWORD alignTo)
  325. {
  326.     return (((badValue + alignTo - 1) / alignTo) * alignTo);
  327. }
  328.  
  329. DWORD ImportRebuild::convertRVAToOffsetVector(DWORD dwRVA)
  330. {
  331.     for (size_t i = 0; i < vecSectionHeaders.size(); i++)
  332.     {
  333.         if ((vecSectionHeaders[i].VirtualAddress <= dwRVA) && ((vecSectionHeaders[i].VirtualAddress + vecSectionHeaders[i].Misc.VirtualSize) > dwRVA))
  334.         {
  335.             return ((dwRVA - vecSectionHeaders[i].VirtualAddress) + vecSectionHeaders[i].PointerToRawData);
  336.         }
  337.     }
  338.  
  339.     return 0;
  340. }
  341.  
  342. /*
  343. DWORD ImportRebuild::convertRVAToOffset(DWORD dwRVA)
  344. {
  345.     PIMAGE_SECTION_HEADER pSectionHeader = IMAGE_FIRST_SECTION(&NTHeader);
  346.  
  347.     for (WORD i = 0; i < NTHeader.FileHeader.NumberOfSections; i++)
  348.     {
  349.         if ((pSectionHeader->VirtualAddress <= dwRVA) && ((pSectionHeader->VirtualAddress + pSectionHeader->Misc.VirtualSize) > dwRVA))
  350.         {
  351.             return ((dwRVA - pSectionHeader->VirtualAddress) + pSectionHeader->PointerToRawData);
  352.         }
  353.         pSectionHeader++;
  354.     }
  355.  
  356.     return 0;
  357. }
  358. */
  359. DWORD_PTR ImportRebuild::convertOffsetToRVAVector(DWORD dwOffset)
  360. {
  361.     for (size_t i = 0; i < vecSectionHeaders.size(); i++)
  362.     {
  363.         if ((vecSectionHeaders[i].PointerToRawData <= dwOffset) && ((vecSectionHeaders[i].PointerToRawData + vecSectionHeaders[i].SizeOfRawData) > dwOffset))
  364.         {
  365.             return ((dwOffset - vecSectionHeaders[i].PointerToRawData) + vecSectionHeaders[i].VirtualAddress);
  366.         }
  367.     }
  368.  
  369.     return 0;
  370. }
  371.  
  372. /*
  373. DWORD ImportRebuild::convertOffsetToRVA(DWORD dwOffset)
  374. {
  375.     PIMAGE_SECTION_HEADER pSectionHeader = IMAGE_FIRST_SECTION(&NTHeader);
  376.  
  377.     for (WORD i = 0; i < NTHeader.FileHeader.NumberOfSections; i++)
  378.     {
  379.         if ((pSectionHeader->PointerToRawData <= dwOffset) && ((pSectionHeader->PointerToRawData + pSectionHeader->SizeOfRawData) > dwOffset))
  380.         {
  381.             return ((dwOffset - pSectionHeader->PointerToRawData) + pSectionHeader->VirtualAddress);
  382.         }
  383.         pSectionHeader++;
  384.     }
  385.  
  386.     return 0;
  387. }
  388. */
  389.  
  390. void ImportRebuild::updatePeHeader()
  391. {
  392.     size_t lastSectionIndex = vecSectionHeaders.size() - 1;
  393.  
  394.     NTHeader.FileHeader.NumberOfSections = (WORD)(lastSectionIndex + 1);
  395.     NTHeader.OptionalHeader.SizeOfImage = vecSectionHeaders[lastSectionIndex].VirtualAddress + vecSectionHeaders[lastSectionIndex].Misc.VirtualSize;
  396.  
  397.     NTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;
  398.     NTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;
  399.  
  400.     if (NTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress)
  401.     {
  402.         for (size_t i = 0; i < vecSectionHeaders.size(); i++)
  403.         {
  404.             if ((vecSectionHeaders[i].VirtualAddress <= NTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress) && ((vecSectionHeaders[i].VirtualAddress + vecSectionHeaders[i].Misc.VirtualSize) > NTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress))
  405.             {
  406.                 //section must be read and writeable
  407.                 vecSectionHeaders[i].Characteristics |= IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE;
  408.             }
  409.         }
  410.  
  411.         NTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = 0;
  412.         NTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size = 0;
  413.     }
  414.  
  415.  
  416.     NTHeader.OptionalHeader.NumberOfRvaAndSizes = 0x10;
  417.  
  418.     NTHeader.OptionalHeader.SizeOfHeaders = alignValue(DosHeader.e_lfanew + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + NTHeader.FileHeader.SizeOfOptionalHeader + (NTHeader.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER)), NTHeader.OptionalHeader.FileAlignment);
  419.  
  420. }
  421.  
  422.  
  423.  
  424. bool ImportRebuild::buildNewImportTable(std::map<DWORD_PTR, ImportModuleThunk> & moduleList)
  425. {
  426.     createNewImportSection(moduleList);
  427.  
  428.     importSectionIndex = vecSectionHeaders.size() - 1;
  429.  
  430.     DWORD dwSize = fillImportSection(moduleList);
  431.  
  432.     if (!dwSize)
  433.     {
  434.         return false;
  435.     }
  436.  
  437.     setFlagToIATSection((*moduleList.begin()).second.firstThunk);
  438.  
  439.     NTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = vecSectionHeaders[importSectionIndex].VirtualAddress;
  440.     NTHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = (DWORD)(numberOfImportDescriptors * sizeof(IMAGE_IMPORT_DESCRIPTOR));
  441.     return true;
  442. }
  443.  
  444. bool ImportRebuild::createNewImportSection(std::map<DWORD_PTR, ImportModuleThunk> & moduleList)
  445. {
  446.     char sectionName[9] = {0};
  447.  
  448.     //DWORD sectionSize = calculateMinSize(moduleList);
  449.     calculateImportSizes(moduleList);
  450.  
  451.     if (wcslen(Scylla::config[IAT_SECTION_NAME].getString()) > IMAGE_SIZEOF_SHORT_NAME)
  452.     {
  453.         strcpy_s(sectionName, ".SCY");
  454.     }
  455.     else
  456.     {
  457.         StringConversion::ToASCII(Scylla::config[IAT_SECTION_NAME].getString(), sectionName, _countof(sectionName));
  458.     }
  459.  
  460.     return addNewSection(sectionName, (DWORD)sizeOfImportSection, 0);
  461. }
  462.  
  463. /*DWORD ImportRebuild::calculateMinSize(std::map<DWORD_PTR, ImportModuleThunk> & moduleList)
  464. {
  465.     DWORD dwSize = 0;
  466.     std::map<DWORD_PTR, ImportModuleThunk>::iterator mapIt;
  467.     std::map<DWORD_PTR, ImportThunk>::iterator mapIt2;
  468.  
  469.     dwSize = (DWORD)((moduleList.size() + 1) * sizeof(IMAGE_IMPORT_DESCRIPTOR)); //last is zero'ed
  470.  
  471.     for ( mapIt = moduleList.begin() ; mapIt != moduleList.end(); mapIt++ )
  472.     {
  473.  
  474.         //dwSize += (DWORD)((*mapIt).second.thunkList.size() + sizeof(IMAGE_IMPORT_BY_NAME));
  475.         dwSize += (DWORD)(wcslen((*mapIt).second.moduleName) + 1);
  476.  
  477.         for ( mapIt2 = (*mapIt).second.thunkList.begin() ; mapIt2 != (*mapIt).second.thunkList.end(); mapIt2++ )
  478.         {
  479.             if((*mapIt2).second.name[0] != '\0')
  480.             {
  481.                 dwSize += sizeof(IMAGE_IMPORT_BY_NAME);
  482.                 dwSize += (DWORD)strlen((*mapIt2).second.name);
  483.             }
  484.         }
  485.     }
  486.  
  487.     return dwSize;
  488. }*/
  489.  
  490. BYTE * ImportRebuild::getMemoryPointerFromRVA(DWORD_PTR dwRVA)
  491. {
  492.     DWORD_PTR offset = convertRVAToOffsetVector((DWORD)dwRVA);
  493.  
  494.     for (size_t i = 0; i < vecSectionHeaders.size(); i++)
  495.     {
  496.         if ((vecSectionHeaders[i].PointerToRawData <= offset) && ((vecSectionHeaders[i].PointerToRawData + vecSectionHeaders[i].SizeOfRawData) > offset))
  497.         {
  498.             return (BYTE *)((DWORD_PTR)vecSectionData[i] + (offset - vecSectionHeaders[i].PointerToRawData));
  499.         }
  500.     }
  501.  
  502.     return 0;
  503. }
  504.  
  505. DWORD ImportRebuild::fillImportSection( std::map<DWORD_PTR, ImportModuleThunk> & moduleList )
  506. {
  507.     std::map<DWORD_PTR, ImportModuleThunk>::iterator mapIt;
  508.     std::map<DWORD_PTR, ImportThunk>::iterator mapIt2;
  509.     PIMAGE_IMPORT_DESCRIPTOR pImportDesc = 0;
  510.     PIMAGE_IMPORT_BY_NAME pImportByName = 0;
  511.     PIMAGE_THUNK_DATA pThunk = 0;
  512.     ImportModuleThunk * importModuleThunk = 0;
  513.     ImportThunk * importThunk = 0;
  514.  
  515.     size_t stringLength = 0;
  516.     DWORD_PTR lastRVA = 0;
  517.  
  518.     BYTE * sectionData = vecSectionData[importSectionIndex];
  519.     DWORD offset = 0;
  520.     DWORD offsetImportLookupTable = 0;
  521.     DWORD importLookupTable = (DWORD)sectionData;
  522.  
  523.     pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(sectionData);
  524.  
  525.     //skip the IMAGE_IMPORT_DESCRIPTOR
  526.     offset += (DWORD)(numberOfImportDescriptors * sizeof(IMAGE_IMPORT_DESCRIPTOR));
  527.    
  528.  
  529.     for ( mapIt = moduleList.begin() ; mapIt != moduleList.end(); mapIt++ )
  530.     {
  531.        
  532.         importModuleThunk = &((*mapIt).second);
  533.        
  534.         offsetImportLookupTable = offset; //offset to the ThunkTable
  535.         offset += ((*mapIt).second.thunkList.size() +1) * sizeof(DWORD_PTR); //offset to the string table
  536.  
  537.         stringLength = addImportDescriptor(importModuleThunk, offset, offsetImportLookupTable);
  538.  
  539. #ifdef DEBUG_COMMENTS
  540.         Scylla::debugLog.log(L"fillImportSection :: importDesc.Name %X", pImportDescriptor->Name);
  541. #endif
  542.  
  543.         offset += (DWORD)stringLength; //stringLength has null termination char
  544.  
  545.         pImportByName = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)sectionData + offset);
  546.  
  547.         //pThunk = (PIMAGE_THUNK_DATA)(getMemoryPointerFromRVA(importModuleThunk->firstThunk));
  548.  
  549.         lastRVA = importModuleThunk->firstThunk - sizeof(DWORD_PTR);
  550.        
  551.         for ( mapIt2 = (*mapIt).second.thunkList.begin() ; mapIt2 != (*mapIt).second.thunkList.end(); mapIt2++ )
  552.         {
  553.             importThunk = &((*mapIt2).second);
  554.  
  555.             pThunk = (PIMAGE_THUNK_DATA)(getMemoryPointerFromRVA(importThunk->rva));
  556.                        
  557.             //check wrong iat pointer
  558.             if (!pThunk)
  559.             {
  560. #ifdef DEBUG_COMMENTS
  561.                 Scylla::debugLog.log(L"fillImportSection :: Failed to get pThunk RVA: %X", importThunk->rva);
  562. #endif
  563.                 return 0;
  564.             }
  565.  
  566.             if ((lastRVA + sizeof(DWORD_PTR)) != importThunk->rva)
  567.             {
  568.                 //add additional import desc
  569.                 addSpecialImportDescriptor(importThunk->rva); //TODO this will totally screw up our table, since we skipped over all IMAGE_IMPORT_DESCRIPTORs, but now add additonal ones
  570.             }
  571.             lastRVA = importThunk->rva;
  572.  
  573. #ifdef DEBUG_COMMENTS
  574.             Scylla::debugLog.log(L"fillImportSection :: importThunk %X pThunk %X pImportByName %X offset %X", importThunk,pThunk,pImportByName,offset);
  575. #endif
  576.             stringLength = addImportToImportTable(importThunk, pThunk, pImportByName, offset, importLookupTable + offsetImportLookupTable);
  577.            
  578.             offsetImportLookupTable += sizeof(DWORD_PTR);
  579.             offset += (DWORD)stringLength; //is 0 by import by ordinal
  580.             pImportByName = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)pImportByName + stringLength);
  581.         }
  582.  
  583.         pImportDescriptor++;
  584.     }
  585.  
  586.     return offset;
  587. }
  588.  
  589. bool ImportRebuild::rebuildImportTable(const WCHAR * targetFilePath, const WCHAR * newFilePath, std::map<DWORD_PTR, ImportModuleThunk> & moduleList)
  590. {
  591.     bool retValue = false;
  592.  
  593.     if (loadTargetFile(targetFilePath))
  594.     {
  595.         splitTargetFile();
  596.  
  597.         retValue = buildNewImportTable(moduleList);
  598.  
  599.         if (retValue)
  600.         {
  601.             retValue = saveNewFile(newFilePath);
  602.         }
  603.  
  604.         return retValue;
  605.     }
  606.     else
  607.     {
  608. #ifdef DEBUG_COMMENTS
  609.         Scylla::debugLog.log(L"rebuildImportTable ::Failed to load target %s", targetFilePath);
  610. #endif
  611.         return false;
  612.     }
  613. }
  614.  
  615. void ImportRebuild::setFlagToIATSection(DWORD_PTR iatAddress)
  616. {
  617.     for (size_t i = 0; i < vecSectionHeaders.size(); i++)
  618.     {
  619.         if ((vecSectionHeaders[i].VirtualAddress <= iatAddress) && ((vecSectionHeaders[i].VirtualAddress + vecSectionHeaders[i].Misc.VirtualSize) > iatAddress))
  620.         {
  621.             //section must be read and writeable
  622.             vecSectionHeaders[i].Characteristics |= IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE;
  623.         }
  624.     }
  625. }
  626.  
  627. size_t ImportRebuild::addImportToImportTable( ImportThunk * pImport, PIMAGE_THUNK_DATA pThunk, PIMAGE_IMPORT_BY_NAME pImportByName, DWORD sectionOffset, DWORD sectionOffsetImportLookupTable)
  628. {
  629.     size_t stringLength = 0;
  630.  
  631.     if(pImport->name[0] == '\0')
  632.     {
  633.         *(PDWORD)sectionOffsetImportLookupTable = (IMAGE_ORDINAL(pImport->ordinal) | IMAGE_ORDINAL_FLAG);
  634.         //pThunk->u1.AddressOfData = (IMAGE_ORDINAL(pImport->ordinal) | IMAGE_ORDINAL_FLAG);
  635.     }
  636.     else
  637.     {
  638.         pImportByName->Hint = pImport->hint;
  639.  
  640.         stringLength = strlen(pImport->name) + 1;
  641.         memcpy(pImportByName->Name, pImport->name, stringLength);
  642.  
  643.         //pThunk->u1.AddressOfData = convertOffsetToRVAVector(vecSectionHeaders[importSectionIndex].PointerToRawData + sectionOffset);
  644.         *(PDWORD)sectionOffsetImportLookupTable = convertOffsetToRVAVector(vecSectionHeaders[importSectionIndex].PointerToRawData + sectionOffset);
  645.  
  646.         if (!pThunk->u1.AddressOfData)
  647.         {
  648. #ifdef DEBUG_COMMENTS
  649.             Scylla::debugLog.log(L"addImportToImportTable :: failed to get AddressOfData %X %X", vecSectionHeaders[importSectionIndex].PointerToRawData, sectionOffset);
  650. #endif
  651.         }
  652.  
  653.         //next import should be nulled
  654.         //pThunk++;
  655.         //pThunk->u1.AddressOfData = 0;
  656.         sectionOffsetImportLookupTable += sizeof(DWORD);
  657.         *(PDWORD)sectionOffsetImportLookupTable = 0;
  658.  
  659. #ifdef DEBUG_COMMENTS
  660.         Scylla::debugLog.log(L"addImportToImportTable :: pThunk->u1.AddressOfData %X %X %X", pThunk->u1.AddressOfData, pThunk, vecSectionHeaders[importSectionIndex].PointerToRawData + sectionOffset);
  661. #endif
  662.         stringLength += sizeof(WORD);
  663.     }
  664.  
  665.     return stringLength;
  666. }
  667.  
  668. size_t ImportRebuild::addImportDescriptor(ImportModuleThunk * pImportModule, DWORD sectionOffset, DWORD sectionOffsetImportLookupTable)
  669. {
  670.     char dllName[MAX_PATH];
  671.  
  672.     StringConversion::ToASCII(pImportModule->moduleName, dllName, _countof(dllName));
  673.     size_t stringLength = strlen(dllName) + 1;
  674.  
  675.     /*
  676.         Warning: stringLength MUST include null termination char
  677.     */
  678.  
  679.     memcpy((vecSectionData[importSectionIndex] + sectionOffset), dllName, stringLength); //copy module name to section
  680.  
  681.     pImportDescriptor->FirstThunk = (DWORD)pImportModule->firstThunk;
  682.     pImportDescriptor->Name = (DWORD)convertOffsetToRVAVector(vecSectionHeaders[importSectionIndex].PointerToRawData + sectionOffset);
  683.     pImportDescriptor->OriginalFirstThunk = (DWORD)convertOffsetToRVAVector(vecSectionHeaders[importSectionIndex].PointerToRawData + sectionOffsetImportLookupTable);
  684.    
  685.     return stringLength;
  686. }
  687.  
  688. void ImportRebuild::addSpecialImportDescriptor(DWORD_PTR rvaFirstThunk)
  689. {
  690.     PIMAGE_IMPORT_DESCRIPTOR oldID = pImportDescriptor;
  691.     pImportDescriptor++;
  692.  
  693.     pImportDescriptor->FirstThunk = (DWORD)rvaFirstThunk;
  694.     pImportDescriptor->Name = oldID->Name;
  695. }
  696.  
  697. void ImportRebuild::calculateImportSizes(std::map<DWORD_PTR, ImportModuleThunk> & moduleList)
  698. {
  699.     std::map<DWORD_PTR, ImportModuleThunk>::iterator mapIt;
  700.     std::map<DWORD_PTR, ImportThunk>::iterator mapIt2;
  701.     DWORD_PTR lastRVA = 0;
  702.  
  703.     numberOfImportDescriptors = 0;
  704.     sizeOfImportSection = 0;
  705.     sizeOfApiAndModuleNames = 0;
  706.  
  707.     numberOfImportDescriptors = moduleList.size() + 1; //last is zero'd
  708.  
  709.     for ( mapIt = moduleList.begin() ; mapIt != moduleList.end(); mapIt++ )
  710.     {
  711.         lastRVA = (*mapIt).second.firstThunk - sizeof(DWORD_PTR);
  712.  
  713.         sizeOfApiAndModuleNames += (DWORD)(wcslen((*mapIt).second.moduleName) + 1);
  714.  
  715.         for ( mapIt2 = (*mapIt).second.thunkList.begin() ; mapIt2 != (*mapIt).second.thunkList.end(); mapIt2++ )
  716.         {
  717.             if ((lastRVA + sizeof(DWORD_PTR)) != (*mapIt2).second.rva)
  718.             {
  719.                 numberOfImportDescriptors++; //add additional import desc
  720.             }
  721.  
  722.             if((*mapIt2).second.name[0] != '\0')
  723.             {
  724.                 sizeOfApiAndModuleNames += sizeof(WORD); //Hint from IMAGE_IMPORT_BY_NAME
  725.                 sizeOfApiAndModuleNames += (DWORD)(strlen((*mapIt2).second.name) + 1);             
  726.             }
  727.             //RVA to ImportThunk
  728.             sizeOfApiAndModuleNames += sizeof(DWORD); //added so we can put the import table completely in the import section
  729.  
  730.             lastRVA = (*mapIt2).second.rva;
  731.         }
  732.         sizeOfApiAndModuleNames += sizeof(DWORD); //each list is terminated by a DWORD=0
  733.     }
  734.  
  735.     sizeOfImportSection = sizeOfApiAndModuleNames + (numberOfImportDescriptors * sizeof(IMAGE_IMPORT_DESCRIPTOR));
  736. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement