flat assembler
Message board for the users of flat assembler.

Index > Windows > 64 bit not understood sub rsp,8 !

Goto page Previous  1, 2, 3, 4, 5, 6, 7  Next
Author
Thread Post new topic Reply to topic
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 18452
Location: In your JS exploiting you and your system
revolution
A debugger is an external program, it doesn't need the app to have an always valid stack pointer. Try it.

Only internally generated exceptions cause a problem. And I can guarantee that "sub rsp, 1" never causes an exception. Try it.

Anyhow, if what you say is true then anytime you make a CALL the stack is unaligned and your app will crash, right? But that doesn't happen, because the app can do whatever it wants with RSP. Try it.
Post 11 May 2022, 11:56
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: 18452
Location: In your JS exploiting you and your system
revolution
I encourage anyone to try this for themselves.

Start up your debugger. Open some code using multiple "sub rsp,1" instructions. Single step through them. Did anything crash?
Post 11 May 2022, 12:15
View user's profile Send private message Visit poster's website Reply with quote
Furs



Joined: 04 Mar 2016
Posts: 1766
Furs
I mean, the stack needs 8 byte alignment, that's the native size.

Read: https://devblogs.microsoft.com/oldnewthing/20190111-00/?p=100685

Short snippet:
Quote:
Since there is no red zone on x86, the memory at negative offsets relative to the stack pointer may be overwritten at any time. Therefore, the above sequence is permitted to jump to panic.
More details if you read it...
Post 11 May 2022, 12:16
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 18452
Location: In your JS exploiting you and your system
revolution
That article is about something else entirely.

Did you try my suggestion?
Post 11 May 2022, 12:24
View user's profile Send private message Visit poster's website Reply with quote
Furs



Joined: 04 Mar 2016
Posts: 1766
Furs
What do you understand from:
Quote:
The memory at negative offsets relative to the stack pointer may be overwritten at any time.
?

What's a "negative offset" to rsp being set to, idk, NULL as a general purpose register?

It even explicitly gives a very rare scenario with a paging I/O page fault. Such things can't be tested easily, but they can happen.

Don't write time bombs.


Also when I said debugger I didn't mean breakpoints. I meant using the debugging API to trigger exceptions or something. I'm not too familiar with it, but I bet it's possible.
Post 12 May 2022, 13:06
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 18452
Location: In your JS exploiting you and your system
revolution
But "sub rsp,1" never generates and exception. So that article does not apply.

I guarantee you the stack won't ever be written, by any process (kernel included), before, during or after execution of "sub rsp, 1".

So the code I posted will work fine. Please stop sowing unnecessary FUD.

An app does not have any obligation to maintain a valid RSP value.

In x86 you can use push to a stack aligned to 1 if you want to. There will be no exception unless your stack overflows it's bounds. Just don't try calling the Windows OS API, because we already know Windows uses the aligned data loads and crashes. But that is purely an OS decision, not a hardware requirement. Inside your code do whatever you want with RSP, the hardware won't care. External exceptions won't kill your process. Only your own internal exceptions will complain about an invalid stack. And "sub rsp,1" doesn't generate any exceptions.
Post 12 May 2022, 13:40
View user's profile Send private message Visit poster's website Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1440
Location: Toronto, Canada
AsmGuru62
This topic is somewhat devolved.
The sub rsp,8 is needed only at the start: label.
Because Windows makes a CALL to that start: label and just immediately after the CALL the stack is not aligned to use OS API.
Now, FASM has invoke macro which implements the shadow space (no need for SUB RSP,0x20).

Also, you can use local directive inside the procedure (macros proc/endp) and it also automatically aligns stack to 16 bytes, so API can be called without any additional measures.

Also #2: why PUSH/POP? x64 has registers (R12 ... R15) which are not used by API, so you can do the following to preserve RAX:
Code:
mov r12,rax
.... call another API
mov rax,r12             ; or just use R12 directly if you need it somewhere
    

