Author Topic: [SOLVED] Dealing with virtual and raw addresses (avoid the use of the linker)  (Read 24960 times)

Offline s_dubrovich

  • Jr. Member
  • *
  • Posts: 8
Re: Dealing with virtual and raw addresses (avoid the use of the linker)
« Reply #15 on: July 20, 2013, 02:41:30 AM »

Yeah, this is exactly what I would like !
Thank you very much for brain tormenting yourself about my problem ! 8)

Yet it would have been cool if we could upgrade this code again.
Is it possible to do something like "vstart=nagoa_round($)" instead of "vstart=0x402000", in order to have a value automatically computed ?


Yes.   vstart=  needs a 'hard' number, as we had done.  This is also furnished through an EQU expression.
Changes follow..

(hmm, this is my second try to post this)

Code: [Select]
[MAP ALL exetest5.map] ;; use this to generate a MAP file of useful information.

; exetest.asm

SECTIONS equ 2
TIME_DATE equ 0

IMAGE_BASE      equ 0x400000
SECTION_ALIGNMENT equ   0x1000
FILE_ALIGNMENT  equ    0x200

BSS_SIZE equ 0

%define nagoa_round(size) ((size + SECTION_ALIGNMENT - 1) & ~(SECTION_ALIGNMENT - 1))

bits 32
org IMAGE_BASE

section .text

; ******************************************************************************************************

;;SECTION .text vstart=400000h

  ;; if the header is part of the image, define it as section .text because .text is put
;; first in the image, and rename the code section as section .code
header:

dw "MZ"                  ; e_magic
dw 0                    ; e_cblp
dw 0                    ; e_cp
dw 0                    ; e_crlc
dw 0                    ; e_cparhdr
dw 0                    ; e_minalloc
dw 0                    ; e_maxalloc
dw 0                    ; e_ss
dw 0                    ; e_sp
dw 0                    ; e_csum
dw 0                    ; e_ip
dw 0                    ; e_cs
dw 0                    ; e_lsarlc
dw 0                    ; e_ovno
dq 0                    ; e_res
dw 0                    ; e_oemid
dw 0                    ; e_oeminfo
dd 0,0,0,0,0                  ; e_res2
dd imageHeader - IMAGE_BASE ; e_lfanew

imageHeader:

dd "PE"              ; Signature
dw 0x014C            ; Machine
dw SECTIONS          ; NumberOfSections
dd TIME_DATE        ; TimeDateStamp
dd 0                ; PointerToSymbolTable
dd 0                ; NumberOfSymbols
dw optionalHeader.SIZE ; SizeOfOptionalHeader
dw 0x0303            ; Characteristics

optionalHeader:

    dw 0x10B                    ; Magic
    db 0                        ; MajorLinkerVersion
    db 0                        ; MinorLinkerVersion
    dd nagoa_round(RAW_CODE.SIZE) ; SizeOfCode
    dd nagoa_round(RAW_DATA.SIZE) ; SizeOfInitializedData
    dd nagoa_round(BSS_SIZE)    ; SizeOfUninitializedData
    dd entryPoint - IMAGE_BASE  ; AddressOfEntryPoint
    dd code - IMAGE_BASE        ; BaseOfCode
    dd data - IMAGE_BASE        ; BaseOfData
    dd IMAGE_BASE                ; ImageBase
    dd SECTION_ALIGNMENT        ; SectionAlignment
    dd FILE_ALIGNMENT            ; FileAlignment
    dw 4                        ; MajorOperatingSystemVersion
    dw 0                        ; MinorOperatingSystemVersion
    dw 0                        ; MajorImageVersion
    dw 0                        ; MinorImageVersion
    dw 4                        ; MajorSubsystemVersion
    dw 0                        ; MinorSubsystemVersion
    dd 0                        ; Win32VersionValue
