x86 assembly - GetStdHandle & WriteConsole - winapi

In response to my question about Windows API's, I have successfully gotten it to work. My question is in regards to this code:
push STD_OUTPUT_HANDLE
call GetStdHandle
push NULL
push offset other
push mlen
push offset msg
push eax
call WriteConsole
push 0
call ExitProcess
This code is supposed to print the value of msg. Why does one need to do:
a)
push STD_OUTPUT_HANDLE
call GetStdHandle
push NULL
And:
b)
push offset other
push mlen
push offset msg
push eax
I am just wondering what the need is for getting a StdHandle and pushing offsets.
Thanks in advance,
Progrmr

Look at the definition of WriteConsole. The NULL is the last argument of the function, the lpReserved argument. Arguments are pushed in right-to-left order. The first function argument is the console handle, the one you got from GetStdHandle and you pass by pushing eax.
So properly commenting the assembly code:
push STD_OUTPUT_HANDLE ; GetStdHandle nStdHandle argument
call GetStdHandle ; eax = Console handle
push NULL ; lpReserved = null
push offset other ; lpNumberOfCharsWritten = pointer to "other"
push mlen ; nNumberOfCharsToWrite = length of "msg"
push offset msg ; lpBuffer = pointer to "msg"
push eax ; hConsoleOutput = console handle from GetStdHandle
call WriteConsole ; Write string
push 0 ; exit code = 0
call ExitProcess ; terminate program

Related

masm32 ReadFile Function x86 -Windows

I've been trying to read the string written inside a .txt file and print it out on the console. But it seems I'm not doing it right. Can someone review my codes and tell me what's wrong? Thanks!
include \masm32\include\masm32rt.inc
.data
txtFilter db "*.txt",0
txtFD WIN32_FIND_DATA <>
txtHandle HANDLE ?
fHandle HANDLE ?
bufferLength db ?
buffer db 5000 dup(?)
lnt db "1024",0
okay db "Okay!",0
dokay db "Dokay!",0
.code
start:
push offset txtFD
push offset txtFilter
call FindFirstFile
mov txtHandle, eax
push offset txtFD.cFileName
call StdOut
push 0
push FILE_ATTRIBUTE_NORMAL
push OPEN_EXISTING
push 0
push 0
push FILE_APPEND_DATA
push offset txtFD.cFileName
call CreateFile
.if eax == INVALID_HANDLE_VALUE
jmp _error
.else
mov fHandle, eax
.endif
push 0
push offset bufferLength
push offset lnt
push offset buffer
push fHandle
call ReadFile
jmp _next
_error:
push offset dokay
call StdOut
jmp _next
_okay:
push offset okay
call StdOut
_next:
push offset buffer
call StdOut
push fHandle
call CloseHandle
push txtHandle
call FindClose
push 0
call ExitProcess
end start
The code can't seem to read what is inside my txt file. However I can successfully search my txt file and perform the function CreateFile
Four issues:
bufferLength db ? reserves only one byte. ReadFile will store there a DWORD and overwrite three bytes of buffer. If there is a NULL, StdOut will stop the output. Change the definition to bufferLength dd ?
lnt db "1024",0 is a string. ReadFile expects a DWORD value. Change it to lnt dd 1024.
push FILE_APPEND_DATA creates a handle only for writing. Change it to push GENERIC_READ.
push offset lnt passes a pointer. However, ReadFile expects a DWORD value. Change it to push lnt.
Like that:
include \masm32\include\masm32rt.inc
.data
txtFilter db "*.txt",0
txtFD WIN32_FIND_DATA <>
txtHandle HANDLE ?
fHandle HANDLE ?
; bufferLength db ?
bufferLength dd ?
buffer db 5000 dup(?)
; lnt db "1024",0
lnt dd 1024
okay db "Okay!",0
dokay db "Dokay!",0
.code
start:
push offset txtFD
push offset txtFilter
call FindFirstFile
mov txtHandle, eax
push offset txtFD.cFileName
call StdOut
; https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx
push 0 ; HANDLE hTemplateFile
push FILE_ATTRIBUTE_NORMAL ; DWORD dwFlagsAndAttributes
push OPEN_EXISTING ; DWORD dwCreationDisposition
push 0 ; LPSECURITY_ATTRIBUTES lpSecurityAttributes
push 0 ; DWORD dwShareMode
; push FILE_APPEND_DATA ; DWORD dwDesiredAccess
push GENERIC_READ ; DWORD dwDesiredAccess
push offset txtFD.cFileName ; LPCTSTR lpFileName,
call CreateFile
.if eax == INVALID_HANDLE_VALUE
jmp _error
.else
mov fHandle, eax
.endif
; https://msdn.microsoft.com/en-us/library/windows/desktop/aa365467(v=vs.85).aspx
push 0 ; LPOVERLAPPED lpOverlapped
push offset bufferLength ; LPDWORD lpNumberOfBytesRead
; push offset lnt ; DWORD nNumberOfBytesToRead
push lnt ; DWORD nNumberOfBytesToRead
push offset buffer ; LPVOID lpBuffer
push fHandle ; HANDLE hFile
call ReadFile
jmp _next
_error:
push offset dokay
call StdOut
jmp _next
_okay:
push offset okay
call StdOut
_next:
push offset buffer
call StdOut
push fHandle
call CloseHandle
push txtHandle
call FindClose
push 0
call ExitProcess
end st

