Exetools  

Go Back   Exetools > General > General Discussion

Notices

Reply
 
Thread Tools Display Modes
  #16  
Old 07-19-2018, 01:45
Insid3Code's Avatar
Insid3Code Insid3Code is offline
Family
 
Join Date: May 2013
Location: Algeria
Posts: 84
Rept. Given: 47
Rept. Rcvd 60 Times in 30 Posts
Thanks Given: 24
Thanks Rcvd at 108 Times in 56 Posts
Insid3Code Reputation: 60
@vic4key
To avoid the application crash you need to allocate/align the stack...
Compiled and tested (MSVC 2017 15.7.3)

PHP Code:
F1 PROC
  SUB RSP
40 Allocate space on the stack (for alignment and 32 for shadow space)...
  
PUSH RBP
  MOV RBP
RSP
  LEA RCX
TXT_F1
  CALL puts
  LEAVE
  ADD RSP
40 Cleanup the stack...
  
RET
F1 ENDP

F2 PROC
  SUB RSP
40 Allocate space on the stack (for alignment and 32 for shadow space)...
  
PUSH RBP
  MOV RBP
RSP
  LEA RCX
TXT_F2
  CALL puts
  LEAVE
  ADD RSP
40 Cleanup the stack...
  
RET
F2 ENDP 
__________________
Computer Forensics
Reply With Quote
The Following User Says Thank You to Insid3Code For This Useful Post:
niculaita (07-19-2018)
  #17  
Old 07-20-2018, 12:56
vic4key vic4key is offline
Family
 
Join Date: Apr 2010
Posts: 57
Rept. Given: 5
Rept. Rcvd 24 Times in 10 Posts
Thanks Given: 60
Thanks Rcvd at 94 Times in 21 Posts
vic4key Reputation: 24
Hi Insid3Code. Not used any local variables inside. So the allocation is unnecessary I think. Even it can be shorter. Eg.

F1 PROC
PUSHAD
LEA RCX, TXT_F1
CALL puts
POPAD
F1 ENDP

More, your edited code should be:

F1 PROC
PUSH RBP
MOV RBP, RSP
SUB RSP, 40 ; Allocate space on the stack (8 for alignment and 32 for shadow space); Below of MOV RBP, RSP, this instruction already saved RSP to RBP.
LEA RCX, TXT_F1
CALL puts
LEAVE
ADD RSP, 40 ; Cleanup the stack... ; Not needed. The LEAVE instruction did it.
RET
F1 ENDP
Reply With Quote
The Following User Says Thank You to vic4key For This Useful Post:
niculaita (07-21-2018)
  #18  
Old 07-21-2018, 00:33
Insid3Code's Avatar
Insid3Code Insid3Code is offline
Family
 
Join Date: May 2013
Location: Algeria
Posts: 84
Rept. Given: 47
Rept. Rcvd 60 Times in 30 Posts
Thanks Given: 24
Thanks Rcvd at 108 Times in 56 Posts
Insid3Code Reputation: 60
Hi Vic,
Are you already tested your snippets ?
Attached, both snippets (allocate/align) and binaries (one crash the other works fine)

I don't know if you can download the attachment from this topic, here external link:
PHP Code:
http://www.mediafire.com/file/s9dd88iel47s7h8/poc.rar 
Compiled and tested (MSVC 2017 15.7.3)
Attached Files
File Type: rar poc.rar (2.3 KB, 5 views)
__________________
Computer Forensics
Reply With Quote
The Following 3 Users Say Thank You to Insid3Code For This Useful Post:
Agmcz (07-22-2018), niculaita (07-21-2018), vic4key (07-21-2018)
  #19  
Old 07-21-2018, 05:05
ionioni ionioni is offline
Friend
 
Join Date: Jul 2016
Posts: 80
Rept. Given: 8
Rept. Rcvd 3 Times in 3 Posts
Thanks Given: 92
Thanks Rcvd at 154 Times in 49 Posts
ionioni Reputation: 3
Quote:
Originally Posted by vic4key View Post
ADD RSP, 40 ; Cleanup the stack... ; Not needed. The LEAVE instruction did it.
Quote:
Originally Posted by Insid3Code View Post
Hi Vic,
Are you already tested your snippets ?
Attached, both snippets (allocate/align) and binaries (one crash the other works fine)

I don't know if you can download the attachment from this topic, here external link:
PHP Code:
http://www.mediafire.com/file/s9dd88iel47s7h8/poc.rar 
Compiled and tested (MSVC 2017 15.7.3)
leave is short for
mov rsp, rbp
pop rbp