;;    dd IMAGE_END - IMAGE_BASE    ; SizeOfImage
    dd (RAW_HEADER.SIZE + RAW_CODE.SIZE + RAW_DATA.SIZE)

    dd RAW_HEADER.SIZE          ; SizeOfHeaders
    dd 0                        ; CheckSum
    dw 2                        ; Subsystem
    dw 0                        ; DllCharacteristics
    dd 0x40000                  ; SizeOfStackReserve
    dd 0x6000                    ; SizeOfStackCommit
    dd 0x100000                  ; SizeOfHeapReserve
    dd 0x1000                    ; SizeOfHeapCommit
    dd 0                        ; LoaderFlags
    dd 16                        ; NumberOfRvaAndSizes
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_EXPORT
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_IMPORT
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_RESOURCE
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_EXCEPTION
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_SECURITY
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_BASERELOC
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_DEBUG
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_COPYRIGHT
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_GLOBALPTR
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_TLS
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_IAT
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
dd 0, 0                      ; reserved

optionalHeader.SIZE equ $ - optionalHeader

sectionHeaders:

    db ".text", 0, 0, 0          ; Name
    dd nagoa_round(RAW_CODE.SIZE) ; VirtualSize
    dd code                      ; VirtualAddress
    dd RAW_CODE.SIZE            ; SizeOfRawData
    dd RAW_CODE.OFFSET          ; PointerToRawData
    dd 0                        ; PointerToRelocations
    dd 0                        ; PointerToLinenumbers
    dw 0                        ; NumberOfRelocations
    dw 0                        ; NumberOfLinenumbers
    dd 0x60000020                ; Characteristics

    db ".data", 0, 0, 0          ; Name
    dd nagoa_round(RAW_DATA.SIZE) ; VirtualSize
    dd data                      ; VirtualAddress
    dd RAW_DATA.SIZE            ; SizeOfRawData
    dd RAW_DATA.OFFSET          ; PointerToRawData
    dd 0                        ; PointerToRelocations
    dd 0                        ; PointerToLinenumbers
    dw 0                        ; NumberOfRelocations
    dw 0                        ; NumberOfLinenumbers
    dd 0xC0000040                ; Characteristics

align FILE_ALIGNMENT, db 0
;;align SECTION_ALIGNMENT, db 0

RAW_HEADER.SIZE equ $ - header

; ******************************************************************************************************

;;section .text vstart=nagoa_round($)
;;section .code vstart=401000h

VS_CODE EQU (IMAGE_BASE + ((1+(RAW_HEADER.SIZE >> 12)) * SECTION_ALIGNMENT))

section .code vstart=VS_CODE

code:
entryPoint:

xor eax, eax
ret

TIMES 1000h db 90h ;; nop

align FILE_ALIGNMENT, db 0
;;align SECTION_ALIGNMENT, db 0

RAW_CODE.OFFSET equ RAW_HEADER.SIZE
RAW_CODE.SIZE equ $ - code ;; $-$$ also gives the size of section .code

; ******************************************************************************************************

;;section .data vstart=nagoa_round($)
;;section .data vstart=402000h

VS_DATA EQU (VS_CODE + ((1+(RAW_CODE.SIZE >> 12)) * SECTION_ALIGNMENT))

section .data vstart=VS_DATA

data:
db "An unused string"

align FILE_ALIGNMENT, db 0
;;align SECTION_ALIGNMENT, db 0

RAW_DATA.OFFSET equ RAW_CODE.OFFSET + RAW_CODE.SIZE
RAW_DATA.SIZE equ $ - data ;; $-$$ also gives the size of section .data

; ******************************************************************************************************

;;IMAGE_END equ nagoa_round($)

IMAGE_END equ $

;; -- eof --


The MAP file shows..

-- Sections (summary) ---------------------------------------------------------

Vstart            Start             Stop              Length    Class     Name
          400000            400000            400200  00000200  progbits  .text
          401000            400200            401400  00001200  progbits  .code
          403000            401400            401600  00000200  progbits  .data

-- Sections (detailed) --------------------------------------------------------

---- Section .text ------------------------------------------------------------

class:     progbits
length:                 200
start:               400000
align:     not defined
follows:   not defined
vstart:              400000
valign:    not defined
vfollows:  not defined

---- Section .code ------------------------------------------------------------

class:     progbits
length:                1200
start:               400200
align:                    4
follows:   not defined
vstart:              401000
valign:    not defined
vfollows:  not defined

---- Section .data ------------------------------------------------------------

class:     progbits
length:                 200
start:               401400
align:                    4
follows:   not defined
vstart:              403000
valign:    not defined
vfollows:  not defined

-- Symbols --------------------------------------------------------------------

hth,  please verify that this works as you intend,

