Author Topic: Shift stack pointer  (Read 9075 times)

Offline lostsky25

  • New Member
  • Posts: 1
Shift stack pointer
« on: August 07, 2020, 08:19:22 PM »
I have this code:
Code: [Select]
default REL
extern GetStdHandle
extern WriteFile
extern ExitProcess

section .data
true_msg db 'Yes', 0

true_msg_len equ $-true_msg

section .text
global _main

print_yes:
and rsp, -10h
sub rsp, 020h

mov rcx, -0Bh
call GetStdHandle

mov rcx, rax
mov rdx, true_msg
mov r8, true_msg_len
xor r9, r9
push r9
sub rsp, 20h
call WriteFile
add rsp, 40h
pop rax
    ret ;// essentially identical to: pop [register] -> jmp [register]

_main:
mov rcx, 2
cmp rcx, 2
jne false1

call print_yes

false1:

mov rcx, 0 ; RCX - first argument.
call ExitProcess

xor rax, rax
ret


Why I must do something like this:
Code: [Select]
and rsp, -10h
sub rsp, 020h
Thereafter, I can call 'GetStdHandle', then I want to use 'WriteFile' and I must do this:
Code: [Select]
sub rsp, 20h
1) Why? How can I find this value for other functions?

Also, I must write this:
Code: [Select]
add rsp, 40h
pop rax
    ret
In the first, I restore the original state of the stack pointer. In the second, 'pop rax' register. If I don't do this, my program will end. RIP will be zero?

2) I always 'pop rax' in other labels/functions?

Offline fredericopissarra

  • Full Member
  • **
  • Posts: 373
  • Country: br
Re: Shift stack pointer
« Reply #1 on: August 08, 2020, 12:54:06 PM »
You don't need to play with the stack to build a simple "hello, world" in ASM for Win64:
Code: [Select]
; Win64 hello.asm
;
; Compiling using NASM and minw64 (linux).
;
;   $ nasm -fwin64 -o hello.o hello.asm
;   $ x86_64-w64-mingw32-ld -s -e _start -o hello.exe hello.o \
;       -L /lib/x86_64-w64-mingw32/ -l:libkernel32.a
;

  bits 64
  default rel

STD_OUTPUT_HANDLE equ -11

  section .rodata

msg:  db  `hello\r\n`
msg_len equ $ - msg

  section .text

; Imported from libkernel32.a
extern __imp_GetStdHandle
extern __imp_WriteConsoleA
extern __imp_ExitProcess

; Entry point
  global _start
_start:
  mov   ecx,STD_OUTPUT_HANDLE
  call  qword [__imp_GetStdHandle]

  mov   rcx,rax
  lea   rdx,[msg]
  mov   r8d,msg_len
  xor   r9d,r9d
  push  r9                          ; 5th argument goes to stack.
  call  qword [__imp_WriteConsoleA] ; WriteConsoleA will cleanup the stack for you!

  xor   ecx,ecx
  jmp   qword [__imp_ExitProcess]
Those RSP manipulations are intended for SEH (Structured Exception Handling).
The first AND RSP,-10, and I suspect this is wrong, is intended to align RSP (but it is already aligned by the loader).

Offline ig

  • Jr. Member
  • *
  • Posts: 12
Re: Shift stack pointer
« Reply #2 on: August 10, 2020, 08:00:35 AM »
We're talking about Windows x64 platform here - so no, those RSP manipulations are not intended for SEH (SEH in x64 uses fixed tables and doesn't involve any instructions whatsoever to set up in the actual code).

The x64 calling convention says that you need to allocate a "shadow space" (20h bytes) before calling any function, see e.g. here:
https://retroscience.net/x64-assembly.html#fast-call-procedure-shadow-space-home-space
So that's what that sub rsp, 20h is about.

There is also a requirement for stack alignment - before calling any function, rsp has to be a multiple of 10h. However, that "and" instruction is most likely incorrect - especially if the original value of rsp wasn't stored anywhere, because after the "and" instruction you wouldn't be able to restore it back to the original value. Usually, since you already know the alignment in the current function (from the alignment requirement), you know if you need to subtract 8 bytes or not (to achieve the correct alignment for the called function), so the alignment is rarely done via "and".

As for the second question - in this particular case, it seems to me that the "pop eax" instruction is only used to fix the stack (i.e. to act as a counterpart of that "push r9") - so it should be possible to do only "add rsp, 48h", instead of "add rsp,40h" (and no pop).