How to properly use PUSH and POP

I have a code that has 3 procedures, one to get an input from the user, one to display a multiplication result, and lastly one for an error message. I am trying to implement the PUSH and POP operations and get my code in to the stack. It will seem long but it makes sense to me, here it is...
.data
line BYTE "The answer is ",0
line2 BYTE "Enter a number",0
kline3 BYTE Wrong.",0
int SWORD ?
.code
Val PROC
call ReadInt
mov int,edx
cmp int, 10000
jl 1
jmp end
L1: cmp intVal1, -10000
jg 2
call error
jmp end
2: ret
Val ENDP
main PROC
call Val
call Val
imul val, val
exit
main ENDP
END main
All this simply does it call to get 2 inputs twice and then call to display the the multiplied result. My question is how do you implement push and pop in to here to have it all make sense?
I would assume that you need to push in the GetValue procedure to put in input in to the stack and then pop it after each call in the main procedure and maybe do the same with the display procedure?
I am just struggling to figure it out so any help would be great!
PS. This code is an asm file in visual studio 2010
Your first call to GetValue stores its result in intVal. But then your second call to GetValue also stores its result in intVal, so the first result is forever lost.
Your MultiplyAndDisplay function expects one of the operands in intVal, and the other operand in eax. So, what you need to do is push [intVal] after the first call to GetValue, and pop eax after the second call to GetValue.
Note that the square brackets in push [intVal] are in some notation that actually makes sense, but if I remember correctly the microsoft assembler does not support that notation which actually makes sense, so you might have to code push intVal instead, or push dword ptr intVal, or something nonsensical like that to get it to work.
Because your question is tagged MASM, this is a MASM answer:
Your code can be restructured in a way that uses the MASM directive PROC with parameters and the INVOKE directive for parameter passing:
MultiplyAndDisplay PROC val1: SDWORD, val2: SDWORD
mov eax, val1
imul eax, val2 ; signed multiply of val1 by val2
mov edx, OFFSET prompt
call WriteString ; Writes the prompt in edx
call WriteDec ; Writes the value in eax
ret
MultiplyAndDisplay ENDP
main PROC
call GetValue
push [intVal] ; PUSH firstParam to the stack
call GetValue
pop eax ; POP previous param/intVal to EAX
invoke MultiplyAndDisplay, eax, intVal ; MultiplyAndDisplay, firstParam(EAX), secondParam(intVal)
exit
main ENDP

Print hexa value in masm

I do a MapViewOfFile to get a pointer on the begin of my file, after that I want to print the value of it in hexa.
When I print it as string I get "MZ" which is the good value (the magic number) but I want it in hexa (5A4D).
I tried to format with %x in wsprintf but it doesn't work, I got 230000 as value..
EDIT the tried for %x:
.data
header_format db "The header is: %x",0
buffer db 256 dup(?) ; File data
.data?
pMemory DWORD ? ; Pointer to the data in the source file
getData:
;pMemory is the ptr which is correctly printed with %s
invoke wsprintf, ADDR buffer, ADDR header_format, [pMemory] ;
invoke MessageBox, NULL, Addr buffer, Addr header_test, MB_OK
Have you any suggestions ?
Thanks.
It finally works by using this solution :
push STD_OUTPUT_HANDLE
call GetStdHandle
mov eax, pMemory
push eax
print right$(uhex$(eax),2),13,10
pop eax
mov eax, pMemory
push eax
print right$(uhex$([eax]),2),13,10
pop eax

Assembly : Dealing with user input in windows nasm

