flat assembler
Message board for the users of flat assembler.

Index > Windows > Stack misalignment setting the entry point with win64ax.inc

Author
Thread Post new topic Reply to topic
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20299
Location: In your JS exploiting you and your system
revolution 24 Mar 2015, 08:07
When setting the entry point with win64ax.inc there exists a problem with stack misalignment.
Code:
include 'win64ax.inc'

.code

proc begin
        test    rsp,0xf
        jnz     .misaligned
        invoke  ExitProcess,0   ;okay
    .misaligned:
        and     rsp,not 0xf
        invoke  MessageBox,0,'Danger Will Robinson!','Oh noes',0
        invoke  ExitProcess,1   ;fail
endp

.end begin    
The problem is because of an errant instruction in the .code macro
Code:
macro .code {
  section '.text' code readable executable
  entry $
  sub rsp,8                     ;<--- This shouldn't be here!
  local main,code
  entry equ main
  if main <> code
  jmp main
  end if
  code: }    
This also creates a problem if one uses more than one .code section.
Post 24 Mar 2015, 08:07
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8351
Location: Kraków, Poland
Tomasz Grysztar 24 Mar 2015, 08:12
The ".end" macro was intended to work with entry point defined directly with a label (like in the HELLO example), I never really thought about extending it to work with "proc". None of the standard examples use the "proc" in this way.
Post 24 Mar 2015, 08:12
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8351
Location: Kraków, Poland
Tomasz Grysztar 24 Mar 2015, 08:18
PS. Also, this behavior is defined by the Windows programming headers documentation:
2.2 Structuring the source wrote:
In 64-bit Windows the .end automatically aligns the stack on 16 bytes boundary.
This problem with "proc" can be viewed in another way - the "proc" macro assumes that the procedure entry has the stack misaligned by 8 bytes, so it translates to a problem with procedure being called in an unexpected way.


Last edited by Tomasz Grysztar on 24 Mar 2015, 08:21; edited 1 time in total
Post 24 Mar 2015, 08:18
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20299
Location: In your JS exploiting you and your system
revolution 24 Mar 2015, 08:21
I think the use of proc would be the norm for anyone wanting to use local labels and/or use the entry parameters for DLL startup.


Last edited by revolution on 24 Mar 2015, 08:21; edited 1 time in total
Post 24 Mar 2015, 08:21
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8351
Location: Kraków, Poland
Tomasz Grysztar 24 Mar 2015, 08:21
revolution wrote:
I think the use of proc would be the norm for anyone wanting to use local labels and/or use the entry parameters for DLL entry.
".end" was not intended for DLL use.
Post 24 Mar 2015, 08:21
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20299
Location: In your JS exploiting you and your system
revolution 24 Mar 2015, 08:23
Tomasz Grysztar wrote:
This problem with "proc" can be viewed in another way - the "proc" macro assumes that the procedure entry has the stack misaligned by 8 bytes, so it translates to a problem with procedure being called in an unexpected way.
But this is the normal entry situation for 64-bit procs.
Post 24 Mar 2015, 08:23
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20299
Location: In your JS exploiting you and your system
revolution 24 Mar 2015, 08:25
Tomasz Grysztar wrote:
".end" was not intended for DLL use.
Fair enough I guess. But for DLLs without exports .end might still be usable.
Post 24 Mar 2015, 08:25
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8351
Location: Kraków, Poland
Tomasz Grysztar 24 Mar 2015, 08:26
revolution wrote:
Tomasz Grysztar wrote:
This problem with "proc" can be viewed in another way - the "proc" macro assumes that the procedure entry has the stack misaligned by 8 bytes, so it translates to a problem with procedure being called in an unexpected way.
But this is the normal entry situation for 64-bit procs.
Yes, it is. But by using the ".end" with an address to "proc" you are causing the procedure entry to be called with a stack aligned - all as per documentation. Thus everything works "as intended" and the error lies really in the incorrect use of not very sophisticated macroinstructions.


Last edited by Tomasz Grysztar on 24 Mar 2015, 08:27; edited 1 time in total
Post 24 Mar 2015, 08:26
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20299
Location: In your JS exploiting you and your system
revolution 24 Mar 2015, 08:27
Tomasz Grysztar wrote:
The ".end" macro was intended to work with entry point defined directly with a label (like in the HELLO example), I never really thought about extending it to work with "proc". None of the standard examples use the "proc" in this way.
All of the current 64-bit examples in the download use win64a.inc (without the 'x') and manually have the 'sub rsp,8' instruction.
Post 24 Mar 2015, 08:27
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8351
Location: Kraków, Poland
Tomasz Grysztar 24 Mar 2015, 08:28
revolution wrote:
Tomasz Grysztar wrote:
The ".end" macro was intended to work with entry point defined directly with a label (like in the HELLO example), I never really thought about extending it to work with "proc". None of the standard examples use the "proc" in this way.
All of the current 64-bit examples in the download use win64a.inc (without the 'x') and manually have the 'sup rsp,8' instruction.
The "hello" example has a comment that states that it should work with "win64ax" or "win64wx" headers, too. This one is thus both a 32-bit and 64-bit example.
Post 24 Mar 2015, 08:28
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20299
Location: In your JS exploiting you and your system
revolution 24 Mar 2015, 08:34
Then using local labels in the entry procedure becomes cumbersome. As it is now everything works only for simple entry procs that don't have entry parameters or local labels.

I suppose I could do:
Code:
;...

begin:
        add     rsp,8
        jmp     start