lose "add rsp, ..."
Reply With Quote
The Following 2 Users Say Thank You to ionioni For This Useful Post:
niculaita (07-21-2018), vic4key (07-21-2018)
  #20  
Old 07-21-2018, 06:51
chants chants is online now
VIP
 
Join Date: Jul 2016
Posts: 725
Rept. Given: 35
Rept. Rcvd 48 Times in 30 Posts
Thanks Given: 666
Thanks Rcvd at 1,050 Times in 475 Posts
chants Reputation: 48
This discussion is majorly lacking a hugely important point:
Calling convention in x64 always uses the RCX, RDX, R8, R9 registers for passing the first 4 arguments (anything up to 64 bit values or pointers), while additionally to those 4 registers, RAX, R10 and R11 are considered volatile. The return value is in the RAX or possibly for a 128-bit return value would be in the RAX:RDX.

This is opposed to x86 where the prior scheme is closest to fastcall which used the ECX and EDX for argument passing before resorting to the stack with additionally the EAX volatile. However in cdecl (caller clean-up stack) calling convention, arguments are all passed on the stack, EAX, ECX and EDX are considered volatile, and the return value in EAX or EAX:EDX. syscall is the same except without the 3 registers being considered volatile. stdcall is also almost the same except the callee cleans up the stack.

If mixing C with external asm, it would be extremely wise to be familiar with all these details.

For more details which are too lengthly to include, refer to:
Quote:
https://en.wikipedia.org/wiki/X86_calling_conventions
Reply With Quote
The Following 2 Users Say Thank You to chants For This Useful Post:
niculaita (07-21-2018), vic4key (07-21-2018)
  #21  
Old 07-21-2018, 07:01
chants chants is online now
VIP
 
Join Date: Jul 2016
Posts: 725
Rept. Given: 35
Rept. Rcvd 48 Times in 30 Posts
Thanks Given: 666
Thanks Rcvd at 1,050 Times in 475 Posts
chants Reputation: 48
Microsoft x64 calling convention

Quote:
Stack aligned on 16 bytes. 32 bytes shadow space on stack.
Therefore code given here is all non-standards compliant with arbitrary calling convention (compiler will have return address of 8 bytes so an extra 8 indeed is needed but if called from assembler directly, etc assumption may not hold). If not calling back into C code which has been externed for use by the asm code (like puts is for sure), this should obviously not be necessary - neither alignment or shadow space.

PHP Code:
  SUB RSP32 Allocate space on the stack 32 for shadow space
  
AND RSP, -16 Align on 16 bytes

  LEAVE 
That pattern is needed for both F1 and F2 and its straightforward.

Last edited by chants; 07-22-2018 at 01:08.
Reply With Quote
The Following 2 Users Say Thank You to chants For This Useful Post:
niculaita (07-21-2018), vic4key (07-21-2018)
  #22  
Old 07-21-2018, 12:57
vic4key vic4key is offline
Family
 
Join Date: Apr 2010
Posts: 57
Rept. Given: 5
Rept. Rcvd 24 Times in 10 Posts
Thanks Given: 60
Thanks Rcvd at 94 Times in 21 Posts
vic4key Reputation: 24
Yes, right. In x64 arch, we always need to allocate the space for which called "shadow space". So, the above code should be:

Code:
F1 PROC
  PUSH RBP
  MOV RBP, RSP
  SUB RSP, 0x30 ; Just need to add this instruction.
  LEA RCX, TXT_F1
  CALL puts
  LEAVE
  RET
F1 ENDP
Thank you, guys.

Last edited by vic4key; 07-23-2018 at 00:39.
Reply With Quote
The Following User Says Thank You to vic4key For This Useful Post:
niculaita (07-21-2018)
  #23  
Old 07-21-2018, 14:39
chants chants is online now
VIP
 
Join Date: Jul 2016
Posts: 725
Rept. Given: 35
Rept. Rcvd 48 Times in 30 Posts
Thanks Given: 666
Thanks Rcvd at 1,050 Times in 475 Posts
chants Reputation: 48
It should be:

Code:
F1 PROC
  PUSH RBP
  MOV RBP, RSP
  SUB RSP, 32 ; Allocate space on the stack 32 for shadow space 
  AND RSP, -16 ; Align on 16 bytes
  LEA RCX, TXT_F1
  CALL puts
  LEAVE
  RET
F1 ENDP
Reply With Quote
The Following 2 Users Say Thank You to chants For This Useful Post:
niculaita (07-21-2018), vic4key (07-21-2018)
  #24  
