x64 calling createthread from asm - windows

push 0 //tid
push 0 //flag
sub rsp, 20
mov r9,0 //parameter
mov rcx,0 //security attribute
mov rdx, 0 //stacksize
mov r8,threadmem //address
call kernel32.createthread
I'm calling createthread in this way.
But if I put any address in parameter, my code doesn't work.
Just making my PC lag and nothing happens, seems like thread is created but my code isn't executed.
However, if I don't put parameter and leave itself for 0 it works.
Can anyone help me?

You are not strictly following the x64 calling convention. Push and sub rsp may only occur in the prolog.
Windows disassembles your code and unreachable code can still hang because of it. I had to give up altogether.

Related

FASM assembly program waits before exiting

This is the code that I use with FASM:
format PE console
entry main
include '..\MACRO\import32.inc'
section '.data' data readable writeable
msg db "привіт!",0dh,0ah,0 ;hi
lcl_set db ?
section '.code' code readable executable
main:
;fail without set locale
push msg
call [printf]
pop ecx
;succeed with set locale
push msg
call _liapnuty
pop ecx
push 0
call [ExitProcess]
_liapnuty:
push ebp
mov ebp, esp
;sub esp, 0
mov ebx,[ebp+8] ; 1st arg addr
mov al, [lcl_set]
or al, al
jnz _liapnuty_rest
call __set_locale
_liapnuty_rest:
push ebx
call [printf]
pop ebx
mov esp, ebp
pop ebp
ret 0
__set_locale:
mov al, [lcl_set]
or al, al
jnz __set_locale_rest
push 1251
call SetConsoleCP
call SetConsoleOutputCP
pop ecx
mov [lcl_set], 1
;push lcl
;call [system]
; pop ecx
; mov [lcl_set], 1
;push cls
;call [printf]
; pop ecx
__set_locale_rest:
ret 0
section '.idata' import data readable
library kernel,'kernel32.dll',\
msvcrt,'msvcrt.dll'
import kernel,\
SetConsoleCP,'SetConsoleCP',\
SetConsoleOutputCP,'SetConsoleOutputCP',\
ExitProcess,'ExitProcess'
import msvcrt,\
printf,'printf'
It works almost perfectly, except that before exiting it waits for like a second for some reason. It outputs data almost instantly, yet it fails to shut down quickly. If the reason is using these libraries or not clearing the stack after calling ExitProcess (which obviously can't be done), then let me know and I will mostly gladly accept this answer, but I want to be 100% sure I'm doing everything correctly.
The reason for all of it was because kernel32 functions pop their parameters themselves on return. If I remove unnecessary pops it starts working fast again. Of course, the program still runs with damaged stack but it does a lot of damage control at the end. That's why it was slow, but still worked. For everyone facing this issue, make sure to be careful with the calling convention.
To debug the application and find the error I used OLLYDBG. It's free and it works. It helps you debug EXEs and DLLs, allowing to step one command at a time. Also it shows the memory, the stack and all of the registers and flags.
Using the stack I was able to find out that it gets corrupted.

Direction Flag DF in the Windows 64-bit calling convention?

According to the docs I can find on calling windows functions, the following applies:-
The Microsoft x64 calling convention[12][13] is followed on Windows
and pre-boot UEFI (for long mode on x86-64). It uses registers RCX,
RDX, R8, R9 for the first four integer or pointer arguments (in that
order), and additional arguments are pushed onto the stack (right to
left). Integer return values (similar to x86) are returned in RAX if
64 bits or less.
In the Microsoft x64 calling convention, it's the caller's
responsibility to allocate 32 bytes of "shadow space" on the stack
right before calling the function (regardless of the actual number of
parameters used), and to pop the stack after the call. The shadow
space is used to spill RCX, RDX, R8, and R9,[14] but must be made
available to all functions, even those with fewer than four
parameters.
The registers RAX, RCX, RDX, R8, R9, R10, R11 are considered volatile
(caller-saved).[15]
The registers RBX, RBP, RDI, RSI, RSP, R12, R13, R14, and R15 are
considered nonvolatile (callee-saved).[15]
So, I have been happily calling kernel32 until a call to GetEnvironmentVariableA failed under certain circumstances. I finally traced it back to the fact that the direction flag DF was set and I needed to clear it.
I have not up till now been able to find any mention of this and wondered if it was prudent to always clear it before a call.
Or maybe that would cause other problems. Anyone aware of the conventions of calling in this instance?
Windows assumes that the direction flag is cleared. Despite in article said about C run-time only, this is true for whole windows (I think because windows code itself is primarily written in c/c++). So when your programme begins to execute - you can assume that DF is 0. Usually you do not need to change this flag. However if you temporarily change it (set it to 1) in some internal routine you must clear it by cld before calling any windows API or any external module (because it assumes that DF is 0).
All windows interrupts at very beginning of execution clear DF to 0 - so it is safe to temporarily set DF to 1 in own internal code, main - before any external call reset it back to 0.

Register ESI causes RunTime-Check Failure #0 error

I've spend lot of time trying to solve this problem and I don't understand, why it doesn't work. Problem's description is in comments below:
.386
.MODEL FLAT, STDCALL
OPTION CASEMAP:NONE
.NOLIST
.NOCREF
INCLUDE \masm32\include\windows.inc
.LIST
.CODE
DllEntry PROC hInstDLL:HINSTANCE, reason:DWORD, reserved1:DWORD
mov eax, TRUE
ret
DllEntry ENDP
caesarAsm proc string: DWORD, key: DWORD, stringLength : DWORD
mov esi, 1 ; I cannot use this register, mov esi, (anything) causes Crash:
; Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention
mov eax, string
ret
caesarAsm endp
END DllEntry
I searched "whole" Internet, I found that the problem is connected with stack, but no operation on stacks helped me to solve it.
I'm using Microsoft Visual Studio 2012
I assume the error does not occur in this function, rather, it is triggered elsewhere. The esi register is a callee-saved register. You must make sure its value is the same at function exit as it was at entry. You can use it in your function, but you must save and restore its value. Such as:
push esi
mov esi, 1
mov eax, string
pop esi
ret
This is all well documented. You may only use eax, ecx and edx without saving.
Side note: you are using high-level features of your assembler, you might want to check the actual generated code or refrain from using them until you are confident in what the result is going to be. Incidentally masm has a USES keyword which would do the save/restore for you.

Having problems with GdiGradientFill in FASM

I'm trying to write an ASM version of a Java app I developed recently, as a project in Win32 ASM, but as the title states, I'm having problems with GdiGradientFill; I'd prefer, for the moment, to use FASM, and avoid higher level ASM constructs, such as INVOKE and the use of the WIN32 includes.
What I have, atm:
PUSH [hWnd]
CALL [User32.GetWindowDC]
MOV [hDC], EAX
PUSH rectClient
PUSH [hWnd]
CALL [User32.GetClientRect]
PUSH [rectClient.left]
POP [colorOne.xPos]
PUSH [rectClient.top]
POP [colorOne.yPos]
MOV [colorOne.red], 0xC000
MOV [colorOne.green], 0xC000
MOV [colorOne.blue], 0xC000
MOV [colorOne.alpha], 0x0000
PUSH [rectClient.right]
POP [colorTwo.xPos]
PUSH [rectClient.bottom]
POP [colorTwo.yPos]
MOV [colorTwo.red], 0x0000
MOV [colorTwo.green], 0x2800
MOV [colorTwo.blue], 0x7700
MOV [colorTwo.alpha], 0x0C00
MOV [gRect.UpperLeft], 0
MOV [gRect.LowerRight], 1
PUSH GRADIENT_FILL_RECT_H
PUSH 1
PUSH gRect
PUSH 2
PUSH colorOne
PUSH [hDC]
CALL [GDI32.GdiGradientFill]
However, the code returns only a FALSE, and after going through both MSDN
(http://msdn.microsoft.com/en-us/library/windows/desktop/dd373585(v=vs.85).aspx)
and some other examples (http://www.asmcommunity.net/board/index.php?topic=4100.0), I still can't see what I am doing wrong, can anyone see the flaw here?
An additional problem has been with my attempts to use Msimg32's GradientFill, as this always leads to a crash, however, I have seen some reports that Win2K+ OS's simply pass the parameters from Msimg32 to GDI32; is this accurate, or has anyone else experienced problems with this form?
Pastebin link for whole code: http://pastebin.com/GEHDw6Qe
Thanks for any help, SS
EDIT:
Code is now working, honestly, I have no idea what has changed, I can't see anything different between the previous and now working data, other than changing the PUSH / POP sequence to MOV EAX, [rectClient.left], ect (The PUSH / POP method works, also) - Many thanks to those who offered assistance!
You're passing what looks like a RECT as the 4th parameter to GdiGradientFill. The function expects a GRADIENT_TRIANGLE.
Also, PUSH/POP is a very weird way to copy from one memory location to another. You're doing 4 memory accesses instead of two. Copy via a register; this is not Java.
Are you sure GetWindowDC is what you need? That one returns the DC for the whole window, title and border and all. For just the client area, people normally use GetDC(). When done, call ReleaseDC().

Endless loop with assember

OK, I'm new to PC Assembler. I"m trying to write an program, but it won't stop looping. I'm guessing the ECX register is being modified? How can I fix this? Thanks.
DATA SECTION
;
KEEP DD 0 ;temporary place to keep things
;
CODE SECTION
;
START:
MOV ECX,12
TOPOFLOOP:
PUSH -11 ;STD_OUTPUT_HANDLE
CALL GetStdHandle ;get, in eax, handle to active screen buffer
PUSH 0,ADDR KEEP ;KEEP receives output from API
PUSH 5,'bruce' ;5=length of string
PUSH EAX ;handle to active screen buffer
CALL WriteFile
XOR EAX,EAX ;return eax=0 as preferred by Windows
LOOP TOPOFLOOP
ENDLABEL:
RET
In most x86 calling convention, including the stdcall convention used by Windows API functions, ECX is a caller-save register -- the called function is not required to make sure the value of the register is the same when it returns as when it was called. You have to save it somewhere safe in your own code.

Resources