I'm a newbie to asm and trying to make a simple hello world which awaits for the user to press a key to end. For now the hello world is all good, but the .exe console program i got from this just close instantly while i want it to stay on screen untill the user press a key.
Now the problem i have is that for some reason, the program keep looping, searching for user input, but when i force close the program (^C) i can see all the keys i pressed are written on the next console line, like if it was using the wrong buffer (?)
I've been searching a fix all over the internet for a few days and finally I'm asking for help cuz this is driving me crazy ^^
Everything i found is mostly based on int system or under linux, while i have to deal with the windows api...
Thank you very much, any help or hint is welcome!
Code :
STD_OUTPUT_HANDLE equ -11
STD_INPUT_HANDLE equ -10
NULL equ 0
global start
extern ExitProcess, GetStdHandle, WriteConsoleA, ReadConsoleInputA
section .data
msg db "Hello World!", 13, 10, 0
msg.len equ $ - msg
consoleInHandle dd 1
section .bss
buffer resd 2
buffer2 resd 2
section .text
start:
push STD_OUTPUT_HANDLE
call GetStdHandle
push NULL
push buffer
push msg.len
push msg
push eax
call WriteConsoleA
read:
push STD_INPUT_HANDLE
call GetStdHandle
mov [consoleInHandle],eax
push consoleInHandle
push dword[buffer2]
push 1
push NULL
call ReadConsoleInputA
cmp eax,1
jge exit
jmp read
exit:
push NULL
call ExitProcess
Moar info about windows functions can be found here:
ReadConsoleInput
WriteConsole
push consoleInHandle pushes the address, not the handle. You want push dword [consoleInHandle]. Conversely, for the buffer you want to pass the address, so you need push buffer2 there. Also, this buffer should be the size of an INPUT_RECORD structure, which I believe is 32 bytes.
Update: As Frank commented, the argument order was also wrong.
This code works for me (note I had to add the #xx stdcall decorations due to how my environment is set up - apparently you don't need those):
STD_OUTPUT_HANDLE equ -11
STD_INPUT_HANDLE equ -10
NULL equ 0
global start
extern ExitProcess#4, GetStdHandle#4, WriteConsoleA#20, ReadConsoleInputA#16
section .data
msg db "Hello World!", 13, 10, 0
msg.len equ $ - msg
consoleInHandle dd 1
section .bss
buffer resd 2
buffer2 resb 32
section .text
start:
push STD_OUTPUT_HANDLE
call GetStdHandle#4
push NULL
push buffer
push msg.len
push msg
push eax
call WriteConsoleA#20
read:
push STD_INPUT_HANDLE
call GetStdHandle#4
mov [consoleInHandle],eax
push NULL
push 1
push buffer2
push dword [consoleInHandle]
call ReadConsoleInputA#16
exit:
push NULL
call ExitProcess#4

Trouble with CommandLineToArgvW Windows Function in Assembly

I am trying just to print out the value of argc using the CommandLineToArgvW Window's API function in NASM. The following is what I have:
extern _ExitProcess#4
extern _GetCommandLineA#0
extern _CommandLineToArgvW#8
extern printf
global _start
section .code
Format:
db "%d",10,0
FormatS:
db "%s",10,0
_start:
push ebp
mov ebp, esp
sub esp, 4 ; Create empty space for ArgC
call _GetCommandLineA#0
push eax; Push value beneath ArgC
mov ebx, ebp ; Set ebx to ebp
sub ebx, 4
push dword ebx ; pushes ArgC address onto stack
push dword [ebp - 8] ; pushes pointer to Command Line String
call _CommandLineToArgvW#8
push dword [ebp - 4]
push Format
call printf
push dword 0
call _ExitProcess#4
No matter what I do, the value for argc is 1. What am I doing wrong?
I assemble and link with these commands:
nasm -fwin32 FunctionTests.asm
golink FunctionTests.obj kernel32.dll msvcrt.dll shell32.dll /console /entry _start
FunctionTests.exe hi asdf asdf asdf asdf
As you can see, from the last line, argc should be 6.
Change _GetCommandLineA to _GetCommandLine*W* CommandLineToArgv expects a pointer to a UNICODE string.
MASM but just about the same:
start:
push ebp
mov ebp, esp
sub esp, 4
call GetCommandLineW
lea ecx, dword ptr[ebp - 4] ; need the address of local
push ecx ; address of local
push eax ; pointer to unicode string
call CommandLineToArgvW
push dword ptr [ebp - 4] ; value of local
push offset Format
call crt_printf
add esp, 8
; this is all? Then we don't have to restore stack.
push 0
call ExitProcess
end start
and this is the output:
D:\Projects>ConTest.exe boo boo I see you
6
D:\Projects>
Set a breakpoint just before you call CommandLineToArgvW and inspect the parameters you're about to pass. Observe that the first parameter you are passing is not a pointer to a string. It is a pointer to a pointer to a string.
You need to use GetCommandLineW rather than GetCommandLineA.
You are using CommandLineToArgvW with an ANSI string, use GetCommandLineW to get the command line in unicode.
You are also not dereferencing the pointer to the command line:
push ebx ; pushes ArgC address onto stack

Resources