I have this NASM code
extern GetStdHandle
extern WriteFile
extern AllocConsole
extern FreeConsole
extern SetConsoleTitleA
extern SetConsoleCursorPosition
extern Sleep
extern ExitProcess
extern ExitWindowsEx
import GetStdHandle kernel32.dll
import WriteFile kernel32.dll
import AllocConsole kernel32.dll
import FreeConsole kernel32.dll
import SetConsoleTitleA kernel32.dll
import SetConsoleCursorPosition kernel32.dll
import Sleep kernel32.dll
import ExitProcess kernel32.dll
import ExitWindowsEx user32.dll
.
section .text use32
..start:
call [ExitWindowsEx]
When I execute it, it doesn't perform the function which is turning off the computer. I read that it requires parameters but how exactly do we pass the parameters like this in C#
I assume you're using 32-bit Intel architecture. In this case you have to pass the arguments in the stack.
mov eax, 1
mov ebx, 0
push eax
push ebx
call [ExitWindowsEx]
Related
So I have some basic asm file that looks like the one below(print_eax is removed as it's large and unrelated to the question) and have been using this http://www.godevtool.com/ExceptFrame.htm as a source of information. But I'm unsure of how to get the EXCEPTION_POINTERS. I've tried popping from the stack, and using different registers in case it was passed through those, as well as various offsets from each of these, but honestly I'm at a loss and have been unable to find a solution through google. How do I get the EXCEPTION_POINTERS when we enter FINAL_HANDLER?
global _main
extern _GetStdHandle#4
extern _WriteFile#20
extern _ExitProcess#4
extern _SetUnhandledExceptionFilter#4
section .text
_main:
push FINAL_HANDLER
CALL _SetUnhandledExceptionFilter#4
;---Protected code---
mov eax, dword [0xffffffff] ;Force C0000005h exception
; ExitProcess(0)
push 0
call _ExitProcess#4
; never here
hlt
FINAL_HANDLER:
; get EXCEPTION_POINTERS
;????
; get EXCEPTION_RECORD(dword [EXCEPTION_POINTERS+0])
mov eax, dword [EXCEPTION_POINTERS]
; get ExceptionCode(dword [EXCEPTION_RECORD+0])
mov eax, dword [eax]
call print_eax ; a simple procedure that outputs eax in hex
; ExitProcess(1)
push 1
call _ExitProcess#4
I'm now programming some Windows native assembly, using NASM 2.12.01 and GCC 4.8.1 as a linker.
However, this simple HelloWorld program compiles & links without any complaints, but doesn't output anything to console screen.
It seems that GetStdHandle doesn't return a valid handle to a current console, so the output doesn't get shown up.
But problem might be some other.
Code:
; Name: hello.asm
; Assemble: nasm.exe -fwin32 hello.asm
; Link: gcc -mwindows -o hello hello.obj -lkernel32 -lmsvcrt
; Run: a.exe
BITS 32
extern _GetStdHandle#4
extern _WriteFile#20
extern _ExitProcess#4
extern __getch
extern _puts
SECTION .data
str: db `Hello world!\n` ; C-like strings in NASM with backticks
strlen equ $-str
pause: db "Do you know where the ANY key is? :-)",0
SECTION .text
GLOBAL _main
_main:
; Stack frame for NumberOfBytesWritten
push ebp
sub esp, 4
; http://msdn.microsoft.com/en-us/library/windows/desktop/ms683231.aspx
; HANDLE WINAPI GetStdHandle(
; _In_ DWORD nStdHandle
; );
push -11
call _GetStdHandle#4
; http://msdn.microsoft.com/en-us/library/windows/desktop/aa365747.aspx
; BOOL WINAPI WriteFile(
; _In_ HANDLE hFile,
; _In_ LPCVOID lpBuffer,
; _In_ DWORD nNumberOfBytesToWrite,
; _Out_opt_ LPDWORD lpNumberOfBytesWritten,
; _Inout_opt_ LPOVERLAPPED lpOverlapped
; );
push 0 ; lpOverlapped,
lea ebx, [ebp-4] ; EBX: address of NumberOfBytesWritten
push ebx ; lpNumberOfBytesWritten,
push strlen ; nNumberOfBytesToWrite
push str ; lpBuffer,
push eax ; hFile (result from GetStdHandle
call _WriteFile#20
; msvcrt.dll (C library)
push pause
call _puts ; http://msdn.microsoft.com/library/tf52y4t1.aspx
add esp, 4
call __getch ; http://msdn.microsoft.com/library/078sfkak.aspx
; ExitProcess (0)
push 0
call _ExitProcess#4
In order to generate a console application, you must use the -mconsole option to GCC. See the online documentation, section 3.18.55, x86 Windows Options.
You're using -mwindows which creates a GUI application. Windows does not create a console or set the standard handles when launching GUI applications.
You never set up the stack frame correctly!
This is not the proper way:
push ebp
sub esp, 4
Are you missing something? Your stack is messed up!
The prolouge should be :
push ebp
mov ebp, esp
sub esp, 4
For the epilouge, just reverse that.
Kernel.LIB file content
_ExitProcess#4, _GetStdHandle#4, _WriteConsoleA#20
For use this, I've tested to declare :
void WINAPI ExitProcess(unsigned int ExitCode);
HANDLE WINAPI GetStdHandle(DWORD nStdHandle);
bool WINAPI WriteConsole#20(HANDLE hConsoleOutput, const void *lpBuffer DWOR......)
But this not work. (undefined reference).
I've tested with "#n"
void WINAPI ExitProcess#4(unsigned int ExitCode);
HANDLE WINAPI GetStdHandle#4(DWORD nStdHandle);
bool WINAPI WriteConsole#20(HANDLE hConsoleOutput, const void *lpBuffer DWOR......)
But this syntax is not allowed.
I've found Linking to Kernel32.lib in assembler
This solution is good, but only for nasm so, my question is :
How do use this in C/C++ with G++/GCC ?
extern _ExitProcess#4, _GetStdHandle#4, _WriteConsoleA#20
%define ExitProcess _ExitProcess#4
%define GetStdHandle _GetStdHandle#4
%define WriteConsoleA _WriteConsoleA#20
Because " #4 #20 " was not allowed syntax in C/C++
Here's the code...
extern GetStdHandle
extern GetModuleFileNameW
extern WriteFile
extern ExitProcess
import GetStdHandle kernel32.dll
import GetModuleFileNameW kernel32.dll
import WriteFile kernel32.dll
import ExitProcess kernel32.dll
global ..start
segment .code USE32
..start:
push dword -11
call [GetStdHandle]
mov dword [hStdOut], eax
;Getting the filepath of exe on disk...
push dword 256 ;MAX_PATH
push dword [filepath] ;Pointer to the buffer
push dword 0 ;NULL
call [GetModuleFileNameW]
;Trying to output the filepath...
push dword 0
push dword nBytes
push dword 256 ;MAX_PATH
push dword filepath
push dword [hStdOut]
call [WriteFile]
xor eax, eax
push eax
call [ExitProcess]
segment .data
segment .bss
hStdOut resd 1
nBytes resd 1
filepath resd 32
I've played around with it a bit, and all I get is a blank output. I've also gotten a bunch of gibberish when I play around with it a bit. Still no file path, and still no joy. I have a hunch that I'm doing something wrong with GetModuleFileNameW, but I can't be sure. I followed the documentation on the Microsoft website, and I put the arguments in in the opposite order like you're supposed to in assembly language. What am I doing wrong?
;Getting the filepath of exe on disk...
push dword 256 ;MAX_PATH
push dword [filepath] ;Pointer to the buffer
push dword 0 ;NULL
call [GetModuleFileNameW]
... must be changed to...
;Getting the filepath of exe on disk...
push dword 256 ;MAX_PATH
push dword filepath ;Pointer to the buffer
push dword 0 ;NULL
call [GetModuleFileNameW]
I want to write a MASM program similar to the following C++ program :
#include <Windows.h>
#include <iostream>
typedef UINT (_stdcall *FuncPtr)(LPCSTR lpCmdLine, UINT uCmdShow);
int main(void)
{
HMODULE hDll = LoadLibrary(TEXT("Kernel32.dll"));
FuncPtr func_addr = reinterpret_cast<FuncPtr>(GetProcAddress(hDll, "WinExec"));
(*func_addr)("C:\\WINDOWS\\system32\\calc.exe", SW_SHOWDEFAULT);
FreeLibrary(hDll);
return (0);
}
As you can see, this code execute the microsoft calculator. I just want to do the same thing using MASM but the execution fails.
Here's the MASM source code :
.386
.model flat, stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\masm32.inc
include \masm32\include\msvcrt.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\msvcrt.lib
.data
LpFileName db "kernel32.dll", 0
procName db "WinExec", 0
display db "addr_func = 0x%x", 0
.data?
hModule HMODULE ?
procAddr FARPROC ?
.code
start:
invoke LoadLibrary, offset LpFileName
mov hModule, eax
invoke GetProcAddress, hModule, ADDR procName
mov procAddr, eax
INVOKE crt_printf, ADDR display, procAddr
mov esi, procAddr
call esi
db "C:\WINDOWS\system32\calc.exe"
invoke FreeLibrary, hModule
invoke ExitProcess, NULL
end start
The crt_printf output is correct. The same address is printed like withe the C++ program. So the address passed to call is the same one. However the execution fails.
Here's a MASM32 code which works but this time the address of the function WinExec is hardcoded like this :
.386
.model flat, stdcall
option casemap:none
include \masm32\include\windows.inc
.code
start:
jmp _Debut
_Final:
TCHAR 233
dword 42424242h
_Suite:
mov esi, 779e304eh
call esi
jmp _Final
_Debut:
xor eax, eax
push eax
call _Suite
db "C:\WINDOWS\system32\calc.exe"
end start
See the line mov esi, 779e304eh. But dynamically, there is a problem. If I disassemble the code just above we can see that the order of bytes is reversed.
8EEH047E379
Maybe it's not the case dynamically and maybe I need a keyword in the following line (between the comma and procAddr):
mov esi, procAddr
I cannot find the solution. I'm lost. Can anyone help me?
Thanks a lot in advance for your help.
The execution fails because you are not passing it's parameters.
Here you just call the function without any arguments or rather with invalid arguments (because whatever is currently on the stack will be taken and the stack is corrupted in the process).
mov esi, procAddr
call esi
You should do
push SW_SHOWDEFAULT
push offset YourPathToCalc
mov esi, procAddr
call esi
In your samplecode this is what is done here implicitly
xor eax, eax
push eax ; uCmdShow
call _Suite ; Returnadress is the address of the commandline so this is bascially the "push path"
Another thing you are missing is, that when WinExec returns, it will start executing the path in your case so you need a jmp somewhere after the call.
And as Gunner pointed out, the path must be 0 terminated.
To add to the correct answer Devolus posted, your path to calc is not NULL terminated.
This
"C:\WINDOWS\system32\calc.exe" is not correct!
Instead it should be:
"C:\WINDOWS\system32\calc.exe", 0
Also, if you are going to put strings in the code section to use, you need to give them a label in order to use them and you need to jump over them otherwise the CPU will try to execute the bytes.
INVOKE crt_printf, ADDR display, procAddr
mov esi, procAddr
push SW_SHOWDEFAULT
push offset Calc
call esi
jmp #F
Calc db "C:\WINDOWS\system32\calc.exe", 0
##:
invoke FreeLibrary, hModule
invoke ExitProcess, NULL
* EDIT *
To convert that code to Assembly using MASM, all that is needed is this:
.data
LpFileName db "kernel32", 0
procName db "WinExec", 0
Calc db "calc", 0
.code
start:
invoke LoadLibrary, offset LpFileName
push eax
invoke GetProcAddress, eax, ADDR procName
push SW_SHOWDEFAULT
push offset Calc
call eax
call FreeLibrary
invoke ExitProcess, NULL
end start