News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

load file as PE-loader

Started by Dimarik__, February 26, 2012, 12:46:12 PM

Previous topic - Next topic

Dimarik__

I want to work with PE-files. But I found that I can't use all addresses (RVA) without change them. For example, I want to know, where starts and ends Section table. But I can't add PointerToRawData from IMAGE_SECTION_HEADER to base address of loaded PE-file. I should to change this adress to work with him. But I found in the Internet, that if I load PE file like PE-loader, I can work with all addresses withoun changes.
Please, tell me algoritm, how to load file as PE-loader.
I started to do this, but I can't finish this.
.586p
.model flat,stdcall
option casemap:none

include \masm32\include\windows.inc
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib

include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib


.data
struct_IMAGE_DOS_HEADER IMAGE_DOS_HEADER <?>;for load this file like PE-loader
struct_IMAGE_NT_HEADERS IMAGE_NT_HEADERS <?>;for load this file like PE-loader
struct_IMAGE_FILE_HEADER IMAGE_FILE_HEADER <?>;for load this file like PE-loader
struct_OPTIONAL_HEADER OPTIONAL_HEADER <?>;;for load this file like PE-loader
struct_IMAGE_DATA_DIRECTORY IMAGE_DATA_DITECTORY 16 dup <?>;;for load this file like PE-loader
struct_IMAGE_SECTION_HEADER IMAGE_SECTION_HEADER 100 dup <?>;for load this file like PE-loader
DD_baseAddress_ReturnedVirtualAlloc DD ?;base address
DD_numberOfBytesToRead DD ?;for function  ReadFile
DD_hFile DD ?
DW_numberOfSections DW ?
DD_addressOfIMAGE_DOS_HEADER DD ?
DD_addressOfIMAGE_FILE_HEADER DD ?
DD_addressOfIMAGE_OPTIONAL_HEADER DD ?
DD_addressOfIMAGE_NT_HEADERS DD ?
DD_addressOfDataDirectory DD ?
DD_addressOfIMAGE_SECTION_HEADER DD ?
.code
_start:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;load file like PE-loader
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Step 1. Open file
push 0
push FILE_ATTRIBUTE_NORMAL;The file does not have other attributes set. This attribute is valid only if used alone.
push OPEN_EXISTING
push 0
push FILE_SHARE_DELETE
push GENERIC_WRITE or GENERIC_READ
push offset DB_strAddress
call CreateFileA
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

cmp EAX, -1;
jz EXIT

mov DD_hFile, EAX

mov EBX, EAX
assume EBX:IMAGE_DOS_HEADER
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
invoke ReadFile, EBX, struct_IMAGE_DOS_HEADER, sizeof struct_IMAGE_DOS_HEADER, DD_numberOfBytesToRead, 0
invoke SetFilePointer,EBX,struct_IMAGE_DOS_HEADER.e_lfanew,0,FILE_BEGIN; set pointer to DOS-header
invoke ReadFile, EBX, struct_IMAGE_NT_HEADERS, sizeof struct_IMAGE_NT_HEADERS, DD_numberOfBytesToRead, 0
invoke SetFilePointer,EBX,struct_IMAGE_NT_HEADERS.FileHeader,0,FILE_CURRENT;set pointer to PE-header
invoke ReadFile, EBX, struct_IMAGE_FILE_HEADER, sizeof struct_IMAGE_FILE_HEADER, DD_numberOfBytesToRead, 0
mov CX, struct_IMAGE_FILE_HEADER.NumberOfSections
mov DW_numberOfSections, CX;number of sections in the file
invoke SetFilePointer, EBX, struct_IMAGE_NT_HEADERS.OptionalHeader,
0, FILE_CURRENT;set pointer to Optional header
invoke ReadFile, EBX, struct_IMAGE_OPTIONAL_HEADER, sizeof struct_IMAGE_OPTIONAL_HEADER,
DD_numberOfBytesToRead, 0
invoke SetFilePointer, EBX, struct_IMAGE_OPTIONAL_HEADER.DataDirectory,
0, FILE_CURRENT;set pointer to IMAGE_DATA_DIRECTORY
mov CX, sizeof IMAGE_DATA_DIRECTORY
mul CX, 16;size of filled array
mov DD_addressOfIMAGE_SECTION_HEADER, EAX
add DD_addressOfIMAGE_SECTION_HEADER, CX;address of IMAGE_SECTION_HEADER
invoke ReadFile, EBX, struct_IMAGE_DATA_DIRECTORY, CX, DD_numberOfBytesToRead, 0;fill IMAGE_DATA_DIRECTORY