proc start
        locals
                ;...
        endl
        ;stuff
        invoke  ExitProcess,0
endp

.end begin    
But it looks terrible.
Post 24 Mar 2015, 08:34
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20299
Location: In your JS exploiting you and your system
revolution 24 Mar 2015, 08:45
Tomasz Grysztar wrote:
The ".end" macro was intended to work with entry point defined directly with a label (like in the HELLO example), I never really thought about extending it to work with "proc". None of the standard examples use the "proc" in this way.
I think you mean the ".code" macro, not the ".end" macro?
Post 24 Mar 2015, 08:45
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8351
Location: Kraków, Poland
Tomasz Grysztar 24 Mar 2015, 08:55
revolution wrote:
I think you mean the ".code" macro, not the ".end" macro?
I was writing from the point of view of usage of macro, not how is it implemented internally. The alignment is defined to be caused by ".end" macro, even though it is really implemented in ".code".
Post 24 Mar 2015, 08:55
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8351
Location: Kraków, Poland
Tomasz Grysztar 24 Mar 2015, 08:59
revolution wrote:
Then using local labels in the entry procedure becomes cumbersome. As it is now everything works only for simple entry procs that don't have entry parameters or local labels.
I think ".end" macro could be made to detect that it has a label defined with "proc" given as argument, and act accordingly.
Post 24 Mar 2015, 08:59
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20299
Location: In your JS exploiting you and your system
revolution 24 Mar 2015, 09:08
Trying to assemble without using ".code"
Code:
include 'win64ax.inc'

section '.custom' code readable executable

proc begin
        test    rsp,0xf
        jnz     .misaligned
        invoke  ExitProcess,0   ;okay
    .misaligned:
        and     rsp,not 0xf
        invoke  MessageBox,0,'Danger Will Robinson!','Oh noes',0
        invoke  ExitProcess,1   ;fail
endp

.end begin    
Gives:
Code:
.end begin
<>\win64ax.inc [169] .end [1]:
   label entry at value
error: invalid argument.    
If a user wants to set custom section attributes then .end becomes unusable.
Post 24 Mar 2015, 09:08
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8351
Location: Kraków, Poland
Tomasz Grysztar 24 Mar 2015, 09:53
revolution wrote:
If a user wants to set custom section attributes then .end becomes unusable.
These macros were created for the very simplified programming, for the people that do not want to know about all these details and advanced settings needed to set up sections, data headers, etc. They were not indented to be suitable for general (and advanced) use.
Post 24 Mar 2015, 09:53
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20299
Location: In your JS exploiting you and your system
revolution 24 Mar 2015, 10:03
Using the auto-named .flat section also creates an issue:
Code:
include 'win64ax.inc'

begin:
        invoke  ExitProcess,0

.end begin    
Code:
.end begin
<>/win64ax.inc [169] .end [1]:
   label entry at value
error: invalid argument.    
Post 24 Mar 2015, 10:03
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8351
Location: Kraków, Poland
Tomasz Grysztar 24 Mar 2015, 10:12
You are putting it upside down, it's not the auto-named section that causes an issue, it simply is the use of ".end" without ".code" that causes the issue, and these macros were not created to be used for any other purpose that just simply structuring the entire program with ".code", ".data" and ".end" triad. Perhaps I should clarify it better in the documentation.
Post 24 Mar 2015, 10:12
View user's profile Send private message Visit poster's website Reply with quote
Feryno



Joined: 23 Mar 2005
Posts: 509
Location: Czech republic, Slovak republic
Feryno 24 Mar 2015, 13:42
guys, every proc in x64 ms win OS starts with misaligned stack
it is because return address from procedure is pushed there

this explains such behaviour:

let code runs with aligned stack (RSP mod 16 = 0)
now the code calls any procedureX, so return address from procedureX is pushed to RSP, now RSP mod 16 = 8 when entering the procedureX

even simple MessageBoxA fails to execute if you forget to align stack at 16, it is because x64 ms win OS often accesses stack with fast 128 bit instructions like movdqa [rsp+...*16],xmm0 (exception raised when RSP mod 16 is not 0)

instruction like sub rsp,8 is bad idea

procedure also needs not only to run with aligned RSP, but also low 4 qwords in stack are reserved (I think it persisted from early versions of OS when putting first 4 params using stack, later it was changed to faster way where first 4 input params are passed in registers rcx, rdx, r8, r9, and 5th and above params stayed passed in stack)
never touch this area as subprocedures may save some registers there
if you forget to subtract from stack this 4 qwords area, subproc may then damage return address from procedure when writing there registers to be preserved

here are some simple examples of procedure prologues and epilogues:

proc0:
sub rsp,8*(4+1)
...code
add rsp,8*(4+1)
ret

proc1:
push rbx
sub rsp,8*(4+0)
...code
add rsp,8*(4+0)
pop rbx
ret

proc2:
push rsi rdi
sub rsp,8*(4+1)
...code
add rsp,8*(4+1)
pop rdi rsi
ret

proc3:
sub rsp,8*(4+5)
...code
add rsp,8*(4+5)
ret

entrypoint behaves in the same way as procedure, entrypoint is called as common procedure by OS DLL (use debugger and RET instruction from main procedure instead of ExitProcess and when returning to DLL, go few instructions backward) - e.g. just compile the above proc0 as the whole exe nothing else and run it under debugger
Post 24 Mar 2015, 13:42
View user's profile Send private message Visit poster's website ICQ Number Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.