Win32 ASM堆栈覆盖

时间:2014-03-05 01:00:33

标签: windows winapi assembly stack nasm

我在WindowPaint事件中调用BeginPaint(hWnd,lpPaint)时遇到问题。似乎函数BeginPaint覆盖了堆栈。

一个小C程序告诉我PAINTSTRUCT(lpPaint)的大小应该是34。 如果我把这个地址放到EBP-34或更多的EBP-56作为lpPaint的返回值,它会崩溃。如果我允许很多堆栈并将返回地址放到EBP-170上就可以了。

简单代码:

;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

编译:

nasm -fobj main.asm
alink -oPE main.obj -o main.exe 

1 个答案:

答案 0 :(得分:4)

  

一个小C程序告诉我PAINTSTRUCT(lpPaint)的大小   应该是34

真的?什么C编译器是???如果您在MSDN上查找PAINTSTRUCT

typedef struct tagPAINTSTRUCT { 
  HDC  hdc; 
  BOOL fErase; 
  RECT rcPaint; 
  BOOL fRestore; 
  BOOL fIncUpdate; 
  BYTE rgbReserved[32]; 
} PAINTSTRUCT, *PPAINTSTRUCT; 

hdc = 4个字节
fErase = 4个字节
rcPaint = RECT` = 16字节
fRestore = 4个字节
fIncUpdate = 4个字节
rgbReserved = 32个字节

RECT

typedef struct _RECT { 
  LONG left; 
  LONG top; 
  LONG right; 
  LONG bottom; 
} RECT, *PRECT; 

所有这些加起来给你64个字节!
这就是[EBP-56]不起作用的原因,但[EBP-170]会起作用,为结构留出足够的空间。