Uninformed: Informative Information for the Uninformed

Vol 6» 2007.Jan


Writing to External Addresses

Due to the fact that the VirtualAddress associated with each relocation block is a 32-bit RVA, it is possible to create relocation blocks that have RVAs that actually reside outside of the mapped executable that is being relocated. This is important because if steps aren't taken to detect this scenario, the application processing the relocation fixups might be tricked into writing to memory that is external to the mapped binary. Creating a test-case for this example is trivial:

static VOID CreateExternalWriteRelocationBlock(
      __in PPE_IMAGE Image,
      __in PRELOC_FUZZ_CONTEXT FuzzContext)
{
   PRELOCATION_BLOCK_CONTEXT ExtBlock = AllocateRelocationBlockContext(2);

   ExtBlock->Rva = 0x10000;
   ExtBlock->Fixups[0] = (3 << 12) | 0x0;
   ExtBlock->Fixups[1] = (3 << 12) | 0x1;

   PrependRelocationBlockContext(
         FuzzContext,
         ExtBlock);
}

In this test, a relocation block is created that has a VirtualAddress of 0x10000. When the binary is relocated to 0x10000, the actual address of the region that will be written to is 0x20000. In almost all versions of Windows NT, this address is the location of the process parameters structure. The block itself contains two fixup descriptors, each of which will result in a write to the first few bytes of the process parameters structure. The results after running this test are:

Application Results

ntdll.dll
The relocation fixup is processed and results in two 32-bit writes to 0x20000 and 0x20001.

IDA
Ignores RVAs outside of the executable.

dumpbin.exe
N/A, dumpbin doesn't actually perform relocation fixups.