invoke VirtualAlloc,0,struct_IMAGE_OPTIONAL_HEADER.SizeOfImage,MEM_COMMIT,PAGE_READWRITE
mov DD_baseAddress_ReturnedVirtualAlloc, EAX
movzx ESI, DW_numberOfSections
movzx EDX, DW_numberOfSections
mul ESI, EDX;size of array IMAGE_SECTION_HEADER
invoke SetFilePointer, EBX, DD_addressOfIMAGE_SECTION_HEADER,
0, FILE_CURRENT;set pointer to IMAGE_SECTION_HEADER
invoke ReadFile, EBX, struct_IMAGE_DATA_DIRECTORY, CX, DD_numberOfBytesToRead, 0;fill IMAGE_SECTION_HEADER

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
EXIT:
invoke ExitProcess,0
end _start

P.S. If you can, speak simply, and sorry for my bad English, I'm from Russia.
Sorry for my bad English. Please, speak simply. I'm from Russia.


dedndave

i didn't look it up, but it seems to me that you should be using DWORD-size, instead of WORD-size operations
Я не смотрел его, но мне кажется, что вы должны использовать DWORD размера, а размер WORD-операций
        mov     CX,sizeof IMAGE_DATA_DIRECTORY
        mul     CX,16 ;size of filled array
        mov     DD_addressOfIMAGE_SECTION_HEADER,EAX
        add     DD_addressOfIMAGE_SECTION_HEADER,CX ;address of IMAGE_SECTION_HEADER


i don't think this is a valid instruction form
Я не думаю, что это действительно форма инструкции
        mul     CX,16

you can use this to multiply a register by 16, provided the value is reasonably small
Вы можете использовать это, чтобы умножить регистр на 16 при условии, что значение сравнительно небольшие
        shl     ecx,4

you can also let the assembler do some of the work because it is a constant that is known at assembly-time
Вы также можете позволить ассемблер сделать часть работы, потому что это константа, которая, как известно на собрании времени
        mov     DD_addressOfIMAGE_SECTION_HEADER,16*sizeof IMAGE_DATA_DIRECTORY

i don't need to look this one up - i know all the parameters must be DWORD-size - try ECX
Я не нужно искать эту вверх - я знаю, что все параметры должны быть DWORD размера - попробуйте ECX
        invoke  ReadFile, EBX, struct_IMAGE_DATA_DIRECTORY, CX, DD_numberOfBytesToRead, 0

Dimarik__

Thank you, I'll read this documentation.
Sorry for my bad English. Please, speak simply. I'm from Russia.

Dimarik__

At this moment I'm reading documentation about Section Table (sections headers).
There is written about field "VirtuallAddress": "For executable images, the address of the first byte of the section relative to the image base when the section is loaded into memory." And about PointerToRawData: "The file pointer to the first page of the section within the COFF file. For executable images, this must be a multiple of FileAlignment from the optional header.".
If you can, answer f few questions:
1. Is COFF files a file which is created bu compiler and used by linker? If I'm wrong, please, explain what is this file.
2. PointerToRawData is used only in COFF files and doesn't used in PE-files? If PointerToRawData is used in PE-files, what is the difference between field PointerToRawData and field VirtuallAddress?
Sorry for my bad English. Please, speak simply. I'm from Russia.

dedndave

1. yes - the COFF format is used for OBJ files, which are input to the linker
2. correct - PointerToRawData is a COFF file member however, the term "raw data" may apply to any section type
the VirtualAddress is essentially the RVA (relative virtual address), which generally applies to PE files after they are loaded into memory
this is the offset of the object in memory from the base address of the module
typically, the base address for the module when loaded is 00400000h

Dimarik__