Steve

Offline ;

  • Jr. Member
  • *
  • Posts: 9
Re: Dealing with virtual and raw addresses (avoid the use of the linker)
« Reply #16 on: July 20, 2013, 10:23:34 AM »
There is just a single word to say : Wonderful ! ;)

Now, the problem is fully solved.
Thanks.

(Though we may continue to discuss about binary compilation tricks, especially if somebody find a magical function that returns the raw file offset from where it is called, somehow like "$" does for virtual address)

Offline s_dubrovich

  • Jr. Member
  • *
  • Posts: 8
Well, there is a flaw to fix.  (RAW_HEADER.SIZE-1) and (RAW_CODE.SIZE-1),  otherwise SECTION_ALIGNMENT can be larger than needed by 1 if the code.size is exactly equal to SECTION_ALIGNMENT. (which is likely if the code is near that size, due to alignment padding.)

Also, as to format, I'm showing next how to split the section information so that, for larger projects, sub modules can be %included easily...

Code: [Select]
[MAP ALL exetest6.map] ;; use this to generate a MAP file of useful information.

; exetest.asm

SECTIONS equ 2
TIME_DATE equ 0

IMAGE_BASE      equ 0x400000
SECTION_ALIGNMENT equ   0x1000
FILE_ALIGNMENT  equ    0x200

BSS_SIZE equ 0

%define nagoa_round(size) ((size + SECTION_ALIGNMENT - 1) & ~(SECTION_ALIGNMENT - 1))

bits 32

org IMAGE_BASE

section .text

;;******************************************************************************************************
;; if the header is part of the image, define it as section .text because .text is put
;; first in the image, and rename the code section as section .code

header:

dw "MZ"                  ; e_magic
dw 0                    ; e_cblp
dw 0                    ; e_cp
dw 0                    ; e_crlc
dw 0                    ; e_cparhdr
dw 0                    ; e_minalloc
dw 0                    ; e_maxalloc
dw 0                    ; e_ss
dw 0                    ; e_sp
dw 0                    ; e_csum
dw 0                    ; e_ip
dw 0                    ; e_cs
dw 0                    ; e_lsarlc
dw 0                    ; e_ovno
dq 0                    ; e_res
dw 0                    ; e_oemid
dw 0                    ; e_oeminfo
dd 0,0,0,0,0                  ; e_res2
dd imageHeader - IMAGE_BASE ; e_lfanew

imageHeader:

dd "PE"              ; Signature
dw 0x014C            ; Machine
dw SECTIONS          ; NumberOfSections
dd TIME_DATE        ; TimeDateStamp
dd 0                ; PointerToSymbolTable
dd 0                ; NumberOfSymbols
dw optionalHeader.SIZE ; SizeOfOptionalHeader
dw 0x0303            ; Characteristics

optionalHeader:

    dw 0x10B                    ; Magic
    db 0                        ; MajorLinkerVersion
    db 0                        ; MinorLinkerVersion
    dd nagoa_round(RAW_CODE.SIZE) ; SizeOfCode
    dd nagoa_round(RAW_DATA.SIZE) ; SizeOfInitializedData
    dd nagoa_round(BSS_SIZE)    ; SizeOfUninitializedData
    dd entryPoint - IMAGE_BASE  ; AddressOfEntryPoint
    dd code - IMAGE_BASE        ; BaseOfCode
    dd data - IMAGE_BASE        ; BaseOfData
    dd IMAGE_BASE                ; ImageBase
    dd SECTION_ALIGNMENT        ; SectionAlignment
    dd FILE_ALIGNMENT            ; FileAlignment
    dw 4                        ; MajorOperatingSystemVersion
    dw 0                        ; MinorOperatingSystemVersion
    dw 0                        ; MajorImageVersion
    dw 0                        ; MinorImageVersion
    dw 4                        ; MajorSubsystemVersion
    dw 0                        ; MinorSubsystemVersion
    dd 0                        ; Win32VersionValue
