Get module from CreateToolhelp32Snapshot - winapi

I can fill out a list box with processe names, for this I use PROCESSENTRY32 struct. But when I try to get th32ParentProcessID from PROCESSENTRY32 struct, I get an error, eax equal -1.
My structures:
PROCESSENTRY32 STRUC
dwSize DWORD ?
cntUsage DWORD ?
th32ProcessID DWORD ?
th32DefaultHeapID DWORD ?
th32ModuleID DWORD ?
cntThreads DWORD ?
th32ParentProcessID DWORD ?
pcPriClassBase DWORD ?
dwFlags DWORD ?
szExeFile dw MAX_PATH dup(?)
PROCESSENTRY32 ENDS
MODULEENTRY32 STRUCT
dwSize DWORD ?
th32ModuleID DWORD ?
th32ProcessID DWORD ?
GlblcntUsage DWORD ?
ProccntUsage DWORD ?
modBaseAddr DWORD ?
modBaseSize DWORD ?
hModule DWORD ?
szModule db MAX_MODULE_NAME32+1 dup(?)
szExePath db MAX_PATH dup(?)
MODULEENTRY32 ENDS
My function:
;Modul begin
push PROCDATA.th32ProcessID
push TH32CS_SNAPMODULE
call CreateToolhelp32Snapshot#8
mov mhSnapshot, eax
;EAX = -1 Why?
mov MODULDATA.dwSize, sizeof MODULEENTRY32
push offset MODULDATA
push mhSnapshot
call Module32FirstW#8
;Module end
I have the correct structures?

Related

WM_DESTROY message not being received by WndProc in x64 Windows Assembly Program

