private static unsafe void PerformBaseReloc(byte* baseaddr, PeFileReader.NtHeaders* ntheader, int relocOffset) { int i; PeFileReader.NtHeaders.ImageDataDirectory* directory; directory = (PeFileReader.NtHeaders.ImageDataDirectory*)&ntheader->OptionalHeader.IDD5; if (directory->Size > 0) { PeFileReader.ImageBaseRelocation* relocation = (PeFileReader.ImageBaseRelocation*)(baseaddr + directory->VirtualAddress); for (; relocation->VirtualAddress > 0; ) { byte* dest = (byte*)(baseaddr + relocation->VirtualAddress); ushort* relocInfo = (ushort*)((byte*)relocation + IMAGE_SIZEOF_BASE_RELOCATION); for (i = 0; i < ((relocation->SizeOfBlock - IMAGE_SIZEOF_BASE_RELOCATION) / 2); i++, relocInfo++) { uint* patch_addr; int type, offset; type = *relocInfo >> 12; offset = *relocInfo & 0xfff; if (type == IMAGE_REL_BASED_HIGHLOW) { patch_addr = (uint*)(dest + offset); *patch_addr += unchecked((uint)relocOffset); } } relocation = (PeFileReader.ImageBaseRelocation*)(((ulong)relocation) + (ulong)relocation->SizeOfBlock); } } }
private static unsafe bool ProcessSection(LockdownSha1.Context context, LockdownHeap heap, byte* baseaddr, byte* preferredBaseAddr, PeFileReader.ImageSectionHeader* section, int sectionAlignment, int seed) { int eax, virtualAddr, virtualSize, value; int index, bytes; int i; using (HeapPtr hpLockdownMem = heap.ToPointer()) { int* lockdown_memory = (int*)hpLockdownMem.ToPointer(); byte* allocatedMemoryBase; int lowerOffset = (int)baseaddr - (int)preferredBaseAddr; virtualAddr = section->VirtualAddress; virtualSize = section->VirtualSize; bytes = ((virtualSize + sectionAlignment - 1) & ~(sectionAlignment - 1)) - virtualSize; if (section->Characteristics < 0) { LockdownSha1.Pad(context, bytes + virtualSize); } else { index = 0; if (heap.CurrentLength > 0) { for (i = 0; index < heap.CurrentLength && lockdown_memory[i] < virtualAddr; i += 4) { index++; } } if (virtualSize > 0) { byte* startingMemory = baseaddr + virtualAddr; byte* ptrMemory = startingMemory; int memoryOffset = index * 4; do { int sectionLength = (int)(startingMemory - ptrMemory + virtualSize); eax = 0; if (index < heap.CurrentLength) { eax = (int)(lockdown_memory[memoryOffset] + startingMemory - virtualAddr); } if (eax != 0) { eax -= (int)ptrMemory; if (eax < sectionLength) sectionLength = eax; } if (sectionLength != 0) { LockdownSha1.Update(context, ptrMemory, sectionLength); ptrMemory += sectionLength; } else { //int* heapBuffer = stackalloc int[0x10]; int* heapBuffer = (int*)Marshal.AllocHGlobal(0x10 * sizeof(int)); Native.Memcpy((void*)heapBuffer, lockdown_memory + memoryOffset, 0x10); value = (*(int*)ptrMemory - lowerOffset) ^ seed; LockdownSha1.Update(context, (byte*)&value, 4); ptrMemory += heapBuffer[1]; index++; memoryOffset += 4; Marshal.FreeHGlobal((IntPtr)heapBuffer); heapBuffer = null; } } while ((ptrMemory - startingMemory) < virtualSize); } if (bytes > 0) { int i2 = 0; IntPtr memoryAllocation = Marshal.AllocHGlobal(bytes); allocatedMemoryBase = (byte*)memoryAllocation.ToPointer(); Native.Memset(allocatedMemoryBase, 0, bytes); do { eax = 0; if (index < heap.CurrentLength) { value = *(int*)(((byte*)lockdown_memory) + (index * 16)); eax = (int)(value - virtualSize - virtualAddr + allocatedMemoryBase); } bytes += i2; if (eax != 0) { eax -= ((int*)allocatedMemoryBase)[i2 / 4]; if (eax < bytes) bytes = eax; } if (bytes != 0) { LockdownSha1.Update(context, &allocatedMemoryBase[i2], bytes); i2 += bytes; } } while (i2 < bytes); Marshal.FreeHGlobal(memoryAllocation); } } } return true; }
private static unsafe void CopySections(byte* data, PeFileReader.NtHeaders* header, byte* baseaddr) { int i, size; byte* dest; // roughly, IMAGE_FIRST_SECTION macro. 0x18 is the offset of the optional header, plus size of optional header. PeFileReader.ImageSectionHeader* section = (PeFileReader.ImageSectionHeader*)(((byte*)header) + 0x18 + header->SizeOfOptionalHeader); for (i = 0; i < header->NumberOfSections; i++, section++) { if (section->SizeOfRawData == 0) { size = header->OptionalHeader.SectionAlignment; if (size > 0) { dest = (byte*)(baseaddr + section->VirtualAddress); section->PhysicalAddress = (int)dest; Native.Memset(dest, 0, size); } } else { dest = (byte*)(baseaddr + section->VirtualAddress); Native.Memcpy(dest, data + section->PointerToRawData, section->SizeOfRawData); section->PhysicalAddress = (int)dest; } } }
private static unsafe bool ProcessRelocDir(LockdownHeap heap, byte* baseaddr, PeFileReader.NtHeaders.ImageDataDirectory* relocDir) { int i, edx; int[] data = new int[4]; PeFileReader.ImageBaseRelocation* relocation = (PeFileReader.ImageBaseRelocation*)(baseaddr + relocDir->VirtualAddress); for (; relocation->VirtualAddress > 0; ) { short* relocInfo = (short*)((byte*)relocation + IMAGE_SIZEOF_BASE_RELOCATION); for (i = 0; i < ((relocation->SizeOfBlock - IMAGE_SIZEOF_BASE_RELOCATION) / 2); i++, relocInfo++) { int type, offset; type = *relocInfo >> 12; offset = *relocInfo & 0xfff; if (type != 0) { switch (type) { case IMAGE_REL_BASED_LOW: edx = 2; break; case IMAGE_REL_BASED_HIGHLOW: edx = 4; break; case IMAGE_REL_BASED_DIR64: edx = 8; break; default: return false; } data[0] = relocation->VirtualAddress + offset; data[1] = edx; data[2] = 2; data[3] = type; heap.Add(data); } } relocation = (PeFileReader.ImageBaseRelocation*)(((byte*)relocation) + relocation->SizeOfBlock); } return true; }