internal unsafe static bool HashFile(LockdownSha1.Context context, string filename, int seed) { int i, headersSize, sectionAlignment; byte * imageBase; PeFileLoader module; byte * firstSection; byte * baseaddr; //PeFileReader.NtHeaders.ImageDataDirectory* importDir; PeFileReader.NtHeaders.ImageDataDirectory *relocDir; PeFileReader.DosImageHeader *dosheader; PeFileReader.NtHeaders * ntheader; LockdownHeap heap = new LockdownHeap(); module = new PeFileLoader(filename); baseaddr = module.BaseAddress; dosheader = (PeFileReader.DosImageHeader *)baseaddr; ntheader = (PeFileReader.NtHeaders *)(baseaddr + dosheader->e_lfanew); sectionAlignment = ntheader->OptionalHeader.SectionAlignment; imageBase = (byte *)ntheader->OptionalHeader.ImageBase; //importDir = (PeFileReader.NtHeaders.ImageDataDirectory*)&ntheader->OptionalHeader.IDD1; relocDir = (PeFileReader.NtHeaders.ImageDataDirectory *) & ntheader->OptionalHeader.IDD5; // roughly, IMAGE_FIRST_SECTION macro. 0x18 is the offset of the optional header, plus size of optional header. firstSection = (byte *)(((byte *)ntheader) + 0x18 + ntheader->SizeOfOptionalHeader); headersSize = ntheader->OptionalHeader.SizeOfHeaders; LockdownSha1.Update(context, baseaddr, headersSize); if (relocDir->VirtualAddress != 0 && relocDir->Size != 0) { if (!ProcessRelocDir(heap, baseaddr, relocDir)) { module.Dispose(); heap = null; return(false); } } for (i = 0; i < (ntheader->NumberOfSections); i++) { if (!ProcessSection(context, heap, baseaddr, imageBase, (PeFileReader.ImageSectionHeader *)(firstSection + (i * 0x28)), sectionAlignment, seed)) { module.Dispose(); heap = null; return(false); } } heap = null; module.Dispose(); return(true); }
private unsafe static 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); }
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]; 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; } } 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); }