;;    dd IMAGE_END - IMAGE_BASE    ; SizeOfImage
    dd (RAW_HEADER.SIZE + RAW_CODE.SIZE + RAW_DATA.SIZE)

    dd RAW_HEADER.SIZE          ; SizeOfHeaders
    dd 0                        ; CheckSum
    dw 2                        ; Subsystem
    dw 0                        ; DllCharacteristics
    dd 0x40000                  ; SizeOfStackReserve
    dd 0x6000                    ; SizeOfStackCommit
    dd 0x100000                  ; SizeOfHeapReserve
    dd 0x1000                    ; SizeOfHeapCommit
    dd 0                        ; LoaderFlags
    dd 16                        ; NumberOfRvaAndSizes
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_EXPORT
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_IMPORT
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_RESOURCE
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_EXCEPTION
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_SECURITY
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_BASERELOC
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_DEBUG
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_COPYRIGHT
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_GLOBALPTR
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_TLS
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_IAT
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
dd 0, 0                      ; reserved

optionalHeader.SIZE equ $ - optionalHeader

sectionHeaders:

    db ".text", 0, 0, 0          ; Name
    dd nagoa_round(RAW_CODE.SIZE) ; VirtualSize
    dd code                      ; VirtualAddress
    dd RAW_CODE.SIZE            ; SizeOfRawData
    dd RAW_CODE.OFFSET          ; PointerToRawData
    dd 0                        ; PointerToRelocations
    dd 0                        ; PointerToLinenumbers
    dw 0                        ; NumberOfRelocations
    dw 0                        ; NumberOfLinenumbers
    dd 0x60000020                ; Characteristics

    db ".data", 0, 0, 0          ; Name
    dd nagoa_round(RAW_DATA.SIZE) ; VirtualSize
    dd data                      ; VirtualAddress
    dd RAW_DATA.SIZE            ; SizeOfRawData
    dd RAW_DATA.OFFSET          ; PointerToRawData
    dd 0                        ; PointerToRelocations
    dd 0                        ; PointerToLinenumbers
    dw 0                        ; NumberOfRelocations
    dw 0                        ; NumberOfLinenumbers
    dd 0xC0000040                ; Characteristics

align FILE_ALIGNMENT, db 0
RAW_HEADER.SIZE equ $ - header

;;******************************************************************************************************
;; F I R S T   . c o d e   S E C T I O N
;;******************************************************************************************************

VS_CODE EQU ( IMAGE_BASE + ( ( 1 + ( (RAW_HEADER.SIZE-1) >> 12 ) ) * SECTION_ALIGNMENT ) )

section .code vstart=VS_CODE

code:
entryPoint:

xor eax, eax
ret

TIMES 1000h db 90h ;; nop

;;******************************************************************************************************
;; F I R S T   . d a t a   S E C T I O N
;;******************************************************************************************************

VS_DATA EQU ( VS_CODE + ( ( 1 + ( (RAW_CODE.SIZE-1) >> 12 ) ) * SECTION_ALIGNMENT ) )

section .data vstart=VS_DATA

data:
db "An unused string"

;;******************************************************************************************************
;; I N C L U D E   S U B R O U T I N E   F I L E S
;;******************************************************************************************************

%INCLUDE "sbr0.sbr"
%INCLUDE "sbr1.sbr"

;;******************************************************************************************************
;; L A S T   . c o d e   S E C T I O N
;;******************************************************************************************************
section .code

align FILE_ALIGNMENT, db 0

RAW_CODE.OFFSET equ RAW_HEADER.SIZE
RAW_CODE.SIZE equ $ - $$

;;******************************************************************************************************
;; L A S T   . d a t a   S E C T I O N
;;******************************************************************************************************
section .data

align FILE_ALIGNMENT, db 0

RAW_DATA.OFFSET equ RAW_CODE.OFFSET + RAW_CODE.SIZE
RAW_DATA.SIZE equ $ - $$

;;******************************************************************************************************

IMAGE_END equ $

;; -- eof --

..with the example include files..

Code: [Select]
;; file sbr0.sbr

SECTION .code

TIMES 220h db 0CCh

SECTION .data

TIMES 210h db 'put some strings'

;; eo sbr0.sbr

and

Code: [Select]
;; file sbr1.sbr

SECTION .code

TIMES 230h db 090h

SECTION .data

TIMES 240h db 'put more strings'

;; eo sbr1.sbr

You will find the section calculations are still maintained this way, and the included files need not do anything special.

My question for you is: what does PE do for a stack?  I see that the header gives some info, so the PE loader must manage the stack from the information given, dynamically, and so the programmer need not manage it. -correct?