To use all these awesome macros -- you need to include "Win64W.Inc".
Post 12 May 2022, 15:33
View user's profile Send private message Send e-mail Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 18452
Location: In your JS exploiting you and your system
revolution
AsmGuru62 wrote:
The sub rsp,8 is needed ...
But why use sub?

push rbp. Fewer bytes (not that is matters)
push rbp. Debugger support (if you ever need it. Ya never know, right?)

sub rsp,8. More bytes, for what?
sub rsp,8. That magic value of 8, what does it mean? Why not 24? Or 72?

I have no idea why everyone loves sub rsp, 8 so much. Is it because it isn't what normal C generators do? Is it because as assembly coders we must do stuff different, even for no purpose? Razz

I like the last reason the most.
Post 12 May 2022, 15:47
View user's profile Send private message Visit poster's website Reply with quote
macomics



Joined: 26 Jan 2021
Posts: 462
Location: Russia
macomics
Code:
entry $
  and spl, -16
...    
or
Code:
entry $
  pop rax
...    
Post 12 May 2022, 15:58
View user's profile Send private message Reply with quote
Overclick



Joined: 11 Jul 2020
Posts: 434
Location: Ukraine
Overclick
'Call' uses 8 bytes at stack only. You do whatever push or sub rsp just to align stack back to 16
You can 'call' twice to do the same
Also don't forget to return the stack back after call by 'pop' or rsp directly: add rsp,8 as example
Post 12 May 2022, 18:12
View user's profile Send private message Visit poster's website Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1440
Location: Toronto, Canada
AsmGuru62
Indeed, PUSH RAX works also. It takes less bytes:
Code:
00000000004022B0 | 48:83EC 08                 | SUB     RSP, 0x8                                       |
00000000004022B4 | 50                         | PUSH    RAX                                            |    

I copied this from FASM template for x64 provided in EXAMPLES folder.
When you make your own function -- using proc/endp macros provide everything connected to stack alignment, so no need to balance the stack with POP. FASM uses LEAVE opcode to do it. All you need is to use CALL and pass values in ANY registers, because you are calling not OS API, but your own function. You can pass parameters in RAX or RSI, whatever is needed by the logic. It is the OS API which requires parameters in RCX,RDX,R8,R9 and needs a shadow stack room. When you design your own function -- none of that is needed. I just coded a large commercial app in x64 FASM and it works great! Just use proc/endp for your own functions and invoke for Windows API calls.
Post 12 May 2022, 18:37
View user's profile Send private message Send e-mail Reply with quote
tthsqe



Joined: 20 May 2009
Posts: 738
tthsqe
> But sub rsp,1 never generates an exception.

I don't think this is the point. The app can be interrupted at any point in time for keyboard, mouse, and spy cam interaction.
Post 12 May 2022, 19:21
View user's profile Send private message Reply with quote
Overclick



Joined: 11 Jul 2020
Posts: 434
Location: Ukraine
Overclick
Most elegant way:
Code:
push rax
call something
...

...
something:
   ...
   invoke...
   ...
   ret 8
    
Post 12 May 2022, 21:30
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: 18452
Location: In your JS exploiting you and your system
revolution
tthsqe wrote:
> But sub rsp,1 never generates an exception.

I don't think this is the point. The app can be interrupted at any point in time for keyboard, mouse, and spy cam interaction.
It doesn't matter. External interrupts will never overwrite the app stack, ever. It doesn't work that way. The kernel will never use your apps stack for it's own purposes. It only uses your stack for things directly related to your code. So if your apps creates an exception and you have added your app to the exception chain, then the kernel necessarily uses your stack to place the exception info, so that your app can examine it.

The app is not obligated to maintain a valid rsp.

So all that matters here is that "sub rsp,1" never causes an exception, so everything works perfectly fine.

There really is no problem with "sub rsp,1", except that many people misunderstand what the kernel does, and think the red zone is for the kernel to place random data when it pleases. It doesn't.

___________________________________________

To macomics:

What is your reasoning for your choice of rax?
Post 13 May 2022, 00:17
View user's profile Send private message Visit poster's website Reply with quote
macomics



Joined: 26 Jan 2021
Posts: 462
Location: Russia
macomics
revolution wrote:
What is your reasoning for your choice of rax?
It's just the first of 8 registers. The second 8 generate long push/pop codes.
Choose any of the 8.
Post 13 May 2022, 00:52
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 18452
Location: In your JS exploiting you and your system
revolution
So can I choose rbp?
Post 13 May 2022, 01:11
View user's profile Send private message Visit poster's website Reply with quote
macomics



Joined: 26 Jan 2021
Posts: 462
Location: Russia
macomics
why not

add: I just want to draw attention to the fact that the module_entry_point call is not performed from an vacuum. If you don't want to bother with rollback and safe return from the main function, you can leave it to the system code. And if the system is lying in the struggle for the completion of a failed program, so what is the price of such a system.
Post 13 May 2022, 02:16
View user's profile Send private message Reply with quote
Furs



Joined: 04 Mar 2016
Posts: 1766
Furs
revolution wrote:
But "sub rsp,1" never generates and exception. So that article does not apply.
Did you even read it? It has two examples where exceptions or corruptions are generated from outside parts.

Here are copy pasted quotes with emphasis:
Quote:
A debugger may use the memory beyond the red zone as a convenient place to store some data. For example, if you use the .call command, the debugger will perform the nested call on the same stack, and likely use some of that stack space to preserve registers so that they can be restored after the .called function returns. Any data stored beyond the red zone will therefore be destroyed.
Quote:
Suppose your thread gets pre-empted immediately after you store the data beyond the red zone. While your thread is waiting for a chance to resume execution, the memory manager pages out the code. Eventually, your thread resumes execution, and the memory manager tries to page it back in. Oh no, there’s an I/O error during the page-in! The operating system pushes an exception frame onto the stack for the STATUS_IN_PAGE_ERROR, clobbering the data you had been hiding beyond the red zone.

The operating system then dispatches the exception. It goes to a vectored exception handler, which some other part of your program had installed specifically to handle this possibility, because your program might be run directly off a CD-ROM or unreliable network. The program displays a prompt to ask the user to reinsert the CD-ROM and offers an opportunity to retry. If the user says to retry, then the vectored exception handler returns EXCEPTION_CONTINUE_EXECUTION, and the operating system will restart the failed instruction.

This time, the restart succeeds because the CD-ROM is present and the code can be paged back in. The next instruction runs, the one that loads the beyond-the-red-zone value into the ecx register, but it doesn’t load the value stored by the previous instruction because the STATUS_IN_PAGE_ERROR exception overwrote it. The comparison fails, and we jump to the label panic.
In respect to vectored exception handlers: they can be installed by any library process-wide, not to mention others attaching to yours.

revolution wrote:
I guarantee you the stack won't ever be written
That's what everyone says about their software with security too until a nasty security vulnerability is found, especially one like Spectre which is on the CPU.
Post 13 May 2022, 13:28
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 18452
Location: In your JS exploiting you and your system
revolution
sub rsp,1 doesn't store data in the red zone.

Your article is not relevant.
Post 13 May 2022, 13:45
View user's profile Send private message Visit poster's website Reply with quote
Furs



Joined: 04 Mar 2016
Posts: 1766
Furs
Do you not understand English in the article, or have you still not read it?
Quote:
A debugger may use the memory beyond the red zone [...]
sub rsp,1 is not a debugger. If the debugger places data in the red zone, then it uses rsp to do that. Which assumes it is aligned at least to 8 bytes.

The point isn't the red zone. The point is that accessing the red zone requires rsp. And what happens if rsp has unaligned value or, worse, arbitrary value (like NULL)?

What's [rsp-10] (red zone address) when rsp is NULL?

It's not rocket science.
Post 14 May 2022, 13:49
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page Previous  1, 2, 3, 4, 5, 6, 7  Next

< 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-2020, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.

Website powered by rwasa.