Sorry for my bad English. Please, speak simply. I'm from Russia.

vanjast

Dave.. how did you translate to Russian.. and can you do it from Russian to English (a translater site) ?
:8)

dedndave

didn't you know i speak Russian fluently ?   :bg

http://translate.google.com/

i have that as one of my bookmarks and use it all the time
you can place text or a URL in the left pane and it will usually translate

clive

You should probably not assume the size of the header, and instead read the SizeOfOptionalHeader, and use that to get to the section table

And yes, you'll need to traverse the section table to convert virtual addresses to offsets in the file image. There is not always a direct relationship, and some sections do not have file data behind them.

You have to convert the Offset into a Section's VirtualAddress, and convert that to a file offset using PointerToRawData.

When the Windows Loader loads an image into memory it likely changes the header/section structures to reflect that.

It could be a random act of randomness. Those happen a lot as well.

Dimarik__

I've read about Certificate Data.
Quote4.7.1. Certificate Data
As stated in the preceding section, the certificates in the attribute certificate table can contain any certificate type. Certificates that ensure a PE file's integrity may include a PE image hash.
A PE image hash (or file hash) is similar to a file checksum in that the hash algorithm produces a message digest that is related to the integrity of a file. However, a checksum is produced by a simple algorithm and is used primarily to detect whether a block of memory on disk has gone bad and the values stored there have become corrupted. A file hash is similar to a checksum in that it also detects file corruption. However, unlike most checksum algorithms, it is very difficult to modify a file without changing the file hash from its original unmodified value. A file hash can thus be used to detect intentional and even subtle modifications to a file, such as those introduced by viruses, hackers, or Trojan horse programs.
When included in a certificate, the image digest must exclude certain fields in the PE Image, such as the Checksum and Certificate Table entry in Optional Header Data Directories. This is because the act of adding a Certificate changes these fields and would cause a different hash value to be calculated.
The Win32 ImageGetDigestStream function provides a data stream from a target PE file with which to hash functions. This data stream remains consistent when certificates are added to or removed from a PE file. Based on the parameters that are passed to ImageGetDigestStream, other data from the PE image can be omitted from the hash computation. For a link to the function's reference page, see "References."
Can you tell me, where is this certificate located? As I understood it is located in some header like Optional header. But in which header and how I should address to this field?
Sorry for my bad English. Please, speak simply. I'm from Russia.

clive

Quote from: Dimarik__ on March 03, 2012, 01:36:23 PM
Can you tell me, where is this certificate located? As I understood it is located in some header like Optional header. But in which header and how I should address to this field?

Wouldn' it be in the Security directory entry?
It could be a random act of randomness. Those happen a lot as well.

donkey

Don't have any experience with certificates but the certificate table address is located at offset 128 (x32) or 144 (x64) in the IMAGE_DATA_DIRECTORY entries of the IMAGE_OPTIONAL_HEADER. Note that the certificate table address is a file offset, not an RVA so it has to be handled as a special case, though it always just appended to the end of the file.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

Dimarik__

Quote from: donkey on March 03, 2012, 03:56:33 PM
Don't have any experience with certificates but the certificate table address is located at offset 128 (x32) or 144 (x64) in the IMAGE_DATA_DIRECTORY entries of the IMAGE_OPTIONAL_HEADER. Note that the certificate table address is a file offset, not an RVA so it has to be handled as a special case, though it always just appended to the end of the file.
Please, clarify difference between RVA and file offset. I understood that file offset used with files on hard disk. RVA used when whis file was loaded into the memory by PE-loader. And if you want to work with RVA, you should convert them to file offset. Am I right?
Sorry for my bad English. Please, speak simply. I'm from Russia.

donkey

RVA or Relative Virtual Address is a memory offset from an unknown base. Generally it is added to the load address of the PE resulting in the actual virtual memory address of a particular peice of data. For example the first entry in the DATA section might have an RVA of 0x1000, if the PE is loaded at 0x400000, the actual VA (Virtual Address) is 0x401000. It is a method of allowing each section to be relocated in memory without have too much to fix up by the PE loader. The file offset is simply the number of bytes from the beginning of the file.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable