IMAGEHLP.ImageRvaToVa
Monday, 14. July 2008, 05:02:15
PVOID WINAPI ImageRvaToVa(__in PIMAGE_NT_HEADERS NtHeaders, __in PVOID Base, __in ULONG Rva, __in_opt PIMAGE_SECTION_HEADER *LastRvaSection );
ImageRvaToVa
The API ImageRvaToVa, exported by IMAGEHLP and also DBGHELP (available in Windows 9x/NT/XP/2K3 and VISTA) convert a relative virtual address (Rva parameter) into a virtual address/offset using the NT header of SYS/DLL/EXE file ...
In the documentation, the function can return the virtual address (offset + BASE addr. in memory) or a NULL pointer..
.text:76C9xxxx push edi ; Rva .text:76C9xxxx push [ebp+Base] ; Base .text:76C9xxxx push [ebp+NtHeaders] ; NtHeaders .text:76C9xxxx call ImageRvaToSection .text:76C9xxxx mov ecx, eax
The API using internally the ImageRvaToSection to find the right section of RVA, with a scan of section table available at addr. NtHeaders+18h+optional header length.
The ImageRvaSection return in eax the address of right section... but this is not always true!
This is the the IDA output on my windows xp sp2 (v 5.1.2600) but it's same code also in SP3 ... (and in dbghelp.dll!)
.text:76C97511 ; PIMAGE_SECTION_HEADER __stdcall ImageRvaToSection(PIMAGE_NT_HEADERS NtHeaders, PVOID Base, ULONG Rva) .76C97511 public ImageRvaToSection .76C97511 ImageRvaToSection proc near .76C97511 .76C97511 NtHeaders = dword ptr 8 .76C97511 Base = dword ptr 0Ch .76C97511 Rva = dword ptr 10h .76C97511 .76C97511 mov edi, edi .76C97513 push ebp .76C97514 mov ebp, esp .76C97516 mov ecx, [ebp+NtHeaders] ; PE header. .76C97519 movzx eax, word ptr [ecx+14h] ; Opt. header size .76C9751D lea eax, [eax+ecx+18h] ; First section descriptor .76C97521 movzx ecx, word ptr [ecx+6] ; Number of Section in PE .76C97525 push esi .76C97526 xor esi, esi .76C97528 test ecx, ecx .76C9752A push edi .76C9752B jbe short loc_76C97547 .76C9752D .76C9752D loc_76C9752D: .76C9752D mov edx, [eax+0Ch] ; Size of RAW data in EAX+0C .76C97530 cmp [ebp+Rva], edx ; compare to RVA .76C97533 jb short loc_76C9753F ; It's below? go next sect. .76C97535 mov edi, [eax+10h] ; Ptr. to raw data .76C97538 add edi, edx ; .76C9753A cmp [ebp+Rva], edi ; RVA < EDI? .76C9753D jb short loc_76C97549 ; Yes. EAX = SECTION! .76C9753F .76C9753F loc_76C9753F: ; .76C9753F add eax, 28h ; 28h = sizeof(IMAGE_SECTION_HEADERS) .76C97542 inc esi .76C97543 cmp esi, ecx .76C97545 jb short loc_76C9752D .76C97547 .76C97547 loc_76C97547: ; Invalid address! .76C97547 xor eax, eax .76C97549 .76C97549 loc_76C97549: ; CODE XREF: ImageRvaToSection+2Cj .76C97549 pop edi .76C9754A pop esi .76C9754B pop ebp .76C9754C retn 0Ch .76C9754C ImageRvaToSection endp
This mean that if an RVA have an abnormal value into Size of Raw Data the function return an incorrect SECTION...
The value of EAX are moved into ECX value into ImageRvaToVa API.
.text:76C9xxxx loc_76C97593: .text:76C9xxxx mov eax, [ecx+14h] ; EAX = Pointer to raw data .text:76C9xxxx sub eax, [ecx+0Ch] ; EAX = EAX - VirtualAddress .text:76C9xxxx add eax, [ebp+Base] ; EAX = EAX + Base addr. in mem .text:76C9xxxx add eax, edi ; EAX = EAX + Rva .text:76C9xxxx jmp short loc_76C975A2
The API with an exe file mapped in memory, and with a a "compromised" Size Of Raw Data into 1 section , the return value can raise an exception in reading/writing, blocking the execution of code..
By wolfcod, # 14. July 2008, 17:55:16