Повреждение RIP после NtUserCreateWindowEx

Тема в разделе "MASM", создана пользователем mantissa, 5 ноя 2022.

Метки:
  1. mantissa

    mantissa Мембер Команда форума

    Публикаций:
    0
    Регистрация:
    9 сен 2022
    Сообщения:
    155
    Есть следующий код:
    Код (Text):
    1. include win64a.inc
    2.  
    3. .code
    4.  
    5. WinMain proc <13>
    6. local hWnd:qword
    7. local msg:MSG
    8. local wnd:WNDCLASSEX
    9. mov rdi, offset wndName                 ;WndName
    10. invoke LoadCursorA, 0, IDC_APPSTARTING
    11. mov wnd.hCursor, rax
    12. invoke LoadIconA, 0, IDI_APPLICATION
    13. mov wnd.hIcon, rax
    14. mov wnd.hIconSm, rax
    15. mov wnd.lpszClassName, rdi
    16. mov wnd.hInstance, IMAGE_BASE
    17. mov rax, offset Wndproc
    18. mov wnd.lpfnWndProc, rax
    19. mov wnd.cbSize, sizeof WNDCLASSEX
    20. mov wnd.hbrBackground, COLOR_WINDOWFRAME
    21. lea rax, wnd
    22. invoke RegisterClassExA, rax
    23. invoke CreateWindowExA, 0, rdi, rdi, WS_OVERLAPPEDWINDOW or WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 600, 800, 0, 0, IMAGE_BASE, 0
    24. mov hWnd, rax
    25. ret
    26. WinMain endp
    27.  
    28. Wndproc proc <12,8,4,8,8> hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
    29. jmp NtdllDefWindowProc_
    30. ret
    31. Wndproc endp
    32. .data
    33. wndName db "test", 0
    34. end
    Перед вызовом CreateWindowExA invoke положил все параметры куда надо, со стеком все в порядке. Генерируется следующий код(отладчик):
    [​IMG]
    Параметры (в регистрах и на стеке):
    [​IMG]
    После вызова CreateWindowExA и соответственно внутри NtUserCreateWindowEx, нарушается RIP и меня выкидывает непонятно куда.
    [​IMG]
    В win64a.inc заданы две опции:
    1. OPTION PROLOGUE:rbpFramePrologue

    2. OPTION EPILOGUE:rbpFrameEpilogue
    Прикрепляю архив с исходниками и bat файлом с помощью которого компилирую.
    Также задал вопрос на StackOverFlow, где есть код без invoke, а с полностью ручным управлением стека, но все равно та же ошибка появляется.
    Пароль от архива: wasm
     

    Вложения:

    • src.7z
      Размер файла:
      1,5 КБ
      Просмотров:
      169
    • src.7z
      Размер файла:
      1,5 КБ
      Просмотров:
      153
    Последнее редактирование: 5 ноя 2022
  2. M0rg0t

    M0rg0t Well-Known Member

    Публикаций:
    0
    Регистрация:
    18 окт 2010
    Сообщения:
    1.576
    почему файл src.asm запаролен?
    ну я понял что пароль wasm , но смысл?
     
  3. mantissa

    mantissa Мембер Команда форума

    Публикаций:
    0
    Регистрация:
    9 сен 2022
    Сообщения:
    155
    Нет смысла, ведь exe нет, но я по привычке запаролил.
     
  4. M0rg0t

    M0rg0t Well-Known Member

    Публикаций:
    0
    Регистрация:
    18 окт 2010
    Сообщения:
    1.576
    mantissa, зачем константа IMAGE_BASE , это же 64 бит, оно может собраться хз с какой базой. Мне кажется, лучше брать GetModuleHandle
     
  5. mantissa

    mantissa Мембер Команда форума

    Публикаций:
    0
    Регистрация:
    9 сен 2022
    Сообщения:
    155
    У меня у линковщика /fixed указан, он всегда по IMAGE_BASE загружается
     
  6. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.792
    mantissa,
    попробуйте найти разницу ;)
    Код (ASM):
    1. ; GUI #
    2. include win64a.inc
    3. .code
    4. WinMain proc
    5. local msg:MSG
    6. local wnd:WNDCLASSEX
    7.  
    8.        mov edi,offset wndName                 ;WndName
    9.        invoke LoadCursorA, 0, IDC_ARROW
    10.        mov wnd.hCursor, rax
    11.        invoke LoadIconA, 0, IDI_APPLICATION
    12.        mov wnd.hIcon, rax
    13.        mov wnd.hIconSm, rax
    14.        mov wnd.lpszClassName, rdi
    15.        mov wnd.hInstance, IMAGE_BASE
    16.        movr wnd.lpfnWndProc,Wndproc
    17.        mov wnd.cbSize, sizeof WNDCLASSEX
    18.        mov wnd.hbrBackground, COLOR_WINDOWFRAME
    19.        lea ecx,wnd
    20.        invoke RegisterClassExA
    21.        invoke CreateWindowExA,0,edi,edi,WS_OVERLAPPEDWINDOW or WS_VISIBLE, CW_USEDEFAULT,\
    22.        CW_USEDEFAULT, 600, 800, 0, 0, IMAGE_BASE, 0
    23.        lea edi,msg
    24. @@:    invoke GetMessageA,edi,NULL,0,0
    25.        invoke DispatchMessageA,edi
    26.        jmp @b
    27. WinMain endp
    28. Wndproc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
    29.        cmp edx,WM_DESTROY
    30.        je wmDESTROY
    31.        leave
    32.        jmp NtdllDefWindowProc_
    33. wmDESTROY:invoke RtlExitUserProcess,NULL
    34. Wndproc endp
    35. .data
    36. wndName db "test", 0
    37. end
     
  7. mantissa

    mantissa Мембер Команда форума

    Публикаций:
    0
    Регистрация:
    9 сен 2022
    Сообщения:
    155
    Поменял WndProc на ваш и все заработало. Спасибо. Теперь осталось понять, чего же такого нет в моем WndProc`е..
    Причем я не добавлял цикл обработки сообщений..
    Итоговый код стал таким:
    Код (ASM):
    1. include win64a.inc
    2.  
    3. .code
    4.  
    5. WinMain proc <13>
    6. local hWnd:qword
    7. local msg:MSG
    8. local wnd:WNDCLASSEX
    9. mov rdi, offset wndName                 ;WndName
    10. invoke LoadCursorA, 0, IDC_APPSTARTING
    11. mov wnd.hCursor, rax
    12. invoke LoadIconA, 0, IDI_APPLICATION
    13. mov wnd.hIcon, rax
    14. mov wnd.hIconSm, rax
    15. mov wnd.lpszClassName, rdi
    16. mov wnd.hInstance, IMAGE_BASE
    17. mov rax, offset Wndproc
    18. mov wnd.lpfnWndProc, rax
    19. mov wnd.cbSize, sizeof WNDCLASSEX
    20. mov wnd.hbrBackground, COLOR_WINDOWFRAME
    21. invoke RegisterClassExA, &wnd
    22. invoke CreateWindowExA, 0, rdi, rdi, WS_OVERLAPPEDWINDOW or WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 600, 800, 0, 0, IMAGE_BASE, 0
    23. mov hWnd, rax
    24. ret
    25. WinMain endp
    26.  
    27. Wndproc proc <12,8,4,8,8> hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
    28.        cmp edx,WM_DESTROY
    29.        je wmDESTROY
    30.        leave
    31.        jmp NtdllDefWindowProc_
    32. wmDESTROY:invoke RtlExitUserProcess,NULL
    33. Wndproc endp
    34. .data
    35. wndName db "test", 0
    36. end
     
  8. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.792
    mantissa,
    а мне кажется, что причина в отсутствии цикла сообщений. А что у вас в угловых скобках после proc? <13> и <12,8,4,8,8>?
     
  9. mantissa

    mantissa Мембер Команда форума

    Публикаций:
    0
    Регистрация:
    9 сен 2022
    Сообщения:
    155
    Проверил еще раз, работает с вашим Wndproc и функция CreateWindowExA возвращает корректное значение, а с моим Wndproc RIP повреждается. И все это без цикла.
    Это можно проверить, добавив в мой код вашу функцию, собрать программу и попробовать запустить, появится окошко и сразу исчезнет, а с моей даже не появится (через отладчик видно, что происходит нарушение RIP в NtUserCreateWindowEx)
     
  10. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.792
    Наверное причина в leave перед jmp NtdllDefWindowProc_. Когда в процедуру передаются аргументы или есть локальные переменные компилятор вставляет в процедуру пролог (enter)
    Без цикла сообщений у меня на семерке, окно появляется на долю секунды и исчезает. А программа закрывается. Только что заметил, что вы уже написали об этом. Это не диалоговая программа и не консольная, цикл просто необходим
     
    mantissa нравится это.
  11. mantissa

    mantissa Мембер Команда форума

    Публикаций:
    0
    Регистрация:
    9 сен 2022
    Сообщения:
    155
    В угловых скобках 4 параметра, которые определяют пролог функции и используются следующим образом:
    1. 12 означает, что в функции будут вызываться функции не больше чем с 12 параметрами, соответственно все Invoke будут выделять в стеке 12*8 байт, учитывая "домашнее место" для регистров, соответственно параметр не может быть меньше 4. Если совсем не указывать этот параметр, то в стеке выделяется место только для 7 параметров (4 в регистрах и 3 в стеке); В WinMain я вызываю CreateWindowExA с 12 параметрами, поэтому указываю после proc <12> (я указал 13 для теста) и тогда в стеке выделяется точно столько места (96 байт).
    2. Остальные четыре числа 8,4,8,8 это размеры в байтах, первых четырёх аргументов которые в начале находятся в регистрах rcx, rdx, r8, r9. Если указать, то они автоматически сохранятся в свое домашнее место в стеке [rsp + 8] и т.д.
    Я и судя по всему Вы тоже, используем в win64a.inc temphls.inc, который содержит высокоуровневые определения типа Invoke и эти угловые скобки для пролога.
    Информация отсюда Клик
     
    Последнее редактирование: 5 ноя 2022
    Mikl___ нравится это.