I was analyzing Win32/Valla.2048 today, a file infector written in x86 Assembly. It keeps almost all of its variables (file handles, API function addresses, etc.) at the end of its section and it references these variables relative to EDI:

XOR:0040619A                 push    2
XOR:0040619C                 push    0
XOR:0040619E                 push    dword ptr [edi+6EBh]
XOR:004061A4                 call    dword ptr [edi+602h]
XOR:004061AA                 mov     [edi+6EFh], eax
XOR:004061B0                 push    0
XOR:004061B2                 push    dword ptr [edi+6F7h]
XOR:004061B8                 push    dword ptr [edi+6EBh]
XOR:004061BE                 call    dword ptr [edi+602h]

 

I would have liked to be able to create symbolic constants for these values, but theres no "New", "Add", etc. button in IDAs "Use standard symbolic constant" window:

 

I probably could have created a Type Library for IDA, but this would have been more trouble than it was worth. So instead, I created a structure (named "v" for "Valla"):

00000000 v               struc ; (sizeof=0x704)
00000000
code            db 1476 dup(?)          ; string(C)
000005C4
moduleAddressOfKernel32 dd ?
000005C8
virtualAddressOfKernel32ExportTable dd ?
000005CC
pOriginalEntrypointMinusInfectorsEntrypoint dd ?
000005D0
originalEntrypointMinusInfectorsEntrypoint dd ?
000005D4
_lopen          dd ?
000005D8 field_5D8      
db 7 dup(?)             ; string(C)
000005DF
_lread          dd ?
000005E3 field_5E3      
db 7 dup(?)             ; string(C)
000005EA
_lwrite         dd ?
000005EE field_5EE      
db 8 dup(?)             ; string(C)
000005F6
_lclose         dd ?
000005FA field_5FA      
db 8 dup(?)             ; string(C)
00000602
_llseek         dd ?
00000606 field_606      
db 8 dup(?)             ; string(C)
0000060E
FindFirstFileA  dd ?
00000612 field_612      
db 15 dup(?)            ; string(C)
00000621
FindNextFileA   dd ?
00000625 field_625      
db 14 dup(?)            ; string(C)
00000633
FindClose       dd ?
00000637 field_637      
db 10 dup(?)            ; string(C)
00000641
GlobalAlloc     dd ?
00000645 field_645      
db 12 dup(?)            ; string(C)
00000651
GlobalLock      dd ?
00000655 field_655      
db 11 dup(?)            ; string(C)
00000660
GlobalFree      dd ?
00000664 field_664      
db 11 dup(?)            ; string(C)
0000066F
GetTickCount    dd ?
00000673 field_673      
db 13 dup(?)            ; string(C)
00000680
GetWindowsDirectoryA dd ?
00000684 field_684      
db 21 dup(?)            ; string(C)
00000699
GetSystemDirectoryA dd ?
0000069D field_69D      
db 20 dup(?)            ; string(C)
000006B1
GetFileAttributesA dd ?
000006B5 field_6B5      
db 19 dup(?)            ; string(C)
000006C8
SetFileAttributesA dd ?
000006CC field_6CC      
db 19 dup(?)            ; string(C)
000006DF
tickCount       dd ?
000006E3 field_6E3       db ?
000006E4
dotdot          db 3 dup(?)             ; string(C)
000006E7
starDotStar     db 4 dup(?)             ; string(C)
000006EB
hFile           dd ?
000006EF
fileSize        dd ?
000006F3
rvaOfNewSection dd ?
000006F7
offsetOfPEHeader dd ?
000006FB
pAllocatedMemory64K dd ?
000006FF
hMem            dd ?
00000703
banner          db ?
00000704
v               ends

 

This allowed me to then tell IDA to interpret the EDI offsets as structure offsets, making it much easier to analyze the virus:

XOR:0040619A                 push    2
XOR:0040619C                 push    0
XOR:0040619E                 push    [edi+v.hFile]
XOR:004061A4                 call    [edi+v._llseek]
XOR:004061AA                 mov     [edi+v.fileSize], eax
XOR:004061B0                 push   
0
XOR:004061B2                 push    [edi+v.offsetOfPEHeader]
XOR:004061B8                 push    [edi+v.hFile]
XOR:004061BE                 call    [edi+v._llseek]