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++
Related
I'd like to get the TIB of a process and afterwards get its PEB and so forth. I'm failing to do so because I'm having some issues with the __readfsdword(0x18) function, so I'd like to do it with __asm inline code, if possible.
The program is compiled for x86, so I think it means that the TIB will be located at offset 0x18 from the FS register. On x64 it should be on gs:[0x30].
How would I implement this inline assembly idea?
Edit
NtCurrentTeb() and __readfsdword gave different return addresses so I wanted to get as low-level as possible to figure out which one was malfunctioning.
The reason why __readfsdword wasn't working is because I think the libraries weren't compatible with each other, so I replaced them with the updated versions and now it's working properly.
__readfsdword/__readgsqword are compiler intrinsic functions that will generate more optimized code, there is no reason to use inline assembly. Inline assembly is not even supported by Microsoft's compilers for 64-bit targets.
#include <intrin.h>
__declspec(naked) void* __stdcall GetTEB()
{
__asm mov eax, dword ptr fs:[0x18] ;
__asm ret ;
}
...
void *teb;
__asm push eax ;
__asm mov eax, dword ptr fs:[0x18] ;
__asm mov teb, eax ;
__asm pop eax ;
printf("%p == %p == %p\n", GetTEB(), teb, __readfsdword(0x18));
And as suggested in the comments, NtCurrentTeb() is provided by the Windows SDK. It most likely just uses __readfsdword.
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.
I'm trying to use a C library with Go using Swig. This is simplified code, I know I can use cgo but I need to use a function with a LPCWSTR argument with Swig.
I saw on https://github.com/AllenDang/w32/blob/c92a5d7c8fed59d96a94905c1a4070fdb79478c9/typedef.go that LPCWSTR is the equivalent of *uint16 so syscall.UTF16PtrFromString() seems to be what I need but I get an exception when I run the code.
I'm wondering if I'm supposed to use SwigcptrLPCWSTR or not.
libtest.c
#include <windows.h>
#include <stdio.h>
#include "libtest.h"
__stdcall void hello(const LPCWSTR s)
{
printf("hello: %ls\n", s);
}
libtest.h
#ifndef EXAMPLE_DLL_H
#define EXAMPLE_DLL_H
#include <windows.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef BUILDING_EXAMPLE_DLL
#define EXAMPLE_DLL __declspec(dllexport)
#else
#define EXAMPLE_DLL __declspec(dllimport)
#endif
void __stdcall EXAMPLE_DLL hello(const LPCWSTR s);
#ifdef __cplusplus
}
#endif
#endif
I build the lib and the DLL with :
gcc -c -DBUILDING_EXAMPLE_DLL libtest.c
gcc -shared -o libtest.dll libtest.o -Wl,--out-implib,libtest.a
main.swig
%module main
%{
#include "libtest.h"
%}
%include "windows.i"
%include "libtest.h"
main.go
package main
import (
"syscall"
"unsafe"
)
func main() {
p, err := syscall.UTF16PtrFromString("test")
if err != nil {
panic(err)
}
Hello(SwigcptrLPCWSTR(unsafe.Pointer(p)))
}
trace
Exception 0xc0000005 0x0 0xffffffffffffffff 0x7ffcc761f2e1
PC=0x7ffcc761f2e1
signal arrived during external code execution
main._Cfunc__wrap_hello_main_90cec49f7d68ac58(0xc082002110)
_/D_/lpcwstr/go/_obj/_cgo_gotypes.go:53 +0x38
main.Hello(0x500028, 0xc082002120)
_/D_/lpcwstr/go/_obj/main.go:63 +0x3c
main.main()
D:/lpcwstr/go/main.go:9 +0x96
goroutine 17 [syscall, locked to thread]:
runtime.goexit()
c:/go/src/runtime/asm_amd64.s:1696 +0x1
rax 0x6c007400690074
rbx 0x6c007400690074
rcx 0x7ffffffe
rdi 0x24fd73
rsi 0x7
rbp 0x24fb00
rsp 0x24fa00
r8 0xffffffffffffffff
r9 0x7ffcc75d0000
r10 0x0
r11 0x200
r12 0xffffffff
r13 0x24fd60
r14 0x10
r15 0x6264403a
rip 0x7ffcc761f2e1
rflags 0x10202
cs 0x33
fs 0x53
gs 0x2b
I suspect the issue you're seeing is because what you're passing into SWIG is a double pointer instead of just a pointer, i.e. wchar_t** instead of just wchar_t*.
I think this comes about because you call UTF16PtrFromString which takes the address of the UTF16 string and then subsequently call unsafe.Pointer(p) which I think again takes the address of its input.
From the go source code:
func UTF16PtrFromString(s string) (*uint16) {
a := UTF16FromString(s)
return &a[0]
}
So I think if you instead use:
func main() {
p, err := syscall.UTF16FromString("test") // Note the subtle change here
if err != nil {
panic(err)
}
Hello(SwigcptrLPCWSTR(unsafe.Pointer(p)))
}
It should work as intended.
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]
I am trying to hide the WinMain function inside a DLL in order to avoid typing again much of the code over and over again.
I exported wWinMain from the DLL by declaring it as
extern "C" int WINAPI wWinMain( ... )
{
// repetitive code here
}
and used the linker option /EXPORT:wWinMain, but when I try to use the import library in another project I get the error
LIBCMTD.lib(wincrt0.obj) : error LNK2019: unresolved external symbol _WinMain#16 referenced in function __tmainCRTStartup
Remark I do want to use the GUI interface and I know this is common error when you define a main instead of a WinMain function. Also, I enabled the UNICODE support in both projects. What should I do?
This is not possible as-is, the linker can only set the entrypoint for an EXE to a function that's inside the EXE. Rename the wWinMain() in the DLL to something else. Write a wWinMain() in a source code file that gets linked into your EXE, simply call the DLL's exported function.
// ...somewhere in a .cpp file within my .dll's sources...
#define WinMain WinMainOld // ...to suppress Win32 declaration of WinMain
#include <windows.h>
#undef WinMain // ...so that WinMain below is not replaced
. . .
#pragma comment(linker, "/export:_WinMain#16") // ...to export it from .dll
extern "C" // ...to suppress C++ name decoration
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR pCmdLine, int nCmdShow)
{
. . .
}
Should you be using WinMain in a DLL? Should it not be DllMain?
If you want to call the WinMain of the dll, you need to replace the CRTWinMainStartup function(_tmainCRTStartup in your liked CRT lib), and make it call your exported WinMain, this stops the linker looking for a local WinMain and still keeps correct flow of the program(the source for the CRT startups should be in the crt source of any compiler)
I find one way to put WinMain inside DLL.
You need to use WinMain instead of wWinMain (I don't know why)
Append a def file into your project and,
append EXPORTS WinMain in def file.
Like this
EXPORTS
WinMain
From the observation, all need exported functions generated, not only WinMain.
After test, the way of __declspec(dllexport) is invalid for WinMain.
Link your program to the DLL library
use #pragma comment(lib, "testDll.lib")
or modify setting in the project.
EXPORT int WINAPI _WinMain_(int (*_main_)(int argc, char **argv), HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR commandLine, int nCmdShow);
int _XMain( int argc, char **argv );
#define XMain WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR commandLine, int nCmdShow)\
{return _WinMain_( _XMain, hInst, hPrevInstance, commandLine, nCmdShow );} \
int _XMain
Then _WinMain_() calls or schedules _XMain().
Over in your application source:
int XMain( int argc, char **argv )
{
}