【问题标题】:Win32 ASM stack overrideWin32 ASM 堆栈覆盖
【发布时间】:2014-04-06 20:13:31
【问题描述】:

我在 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 

【问题讨论】:

    标签: windows winapi assembly stack nasm


    【解决方案1】:

    一个小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] 会起作用,结构有足够的空间。

    【讨论】:

    • 该死的,我没有从数组中添加 31 个其他字节。看错了!非常感谢!
    猜你喜欢
    • 2012-04-02
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 2019-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多