Uninformed: Informative Information for the Uninformed

Vol 6» 2007.Jan


Consistent Handling of Fixup Types

Applications that process relocation fixups may also differ in their level of support for different types of fixups. While most binaries today use the HIGHLOW fixup exclusively, there are still quite a few other types of fixups that can be applied. If differences in the way relocation fixups are processed can be identified, it may be possible to create a binary that relocates correctly in one application but not in another application. The following code demonstrates an example of this type of test:

static VOID TestConsistentRelocations(
      __in PPE_IMAGE Image,
      __in PRELOC_FUZZ_CONTEXT FuzzContext)
{
   PRELOCATION_BLOCK_CONTEXT Block = AllocateRelocationBlockContext(16);
   ULONG                     Rva = FuzzContext->BaseRelocationSection->VirtualAddress;
   INT                       Index;

   PrependRelocationBlockContext(
         FuzzContext,
         Block);

   Block->Rva = 0x1000;

   for (Index = 0; Index < 16; Index++)
   {
      //
      // Skip invalid fixup types
      //
      if ((Index >= 6 && Index <= 8) ||
            (Index >= 0xb && Index <= 0x10))
         continue;

      Block->Fixups[Index] = (Index << 12) | Index;
   }
}

This test works by prepending a relocation block that contains a relocation fixup for each different valid fixup type. This results in a relocation block that looks something like this:

BASE RELOCATIONS #4
    1000 RVA,       28 SizeOfBlock
       0  ABS
       1  HIGH                   EC8B
       2  LOW                    8BEC
       3  HIGHLOW            5008458B
       4  HIGHADJ                0845 (5005)
       0  ABS
       0  ABS
       0  ABS
       9  IMM64
       A  DIR64      8000209C15FF8000
       0  ABS
       0  ABS
       0  ABS
       0  ABS
       0  ABS

The results for this test are shown below:

Application Results

ntdll.dll
While not confirmed, it is assumed that the dynamic loader performs all fixup types correctly. This results in the following code being produced in the test binary:

foo+0x1000:
00011000 55              push    ebp
00011001 8c6c8b46        mov     word ptr [ebx+ecx*4+46h],gs
00011005 895068          mov     dword ptr [eax+68h],edx
00011008 1830            sbb     byte ptr [eax],dh
0001100a 0100            add     dword ptr [eax],eax
0001100c 00b69b200100    add     byte ptr foo+0x209b (0001209b)[esi],dh
00011012 83c408          add     esp,8

IDA
Appears to handle some relocation fixup types differently than the dynamic loader. The result of IDA relocating the same binary results in the following being produced:

.text:00011000    push    ebp
.text:00011001    mov     ebp, esp
.text:00011003    mov     eax, [ebp+9]
.text:00011006    shr     byte ptr [eax+18h], 1 ; "Called TestFunction()\n"
.text:00011009    xor     [ecx], al
.text:00011009 
.text:0001100B    db 0
.text:0001100C
.text:0001100C    add     byte ptr ds:printf[esi], dl
.text:00011012    add     esp, 8

Equates to:

.text:00011000  55 8B EC 8B 45 09 D0 68  18 30 01 00 00 96 9C 20 
.text:00011010  01 00 83 C4 08 C7 05 50

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