I'm trying to recreate using MASM /w Visual Studio 2019 something similar to the following C++ code which works. Essentially at this stage just want the window to be movable and the close button to work.
#include <iostream>
#include <Windows.h>
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM
lParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
int main()
{
wchar_t windowclass[] = L"MyWinTest";
HINSTANCE hInstance = GetModuleHandleW(NULL);
MSG msg;
WNDCLASSEXW wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = 0;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
wc.hIconSm = NULL;
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = windowclass;
wc.lpszMenuName = nullptr;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassExW(&wc);
HWND hWnd = CreateWindowExW(
0,
windowclass,
L"MyWindow",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
800,
600,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
In my version of x64 assembly using MASM the Window is created and displayed, also WndProc is being hit, can see it get message WM_CREATE and WM_PAINT but the Window can't be moved and can't be closed. I did compile the C++ version as x64 and output assembly listing for comparison, but it looks very similar as far as I can tell to the assembly version.
WSTR MACRO lbl:req,qstr:VARARG
LOCAL arg,unq,qot,q
lbl LABEL WORD
FOR arg,<qstr>
qot SubStr <arg>,1,1
q = 0
IFIDNI qot,<!'>;'
q = 1
ELSEIFIDNI qot,<!">;"
q = 1
ELSE
DW arg
ENDIF
IF q EQ 1
unq SubStr <arg>,2,#SizeStr(<arg>)-2
% FORC c,<unq>
DW "&c"
ENDM
ENDIF
ENDM
DW 0
ENDM
L MACRO qstr:VARARG
LOCAL sym,seg
seg EQU <.code>
%IFIDNI <#CurSeg>,<_DATA>
seg EQU <.data>
ENDIF
.CONST
ALIGN 4
WSTR sym,qstr
seg
EXITM <OFFSET sym>
ENDM
extrn LoadCursorW: PROC
extrn MessageBoxW: PROC
extrn ExitProcess: PROC
extrn GetModuleHandleW: PROC
extrn RegisterClassExW: PROC
extrn CreateWindowExW: PROC
extrn GetLastError: PROC
extrn DefWindowProcW: PROC
extrn ShowWindow: PROC
extrn Sleep: PROC
extrn GetMessageW: PROC
extrn TranslateMessage: PROC
extrn DispatchMessageW: PROC
extrn DestroyWindow: PROC
extrn UpdateWindow: PROC
extrn PostQuitMessage: PROC
extrn BeginPaint: PROC
extrn EndPaint: PROC
.data
wstr windowClassName,"AsmTestClass",0,0
wstr windowTitle,"AsmTest",0,0
HWND_DESKTOP textequ <0h>
MB_OK textequ <0h>
INFINITE textequ <0ffffffffh>
WM_CREATE textequ <0001h>
WM_DESTROY textequ <0002h>
WM_SIZE textequ <0005h>
WM_PAINT textequ <000fh>
WM_CLOSE textequ <0010h>
WM_QUIT textequ <0012h>
SW_HIDE textequ <0000h>
SW_SHOW textequ <0005h>
CS_VREDRAW textequ <0001h>
CS_HREDRAW textequ <0002h>
WS_OVERLAPPED textequ <00000000h>
WS_CAPTION textequ <00c00000h>
WS_SYSMENU textequ <00080000h>
WS_MINIMIZEBOX textequ <00020000h>
CW_USEDEFAULT textequ <80000000h>
IDI_APPLICATION textequ <00007f00h>
WINDOW_WIDTH DWORD 800
WINDOW_HEIGHT DWORD 600
WNDCLASSEX STRUCT DWORD
cbSize DWORD ?
style DWORD ?
lpfnWndProc QWORD ?
cbClsExtra DWORD ?
cbWndExtra DWORD ?
hInstance QWORD ?
hIcon QWORD ?
hCursor QWORD ?
hbrBackground QWORD ?
lpszMenuName QWORD ?
lpszClassName QWORD ?
hIconSm QWORD ?
WNDCLASSEX ENDS
MSG STRUCT
hwnd QWORD ?
message DWORD ?
wParam QWORD ?
lParam QWORD ?
time DWORD ?
x DWORD ?
y DWORD ?
MSG ENDS
PAINTSTRUCT STRUCT 8
hdc QWORD ?
fErase DWORD ?
left DWORD ?
top DWORD ?
right DWORD ?
bottom DWORD ?
fRestore DWORD ?
fIncUpdate DWORD ?
rgbReserved BYTE 32 DUP (?)
PAINTSTRUCT ENDS
.code
main proc
LOCAL wc:WNDCLASSEX
LOCAL hWnd:QWORD
LOCAL hInstance:QWORD
LOCAL hCursor:QWORD
LOCAL ATOM:WORD
LOCAL message:MSG
sub rsp, 8
; hInstance = GetModuleHandle(NULL)
mov rcx, 0
call GetModuleHandleW
mov hInstance, rax
; hCursor = LoadCursor(NULL,IDI_APPLICATION)
mov edx, IDI_APPLICATION
xor ecx, ecx
call LoadCursorW
mov hCursor, rax
; Setup Window Class
mov wc.cbSize, SIZEOF WNDCLASSEX
mov wc.style, CS_VREDRAW or CS_HREDRAW
lea rax, OFFSET WndProc
mov wc.lpfnWndProc, rax
mov wc.cbClsExtra, 0
mov wc.cbWndExtra, 0
lea rax, hInstance
mov wc.hInstance, rax
mov wc.hbrBackground, 0
mov wc.lpszMenuName, 0
lea rax, hCursor
mov wc.hCursor, rax
lea rax, windowClassName
mov wc.lpszClassName, rax
mov wc.hIconSm, 0
lea rcx, wc
call RegisterClassExW
mov ATOM, ax
; CreateWindowExW
mov QWORD PTR [rsp+88], 0 ; lpParam
lea rax, hInstance
mov QWORD PTR [rsp+80], rax ; hInstance
mov QWORD PTR [rsp+72], 0 ; hMenu
mov QWORD PTR [rsp+64], 0 ; hWndParent
mov edx, WINDOW_HEIGHT
mov DWORD PTR [rsp+56], edx ; nHeight
mov edx, WINDOW_WIDTH
mov DWORD PTR [rsp+48], edx ; nWidth
mov DWORD PTR [rsp+40], CW_USEDEFAULT ; Y
mov DWORD PTR [rsp+32], CW_USEDEFAULT ; X
mov r9d, WS_OVERLAPPED or WS_CAPTION or WS_SYSMENU or WS_MINIMIZEBOX ; dwStyle
lea r8, windowTitle ; lpWindowName
lea rdx, windowClassName ; lpClassName
xor ecx,ecx ; dwExStyle
call CreateWindowExW
cmp rax, 0
je WindowFailed
jmp WindowSuccess
WindowFailed:
call GetLastError
; to-do check error ?
WindowSuccess:
mov hWnd, rax
mov rcx, hWnd ; hWnd
mov edx, SW_SHOW ; nCmdShow
call ShowWindow
mov rcx, hWnd ; hWnd
call UpdateWindow
MessageLoop:
xor r9d, r9d ; wMsgFilterMax
xor r8d, r8d ; wMsgFilterMin
xor edx, edx ; hWnd
lea rcx, message ; lpMsg
call GetMessageW
test eax, eax
je QuitMessageLoop
lea rcx, message ; lpMsg
call TranslateMessage
lea rcx, message ; lpMsg
call DispatchMessageW
jmp MessageLoop
QuitMessageLoop:
mov ecx, eax ; uExitCode
call ExitProcess
main endp
WndProc proc
LOCAL hWnd:QWORD
LOCAL uMsg:DWORD
LOCAL wParam:QWORD
LOCAL lParam:QWORD
LOCAL result:QWORD
LOCAL ps:PAINTSTRUCT
LOCAL hdc:QWORD
sub rsp, 8
mov lParam, r9
mov wParam, r8
mov uMsg, edx
mov hWnd, rcx
; msg handler
cmp uMsg,WM_CREATE
je create
cmp uMsg,WM_PAINT
je paint
cmp uMsg,WM_DESTROY
je destroy
; default
mov r9, lParam
mov r8, wParam
mov edx, uMsg
mov rcx, hWnd
call DefWindowProcW
mov result,rax
jmp finish
create:
mov result, 0
jmp finish
paint:
mov rcx, hWnd
lea rdx, ps
call BeginPaint
mov hdc, rax
; to-do HDC paint stuff here
mov rcx, hWnd
lea rdx, ps
call EndPaint
mov result, 0
jmp finish
destroy:
xor ecx, ecx ; nExitCode
call PostQuitMessage
mov result, 0
jmp finish
finish:
mov rax, result
ret
WndProc endp
End
Note due to local statement masm is automatically adding to my main before the sub rsp,8: (-152 + -8 = -160 )
push rbp
mov rbp, rsp
add rsp, 0FFFFFFFFFFFFFF68h
and adding to wndproc routine (-120 + -8 = -128)
push rbp
mov rbp, rsp
add rsp, 0FFFFFFFFFFFFFF88h
...
leave
error in code - in both procs -
sub rsp, 8
when from x64 calling convention
The caller is responsible for allocating space for the callee's parameters. The caller must always allocate sufficient space to store
four register parameters, even if the callee doesn't take that many
parameters.
so need - to store four register parameters - 4*8 and +8 for 16-byte align, so
sub rsp, 40
in concrete case calls to DispatchMessageW and TranslateMessage can corrupt (overwrite) message because it located in callee's parameters space. if test under debugger - i view that DispatchMessageW overwrite message in prolog and than already use wrong message

decryptmessage fail with access violation

function for initiliase Schannel
SecureConnect proc uses ebx edi esi, _host: dword, _port: dword, phContext: dword, pCredHandle: dword, cSocket: dword
SECPKG_CRED_OUTBOUND equ 2
SCHANNEL_CRED_VERSION equ 4
SCH_CRED_NO_DEFAULT_CREDS equ 10h
SCH_CRED_MANUAL_CRED_VALIDATION equ 8
ISC_REQ_SEQUENCE_DETECT equ 8
ISC_REQ_REPLAY_DETECT equ 4
ISC_REQ_CONFIDENTIALITY equ 10h
ISC_RET_EXTENDED_ERROR equ 4000h
ISC_REQ_ALLOCATE_MEMORY equ 100h
ISC_REQ_STREAM equ 8000h
ISC_RET_EXTENDED_ERROR equ 4000h
SECURITY_NATIVE_DREP equ 10h
IO_BUFFER_SIZE equ 8000h
SEC_I_INCOMPLETE_CREDENTIALS equ 90320h
SEC_I_CONTINUE_NEEDED equ 90312h
SEC_E_INCOMPLETE_MESSAGE equ 80090318h
SCHANNEL_CRED STRUCT
dwVersion dd ?
cCreds dd ?
paCred dd ?
hRootStore dd ?
cMappers dd ?
aphMappers dd ?
cSupportedAlgs dd ?
palgSupportedAlgs dd ?
grbitEnabledProtocols dd ?
dwMinimumCipherStrength dd ?
dwMaximumCipherStrength dd ?
dwSessionLifespan dd ?
dwFlags dd ?
dwCredFormat dd ?
SCHANNEL_CRED ENDS
SecBufferDesc STRUCT
ulVersion dd ?
cBuffers dd ?
pBuffers dd ?
SecBufferDesc ENDS
SecBuffer STRUCT
cbBuffer dd ?
BufferType dd ?
pvBuffer dd ?
SecBuffer ENDS
CERT_CONTEXT STRUCT
dwCertEncodingType dd ?
pbCertEncoded dd ?
cbCertEncoded dd ?
pCertInfo dd ?
hCertStore dd ?
CERT_CONTEXT ENDS
local credentials : SCHANNEL_CRED
local sSocket : dword
local sin : sockaddr_in
local iMode : dword
local fd : fds_set
local dwSSPIFlags : dword
local out_buffer_desc : SecBufferDesc
local _out_buffer : SecBuffer
local in_buffer_desc : SecBufferDesc
local _in_buffer[2] : SecBuffer
local dwSSPIOutFlags : dword
local IoBuffer : dword
local cbIoBuffer : dword
local fDoRead : dword
local scRet : dword
local ExtraData : SecBuffer
lea ecx, [ebp - 3 * 4]
sub ecx, esp
invoke ZeroMemory, addr [esp + 3 * 4 + 4], ecx
mov credentials.dwVersion, SCHANNEL_CRED_VERSION
mov credentials.dwFlags, SCH_CRED_NO_DEFAULT_CREDS or SCH_CRED_MANUAL_CRED_VALIDATION
invoke AcquireCredentialsHandleA, NULL, _T("Microsoft Unified Security Protocol Provider"), SECPKG_CRED_OUTBOUND, NULL, addr credentials, NULL, NULL, dword ptr [pCredHandle], NULL
.if eax == 0
invoke socket, AF_INET, SOCK_STREAM, IPPROTO_TCP
mov dword ptr [sSocket], eax
invoke copydata, addr sSocket, dword ptr [cSocket], sizeof dword
invoke isip, dword ptr [_host]
.if eax != 0
mov eax, dword ptr [_host]
jmp #f
.endif
invoke xgethostbyname, dword ptr [_host], AF_INET
invoke inet_ntoa, eax
##:
invoke inet_addr, eax
mov sin.sin_addr, eax
mov eax, dword ptr [_port]
cmp eax, 65536
jna #f
invoke atoi, eax
##:
invoke htons, eax
mov sin.sin_port, ax
mov sin.sin_family, AF_INET ;???????? ???? ? ??? "AF_INET"
mov iMode, 1
invoke setsockopt, dword ptr [sSocket], IPPROTO_TCP, TCP_NODELAY, addr iMode, 4
mov iMode, 1
invoke ioctlsocket, dword ptr [sSocket], FIONBIO, addr iMode
invoke connect, dword ptr [sSocket], addr sin, sizeof sin ;??????????? ?????? ????????
invoke fd_set_, dword ptr [sSocket], 0, addr fd, 10, 0
invoke select, 0, 0, addr fd, 0, addr [fd + 4 * 3]
cmp eax, 1
jnz close
mov iMode, 0
invoke ioctlsocket, dword ptr [sSocket], FIONBIO, addr iMode
mov dword ptr [dwSSPIFlags], ISC_REQ_SEQUENCE_DETECT or ISC_REQ_REPLAY_DETECT or ISC_REQ_CONFIDENTIALITY or ISC_RET_EXTENDED_ERROR or ISC_REQ_ALLOCATE_MEMORY or ISC_REQ_STREAM
mov _out_buffer.cbBuffer, 0
mov _out_buffer.BufferType, SECBUFFER_TOKEN
mov _out_buffer.pvBuffer, NULL
mov out_buffer_desc.ulVersion, SECBUFFER_VERSION
mov out_buffer_desc.cBuffers, 1
lea eax, _out_buffer
mov out_buffer_desc.pBuffers, eax
invoke InitializeSecurityContextA, dword ptr [pCredHandle], NULL, dword ptr [_host], dword ptr [dwSSPIFlags], 0, SECURITY_NATIVE_DREP, NULL, 0, dword ptr [phContext], addr out_buffer_desc, addr dwSSPIOutFlags, NULL
.if _out_buffer.cbBuffer != 0 && _out_buffer.pvBuffer != NULL
invoke synsend, dword ptr [sSocket], _out_buffer.pvBuffer, _out_buffer.cbBuffer, NULL
invoke FreeContextBuffer, dword ptr [_out_buffer.pvBuffer]
invoke VirtualAlloc, 0, IO_BUFFER_SIZE, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE
test eax, eax
jz close
mov dword ptr [IoBuffer], eax
mov dword ptr [scRet], SEC_I_CONTINUE_NEEDED
mov dword ptr [cbIoBuffer], 0
mov dword ptr [fDoRead], TRUE
.while dword ptr [scRet] == SEC_I_CONTINUE_NEEDED || dword ptr [scRet] == SEC_E_INCOMPLETE_MESSAGE || dword ptr [scRet] == SEC_I_INCOMPLETE_CREDENTIALS
.if dword ptr [cbIoBuffer] == 0 || dword ptr [scRet] == SEC_E_INCOMPLETE_MESSAGE
.if dword ptr [fDoRead] == TRUE
mov eax, dword ptr [IoBuffer]
add eax, dword ptr [cbIoBuffer]
mov ecx, IO_BUFFER_SIZE
sub ecx, dword ptr [cbIoBuffer]
invoke recv_, dword ptr [sSocket], eax, ecx, 10
.break .if eax == 0 || sdword ptr eax < 0
add dword ptr [cbIoBuffer], eax
.else
mov dword ptr [fDoRead], TRUE
.endif
.endif
mov _out_buffer.cbBuffer, 0
mov _out_buffer.BufferType, SECBUFFER_TOKEN
mov _out_buffer.pvBuffer, NULL
mov out_buffer_desc.ulVersion, SECBUFFER_VERSION
mov out_buffer_desc.cBuffers, 1
lea eax, _out_buffer
mov out_buffer_desc.pBuffers, eax
mov eax, dword ptr [IoBuffer]
mov ecx, dword ptr [cbIoBuffer]
mov (0Ch * 0) + _in_buffer.cbBuffer, ecx
mov (0Ch * 0) + _in_buffer.BufferType, SECBUFFER_TOKEN
mov (0Ch * 0) + _in_buffer.pvBuffer, eax
mov (0Ch * 1) + _in_buffer.cbBuffer, 0
mov (0Ch * 1) + _in_buffer.BufferType, SECBUFFER_EMPTY
mov (0Ch * 1) + _in_buffer.pvBuffer, NULL
mov in_buffer_desc.ulVersion, SECBUFFER_VERSION
mov in_buffer_desc.cBuffers, 2
lea eax, _in_buffer
mov in_buffer_desc.pBuffers, eax
invoke InitializeSecurityContextA, dword ptr [pCredHandle], dword ptr [phContext], NULL, dword ptr [dwSSPIFlags], 0, SECURITY_NATIVE_DREP, addr in_buffer_desc, 0, NULL, addr out_buffer_desc, addr dwSSPIOutFlags, NULL
mov dword ptr [scRet], eax
.continue .if dword ptr [scRet] == SEC_E_INCOMPLETE_MESSAGE
.break .if sdword ptr [scRet] < 0
.if dword ptr [scRet] == SEC_E_OK || dword ptr [scRet] == SEC_I_CONTINUE_NEEDED && _out_buffer.cbBuffer != 0 && _out_buffer.pvBuffer != NULL
invoke synsend, dword ptr [sSocket], _out_buffer.pvBuffer, _out_buffer.cbBuffer, NULL
invoke FreeContextBuffer, dword ptr [_out_buffer.pvBuffer]
.endif
.if dword ptr [scRet] == SEC_I_INCOMPLETE_CREDENTIALS
invoke MessageBoxA, 0, _T("SEC_I_INCOMPLETE_CREDENTIALS"), 0, 0
;//GetNewClientCredentials(phCreds, dword ptr [phContext]);
;// Повторная попытка.
;fDoRead = FALSE;
;scRet = SEC_I_CONTINUE_NEEDED;
;// Исправляем ошибку Platform SDK!
;// Считаем, что за этим сообщением не может следовать другое
;cbIoBuffer = 0;
;.continue
.endif
.if dword ptr [(0Ch * 1) + _in_buffer.BufferType] == SECBUFFER_EXTRA
mov eax, dword ptr [IoBuffer]
add eax, dword ptr [cbIoBuffer]
mov ecx, (0Ch * 1) + _in_buffer.cbBuffer
mov dword ptr [cbIoBuffer], ecx
sub eax, ecx
invoke copydata, eax, dword ptr [IoBuffer], (0Ch * 1) + _in_buffer.cbBuffer
.else
mov dword ptr [cbIoBuffer], 0
.endif
.endw
invoke VirtualFree, dword ptr [IoBuffer], 0, MEM_RELEASE
cmp dword ptr [scRet], SEC_E_OK
jnz close
mov eax, dword ptr [sSocket]
jmp _ret
.endif
.endif
close:
xor eax, eax
_ret:
ret
SecureConnect endp
decryptmessage
cryptrecv proc uses ebx edi esi, _socket: dword, rbuffer: dword, phContext: dword
IO_BUFFER_SIZE equ 8000h
SecBufferDesc STRUCT
ulVersion dd ?
cBuffers dd ?
pBuffers dd ?
SecBufferDesc ENDS
SecBuffer STRUCT
cbBuffer dd ?
BufferType dd ?
pvBuffer dd ?
SecBuffer ENDS
local Cbuffer : dword
local cb : dword
local _edx : dword
local in_buffer_desc : SecBufferDesc
local _in_buffer[4] : SecBuffer
local scRet : dword
local _result : dword
lea ecx, [ebp - 3 * 4]
sub ecx, esp
invoke ZeroMemory, addr [esp + 3 * 4 + 4], ecx
invoke ZeroMemory, dword ptr [rbuffer], 4
mov edi, dword ptr [rbuffer]
mov dword ptr [_edx], IO_BUFFER_SIZE
invoke VirtualAlloc, 0, dword ptr [_edx], MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE
test eax, eax
jz close
mov dword ptr [Cbuffer], eax
_recv:
.if dword ptr [cb] == 0 || dword ptr [scRet] == SEC_E_INCOMPLETE_MESSAGE
##:
mov eax, dword ptr [Cbuffer]
add eax, dword ptr [cb]
mov ecx, dword ptr [_edx]
sub ecx, dword ptr [cb]
test ecx, ecx
jnz #f
add dword ptr [_edx], IO_BUFFER_SIZE
invoke VirtualAlloc, 0, dword ptr [_edx], MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE
test eax, eax
jz close
mov esi, eax
invoke copydata, dword ptr [Cbuffer], esi, dword ptr [cb]
invoke VirtualFree, dword ptr [Cbuffer], 0, MEM_RELEASE
mov dword ptr [Cbuffer], esi
jmp #b
##:
invoke recv, dword ptr [_socket], eax, ecx, 0
test eax, eax
jle close
add dword ptr [cb], eax
.endif
invoke copydata, addr cb, addr [(0Ch * 0) + _in_buffer.cbBuffer], 4
mov (0Ch * 0) + _in_buffer.BufferType, SECBUFFER_DATA
invoke copydata, addr Cbuffer, addr [(0Ch * 0) + _in_buffer.pvBuffer], 4
mov (0Ch * 1) + _in_buffer.cbBuffer, 0
mov (0Ch * 1) + _in_buffer.BufferType, SECBUFFER_EMPTY
mov (0Ch * 1) + _in_buffer.pvBuffer, NULL
mov (0Ch * 2) + _in_buffer.cbBuffer, 0
mov (0Ch * 2) + _in_buffer.BufferType, SECBUFFER_EMPTY
mov (0Ch * 2) + _in_buffer.pvBuffer, NULL
mov (0Ch * 3) + _in_buffer.cbBuffer, 0
mov (0Ch * 3) + _in_buffer.BufferType, SECBUFFER_EMPTY
mov (0Ch * 3) + _in_buffer.pvBuffer, NULL
lea eax, _in_buffer
mov in_buffer_desc.pBuffers, eax
mov in_buffer_desc.ulVersion, SECBUFFER_VERSION
mov in_buffer_desc.cBuffers, 4
invoke DecryptMessage, dword ptr [phContext], addr in_buffer_desc, 0, NULL
mov dword ptr [scRet], eax
cmp dword ptr [scRet], SEC_E_INCOMPLETE_MESSAGE
jz _recv
cmp dword ptr [scRet], SEC_I_CONTEXT_EXPIRED
jz close
.if dword ptr [scRet] == SEC_I_RENEGOTIATE
invoke MessageBoxA, 0, _T("SEC_I_RENEGOTIATE"), 0, 0
jmp close
.endif
cmp eax, SEC_E_OK
jnz close
mov dword ptr [cb], 0
mov ebx, 1
.while ebx <= 3
imul ecx, ebx, 0Ch
lea esi, [ecx + _in_buffer]
.if dword ptr [esi + SecBuffer.BufferType] == SECBUFFER_DATA && dword ptr [esi + SecBuffer.cbBuffer] != 0
.if dword ptr [edi] == NULL
invoke VirtualAlloc, 0, dword ptr [esi + SecBuffer.cbBuffer], MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE
test eax, eax
jz close
mov dword ptr [edi], eax
invoke copydata, dword ptr [esi + SecBuffer.pvBuffer], dword ptr [edi], dword ptr [esi + SecBuffer.cbBuffer]
.else
mov ecx, dword ptr [_result]
add ecx, dword ptr [esi + SecBuffer.cbBuffer]
invoke VirtualAlloc, 0, ecx, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE
test eax, eax
jz close
mov edx, dword ptr [edi]
mov dword ptr [edi], eax
invoke copydata, edx, eax, dword ptr [_result]
invoke VirtualFree, edx, 0, MEM_RELEASE
mov eax, dword ptr [edi]
add eax, dword ptr [_result]
invoke copydata, dword ptr [esi + SecBuffer.pvBuffer], eax, dword ptr [esi + SecBuffer.cbBuffer]
.endif
mov eax, dword ptr [esi + SecBuffer.cbBuffer]
add dword ptr [_result], eax
.elseif dword ptr [esi + SecBuffer.BufferType] == SECBUFFER_EXTRA
mov edx, dword ptr [Cbuffer]
add edx, dword ptr [cb]
mov ecx, dword ptr [esi + SecBuffer.cbBuffer]
add dword ptr [cb], ecx
mov dword ptr [scRet], SEC_I_CONTINUE_NEEDED
invoke copydata, dword ptr [esi + SecBuffer.pvBuffer], edx, dword ptr [esi + SecBuffer.cbBuffer]
.endif
inc ebx
.endw
cmp dword ptr [scRet], SEC_I_CONTINUE_NEEDED
jz _recv
jmp _ret
close:
invoke VirtualFree, dword ptr [edi], 0, MEM_RELEASE
mov dword ptr [_result], NULL
_ret:
invoke VirtualFree, dword ptr [Cbuffer], 0, MEM_RELEASE
mov eax, dword ptr [_result]
ret
cryptrecv endp
this code work good. but sometime DecryptMessage fail with access violation. it cant read data from dword ptr [Cbuffer]
i am see it in debugger. and after error it say me that memory from dword ptr [Cbuffer] not allocated
access violation has occured inside DecryptMessage windows api function.
instruction that occure
movzx ecx, byte ptr [edi + 3]
in edi placed address that have dword ptr [Cbuffer]

Win32 ASM stack override

I'm having trouble with the call to BeginPaint(hWnd, lpPaint) in the WindowPaint event. It seems that the function BeginPaint overwrite the stack.
A little C program tell me that the size of PAINTSTRUCT (lpPaint) should be 34.
If i put the adresse to EBP-34 or a little more EBP-56 for the return value of lpPaint, it crash. If I allow alot of stack and put the return adresse to EBP-170 it works.
Simple code:
;Note : All Win32 API functions preserve the EBP, EBX, ESI, and EDI registers
extern GetModuleHandleA
extern ExitProcess
extern GetCommandLineA
extern RegisterClassExA
extern LoadIconA
extern LoadCursorA
extern CreateWindowExA
extern ShowWindow
extern UpdateWindow
extern MessageBoxA
extern GetMessageA
extern TranslateMessage
extern DispatchMessageA
extern PostQuitMessage
extern DefWindowProcA
extern DrawTextA
extern BeginPaint
extern EndPaint
import GetModuleHandleA kernel32.dll
import ExitProcess kernel32.dll
import GetCommandLineA kernel32.dll
import RegisterClassExA user32.dll
import LoadIconA user32.dll
import LoadCursorA user32.dll
import CreateWindowExA user32.dll
import ShowWindow user32.dll
import UpdateWindow user32.dll
import MessageBoxA user32.dll
import GetMessageA user32.dll
import TranslateMessage user32.dll
import DispatchMessageA user32.dll
import PostQuitMessage user32.dll
import DefWindowProcA user32.dll
import DrawTextA user32.dll
import BeginPaint user32.dll
import EndPaint user32.dll
section .text use32
..start:
;Handle from calling process
push dword 0
call [GetModuleHandleA]
mov dword [hInstance], eax
;Get command line
call [GetCommandLineA]
mov dword [commandLine], eax
;Main window
Call WindowMain
;Exit
Push eax
call [ExitProcess]
;========================================================================================
; Create a main windows
;========================================================================================
WindowMain:
push ebp
mov ebp, esp
;Local variable
;==============
;EBP-48 = WNDCLASSEX Structure 48 bytes
;EBP-72 = MSG 24 bytes
;EBP-76 = HWND, handle of our window 4 bytes
sub esp, 76
lea ebx, [ebp-48] ;EBX is now address of WNDCLASSEX
;WNDCLASSEX Structure : http://msdn.microsoft.com/en-us/library/ms633577(v=vs.85).aspx
mov dword [ebx+00], 48 ;Size of the structure
mov dword [ebx+04], 3 ;Style of the window
mov dword [ebx+08], WindowProcedure ;Callback function for events
mov dword [ebx+12], 0
mov dword [ebx+16], 0
mov dword [ebx+20], hInstance ;Handle to the window
;[ebx+24] = HICON
;[ebx+28] = HCURSOR
mov dword [ebx+32], 6 ;Background brush
mov dword [ebx+36], 0 ;Menu name NULL
mov dword [ebx+40], ClassName ;Class name for the window
;[ebx+44] = HICON
;LoadIconA(0, IDI_APPLICATION);
push 32512
push 0
call [LoadIconA]
mov dword [ebx+24], eax ;Icon for our window
mov dword [ebx+44], eax ;Small icon for our window
;LoadCursorA(0, IDC_ARROW);
push dword 32512
push 0
call [LoadCursorA]
mov dword [ebx+28], eax
;RegisterClassExA(WNDCLASSEX address);
push ebx
call [RegisterClassExA]
;CreateWindowEx(0, ClassName, window title, WS_OVERLAPPEDWINDOW, x, y, width, height, handle to parent window, handle to menu, hInstance, NULL);
push 0
push hInstance
push 0
push 0
push 400 ;High
push 500 ;Wide
push dword 0x80000000 ;CW_USEDEFAULT
push dword 0x80000000 ;CW_USEDEFAULT
;WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX
push dword 0x00 | 0xC00000 | 0x80000 | 0x40000 | 0x20000 | 0x10000 ;WS_OVERLAPPEDWINDOW
push dword ApplicationName
push dword ClassName
push dword 0
call [CreateWindowExA]
mov dword [ebp-76], eax ;Handle of our window
cmp eax, 0
jz .newWindowsFailed
;ShowWindow(hWind, SW_SHOWDEFAULT);
push dword 10
push dword [ebp-76]
call [ShowWindow]
;UpdateWindow(hWind);
push dword [ebp-76]
call [UpdateWindow]
.MessageLoop:
;GetMessageA(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
push dword 0
push dword 0
push dword 0
lea ebx, [ebp-72]
push ebx
call [GetMessageA]
cmp eax, 0 ;WM_QUIT
jz .MessageLoopExit
;TranslateMessage(lpMsg);
lea ebx, [ebp-72]
push ebx
call [TranslateMessage]
;DispatchMessageA(lpMsg);
lea ebx, [ebp-72]
push ebx
call [DispatchMessageA]
jmp .MessageLoop
.MessageLoopExit:
jmp .finish
.newWindowsFailed:
push dword 0
push dword 0
push errMsg
push 0
call [MessageBoxA]
mov eax, 1 ;Return error
mov esp, ebp
pop ebp
ret
.finish:
mov esp, ebp
pop ebp
ret
;========================================================================================
; Handle the events that our window sends us.
;========================================================================================
;LRESULT CALLBACK WindowProc(
; _In_ HWND hwnd,
; _In_ UINT uMsg,
; _In_ WPARAM wParam,
; _In_ LPARAM lParam
;);
;========================================================================================
WindowProcedure:
push ebp
mov ebp, esp
;Local variable
;==============
;EBP-56 = PAINTSTRUCT <- RECALCULER LA TAILLE DE LA STUCTURE!!!
;EBP-60 = HDC
;EBP-76 = RECT
sub esp, 170
mov eax, dword [ebp+12] ;uMsg
cmp eax, 2 ;WM_DESTROY
jz .WindowDestroy
cmp eax, 0X0F ;WM_PAINT
jz .WindowPaint
.WindowDefault:
push dword [ebp+20]
push dword [ebp+16]
push dword [ebp+12]
push dword [ebp+08]
call [DefWindowProcA]
;The return value is from DefWindowProcA so we can't change EAX
mov esp, ebp
pop ebp
ret 16
.WindowDestroy:
;We pass 0 as an argument to the PostQuitMessage() function, to tell it
;to pass 0 as the value of wParam for the next message. At that point,
;GetMessage() will return 0, and the message loop will terminate.
;PostQuitMessage(nExitCode);
push dword 0
call [PostQuitMessage]
jmp .WindowProcedureFinish
.WindowPaint:
;BeginPaint(hWnd, lpPaint);
lea ebx, [ebp-34]
push ebx
push dword [ebp+8]
call [BeginPaint]
mov dword [ebp-60], eax ;Save device context
jmp .WindowProcedureFinish
.WindowProcedureFinish:
xor eax, eax
mov esp, ebp
pop ebp
ret 16
msgBox:
; MessageBoxA(0, msg1, title, 0);
push dword 0
push dword ClassName
push dword TextLabel
push dword 0
call [MessageBoxA]
ret
section .data
ClassName db "Main Window", 0
ApplicationName db "Win32 Assembler", 0
errMsg db "An error occured while making the new window.", 0
TextLabel db "Welcom to the main event!", 13, 10, 13, 10, 0
section .bss
hInstance resd 1
commandLine resd 1
Compile with :
nasm -fobj main.asm
alink -oPE main.obj -o main.exe
A little C program tell me that the size of PAINTSTRUCT (lpPaint)
should be 34
Really? What C compiler is that??? If you look up PAINTSTRUCT on MSDN:
typedef struct tagPAINTSTRUCT {
HDC hdc;
BOOL fErase;
RECT rcPaint;
BOOL fRestore;
BOOL fIncUpdate;
BYTE rgbReserved[32];
} PAINTSTRUCT, *PPAINTSTRUCT;
hdc = 4 bytes
fErase = 4 bytes
rcPaint = RECT` = 16 bytes
fRestore = 4 bytes
fIncUpdate = 4 bytes
rgbReserved = 32 bytes
and RECT:
typedef struct _RECT {
LONG left;
LONG top;
LONG right;
LONG bottom;
} RECT, *PRECT;
All of that added together gives you 64 bytes!!!
That is why [EBP-56] won't work, but [EBP-170] will work, plenty of room for the structure.

How to get window proc parameters?

I try to create the simplest WinAPI window using assembly NASM.
I have problem with Window Proc. Look at commented lines:
%macro API 2
import %1 %2
extern %1
%endmacro
API GetModuleHandleA, kernel32.dll
API LoadIconA,user32.dll
API LoadCursorA,user32.dll
API RegisterClassExA, user32.dll
API CreateWindowExA, user32.dll
API MessageBoxA, user32.dll
API SendMessageA, user32.dll
API DefWindowProcA, user32.dll
API ExitProcess, kernel32.dll
API GetMessageA, user32.dll
API DispatchMessageA, user32.dll
API TranslateMessage,user32.dll
API ShowWindow,user32.dll
API UpdateWindow,user32.dll
API GetCommandLineA,kernel32.dll
API PostQuitMessage,user32.dll
segment .data USE32
windowName db "Hello world!", 0
cmdLine dd 0
hWnd dd 0
hInst dd 0
hCursor dd 0
className db "moje_okno",0
blad db "Blad!!!",0
segment .bss
struc WNDCLASSEX
.sSize resb 4
.style resb 4
.wndProc resb 4
.clsExtra resb 4
.wndExtra resb 4
.hInstance resb 4
.hIcon resb 4
.hCursor resb 4
.background resb 4
.sMenuName resb 4
.sClassName resb 4
.hIconSm resb 4
endstruc
wndClass istruc WNDCLASSEX
iend
global ..start
segment .text USE32
..start:
push 0
call [GetModuleHandleA]
mov dword [hInst], eax ; application handle
push dword 0x00007f00 ; MAKEINTRESOURCE(32512)
push dword 0
call [LoadCursorA]
mov dword [hCursor], eax ; cursor handle
mov dword [wndClass + WNDCLASSEX.sSize], dword 48 ; struct size
mov dword [wndClass + WNDCLASSEX.style], dword 0 ; style
mov dword [wndClass + WNDCLASSEX.wndProc], wndproc ; window proc
mov dword [wndClass + WNDCLASSEX.clsExtra], dword 0
mov dword [wndClass + WNDCLASSEX.wndExtra], dword 0
mov eax, dword [hInst]
mov dword [wndClass + WNDCLASSEX.hInstance], eax ; handle
mov dword [wndClass + WNDCLASSEX.hIcon], dword 0
mov eax, dword [hCursor]
mov dword [wndClass + WNDCLASSEX.hCursor], eax
mov dword [wndClass + WNDCLASSEX.background], dword 0
mov dword [wndClass + WNDCLASSEX.sMenuName], dword 0
mov dword [wndClass + WNDCLASSEX.sClassName], className ; class name
mov dword [wndClass + WNDCLASSEX.hIconSm], dword 0
push wndClass
call [RegisterClassExA]
call near sprawdz_blad ; check return value of RegisterClassExA
push 0 ; param
push dword [hInst] ; handle
push 0 ;hMenu
push 0 ;parent
push 200 ;height
push 200 ;width
push 200 ;y
push 200 ;x
push 0 ;style
push className ;window name
push className ;window class
push 0 ;extended style
call [CreateWindowExA]
push eax
call near sprawdz_blad ;check return value of CreateWindowExA. RETURNS 0
push 0
call [ExitProcess]
wndproc:
; HERE I NEED ACCESS TO WINDOW PROC PARAMETERS: HWND, MSG, WPARAM, LPARAM
; I TRIED:
pop eax
pop ebx
pop ecx
pop edx
; BUT IT DOESN'T WORK
; THERE ARE NOT RIGHT VALUES IN THESE REGISTRIES
ret
box:
push 0
push blad
push blad
push 0
call [MessageBoxA]
ret
sprawdz_blad:
pop eax
cmp eax, 0
jne ok ; if function returns 0 everything is allright
push 0
push blad
push blad
push 0
call [MessageBoxA]
push 1
call [ExitProcess]
ok:
ret
I try to make it work for hours but I'm out of ideas.
Please help.
Greetings, Michal.
A called subroutine, wheether you call it yourself or it's called by Windows (like wndproc) has its return address as the first thing on the stack. You do NOT want to pop this! To access the parameters, you need to look farther up the stack. Try something like...
wndproc:
mov eax, [esp + 4]
mov ebx, [esp + 8]
; etc...
See if that helps...
Best,
Frank

RegisterClassEx in Assembly

I'm trying to manually call RegisterClassEx Windows API without using a WNDCLASS structure on .data section, I need to create this structure only using push instruction.
Could someone help me on that please?
Thanks a lot
In fact you can easily do what you want. You just need to be careful to correctly calculate the addresses of each element of the structure. But this is also an easy task... ;)
Please check out the code I did:
WinMain:
push ebp
mov ebp, esp
add esp, -50h
push 7F00h
push 0h
call LoadIconA
mov ebx, eax
push 7F00h
push 0h
call LoadCursorA
;eax = return of LoadCursorA
;ebx = return of LoadIconA
mov dword ptr ss:[ebp-30h], 30h ;WNDCLASSEX.cbSize, dd WNDCLASSEX_size
mov dword ptr ss:[ebp-2Ch], 3h ;WNDCLASSEX.style, dd CS_VREDRAW + CS_HREDRAW
mov dword ptr ss:[ebp-28h], WndProc ;WNDCLASSEX.lpfnWndProc, dd WndProc
mov dword ptr ss:[ebp-24h], 0h ;WNDCLASSEX.cbClsExtra, dd NULL
mov dword ptr ss:[ebp-20h], 0h ;WNDCLASSEX.cbWndExtra, dd NULL
mov dword ptr ss:[ebp-1Ch], 0h ;WNDCLASSEX.hInstance, dd NULL
mov dword ptr ss:[ebp-18h], ebx ;WNDCLASSEX.hIcon, dd return of LoadIconA
mov dword ptr ss:[ebp-14h], eax ;WNDCLASSEX.hIconSm, dd return of LoadCursorA
mov dword ptr ss:[ebp-10h], 06h ;WNDCLASSEX.hbrBackground, dd COLOR_BTNFACE + 1
mov dword ptr ss:[ebp-0Ch], 0h ;WNDCLASSEX.lpszMenuName, dd NULL
mov dword ptr ss:[ebp-08h], offset WndProc ;WNDCLASSEX.lpszClassName, dd offset of ClassName
mov dword ptr ss:[ebp-04h], ebx ;WNDCLASSEX.hCursor, dd return of LoadIconA
lea eax,[ebp-30h]
push eax
call RegisterClassEx
You just need to put this before the call to CreateWindow.
Any doubt just shout.
PS.: Remember that WndProc is the loop procedure of your Assembly program
.data
wndclass WNDCLASS
.code
push offset wndclass
call RegisterClassEx
You should push its offset, not structure itself
For local variable, push its address
LOCAL wndclass:WNDCLASS
lea edx, wndclass
push edx
call RegisterClassEx
Reverse push the structure to the stack, push the effective address to the first item, call RegisterClassEx, pop the structure off the stack.

Resources