If you could go into more detail about what else you are after, with examples of what you need to do, I (and others) may have some ideas.

hth,

Steve

Offline ;

  • Jr. Member
  • *
  • Posts: 9
Oh yeah, I wondered how to deal with the growing size of the source file.

Indeed, stack is automatically managed by Windows from values given in the file header. However I don't know how the default Stack Pointer value is defined, and if risks of memory overwriting by over-pushing are serious or not.

While you was looking for a way to include subroutine files, I fixed some wrong values that prevented the program to be considered as a valid EXE file by Windows.
Now here is a version which can be executed, it displays a message box (in order to include the API calls) and then exits.
Unfortunately I didn't know your last post when I worked on it, so I didn't had the time to include your improvement yet, sorry for that :

Code: [Select]
SECTIONS equ 3
TIME_DATE equ 0

IMAGE_BASE      equ 0x400000
SECTION_ALIGNMENT equ   0x1000
FILE_ALIGNMENT  equ    0x200

BSS_SIZE equ 0

%define nagoa_round(size) ((size + SECTION_ALIGNMENT - 1) & ~(SECTION_ALIGNMENT - 1))



; ******************************************************************************************************



bits 32
section header vstart=IMAGE_BASE

dw "MZ"                  ; e_magic
dw 0                    ; e_cblp
dw 0                    ; e_cp
dw 0                    ; e_crlc
dw 0                    ; e_cparhdr
dw 0                    ; e_minalloc
dw 0                    ; e_maxalloc
dw 0                    ; e_ss
dw 0                    ; e_sp
dw 0                    ; e_csum
dw 0                    ; e_ip
dw 0                    ; e_cs
dw 0                    ; e_lsarlc
dw 0                    ; e_ovno
dq 0                    ; e_res
dw 0                    ; e_oemid
dw 0                    ; e_oeminfo
dd 0,0,0,0,0            ; e_res2
dd imageHeader - IMAGE_BASE ; e_lfanew

imageHeader:

dd "PE"              ; Signature
dw 0x014C            ; Machine
dw SECTIONS          ; NumberOfSections
dd TIME_DATE        ; TimeDateStamp
dd 0                ; PointerToSymbolTable
dd 0                ; NumberOfSymbols
dw optionalHeader.SIZE ; SizeOfOptionalHeader
dw 0x0303            ; Characteristics

optionalHeader:

    dw 0x10B                    ; Magic
    db 0                        ; MajorLinkerVersion
    db 0                        ; MinorLinkerVersion
    dd nagoa_round(RAW_CODE.SIZE) ; SizeOfCode
    dd nagoa_round(RAW_RDATA.SIZE) ; SizeOfInitializedData
    dd nagoa_round(BSS_SIZE)    ; SizeOfUninitializedData
    dd entryPoint - IMAGE_BASE  ; AddressOfEntryPoint
    dd code - IMAGE_BASE        ; BaseOfCode
    dd rdata - IMAGE_BASE        ; BaseOfData
    dd IMAGE_BASE                ; ImageBase
    dd SECTION_ALIGNMENT        ; SectionAlignment
    dd FILE_ALIGNMENT            ; FileAlignment
    dw 4                        ; MajorOperatingSystemVersion
    dw 0                        ; MinorOperatingSystemVersion
    dw 0                        ; MajorImageVersion
    dw 0                        ; MinorImageVersion
    dw 4                        ; MajorSubsystemVersion
    dw 0                        ; MinorSubsystemVersion
    dd 0                        ; Win32VersionValue
    dd IMAGE_END - IMAGE_BASE    ; SizeOfImage
    dd RAW_HEADER.SIZE          ; SizeOfHeaders
    dd 0                        ; CheckSum
    dw 2                        ; Subsystem
    dw 0                        ; DllCharacteristics
    dd 0x40000                  ; SizeOfStackReserve
    dd 0x6000                    ; SizeOfStackCommit
    dd 0x100000                  ; SizeOfHeapReserve
    dd 0x1000                    ; SizeOfHeapCommit
    dd 0                        ; LoaderFlags
    dd 16                        ; NumberOfRvaAndSizes

dd 0, 0                              ; IMAGE_DIRECTORY_ENTRY_EXPORT
dd ImportDirectoryTable - IMAGE_BASE ; IMAGE_DIRECTORY_ENTRY_IMPORT.addresss
dd import.SIZE                      ; IMAGE_DIRECTORY_ENTRY_IMPORT.size
dd 0, 0                              ; IMAGE_DIRECTORY_ENTRY_RESOURCE
dd 0, 0                              ; IMAGE_DIRECTORY_ENTRY_EXCEPTION
dd 0, 0                              ; IMAGE_DIRECTORY_ENTRY_SECURITY
dd 0, 0                              ; IMAGE_DIRECTORY_ENTRY_BASERELOC
dd 0, 0                              ; IMAGE_DIRECTORY_ENTRY_DEBUG
dd 0, 0                              ; IMAGE_DIRECTORY_ENTRY_COPYRIGHT
dd 0, 0                              ; IMAGE_DIRECTORY_ENTRY_GLOBALPTR
dd 0, 0                              ; IMAGE_DIRECTORY_ENTRY_TLS
dd 0, 0                              ; IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
dd 0, 0                              ; IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
dd ImportAddressTable - IMAGE_BASE  ; IMAGE_DIRECTORY_ENTRY_IAT.address
dd iat.SIZE                          ; IMAGE_DIRECTORY_ENTRY_IAT.size
dd 0, 0                              ; IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
dd 0, 0                              ; IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
dd 0, 0                              ; reserved

optionalHeader.SIZE equ $ - optionalHeader

sectionHeaders:

    dq ".text"          ; Name
    dd VIRTUAL_CODE.SIZE ; VirtualSize
    dd code - IMAGE_BASE ; VirtualAddress
    dd RAW_CODE.SIZE    ; SizeOfRawData
    dd RAW_CODE.OFFSET  ; PointerToRawData
    dd 0                ; PointerToRelocations
    dd 0                ; PointerToLinenumbers
    dw 0                ; NumberOfRelocations
    dw 0                ; NumberOfLinenumbers
    dd 0x60000020        ; Characteristics

    dq ".rdata"          ; Name
    dd VIRTUAL_RDATA.SIZE ; VirtualSize
    dd rdata - IMAGE_BASE ; VirtualAddress
    dd RAW_RDATA.SIZE    ; SizeOfRawData
    dd RAW_RDATA.OFFSET ; PointerToRawData
    dd 0                ; PointerToRelocations
    dd 0                ; PointerToLinenumbers
    dw 0                ; NumberOfRelocations
    dw 0                ; NumberOfLinenumbers
    dd 0x40000040        ; Characteristics

    dq ".idata"          ; Name
    dd VIRTUAL_IDATA.SIZE ; VirtualSize
    dd idata - IMAGE_BASE ; VirtualAddress
    dd RAW_IDATA.SIZE    ; SizeOfRawData
    dd RAW_IDATA.OFFSET ; PointerToRawData
    dd 0                ; PointerToRelocations
    dd 0                ; PointerToLinenumbers
    dw 0                ; NumberOfRelocations
    dw 0                ; NumberOfLinenumbers
    dd 0xC0000040        ; Characteristics

align FILE_ALIGNMENT, db 0

RAW_HEADER.SIZE equ $ - $$



; ******************************************************************************************************



RAW_CODE.OFFSET equ RAW_HEADER.SIZE
VIRTUAL_CODE.OFFSET equ IMAGE_BASE + nagoa_round(RAW_HEADER.SIZE)

section .text follows=header vstart=VIRTUAL_CODE.OFFSET

code:
entryPoint:

xor eax, eax

push eax
push dword stringBoxCaption
push dword stringBoxMessage
push eax

call [MessageBox]

xor eax, eax
ret

align FILE_ALIGNMENT, db 0

RAW_CODE.SIZE    equ $ - $$
VIRTUAL_CODE.SIZE equ nagoa_round(RAW_CODE.SIZE)



; ******************************************************************************************************



RAW_RDATA.OFFSET    equ RAW_CODE.OFFSET + RAW_CODE.SIZE
VIRTUAL_RDATA.OFFSET equ VIRTUAL_CODE.OFFSET + VIRTUAL_CODE.SIZE

section .rdata vstart=VIRTUAL_RDATA.OFFSET

rdata:

stringBoxCaption:

db "exetest", 0

stringBoxMessage:

db "Hi, I'm exetest, a tiny valid win32 program.", 0

align FILE_ALIGNMENT, db 0

RAW_RDATA.SIZE  equ $ - $$
VIRTUAL_RDATA.SIZE equ nagoa_round(RAW_RDATA.SIZE)



; ******************************************************************************************************



RAW_IDATA.OFFSET    equ RAW_RDATA.OFFSET + RAW_RDATA.SIZE
VIRTUAL_IDATA.OFFSET equ VIRTUAL_RDATA.OFFSET + VIRTUAL_RDATA.SIZE

section .idata vstart=VIRTUAL_IDATA.OFFSET

idata:

ImportDirectoryTable:

dd lookup_User32 - IMAGE_BASE ; OriginalFirstThunk
dd 0                        ; TimeDateStamp
dd 0xFFFFFFFF                ; ForwarderChain
dd string_User32 - IMAGE_BASE ; Name
dd iat_User32 - IMAGE_BASE    ; FirstThunk

dd 0, 0, 0, 0, 0

lookup_User32:

dd hintName_MessageBox - IMAGE_BASE
dd 0

hintName_MessageBox:

dw 0            ; Hint
db "MessageBoxA", 0 ; Name
align 2, db 0    ; Pad

import.SIZE equ $ - ImportDirectoryTable



ImportAddressTable:

iat_User32:

MessageBox:

dd hintName_MessageBox - IMAGE_BASE

dd 0

iat.SIZE equ $ - ImportAddressTable



string_User32:

db "User32.dll", 0



align FILE_ALIGNMENT, db 0

RAW_IDATA.SIZE    equ $ - $$
VIRTUAL_IDATA.SIZE equ nagoa_round(RAW_IDATA.SIZE)



; ******************************************************************************************************



IMAGE_END equ VIRTUAL_IDATA.OFFSET + VIRTUAL_IDATA.SIZE

It can be compiled with the following command :

Code: [Select]
nasm -f bin exetest.asm -o exetest.exe 2> error.log
Something can bother you : I revert back the ".text" section at second position behind the "header" section. I did this in order to make section names matches between the source code and the produced binary. (Microsoft defines the ".text" section as located after the header)

So, the binary file weight is 2KB.
I know we can produce an exe file with same effect in about 200 or 300 bytes only, but its tricky content would not be totally valid according to the PE specification.
The excinting thing here is, we have a program that is simultaneously tiny and valid ! :P

So many emotions...

Offline s_dubrovich

  • Jr. Member
  • *
  • Posts: 8

So, the binary file weight is 2KB.
I know we can produce an exe file with same effect in about 200 or 300 bytes only, but its tricky content would not be totally valid according to the PE specification.
The excinting thing here is, we have a program that is simultaneously tiny and valid ! :P

So many emotions...


Very Good!  Congrats,

Steve

Offline Laocoon

  • Jr. Member
  • *
  • Posts: 14
Re: Dealing with virtual and raw addresses (avoid the use of the linker)
« Reply #20 on: October 18, 2013, 09:51:41 PM »
(Though we may continue to discuss about binary compilation tricks, especially if somebody find a magical function that returns the raw file offset from where it is called, somehow like "$" does for virtual address)

label the line you want
Code: [Select]
proc GetRawFileOffset, dword pFile, dword pAddress
if pFile == 0
    invoke GetModuleHandle,NULL
else
    mov eax, pFile
endif
add eax, dword [eax + IMAGE_DOS_HEADER.e_lfanew]
mov eax, dword [eax +IMAGE_NT_HEADERS.OptionalHeader.BaseOfCode]
;EDITED - Use BaseOfData for address' in .data sections. You can go through and do
;$-StartOfSectionLabel+ dword [IMAGE_SECTION_HEADER.PointerToRawData]
push ebx
mov ebx, .SomeLabel
sub ebx, eax
xchg eax, ebx
pop ebx
endproc


push .SomeLabel
push strict dword 0
call GetRawFileOffset
.SomeLabel
;We have the raw file offset to this address in eax
;So eax = eip - BaseOfCode

If You want this hardcoded, a TopLabel at the top and a $-TopLabel should also work.


« Last Edit: October 18, 2013, 10:28:05 PM by Laocoon »