assembly - 调用 WinApi 函数后 RIP 损坏

标签 assembly winapi x86-64 calling-convention masm64

在调用 CreateWindowExA 后,我有一个错误的 RIP,但在 NtUserCreateWindowEx 之后它已损坏,这是我通过 x64dbg 发现的,也许我在堆栈分配上做错了什么。

这是我的代码:

include win64a.inc

.code
WinMain proc
push rbp                        ; save old rbp
mov rbp, rsp                    ; set-up rbp
sub rsp, 20h                    ; allocate space for local vars
mov rcx, 0                      ; 1 param
mov rdx, IDC_ARROW              ; 2 param 
sub rsp, 20h                    ; allocate home-space
call LoadCursorA                
mov [rbp - 8h], rax             ; 1 local param, hCursor 
mov rcx, 0                      ; 1 param
mov rdx, IDI_APPLICATION        ; 2 param
call LoadIconA                  ; home-space allocated at 11 
mov [rbp - 10h], rax            ; 2 local param, hIcon
add rsp, 20h                    ; deallocate home-space
; Develope WNDCLASSEXA structure
push [rbp-10h]                  
pushaddr wndName
push 0
push COLOR_WINDOWFRAME
push [rbp-8h]
push [rbp-10h]
push IMAGE_BASE
push 0
pushaddr WndProc
push sizeof WNDCLASSEX

mov rcx, rsp                    ; 1 param - ptr to the structure
sub rsp, 20h                    ; allocate home-space
call RegisterClassExA
sub rsp, 40h                                ; Allocate stack for params
xor rcx, rcx                                ; dwExStyle
lea rdx, wndName                            ; lpClassName
lea r8, wndName                             ; lpWindowName
mov r9, WS_OVERLAPPEDWINDOW or WS_VISIBLE   ; dwStyle
mov qword ptr [rsp + 20h], 0                ; x
mov qword ptr [rsp + 28h], 0                ; y
mov qword ptr [rsp + 30h], 600              ; w
mov qword ptr [rsp + 38h], 800              ; h
mov qword ptr [rsp + 40h], 0                ; hWndParent
mov qword ptr [rsp + 48h], 0                ; hMenu
mov qword ptr [rsp + 50h], IMAGE_BASE       ; hInstance
mov qword ptr [rsp + 58h], 0                ; lpParam
call CreateWindowExA
add rsp, 40h                                ; Deallocate stack
mov [rbp-18h], rax                          ; 3 local param, hWnd
leave
WinMain endp

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
WndProc endp

.data
wndName db "test", 0
end

在 win64a.inc 中:

OPTION DOTNAME
OPTION PROLOGUE:rbpFramePrologue
OPTION EPILOGUE:rbpFrameEpilogue
include win64.inc
include temphls.inc
include ntdll.inc
includelib ntdll.lib
include user32.inc
includelib user32.lib
include gdi32.inc
includelib gdi32.lib
include kernel32.inc
includelib kernel32.lib
include shell32.inc
includelib shell32.lib
;---------------------------
pushaddr macro x
    db 68h
    dd x
endm
IMAGE_BASE  equ 400000h

所以我研究并绘制了堆栈分配的图形,这对我来说完全没问题,我有什么问题吗?

enter image description here

在它调用 NtUserCreateWindowEx RIP 损坏之后,我得到了这样的结果: enter image description here

enter image description here

而且我还使用 Invoke 宏创建版本,它会导致相同的错误:(我使用 MASM64 SDK )

include win64a.inc  

.code 

WinMain proc <13>
local hWnd:qword
local msg:MSG
local wnd:WNDCLASSEX
mov rdi, offset wndName                 ;WndName
invoke LoadCursorA, 0, IDC_APPSTARTING
mov wnd.hCursor, rax
invoke LoadIconA, 0, IDI_APPLICATION
mov wnd.hIcon, rax
mov wnd.hIconSm, rax
mov wnd.lpszClassName, rdi
mov wnd.hInstance, IMAGE_BASE
mov rax, offset Wndproc
mov wnd.lpfnWndProc, rax
mov wnd.cbSize, sizeof WNDCLASSEX
mov wnd.hbrBackground, COLOR_WINDOWFRAME
lea rax, wnd
invoke RegisterClassExA, rax
invoke CreateWindowExA, 0, rdi, rdi, WS_OVERLAPPEDWINDOW or WS_VISIBLE, 0, 0, 600, 800, 0, 0, IMAGE_BASE, 0
mov hWnd, rax
ret
WinMain endp

Wndproc proc <12,8,4,8,8> hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
jmp NtdllDefWindowProc_
ret
Wndproc endp
.data
wndName db "test", 0
end

生成以下代码:

enter image description here

以及 CreateWindowExA 调用之前的参数: enter image description here

和 ml64.exe/link.exe 选项:

  1. ml64.exe /I"%masm64_path%/include" /Zp16 /c /Cp %filename%.asm >>errors.txt
    
  2. link /LIBPATH:"%masm64_path%\lib" /LARGEADDRESSAWARE:NO /SUBSYSTEM:WINDOWS ^
     /STUB:%masm64_path%\bin\stubby.exe ^
     /entry:WinMain /fixed %filename%.obj
    

最佳答案

Michael Petch 和 bitRAKE 表示该问题的原因是 NtUserCreateWindowEx 在返回之前调用 WndProc 函数,因此我需要使用以下命令创建完整的 WndProc堆栈处理。 所以我添加了这个leave并且它现在可以工作了。

Wndproc proc <12,8,4,8,8> hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
leave                   ;<----------- Added to resolve issue
jmp NtdllDefWindowProc_
ret
Wndproc endp

关于assembly - 调用 WinApi 函数后 RIP 损坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74326400/

相关文章:

将 x86-64 代码转换为 Y86-64 代码

c++ - 无法在 Windows 10 下关闭 OSK.exe

c# - Winapi - 用户打印文件时的回调

assembly - 当 x86-64 linux 内核需要运行 x86-32 程序时,它做了什么?

c - 即使使用 -m32,32 位 shellcode 在汇编中执行,但在 64 位操作系统上不能在 c 中执行

c++ - 优化算术编码器

c++ - 为什么 std atomic 将 5 插入堆栈

windows - KEY_WOW64_32KEY 和 KEY_WOW64_64KEY

gcc - 退出系统调用的正确常量是什么?

x86 - "unscrambled"在这种情况下是什么意思?