Old 07-21-2018, 16:25
gigaman gigaman is offline
Friend
 
Join Date: Jun 2002
Posts: 87
Rept. Given: 0
Rept. Rcvd 3 Times in 2 Posts
Thanks Given: 0
Thanks Rcvd at 14 Times in 11 Posts
gigaman Reputation: 4
You normally don't align stack like that.
You know that the caller has (according to the calling convention) taken care of its stack alignment and therefore the RSP on entry ends by 8 (the stack was 16B aligned before and then the return address has been pushed there by the CALL).
So the initial PUSH RBP has aligned the stack to 16B again, SUB RSP, 32 didn't break the alignment - and the AND instruction is useless, RSP is already aligned there.
Reply With Quote
The Following 2 Users Say Thank You to gigaman For This Useful Post:
niculaita (07-21-2018), vic4key (07-21-2018)
  #25  
Old 07-21-2018, 18:09
Mahmoudnia's Avatar
Mahmoudnia Mahmoudnia is offline
Family
 
Join Date: Nov 2012
Posts: 228
Rept. Given: 64
Rept. Rcvd 142 Times in 49 Posts
Thanks Given: 198
Thanks Rcvd at 282 Times in 97 Posts
Mahmoudnia Reputation: 100-199 Mahmoudnia Reputation: 100-199
I have to say thank you to all of you guys thank you for your solutions I learned a lot of things.
Reply With Quote
  #26  
Old 07-22-2018, 01:04
chants chants is online now
VIP
 
Join Date: Jul 2016
Posts: 725
Rept. Given: 35
Rept. Rcvd 48 Times in 30 Posts
Thanks Given: 666
Thanks Rcvd at 1,050 Times in 475 Posts
chants Reputation: 48
Quote:
Originally Posted by gigaman View Post
You normally don't align stack like that.
You know that the caller has (according to the calling convention) taken care of its stack alignment.
If your asm function is designed to be called from C only then yes I suppose that is a fair assumption. But in fact if it is called from asm including your own or I suppose unknown callers, then it is a false assumption. And this code is known.

The extra 8 bytes comes from having called your own function within proper convention asm already or the return address in case of Windows ABI invocation. CALL F1 in an improperly aligned routine of course adds 8 bytes to the stack and then adding 8 again would misalign it (hence the code examples leaked out there and above which show 40 byte assuming misalignment by an internal call already from ASM despite not having this in examples). The safest assumption is to assume any caller, and realign the stack with an AND RSP, -16 or even to just do it on just the lower 32-bit ESP.

Linux has the same issue even with 32-bit code for late GCC versions as seen in this discussion: Calling printf in extended inline ASM
Quote:
https://stackoverflow.com/questions/37502841/calling-printf-in-extended-inline-asm/37503773
Even better here is a book on the issue for more in depth detail though unfortunately not listing the generic solution and instead letting you make assumptions or track things:
Quote:
https://github.com/simon-whitehead/assembly-fun/tree/master/windows-x64
Quote:
As with the AMD64/SystemV ABI, the Windows ABI dictates that the stack should be aligned on a 16-byte boundary. What this means is that, at the conclusion of the prologue of a function, the memory address that rsp points to should be aligned on a memory address that is a multiple of 16.
The simple act of calling a function misaligns the stack by placing an 8 byte return address on the stack when entering a function.
...
The 64-bit Windows ABI specifies that every single non-leaf function must allocate 32 bytes of stack space for "register spill". This is commonly referred to as "Shadow Space" and must be adjacent to the return address to the previous function. The ABI states that it is the callers job to allocate this stack space, and not the callee. The stack must also always be 16 byte aligned, which can be confusing because on entry to a function the last entry in the stack is the return address of the preview function - which is already 8 bytes. Therefore, for a function to allocate 32 bytes of "Shadow Space" and keep the stack aligned, it must allocate 40 bytes (40 + 8 = 48, which is a multiple of 16).

Last edited by chants; 07-22-2018 at 02:26.
Reply With Quote
The Following User Gave Reputation+1 to chants For This Useful Post:
niculaita (07-22-2018)
The Following User Says Thank You to chants For This Useful Post:
niculaita (07-22-2018)
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
inline patche hp3 Source Code 3 06-04-2021 14:48
X64 inline asm Fyyre x64 OS 48 08-10-2014 16:50
Inline Patching MaRKuS-DJM General Discussion 1 01-24-2004 23:03


All times are GMT +8. The time now is 17:42.


Always Your Best Friend: Aaron, JMI, ahmadmansoor, ZeNiX, chessgod101
( 1998 - 2024 )