Hi,
I have found a source code for Converting Rva Address To Raw Offset
I am Getting an Error Here :
mov ax, word ptr [edi.3ch] ; offset 'PE'
mov dx, [edi.6h] ; number of sections
mov eax, [edi.0ch] ; virtual address
I have never seen "edi.0ch" ?
; RvaToRaw procedure
; ¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤
; ##################################################
; RvaToRaw() - Takes a rva and converts it to a raw offset.
; Returns : EAX=raw.
; it relies on you doing is passing a pointer to the PE header and the RVA you desire converting,
; (how you get the PE header is your business).
; ##################################################
RvaToRaw proc pe_header:DWORD, rva:DWORD
push ebp
push ebx
push ecx
push edx
push esi
push edi
xor eax, eax
mov ecx, rva
cdq
mov edi, pe_header
mov ax, word ptr [edi.3ch] ; offset 'PE'
add edi, eax
mov dx, [edi.6h] ; number of sections
add edi, 0f8h ; start of sections
RvaToRawLoop:
mov eax, [edi.0ch] ; virtual address
cmp eax, ecx
ja RvaToRawDone
add edi, 28h ; next section
dec edx
jnz RvaToRawLoop ; last section drops out of the loop
RvaToRawDone:
mov eax, rva
mov ecx, [edi-1ch] ; previous sections virtual address
sub eax, ecx
mov ecx, [edi-14h] ; previous sections raw offset
add ecx, eax
xchg eax, ecx
RvaToRawEnd:
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop ebp
ret
RvaToRaw endp
Yes I know I should stop Cruising the Net at 2AM ......
Leads to this type of questions
Thank you !
Your code is just unreadable.
use a structure instead.
;lea edi,something
movzx eax,[edi].MYSTRUCTURE.value
Quote from: hfheatherfox07 on December 03, 2012, 06:03:38 PM
I am Getting an Error Here :
mov ax, word ptr [edi.3ch] ; offset 'PE'
mov dx, [edi.6h] ; number of sections
mov eax, [edi.0ch] ; virtual address
I have never seen "edi.0ch" ?
It's old Masm5-style syntax. Just replace the '.' with a '+'.
However, there a lots of problems/misconceptions in your source:
- the "pe_header" argument is in fact a MZ-header pointer
- the offset at 03Ch is a dword, not a word
- the value to "start to sections" is not always 0F8h (depends on 32-bit vs. 64-bit )
- no error handling
- ...
Thank you for the answers ..... :biggrin:
I admit I was scratching my head with the MZ-header pointer (Icezlion PE tuts are showing how to get that, but I had no idea how to tie it in to this proc)
I found this source and I though of making a crude
Converter just for the fun of making one ....
Nothing more than open and map a PE and an edit box to enter RVA address
And a second box to display the result ....
.......
Thank you again :greenclp:
Still Having some trouble ...... I am getting error : error A2022: instruction operands must be the same size
I made a bare bone example to try and get the proc working ....
As I realized ..... Finding the Pointer to the PE header will be harder than I though LOL
I found one source that uses a snap shot ....
RVAtoRAWOffsetBareBones.asm
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\masm32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\masm32.lib
; Prototype
RvaToRaw PROTO :DWORD, :DWORD
.data
UserInput db "403007h",0 ; RVA Address:403007 Should give RAW Offset address: 807
Format db "RAW Offset: %dh", 0 ; prefix
pehdr db"00401000h",0 ;<- Not sure if this is right pointer to the PE header "ptrPEHdr DWORD ? ; pointer to the PE header..."
cpt db "RVA Address:403007" , 0
.data?
buffer db 64 dup (?)
mybuffer db 4096 dup(?) ; total converted string
.code
start:
invoke RvaToRaw,addr UserInput,addr pehdr
invoke lstrcat, ADDR UserInput , ADDR mybuffer
invoke MessageBox, NULL, addr mybuffer, addr cpt, MB_OK
invoke ExitProcess, NULL
; RvaToRaw procedure
; ¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤
; ##################################################
; RvaToRaw() - Takes a rva and converts it to a raw offset.
; Returns : EAX=raw.
; it relies on you doing is passing a pointer to the PE header and the RVA you desire converting,
; (how you get the PE header is your business).
; ##################################################
RvaToRaw proc pe_header:DWORD, rva:DWORD
push ebp
push ebx
push ecx
push edx
push esi
push edi
xor eax, eax
mov ecx, rva
cdq
mov edi, pe_header
;mov ax, dword ptr [edi+3ch] ; offset 'PE'
add edi, eax
;mov dx, [edi+6h] ; number of sections
add edi, 0f8h ; start of sections
RvaToRawLoop:
;mov eax, [edi+0ch] ; virtual address
cmp eax, ecx
ja RvaToRawDone
add edi, 28h ; next section
dec edx
jnz RvaToRawLoop ; last section drops out of the loop
RvaToRawDone:
mov eax, rva
;mov ecx, [edi-1ch] ; previous sections virtual address
sub eax, ecx
;mov ecx, [edi-14h] ; previous sections raw offset
add ecx, eax
xchg eax, ecx
RvaToRawEnd:
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop ebp
ret
RvaToRaw endp
end start
Target File : TestMASM.asm
include \masm32\include\masm32rt.inc
.data
caption db "MASM32", 0
text db "It works!", 0
.code
Start:
invoke MessageBox, 0, addr text, addr caption, MB_ICONQUESTION + MB_OKCANCEL
invoke ExitProcess, 0
end Start
open the EXE and read it
verify the MZ marker (recommended, as it validates the next step)
at file offset 3Ch is a dword that is the file relative offset of the PE marker
it only gets harder after that :biggrin:
I wrote such proc a while ago..
but Its not yet executed in my unfinished project. :P
maybe you could give it a try:
RVAToOffset PROC uses edi esi edx ecx pFileMap:DWORD,RVA:DWORD
mov esi,pFileMap
assume esi:ptr IMAGE_DOS_HEADER
add esi,[esi].e_lfanew
assume esi:ptr IMAGE_NT_HEADERS
mov edi,RVA ; edi == RVA
mov edx,esi
; check the PE type first, before calling this proc, store it some where. I called PEFileType which is a global variable..
; also give a definition to PE32, PE64, and PEisNE. they are just the return value from checking PE type.
; OR make them as the last param.
.if PEFileType == PE32
add edx,sizeof IMAGE_NT_HEADERS
.elseif PEFileType == PE64
add edx, sizeof IMAGE_NT_HEADER64 ; make a new one, i's not defined in windows.inc
.elseif PEFileType == PEisNE
Jmp RVAToOffset_zero;
.endif
mov cx,[esi].FileHeader.NumberOfSections
movzx ecx,cx
assume edx:ptr IMAGE_SECTION_HEADER
.while ecx>0 ; check all sections
.if edi>=[edx].VirtualAddress
mov eax,[edx].VirtualAddress
add eax,[edx].SizeOfRawData
.if edi<eax ; The address is in this section
mov eax,[edx].VirtualAddress
sub edi,eax
mov eax,[edx].PointerToRawData
add eax,edi
; eax == file offset
ret
.endif
.endif
add edx,sizeof IMAGE_SECTION_HEADER
dec ecx
.endw
assume edx:nothing
RVAToOffset_zero:
assume esi:nothing
xor eax, eax ; return zero if nothing found
ret
RVAToOffset end
it's a reverse from Iczelion's proc if I'm not mistaken..
DUH, my apologies, it's a modification from Iczelion tutorial..
I wrote the reverse, OffsetToRVA..
Quote from: dedndave on December 04, 2012, 12:47:43 PM
open the EXE and read it
verify the MZ marker (recommended, as it validates the next step)
at file offset 3Ch is a dword that is the file relative offset of the PE marker
it only gets harder after that :biggrin:
That is hilarious ....I found a source that I had laying around of an OEP find tool and I added a message box it poops up with "MZ"
I wonder how to modify this to give me PE header pointer
I have modified my routine a bit,
so here is the invokeable procedure:
IMAGE_OPTIONAL_HEADER64 STRUCT
Magic WORD ?
MajorLinkerVersion BYTE ?
MinorLinkerVersion BYTE ?
SizeOfCode DWORD ?
SizeOfInitializedData DWORD ?
SizeOfUninitializedData DWORD ?
AddressOfEntryPoint DWORD ?
BaseOfCode DWORD ?
ImageBase QWORD ?
SectionAlignment DWORD ?
FileAlignment DWORD ?
MajorOperatingSystemVersion WORD ?
MinorOperatingSystemVersion WORD ?
MajorImageVersion WORD ?
MinorImageVersion WORD ?
MajorSubsystemVersion WORD ?
MinorSubsystemVersion WORD ?
Win32VersionValue DWORD ?
SizeOfImage DWORD ?
SizeOfHeaders DWORD ?
CheckSum DWORD ?
Subsystem WORD ?
DllCharacteristics WORD ?
SizeOfStackReserve QWORD ?
SizeOfStackCommit QWORD ?
SizeOfHeapReserve QWORD ?
SizeOfHeapCommit QWORD ?
LoaderFlags DWORD ?
NumberOfRvaAndSizes DWORD ?
DataDirectory IMAGE_DATA_DIRECTORY IMAGE_NUMBEROF_DIRECTORY_ENTRIES dup(<>)
IMAGE_OPTIONAL_HEADER64 ENDS
IMAGE_NT_HEADER64 STRUCT
Signature DWORD ?
FileHeader IMAGE_FILE_HEADER <>
OptionalHeader IMAGE_OPTIONAL_HEADER64 <>
IMAGE_NT_HEADER64 ENDS
RVAToOffset PROC uses edi esi pPEFileMap:DWORD,RVA:DWORD
mov esi,pPEFileMap
assume esi:ptr IMAGE_DOS_HEADER
.if ( word ptr [esi] == 'ZM') ;DOSHEADER
add esi, [esi].e_lfanew
assume esi:ptr IMAGE_NT_HEADERS
lea eax, (IMAGE_NT_HEADERS ptr [esi]).OptionalHeader
mov ax, [( IMAGE_OPTIONAL_HEADER ptr [eax]).Magic]
movzx eax, ax
Mov edi, RVA
Mov edx, esi
.if ( word ptr [esi] == 'EP') ; PE HEADER
.if ax == 010Bh
; x86
add edx,sizeof IMAGE_NT_HEADERS
.elseif ax == 020Bh
; x64
add edx,sizeof IMAGE_NT_HEADERS64
.endif
.else
; NE header here
jmp return_zero
.endif
mov cx,[esi].FileHeader.NumberOfSections
movzx ecx,cx
assume edx:ptr IMAGE_SECTION_HEADER
.while ecx>0 ; check all sections
.if edi>=[edx].VirtualAddress
mov eax,[edx].VirtualAddress
add eax,[edx].SizeOfRawData
.if edi<eax ; The address is in this section
mov eax,[edx].VirtualAddress
sub edi,eax
mov eax,[edx].PointerToRawData
add eax,edi
; eax == file offset
jmp return_success
.endif
.endif
add edx,sizeof IMAGE_SECTION_HEADER
dec ecx
.endw
assume edx:nothing
.endif
return_zero:
assume esi:nothing
xor eax, eax ; return zero if nothing found
return_success:
ret
RVAToOffset endp
EDIT....
I realized that I am having difficulty getting the PE header pointer
I was planing to make a bare bones trail .....I butchered Iczelion's PE tutorial 2
this is for that Target File : TestMASM.asm
It would be nice to see the OffsetToRVA....
I will take another look at it
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\comdlg32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\comdlg32.lib
; Prototype
RVAToOffset PROTO :DWORD, :DWORD
IMAGE_OPTIONAL_HEADER64 STRUCT
Magic WORD ?
MajorLinkerVersion BYTE ?
MinorLinkerVersion BYTE ?
SizeOfCode DWORD ?
SizeOfInitializedData DWORD ?
SizeOfUninitializedData DWORD ?
AddressOfEntryPoint DWORD ?
BaseOfCode DWORD ?
ImageBase QWORD ?
SectionAlignment DWORD ?
FileAlignment DWORD ?
MajorOperatingSystemVersion WORD ?
MinorOperatingSystemVersion WORD ?
MajorImageVersion WORD ?
MinorImageVersion WORD ?
MajorSubsystemVersion WORD ?
MinorSubsystemVersion WORD ?
Win32VersionValue DWORD ?
SizeOfImage DWORD ?
SizeOfHeaders DWORD ?
CheckSum DWORD ?
Subsystem WORD ?
DllCharacteristics WORD ?
SizeOfStackReserve QWORD ?
SizeOfStackCommit QWORD ?
SizeOfHeapReserve QWORD ?
SizeOfHeapCommit QWORD ?
LoaderFlags DWORD ?
NumberOfRvaAndSizes DWORD ?
DataDirectory IMAGE_DATA_DIRECTORY IMAGE_NUMBEROF_DIRECTORY_ENTRIES dup(<>)
IMAGE_OPTIONAL_HEADER64 ENDS
IMAGE_NT_HEADERS64 STRUCT
Signature DWORD ?
FileHeader IMAGE_FILE_HEADER <>
OptionalHeader IMAGE_OPTIONAL_HEADER64 <>
IMAGE_NT_HEADERS64 ENDS
SEH struct
PrevLink dd ? ; the address of the previous seh structure
CurrentHandler dd ? ; the address of the new exception handler
SafeOffset dd ? ; The offset where it's safe to continue execution
PrevEsp dd ? ; the old value in esp
PrevEbp dd ? ; The old value in ebp
SEH ends
.data
AppName db "PE tutorial no.2",0
ofn OPENFILENAME <>
FilterString db "Executable Files (*.exe, *.dll)",0,"*.exe;*.dll",0
db "All Files",0,"*.*",0,0
FileOpenError db "Cannot open the file for reading",0
FileOpenMappingError db "Cannot open the file for memory mapping",0
FileMappingError db "Cannot map the file into memory",0
FileValidPE db "This file is a valid PE",0
FileInValidPE db "This file is not a valid PE",0
UserInput db "403007h",0 ; RVA Address:403007 Should give RAW Offset address: 807
Format db "RAW Offset: %dh", 0 ; prefix
cpt db "RVA Address:403007" , 0
.data?
buffer db 512 dup(?)
hFile dd ?
hMapping dd ?
pMapping dd ?
ValidPE dd ?
PEFileType dd ?
mybuffer db 4096 dup(?) ; total converted string
ptrPEHdr DWORD ?
DD_addressOfIMAGE_SECTION_HEADER dd ?
.code
start proc
LOCAL seh:SEH
mov ofn.lStructSize,SIZEOF ofn
mov ofn.lpstrFilter, OFFSET FilterString
mov ofn.lpstrFile, OFFSET buffer
mov ofn.nMaxFile,512
mov ofn.Flags, OFN_FILEMUSTEXIST or \
OFN_PATHMUSTEXIST or OFN_LONGNAMES or\
OFN_EXPLORER or OFN_HIDEREADONLY
invoke GetOpenFileName, ADDR ofn
.if eax==TRUE
invoke CreateFile, addr buffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
.if eax!=INVALID_HANDLE_VALUE
mov hFile, eax
invoke CreateFileMapping, hFile, NULL, PAGE_READONLY,0,0,0
.if eax!=NULL
mov hMapping, eax
invoke MapViewOfFile,hMapping,FILE_MAP_READ,0,0,0
.if eax!=NULL
mov pMapping,eax
assume fs:nothing
push fs:[0]
pop seh.PrevLink
mov seh.CurrentHandler,offset SEHHandler
mov seh.SafeOffset,offset FinalExit
lea eax,seh
mov fs:[0], eax
mov seh.PrevEsp,esp
mov seh.PrevEbp,ebp
mov edi, pMapping
assume edi:ptr IMAGE_DOS_HEADER
.if [edi].e_magic==IMAGE_DOS_SIGNATURE
add edi, [edi].e_lfanew
assume edi:ptr IMAGE_NT_HEADERS
.if [edi].Signature==IMAGE_NT_SIGNATURE
mov ValidPE, TRUE
.else
mov ValidPE, FALSE
.endif
.else
mov ValidPE,FALSE
.endif
FinalExit:
.if ValidPE==TRUE
; invoke MessageBox, 0, addr FileValidPE, addr AppName,MB_OK+MB_ICONINFORMATION
invoke RVAToOffset,addr UserInput,addr ptrPEHdr
invoke wsprintf, ADDR buffer, ADDR Format, eax ; buffer = 5dup(0)
invoke lstrcat, ADDR mybuffer, ADDR buffer ; mybuffer db 512 dup(0)
invoke MessageBox, NULL, addr mybuffer, addr cpt, MB_OK
.else
invoke MessageBox, 0, addr FileInValidPE, addr AppName,MB_OK+MB_ICONINFORMATION
.endif
push seh.PrevLink
pop fs:[0]
invoke UnmapViewOfFile, pMapping
.else
invoke MessageBox, 0, addr FileMappingError, addr AppName,MB_OK+MB_ICONERROR
.endif
invoke CloseHandle,hMapping
.else
invoke MessageBox, 0, addr FileOpenMappingError, addr AppName,MB_OK+MB_ICONERROR
.endif
invoke CloseHandle, hFile
.else
invoke MessageBox, 0, addr FileOpenError, addr AppName, MB_OK+MB_ICONERROR
.endif
.endif
invoke ExitProcess, 0
start endp
SEHHandler proc C uses edx pExcept:DWORD,pFrame:DWORD,pContext:DWORD,pDispatch:DWORD
mov edx,pFrame
assume edx:ptr SEH
mov eax,pContext
assume eax:ptr CONTEXT
push [edx].SafeOffset
pop [eax].regEip
push [edx].PrevEsp
pop [eax].regEsp
push [edx].PrevEbp
pop [eax].regEbp
mov ValidPE, FALSE
mov eax,ExceptionContinueExecution
ret
SEHHandler endp
; RvaToRaw procedure
; ¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤*¤
RVAToOffset PROC uses edi esi pPEFileMap:DWORD,RVA:DWORD
mov esi,pPEFileMap
assume esi:ptr IMAGE_DOS_HEADER
.if ( word ptr [esi] == 'ZM') ;DOSHEADER
add esi, [esi].e_lfanew
assume esi:ptr IMAGE_NT_HEADERS
lea eax, (IMAGE_NT_HEADERS ptr [esi]).OptionalHeader
mov ax, [( IMAGE_OPTIONAL_HEADER ptr [eax]).Magic]
movzx eax, ax
Mov edi, RVA
Mov edx, esi
.if ( word ptr [esi] == 'EP') ; PE HEADER
.if ax == 010Bh
; x86
add edx,sizeof IMAGE_NT_HEADERS
.elseif ax == 020Bh
; x64
add edx,sizeof IMAGE_NT_HEADERS64
.endif
.else
; NE header here
jmp return_zero
.endif
mov cx,[esi].FileHeader.NumberOfSections
movzx ecx,cx
assume edx:ptr IMAGE_SECTION_HEADER
.while ecx>0 ; check all sections
.if edi>=[edx].VirtualAddress
mov eax,[edx].VirtualAddress
add eax,[edx].SizeOfRawData
.if edi<eax ; The address is in this section
mov eax,[edx].VirtualAddress
sub edi,eax
mov eax,[edx].PointerToRawData
add eax,edi
; eax == file offset
jmp return_success
.endif
.endif
add edx,sizeof IMAGE_SECTION_HEADER
dec ecx
.endw
assume edx:nothing
.endif
return_zero:
assume esi:nothing
xor eax, eax ; return zero if nothing found
return_success:
ret
RVAToOffset endp
end start
try this:
.586
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\comdlg32.inc
include \masm32\include\user32.inc
include \masm32\macros\macros.asm
include \masm32\include\masm32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\comdlg32.lib
includelib \masm32\lib\masm32.lib
IFNDEF IMAGE_OPTIONAL_HEADER64
IMAGE_OPTIONAL_HEADER64 STRUCT
Magic WORD ?
MajorLinkerVersion BYTE ?
MinorLinkerVersion BYTE ?
SizeOfCode DWORD ?
SizeOfInitializedData DWORD ?
SizeOfUninitializedData DWORD ?
AddressOfEntryPoint DWORD ?
BaseOfCode DWORD ?
ImageBase QWORD ?
SectionAlignment DWORD ?
FileAlignment DWORD ?
MajorOperatingSystemVersion WORD ?
MinorOperatingSystemVersion WORD ?
MajorImageVersion WORD ?
MinorImageVersion WORD ?
MajorSubsystemVersion WORD ?
MinorSubsystemVersion WORD ?
Win32VersionValue DWORD ?
SizeOfImage DWORD ?
SizeOfHeaders DWORD ?
CheckSum DWORD ?
Subsystem WORD ?
DllCharacteristics WORD ?
SizeOfStackReserve QWORD ?
SizeOfStackCommit QWORD ?
SizeOfHeapReserve QWORD ?
SizeOfHeapCommit QWORD ?
LoaderFlags DWORD ?
NumberOfRvaAndSizes DWORD ?
DataDirectory IMAGE_DATA_DIRECTORY IMAGE_NUMBEROF_DIRECTORY_ENTRIES dup(<>)
IMAGE_OPTIONAL_HEADER64 ENDS
IMAGE_NT_HEADERS64 STRUCT
Signature DWORD ?
FileHeader IMAGE_FILE_HEADER <>
OptionalHeader IMAGE_OPTIONAL_HEADER64 <>
IMAGE_NT_HEADERS64 ENDS
ENDIF
; prototypes
WinMain Proto :HINSTANCE, :DWORD, :LPSTR,:DWORD
.code
RVAToOffset PROC uses edi esi pPEFileMap:DWORD,RVA:DWORD
mov esi,pPEFileMap
assume esi:ptr IMAGE_DOS_HEADER
.if ( word ptr [esi] == 'ZM') ;DOSHEADER
add esi, [esi].e_lfanew
assume esi:ptr IMAGE_NT_HEADERS
lea eax, (IMAGE_NT_HEADERS ptr [esi]).OptionalHeader
mov ax, [( IMAGE_OPTIONAL_HEADER ptr [eax]).Magic]
movzx eax, ax
Mov edi, RVA
Mov edx, esi
.if ( word ptr [esi] == 'EP') ; PE HEADER
.if ax == 010Bh
; x86
add edx,sizeof IMAGE_NT_HEADERS
.elseif ax == 020Bh
; x64
add edx,sizeof IMAGE_NT_HEADERS64
.endif
.else
; NE header here
jmp return_zero
.endif
mov cx,[esi].FileHeader.NumberOfSections
movzx ecx,cx
assume edx:ptr IMAGE_SECTION_HEADER
.while ecx>0 ; check all sections
.if edi>=[edx].VirtualAddress
mov eax,[edx].VirtualAddress
add eax,[edx].SizeOfRawData
.if edi<eax ; The address is in this section
mov eax,[edx].VirtualAddress
sub edi,eax
mov eax,[edx].PointerToRawData
add eax,edi
; eax == file offset
jmp return_success
.endif
.endif
add edx,sizeof IMAGE_SECTION_HEADER
dec ecx
.endw
assume edx:nothing
.endif
return_zero:
assume esi:nothing
xor eax, eax ; return zero if nothing found
return_success:
ret
RVAToOffset endp
start:
Invoke GetModuleHandle, NULL
Mov Edx, Eax
Push Edx
Invoke GetCommandLine
Pop Edx
Invoke WinMain, Edx, NULL, Eax, SW_SHOW
invoke ExitProcess, 0
WinMain Proc hInstance: HINSTANCE, hPrevInstance:DWORD, lpCmdLine: LPSTR,nCmdShow:DWORD
local LocalBuffer[512]:byte
.data
hFile dd ?
hMapping dd ?
pMapping dd ?
.code
STRING Format,"VA Address:403007", 0Ah, "RAW Offset: %xh"; x for asm number
STRING Explorer, "\Explorer.exe"
STRING cpt, "RVA to Offset"
Invoke GetWindowsDirectory, Addr LocalBuffer, 512
Invoke lstrcat, Addr LocalBuffer, Addr Explorer
invoke CreateFile, Addr LocalBuffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
.if Eax != INVALID_HANDLE_VALUE
Mov hFile, Eax
Invoke CreateFileMapping, Eax, NULL, PAGE_READONLY,0,0,0
.if Eax != NULL
Mov hMapping, Eax
Invoke MapViewOfFile, Eax, FILE_MAP_READ,0,0,0
Mov pMapping, Eax
lea Ecx, LocalBuffer
Push Ecx
Invoke RtlZeroMemory, Ecx, sizeof LocalBuffer
Invoke RVAToOffset, pMapping, 2007h
Pop Ecx
invoke wsprintf, ADDR LocalBuffer, ADDR Format, eax
Invoke MessageBox, NULL, Addr LocalBuffer, Addr cpt, MB_OK
Invoke UnmapViewOfFile, pMapping
Invoke CloseHandle, hMapping
.endif
Invoke CloseHandle, hFile
.endif
ret
WinMain endp
end start
actually the expected parameters are:
1st Param == the starting address of loaded PE file in the memory
2nd Param == the number of RVA which wished to be converted, in DWORD value.
you might confuse between RVA and VA,
from "Microsoft Portable Executable and Common Object File Format Specification"
Quote
RVA (relative virtual address). In an image file, the address of an item after it is loaded into memory, with the base address of the image file subtracted from it. The RVA of an item almost always differs from its position within the file on disk (file pointer).
In an object file, an RVA is less meaningful because memory locations are not assigned. In this case, an RVA would be an address within a section (described later in this table), to which a relocation is later applied during linking. For simplicity, a compiler should just set the first RVA in each section to zero.
VA (virtual address). Same as RVA, except that the base address of the image file is not subtracted. The address is called a "VA" because Windows creates a distinct VA space for each process, independent of physical memory. For almost all purposes, a VA should be considered just an address. A VA is not as predictable as an RVA because the loader might not load the image at its preferred location.
see the bold words..
which is mean that the RVA is VA - Base Address (preferred address), thus the RVA of 403007h is 403007h - 401000h = 2007h, it can be different or it can be read from the opened PE itself, but I assume the bas address 401000.
Please someone correct me if I'm wrong, it have been a year since the last time I dealt with PE file...
i think 401000 is the default, but may be changed with linker switches or something like that
@Dubby I have no Idea ? your bare bones example only works with Explorer So I can not test it :(
Also I thought your proc included the subtraction in it (that can be added LOL)
http://www.tech-juice.org/2011/02/21/portable-executable-converting-rva-to-file-offset-and-back/
Here is Converting tool from Iczelion done back in 1999 LOL
http://www.woodmann.com/RCE-CD-SITES/Protools/files/debuggers/pc_offset.zip
you can always change it to accept return value from GetOpenFileName API.. just change 2 lines of code.. before CreateFile API, should be easy..
I'm feelin' lazy right now.. :P
better look at the Iczelion tutorial about PE.
also the official PECOFF specification from MS. it's describe everything almost clearly..
anyway thank you for the links.. :t
Quote from: Dubby on December 04, 2012, 08:32:42 PM
which is mean that the RVA is VA - Base Address (preferred address), thus the RVA of 403007h is 403007h - 401000h = 2007h, it can be different or it can be read from the opened PE itself, but I assume the bas address 401000.
Please someone correct me if I'm wrong, it have been a year since the last time I dealt with PE file...
Actually I am getting 400000 as an imagebase
So now do we subtract 400000 or get the actual imagebase of the PE ?????
Here is a better
RVA Converter so you will see better than Iczelion's
So RVA of 403007h -400000h = 3007h gave me the correct offset of 807h in TestMASM.ASM
By the way ...Nice Work Dubby!!! :t
include \masm32\include\masm32rt.inc
.data
caption db "MASM32", 0
text db "It works!", 0
.code
Start:
invoke MessageBox, 0, addr text, addr caption, MB_ICONQUESTION + MB_OKCANCEL
invoke ExitProcess, 0
end Start
RVAToOffset.ASM
.586
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\comdlg32.inc
include \masm32\include\user32.inc
include \masm32\macros\macros.asm
include \masm32\include\masm32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\comdlg32.lib
includelib \masm32\lib\masm32.lib
IFNDEF IMAGE_OPTIONAL_HEADER64
IMAGE_OPTIONAL_HEADER64 STRUCT
Magic WORD ?
MajorLinkerVersion BYTE ?
MinorLinkerVersion BYTE ?
SizeOfCode DWORD ?
SizeOfInitializedData DWORD ?
SizeOfUninitializedData DWORD ?
AddressOfEntryPoint DWORD ?
BaseOfCode DWORD ?
ImageBase QWORD ?
SectionAlignment DWORD ?
FileAlignment DWORD ?
MajorOperatingSystemVersion WORD ?
MinorOperatingSystemVersion WORD ?
MajorImageVersion WORD ?
MinorImageVersion WORD ?
MajorSubsystemVersion WORD ?
MinorSubsystemVersion WORD ?
Win32VersionValue DWORD ?
SizeOfImage DWORD ?
SizeOfHeaders DWORD ?
CheckSum DWORD ?
Subsystem WORD ?
DllCharacteristics WORD ?
SizeOfStackReserve QWORD ?
SizeOfStackCommit QWORD ?
SizeOfHeapReserve QWORD ?
SizeOfHeapCommit QWORD ?
LoaderFlags DWORD ?
NumberOfRvaAndSizes DWORD ?
DataDirectory IMAGE_DATA_DIRECTORY IMAGE_NUMBEROF_DIRECTORY_ENTRIES dup(<>)
IMAGE_OPTIONAL_HEADER64 ENDS
IMAGE_NT_HEADERS64 STRUCT
Signature DWORD ?
FileHeader IMAGE_FILE_HEADER <>
OptionalHeader IMAGE_OPTIONAL_HEADER64 <>
IMAGE_NT_HEADERS64 ENDS
ENDIF
; prototypes
WinMain Proto :HINSTANCE, :DWORD, :LPSTR,:DWORD
.data
ofn OPENFILENAME <>
FilterString db "Executable Files (*.exe, *.dll)",0,"*.exe;*.dll",0
db "All Files",0,"*.*",0,0
Format db "VA Address:403007h", 0Ah, "RAW Offset: %xh",0; x for asm number
cpt db "RVA to Offset",0
.data?
Buffer db 32 dup(?) ; buffer
.code
RVAToOffset PROC uses edi esi pPEFileMap:DWORD,RVA:DWORD
mov esi,pPEFileMap
assume esi:ptr IMAGE_DOS_HEADER
.if ( word ptr [esi] == 'ZM') ;DOSHEADER
add esi, [esi].e_lfanew
assume esi:ptr IMAGE_NT_HEADERS
lea eax, (IMAGE_NT_HEADERS ptr [esi]).OptionalHeader
mov ax, [( IMAGE_OPTIONAL_HEADER ptr [eax]).Magic]
movzx eax, ax
Mov edi, RVA
Mov edx, esi
.if ( word ptr [esi] == 'EP') ; PE HEADER
.if ax == 010Bh
; x86
add edx,sizeof IMAGE_NT_HEADERS
.elseif ax == 020Bh
; x64
add edx,sizeof IMAGE_NT_HEADERS64
.endif
.else
; NE header here
jmp return_zero
.endif
mov cx,[esi].FileHeader.NumberOfSections
movzx ecx,cx
assume edx:ptr IMAGE_SECTION_HEADER
.while ecx>0 ; check all sections
.if edi>=[edx].VirtualAddress
mov eax,[edx].VirtualAddress
add eax,[edx].SizeOfRawData
.if edi<eax ; The address is in this section
mov eax,[edx].VirtualAddress
sub edi,eax
mov eax,[edx].PointerToRawData
add eax,edi
; eax == file offset
jmp return_success
.endif
.endif
add edx,sizeof IMAGE_SECTION_HEADER
dec ecx
.endw
assume edx:nothing
.endif
return_zero:
assume esi:nothing
xor eax, eax ; return zero if nothing found
return_success:
ret
RVAToOffset endp
start:
Invoke GetModuleHandle, NULL
Mov Edx, Eax
Push Edx
Invoke GetCommandLine
Pop Edx
Invoke WinMain, Edx, NULL, Eax, SW_SHOW
invoke ExitProcess, 0
WinMain Proc hInstance: HINSTANCE, hPrevInstance:DWORD, lpCmdLine: LPSTR,nCmdShow:DWORD
local LocalBuffer[512]:byte
.data
hFile dd ?
hMapping dd ?
pMapping dd ?
.code
mov ofn.lStructSize,SIZEOF ofn
mov ofn.lpstrFilter, OFFSET FilterString
mov ofn.lpstrFile, OFFSET Buffer
mov ofn.nMaxFile,512
mov ofn.Flags, OFN_FILEMUSTEXIST or \
OFN_PATHMUSTEXIST or OFN_LONGNAMES or\
OFN_EXPLORER or OFN_HIDEREADONLY
invoke GetOpenFileName, ADDR ofn
.if eax==TRUE
invoke CreateFile, Addr Buffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
.if Eax != INVALID_HANDLE_VALUE
Mov hFile, Eax
Invoke CreateFileMapping, Eax, NULL, PAGE_READONLY,0,0,0
.if Eax != NULL
Mov hMapping, Eax
Invoke MapViewOfFile, Eax, FILE_MAP_READ,0,0,0
Mov pMapping, Eax
lea Ecx, Buffer
Push Ecx
Invoke RtlZeroMemory, Ecx, sizeof Buffer
Invoke RVAToOffset, pMapping, 3007h
Pop Ecx
invoke wsprintf, ADDR Buffer, ADDR Format, eax
Invoke MessageBox, NULL, Addr Buffer, Addr cpt, MB_OK
Invoke UnmapViewOfFile, pMapping
Invoke CloseHandle, hMapping
.endif
Invoke CloseHandle, hFile
.endif
.endif
ret
WinMain endp
end start
I found this for Get Imagebase ,It works but we need to use kernel32.inc and kernel32.lib from MASMv8 SDK
http://www.masmforum.com/board/index.php?PHPSESSID=786dd40408172108b65a5a36b09c88c0&topic=12663;prev_next=next
It is 548 AM I want to scream
http://www.masmforum.com/board/index.php?PHPSESSID=786dd40408172108b65a5a36b09c88c0&topic=18294.0
http://masm32.com/board/index.php?topic=716.0
To be safe subtract it with the PE's Image Base. its not always 400000.
we can get the image base of offline PE file from "IMAGE_OPTIONAL_HEADER.ImageBase" member.
but certain condition does apply.
Oh anyway for the reverse function (use the same routine)
replace:
VirtualAddress ==> PointerToRawData
PointerToRawData ==>VirtualAddress
simple isn't it.. :icon_redface:
Looking at Iczelion's PE tut 5. http://win32assembly.programminghorizon.com/pe-tut5.html
He says "Read the value in VirtualAddress and add the value in ImageBase to it to get the virtual address the section should start from. "
Where does he do that?
I should really stop going to bed at 6AM .... Sorry if I am missing where that is
well of course dude... it's totally true..
he means to get the VA of starting certain section in the memory, when the PE get loaded/executed ,don't mix it up with VirtualAddress of Section header member.
now better go get some sleep,,
I should definitely clear my head before looking at this ..... :biggrin:
Than we can just subtract user input from that to calculate the raw offset ....
Something like:
.data
userVAAddress db "403007", 0 OR userVAAddress db 403007h
.data?
hVAAddress dd ?
Invoke RVAToOffset, pMapping, hVAAddress
OK It is 230 AM here and I am a little stuck ..... :(
Just trying to make a Bare Bones GetImagebase.ASM
.586
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\comdlg32.inc
include \masm32\include\user32.inc
include \masm32\macros\macros.asm
include \masm32\include\masm32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\comdlg32.lib
includelib \masm32\lib\masm32.lib
; prototypes
WinMain Proto :HINSTANCE, :DWORD, :LPSTR,:DWORD
_ImageBase Proto :DWORD
.data
ImageBase dd 0
ofn OPENFILENAME <>
FilterString db "Executable Files (*.exe, *.dll)",0,"*.exe;*.dll",0
db "All Files",0,"*.*",0,0
Format db "%d",0; d for asm number
cpt2 db "ImageBase:",0
.data?
Buffer db 32 dup(?) ; buffer
.code
start:
Invoke GetModuleHandle, NULL
Mov Edx, Eax
Push Edx
Invoke GetCommandLine
Pop Edx
Invoke WinMain, Edx, NULL, Eax, SW_SHOW
invoke ExitProcess, 0
WinMain Proc hInstance: HINSTANCE, hPrevInstance:DWORD, lpCmdLine: LPSTR,nCmdShow:DWORD
local LocalBuffer[512]:byte
.data
hFile dd ?
hMapping dd ?
pMapping dd ?
.code
mov ofn.lStructSize,SIZEOF ofn
mov ofn.lpstrFilter, OFFSET FilterString
mov ofn.lpstrFile, OFFSET Buffer
mov ofn.nMaxFile,512
mov ofn.Flags, OFN_FILEMUSTEXIST or \
OFN_PATHMUSTEXIST or OFN_LONGNAMES or\
OFN_EXPLORER or OFN_HIDEREADONLY
invoke GetOpenFileName, ADDR ofn
.if eax==TRUE
invoke CreateFile, Addr Buffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
.if Eax != INVALID_HANDLE_VALUE
Mov hFile, Eax
Invoke CreateFileMapping, Eax, NULL, PAGE_READONLY,0,0,0
.if Eax != NULL
Mov hMapping, Eax
Invoke MapViewOfFile, Eax, FILE_MAP_READ,0,0,0
Mov pMapping, Eax
lea Ecx, Buffer
Push Ecx
Invoke RtlZeroMemory, Ecx, sizeof Buffer
Invoke _ImageBase, pMapping
Pop Ecx
invoke wsprintf, ADDR Buffer, ADDR Format, eax
Invoke MessageBox, NULL, Addr Buffer, Addr cpt2, MB_OK
Invoke UnmapViewOfFile, pMapping
Invoke CloseHandle, hMapping
.endif
Invoke CloseHandle, hFile
.endif
.endif
ret
WinMain endp
_ImageBase proc MappedFile:DWORD
LOCAL FileAlignment: DWORD
mov eax, MappedFile
assume eax: PTR IMAGE_DOS_HEADER
add eax, dword ptr[eax].e_lfanew
assume eax: PTR IMAGE_NT_HEADERS32
push dword ptr[eax].OptionalHeader.FileAlignment
pop dword ptr[FileAlignment]
push dword ptr[eax].OptionalHeader.ImageBase
pop dword ptr[ImageBase]
ret
_ImageBase endp
end start
I found so many things online ...apparently we can use :
proc dwProc, dwImage:DWORD
LOCAL dwMem:DWORD
MOV EAX, dwMem
MOV ECX, PHeaders
MOV ECX, IMAGE_NT_HEADERS.OptionalHeader.ImageBase[ECX]
SUB EAX, ECX
MOV dwDelta, EAX
;ECX CANT Be Modified here, has to stay same (ImageBase)
MOV EAX, dwImage
SUB EAX, ECX
MOV dwOldDelta, EAX
I am a little lost ...... :(
Also I found an OffsetToRVA Proc :biggrin:
OffsetToRVA PROTO SectionHeader: DWORD, lOffset: DWORD, NumberOfSections: WORD
.data
NumberOfSections dw 0
and SectionHeader would be defines as "LOCAL SectionHeader: DWORD" in another proc
invoke OffsetToRVA, dword ptr[SectionHeader], eax, word ptr[NumberOfSections]
mov edx, ebx
push edx
OffsetToRVA PROC SectionHeader: DWORD, lOffset: DWORD, lNumberOfSections: WORD
LOCAL Result: DWORD
pushad
mov eax, SectionHeader
mov ebx, lOffset
mov cx, lNumberOfSections
assume eax: PTR IMAGE_SECTION_HEADER
Begin:
mov edi, dword ptr[eax].PointerToRawData
add edi, dword ptr[eax].SizeOfRawData
cmp ebx, edi
jge @F
cmp ebx, dword ptr[eax].PointerToRawData
jb @F
sub ebx, dword ptr[eax].PointerToRawData
add ebx, dword ptr[eax].VirtualAddress
mov dword ptr[Result], ebx
jmp Finish
@@:
add eax, 28h
dec cx
or cx, cx
jnz Begin
mov dword ptr[Result], 0
Finish:
popad
mov ebx, dword ptr[Result]
Ret
OffsetToRVA EndP
wsprintf, ADDR Buffer, ADDR Format, eax
the last one is EAX, which is the return value from _ImageBase function, but what happen inside it..?
mov eax, MappedFile
assume eax: PTR IMAGE_DOS_HEADER
add eax, dword ptr[eax].e_lfanew
this was the last value assigned into eax right..?
so return the imagebase into eax. something like
mov Eax, dword ptr[eax].OptionalHeader.ImageBase
also the %d of wsprintf format will print the value in decimal (base ten), %x will print the hexadecimal value.
I have add the return value inside _ImageBase proc and change the %d into %x and the expected value get popped in the messagebox
---------------------------
ImageBase:
---------------------------
400000
---------------------------
OK
---------------------------
Thank You .... :biggrin:
Works Now ! :greenclp:
By the way take a look Here: http://www.masmforum.com/board/index.php?PHPSESSID=786dd40408172108b65a5a36b09c88c0&topic=18148.0
What is ImageRvaToVa from imagehlp.lib used for ? can we use it ?
invoke ImageRvaToVa,[pIMAGE_NT_HEADERS],[pMapFile],[edi+IMAGE_IMPORT_DESCRIPTOR.Name],NULL
GetImagebase.ASM
.586
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\comdlg32.inc
include \masm32\include\user32.inc
include \masm32\macros\macros.asm
include \masm32\include\masm32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\comdlg32.lib
includelib \masm32\lib\masm32.lib
; prototypes
WinMain Proto :HINSTANCE, :DWORD, :LPSTR,:DWORD
_ImageBase Proto :DWORD
.data
ImageBase dd 0
ofn OPENFILENAME <>
FilterString db "Executable Files (*.exe, *.dll)",0,"*.exe;*.dll",0
db "All Files",0,"*.*",0,0
Format db "%x",0; x for asm number ; %d of wsprintf format will print the value in decimal (base ten), %x will print the hexadecimal value.
cpt2 db "ImageBase:",0
.data?
Buffer db 32 dup(?) ; buffer
.code
start:
Invoke GetModuleHandle, NULL
Mov Edx, Eax
Push Edx
Invoke GetCommandLine
Pop Edx
Invoke WinMain, Edx, NULL, Eax, SW_SHOW
invoke ExitProcess, 0
WinMain Proc hInstance: HINSTANCE, hPrevInstance:DWORD, lpCmdLine: LPSTR,nCmdShow:DWORD
local LocalBuffer[512]:byte
.data
hFile dd ?
hMapping dd ?
pMapping dd ?
.code
mov ofn.lStructSize,SIZEOF ofn
mov ofn.lpstrFilter, OFFSET FilterString
mov ofn.lpstrFile, OFFSET Buffer
mov ofn.nMaxFile,512
mov ofn.Flags, OFN_FILEMUSTEXIST or \
OFN_PATHMUSTEXIST or OFN_LONGNAMES or\
OFN_EXPLORER or OFN_HIDEREADONLY
invoke GetOpenFileName, ADDR ofn
.if eax==TRUE
invoke CreateFile, Addr Buffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
.if Eax != INVALID_HANDLE_VALUE
Mov hFile, Eax
Invoke CreateFileMapping, Eax, NULL, PAGE_READONLY,0,0,0
.if Eax != NULL
Mov hMapping, Eax
Invoke MapViewOfFile, Eax, FILE_MAP_READ,0,0,0
Mov pMapping, Eax
lea Ecx, Buffer
Push Ecx
Invoke RtlZeroMemory, Ecx, sizeof Buffer
Invoke _ImageBase, pMapping
Pop Ecx
invoke wsprintf, ADDR Buffer, ADDR Format, eax
Invoke MessageBox, NULL, Addr Buffer, Addr cpt2, MB_OK
Invoke UnmapViewOfFile, pMapping
Invoke CloseHandle, hMapping
.endif
Invoke CloseHandle, hFile
.endif
.endif
ret
WinMain endp
_ImageBase proc MappedFile:DWORD
LOCAL FileAlignment: DWORD
mov eax, MappedFile
assume eax: PTR IMAGE_DOS_HEADER
add eax, dword ptr[eax].e_lfanew
assume eax: PTR IMAGE_NT_HEADERS32
push dword ptr[eax].OptionalHeader.FileAlignment
pop dword ptr[FileAlignment]
push dword ptr[eax].OptionalHeader.ImageBase
mov Eax, dword ptr[eax].OptionalHeader.ImageBase
pop dword ptr[ImageBase]
ret
_ImageBase endp
end start
hello again,
yes we can utilize that function, but the result should be the same with RVA-To-Filemap.. just add the pMapFile to return value of RVAToOffset..
a link to MSDN should be clear..
http://msdn.microsoft.com/en-us/library/windows/desktop/ms680218(v=vs.85).aspx