-1

I tried to use

mov rdx, 4
push rdx
mov rsi, temp_str
push rsi
mov rdi, temp_str1
push rdi
call memmove

and

sub rsp, 24
mov [rsp + 16], rdx
mov [rsp + 8], rsi
mov [rsp], rdi
call memmove
add rsp, 24

and other kinds of magic, but nothing works. Which spell do the job?

(temp_str and temp_str1 defined as

temp_str db "abc", 0
temp_str1 db "def", 0

, memmove is from msvcrt)

EDIT:

sub rsp, 32
mov rcx, temp_str1
mov rdx, temp_str
mov r8, 4
call memmove

also crashes.

EDIT 2: Full code:

format PE64 console
entry prog

include "win64ax.inc"

section '.idata' import data readable writeable

library kernel32, 'kernel32.dll', msvcrt, 'msvcrt.dll'

import kernel32, ExitProcess,'ExitProcess'
import msvcrt, memmove, 'memmove'

section '.text' code readable executable

prog:

;;mov rdx, 4
;;push rdx
;;mov rsi, temp_str
;;push rsi
;;mov rdi, temp_str1
;;push rdi
;;call memmove


;;sub   rsp, 24
;;mov   [rsp + 16], rdx
;;mov   [rsp + 8], rsi
;;mov   [rsp], rdi
;;call memmove
;;add rsp, 24


;;push rbp
;;mov rbp, rsp
;;push rdx
;;push rsi
;;push rdi
;;call memmove
;;mov rsp, rbp
;;pop rbp


sub rsp, 32
mov rcx, temp_str1
mov rdx, temp_str
mov r8, 3
call memmove         ; crash
add rsp, 32

end_prog:
    invoke ExitProcess, 0

section '.data' data readable writeable
    temp_str db "abc", 0
    temp_str1 db "def", 0
DSblizzard
  • 4,007
  • 7
  • 48
  • 76
  • 2
    You seem to be confusing the sysv abi with the microsoft one. See the [documentation](https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention). TL;DR: allocate 32 bytes of shadow space and pass arguments in `rcx`, `rdx` and `r8`. Also, if you are using assembly it's really pointless to call `memmove` especially if you know your ranges don't overlap. – Jester Nov 18 '19 at 13:34
  • Also not working (see Edit). And why memmove is pointless? – DSblizzard Nov 18 '19 at 13:44
  • 1
    @Jester actually it's not that pointless. Simple `rep movs` may not be the optimal solution, even with non-overlapping ranges. See e.g. [how `memmove`'s backward part is implemented in glibc](https://code.woboq.org/userspace/glibc/sysdeps/x86_64/multiarch/memcpy-ssse3-back.S.html). – Ruslan Nov 18 '19 at 13:51
  • I recommend checking on the FASM forum too https://board.flatassembler.net as there might be a macro for it – Slai Nov 18 '19 at 13:52
  • 1
    Macro cinvoke has a bug, therefore I'm searching for direct method. – DSblizzard Nov 18 '19 at 13:54
  • Post [mcve] and use a debugger to pinpoint the crash. Also make sure your destination is in writable memory (code section isn't). Of course restore stack pointer afterwards. – Jester Nov 18 '19 at 14:00
  • @Jester: done (EDIT 2). – DSblizzard Nov 18 '19 at 14:07
  • Since your stack pointer isn't aligned to start with, change `sub rsp, 32` to `sub rsp, 40`. – Jester Nov 18 '19 at 14:14
  • @Jester: Also not working. – DSblizzard Nov 18 '19 at 14:18

2 Answers2

2

For whatever reason my fasm can't assemble that but the equivalent nasm code works fine:

extern memmove
extern puts
extern exit

section .text
global WinMain
WinMain:
push rbp
mov rbp, rsp
sub rsp, 32
mov rcx, temp_str1
mov rdx, temp_str
mov r8, 4
call memmove
mov rcx, temp_str1
call puts
mov rsp, rbp
pop rbp
jmp exit

section .data
temp_str db "abc", 0
temp_str1 db "def", 0
Jester
  • 56,577
  • 4
  • 81
  • 125
0

User revolution on board.flatassembler.net suggested solution:

call memmove

must be

call [memmove]    
DSblizzard
  • 4,007
  • 7
  • 48
  • 76
  • Calls to DLL functions are normally done via indirect calls through a function pointer. Dynamic linking sets function pointers instead of fixing up `call rel32` offsets everywhere in the calling code. Apparently in Windows / FASM, the function symbol name ends up resolving to a pointer. But this answer doesn't cover the other bugs in the question: wrong calling convention. – Peter Cordes Nov 19 '19 at 05:01