На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Перед отправкой сообщения внимательно прочтите правила раздела!!!
1. Запрещается обсуждать написание вирусов, троянов и других вредоносных программ!
2. Помните, что у нас есть FAQ раздела Assembler и Полезные ссылки. Посмотрите, возможно, там уже имеется решение вашего вопроса.

3. Настоятельно рекомендуем обратить особое внимание на правила форума, которые нарушаются чаще всего:
  3.1. Заголовок темы должен кратко отражать её суть. Темы с заголовками типа "Срочно помогите!" или "Ассемблер" будут отправляться в Корзину для мусора.
  3.2. Исходники программ обязательно выделяйте тегами [code]...[/code] (одиночные инструкции можно не выделять).
  3.3. Нежелательно поднимать старые темы (не обновлявшиеся более года) без веской на то причины.

Не забывайте также про главные Правила форума!

Добро пожаловать и приятного вам общения!!! ;)
 
Модераторы: Jin X, Qraizer
  
> Валится MessageBoxW
    Вот такая программулька.

    ExpandedWrap disabled
          .CODE
       
      extrn   ExitProcess:proc
      extrn   MessageBoxW:proc
       
      header  dw  'A', 'M', 'D', '6', '4', 0
      message dw  'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!', 0
       
      EntryPoint  proc
          xor rcx, rcx
          lea rdx, message
          lea r8, header
          xor r9, r9
          call    MessageBoxW
       
          xor rcx, rcx
          call    ExitProcess
      EntryPoint  endp
       
       
          END


    И валится при вызове MessageBoxW: Exception thrown at 0x00007FFB8012971C (user32.dll) in msgbox.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.

    Коллстек такой:
    ExpandedWrap disabled
          user32.dll!GetMessageBoxFontForDpi(unsigned int)
          user32.dll!SoftModalMessageBox()
          user32.dll!MessageBoxWorker(struct _MSGBOXDATA *)
          user32.dll!MessageBoxTimeoutW()
          user32.dll!MessageBoxW()
          msgbox.exe!EntryPoint() Line 16


    Может надо какую-то инициализацию для USER32.DLL дополнительную делать?
      1) Надо выделять в стеке место для параметров MessageBoxW
      2) Стек необходимо выравнивать на 16 байт

      ExpandedWrap disabled
        EntryPoint:
            enter 32,  0 ; Выравнивает стек запихивая туда rbp и выделяет 32 байта для вызовов MessageBoxW и ExitProcess
         
            xor   r9,  r9
            lea   r8,  header
            lea   rdx, message
            xor   ecx, ecx
            call  MessageBoxW
         
            xor   ecx, ecx
            call  ExitProcess


      ADD: чтобы не спрашивать про такие ошибки надо использовать отладчик. Скажем x64dbg
      Сообщение отредактировано: macomics -
        Как минимум нужно убедиться, что стек выровнен на 16 байт. Добавь в начало
        ExpandedWrap disabled
          and     rsp, not 0Fh
        Вообще, у x64 API немало отличий от x86 API
          Ух ты! Заработало! Спасибо.

          Но не понял, зачем выделять в стеке 32 байта для вызовов MessageBoxW и ExitProcess. Почём я знаю, сколько им нужно выделить? Разве они сами не должны этим заниматься?
          Поэтому я попробовал инструкцию enter 0, 0 - все нормально.

          Т.е. можно быть уверенным, что инструкция enter однозначно выровняет стек на 16 байт? Заглянул что C-Runtime делает

          ExpandedWrap disabled
            extern "C" DWORD wWinMainCRTStartup(LPVOID)
            {
            00007FF6AA37A6F0  mov         qword ptr [rsp+8],rcx  
            00007FF6AA37A6F5  sub         rsp,28h  
                return __scrt_common_main();
            00007FF6AA37A6F9  call        __scrt_common_main (07FF6AA37A450h)  
            }
            00007FF6AA37A6FE  add         rsp,28h  
            00007FF6AA37A702  ret


          Ну и дальше пошагал - как правило первая инструкция sub rsp, минимум 28h

          Или я не прав и таки надо 32 байта для чего-то выделять?


          З.Ы. отладчик я использую Visual Studio.

          Добавлено
          Цитата Qraizer @
          Как минимум нужно убедиться, что стек выровнен на 16 байт. Добавь в начало
          ExpandedWrap disabled
            and     rsp, not 0Fh
          Вообще, у x64 API немало отличий от x86 API

          Ага, когда вызывается функция, выравнивание сбивается, ибо в стек помещается как минимум 8 байт адреса возврата. В общем с выравниванием понятно. Вопрос только про 32 байта - нужны ли они?
            Цитата GAGARIN @
            Но не понял, зачем выделять в стеке 32 байта для вызовов MessageBoxW и ExitProcess. Почём я знаю, сколько им нужно выделить? Разве они сами не должны этим заниматься?
            Поэтому я попробовал инструкцию enter 0, 0 - все нормально.

            Прям самый первый же абзац. Первые 4 параметра передаются через регистры, но под них все равно надо выделять место в стеке.

            Добавлено
            Цитата GAGARIN @
            Ну и дальше пошагал - как правило первая инструкция sub rsp, минимум 28h

            028h этот как раз 32 байта + 8 байт на push rbp, которую положит enter 32, 0
              Всё понятно. Вопрос закрыт. Большое спасибо.

              Добавлено
              Цитата macomics @
              028h этот как раз 32 байта + 8 байт на push rbp, которую положит enter 32, 0

              rbp там не пушается. 8 байт - это адрес возврата, который, собственно, и сбивает 16-байтное выравнивание стека.
                Цитата GAGARIN @
                rbp там не пушается. 8 байт - это адрес возврата, который, собственно, и сбивает 16-байтное выравнивание стека.

                rbp запушит enter. enter N,0 эквивалентна последовательности
                ExpandedWrap disabled
                  ; enter N, 0
                  push rbp ; этот push rbp вместе с push rip как часть call label как раз и дадут выравнивание стека (8+8)
                  mov rbp, rsp
                  sub rsp, N
                Сообщение отредактировано: macomics -
                  Ну так никто не делает. Во всяком случае MS компилер делает так:

                  ExpandedWrap disabled
                    foo proc
                       sub rsp, 28h ; (+ сколько там нужно на локальные переменные)
                       ...


                  И да, в X64, enter 32, 0 не помещает rbp в стек. Наверное поэтому эта инструкция и не используется, т.к. проще sub rsp сразу выделить сколько нужно.

                  Добавлено
                  Сделал так.
                  ExpandedWrap disabled
                        .CODE
                     
                    extrn   ExitProcess:proc
                    extrn   MessageBoxW:proc
                    extrn   MessageBeep:proc
                     
                    header  dw  'A', 'M', 'D', '6', '4', 0
                    message dw  'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!', 0
                     
                    beep        proc
                        sub rsp, 28h
                     
                        xor rcx, rcx
                        dec rcx
                        call    MessageBeep
                     
                        add rsp, 28h
                        ret
                    beep        endp
                     
                    EntryPoint  proc
                        sub rsp, 28h
                     
                        call    beep
                     
                        xor rcx, rcx
                        lea rdx, message
                        lea r8, header
                        xor r9, r9
                        call    MessageBoxW
                     
                        xor rcx, rcx
                        call    ExitProcess
                    EntryPoint  endp
                     
                     
                        END


                  Нраицца!
                    Цитата GAGARIN @
                    И да, в X64, enter 32, 0 не помещает rbp в стек. Наверное поэтому эта инструкция и не используется, т.к. проще sub rsp сразу выделить сколько нужно.

                    Скрытый текст
                    ExpandedWrap disabled
                      macomics@home-kde ~/testDir/testEnterPushRBP $ nano main.asm
                      macomics@home-kde ~/testDir/testEnterPushRBP $ cat main.asm
                      format ELF64 executable 3
                      segment executable
                      entry $
                              mov   rbp, $FEDCBA9876543210
                              enter 32, 0
                       
                              mov  edx, mess.len
                              lea  rsi, [mess]
                              push 1
                              pop  rdi
                              mov  eax, edi
                              syscall
                       
                              mov  eax, 60
                              xor  dil, dil
                              syscall
                       
                      mess db 'Wellcome text!', 0xa
                      .len = $ - mess
                      macomics@home-kde ~/testDir/testEnterPushRBP $ fasm main.asm
                      flat assembler  version 1.73.32  (16384 kilobytes memory, x64)
                      2 passes, 178 bytes.
                      macomics@home-kde ~/testDir/testEnterPushRBP $ gdb -q ./main
                      Reading symbols from ./main...
                      (No debugging symbols found in ./main)
                      (gdb) define showstack
                      Type commands for definition of "showstack".
                      End with a line saying just "end".
                      >printf "0x%016lX  0x%016lX\n", $rsp+0x00, *(unsigned long long *)($rsp+0x00)
                      >printf "0x%016lX  0x%016lX\n", $rsp+0x08, *(unsigned long long *)($rsp+0x08)
                      >printf "0x%016lX  0x%016lX\n", $rsp+0x10, *(unsigned long long *)($rsp+0x10)
                      >printf "0x%016lX  0x%016lX\n", $rsp+0x18, *(unsigned long long *)($rsp+0x18)
                      >printf "0x%016lX  0x%016lX\n", $rsp+0x20, *(unsigned long long *)($rsp+0x20)
                      >printf "0x%016lX  0x%016lX\n", $rsp+0x28, *(unsigned long long *)($rsp+0x28)
                      >printf "0x%016lX  0x%016lX\n", $rsp+0x30, *(unsigned long long *)($rsp+0x30)
                      >printf "0x%016lX  0x%016lX\n", $rsp+0x38, *(unsigned long long *)($rsp+0x38)
                      >printf "0x%016lX  0x%016lX\n", $rsp+0x40, *(unsigned long long *)($rsp+0x40)
                      >printf "0x%016lX  0x%016lX\n", $rsp+0x48, *(unsigned long long *)($rsp+0x48)
                      >end
                      (gdb) define showcpu
                      Type commands for definition of "showcpu".
                      End with a line saying just "end".
                      >x /5i $pc
                      >info registers
                      >showstack
                      >end
                      (gdb) define stepcmd
                      Type commands for definition of "stepcmd".
                      End with a line saying just "end".
                      >nexti
                      >showcpu
                      >end
                      (gdb) shell readelf -h ./main
                      Заголовок ELF:
                        Magic:   7f 45 4c 46 02 01 01 03 00 00 00 00 00 00 00 00
                        Класс:                             ELF64
                        Данные:                            дополнение до 2, от младшего к старшему
                        Version:                           1 (current)
                        OS/ABI:                            UNIX - GNU
                        Версия ABI:                        0
                        Тип:                               EXEC (Исполняемый файл)
                        Машина:                            Advanced Micro Devices X86-64
                        Версия:                            0x1
                        Адрес точки входа:                 0x400078
                        Начало заголовков программы:       64 (байт в файле)
                        Начало заголовков раздела:         0 (байт в файле)
                        Флаги:                             0x0
                        Size of this header:               64 (bytes)
                        Size of program headers:           56 (bytes)
                        Number of program headers:         1
                        Size of section headers:           64 (bytes)
                        Number of section headers:         0
                        Section header string table index: 0
                      (gdb) break *0x400078
                      Breakpoint 1 at 0x400078
                      (gdb) run
                      Starting program: /home/macomics/testDir/testEnterPushRBP/main
                       
                      Breakpoint 1, 0x0000000000400078 in ?? ()
                      (gdb) showcpu
                      => 0x400078:    movabs rbp,0xfedcba9876543210
                         0x400082:    enter  0x20,0x0
                         0x400086:    mov    edx,0xf
                         0x40008b:    lea    rsi,[rip+0x11]        # 0x4000a3
                         0x400092:    push   0x1
                      rax            0x0                 0
                      rbx            0x0                 0
                      rcx            0x0                 0
                      rdx            0x0                 0
                      rsi            0x0                 0
                      rdi            0x0                 0
                      rbp            0x0                 0x0
                      rsp            0x7fffffffd560      0x7fffffffd560
                      r8             0x0                 0
                      r9             0x0                 0
                      r10            0x0                 0
                      r11            0x0                 0
                      r12            0x0                 0
                      r13            0x0                 0
                      r14            0x0                 0
                      r15            0x0                 0
                      rip            0x400078            0x400078
                      eflags         0x202               [ IF ]
                      cs             0x33                51
                      ss             0x2b                43
                      ds             0x0                 0
                      es             0x0                 0
                      fs             0x0                 0
                      gs             0x0                 0
                      k0             0x0                 0
                      k1             0x0                 0
                      k2             0x0                 0
                      k3             0x0                 0
                      k4             0x0                 0
                      k5             0x0                 0
                      k6             0x0                 0
                      k7             0x0                 0
                      fs_base        0x0                 0
                      gs_base        0x0                 0
                      0x00007FFFFFFFD560  0x0000000000000001
                      0x00007FFFFFFFD568  0x00007FFFFFFFD9CC
                      0x00007FFFFFFFD570  0x0000000000000000
                      0x00007FFFFFFFD578  0x00007FFFFFFFD9F9
                      0x00007FFFFFFFD580  0x00007FFFFFFFDA09
                      0x00007FFFFFFFD588  0x00007FFFFFFFDA5F
                      0x00007FFFFFFFD590  0x00007FFFFFFFDA71
                      0x00007FFFFFFFD598  0x00007FFFFFFFDA85
                      0x00007FFFFFFFD5A0  0x00007FFFFFFFDAC1
                      0x00007FFFFFFFD5A8  0x00007FFFFFFFDAD6
                      (gdb) stepcmd
                      0x0000000000400082 in ?? ()
                      => 0x400082:    enter  0x20,0x0
                         0x400086:    mov    edx,0xf
                         0x40008b:    lea    rsi,[rip+0x11]        # 0x4000a3
                         0x400092:    push   0x1
                         0x400094:    pop    rdi
                      rax            0x0                 0
                      rbx            0x0                 0
                      rcx            0x0                 0
                      rdx            0x0                 0
                      rsi            0x0                 0
                      rdi            0x0                 0
                      rbp            0xfedcba9876543210  0xfedcba9876543210
                      rsp            0x7fffffffd560      0x7fffffffd560
                      r8             0x0                 0
                      r9             0x0                 0
                      r10            0x0                 0
                      r11            0x0                 0
                      r12            0x0                 0
                      r13            0x0                 0
                      r14            0x0                 0
                      r15            0x0                 0
                      rip            0x400082            0x400082
                      eflags         0x202               [ IF ]
                      cs             0x33                51
                      ss             0x2b                43
                      ds             0x0                 0
                      es             0x0                 0
                      fs             0x0                 0
                      gs             0x0                 0
                      k0             0x0                 0
                      k1             0x0                 0
                      k2             0x0                 0
                      k3             0x0                 0
                      k4             0x0                 0
                      k5             0x0                 0
                      k6             0x0                 0
                      k7             0x0                 0
                      fs_base        0x0                 0
                      gs_base        0x0                 0
                      0x00007FFFFFFFD560  0x0000000000000001
                      0x00007FFFFFFFD568  0x00007FFFFFFFD9CC
                      0x00007FFFFFFFD570  0x0000000000000000
                      0x00007FFFFFFFD578  0x00007FFFFFFFD9F9
                      0x00007FFFFFFFD580  0x00007FFFFFFFDA09
                      0x00007FFFFFFFD588  0x00007FFFFFFFDA5F
                      0x00007FFFFFFFD590  0x00007FFFFFFFDA71
                      0x00007FFFFFFFD598  0x00007FFFFFFFDA85
                      0x00007FFFFFFFD5A0  0x00007FFFFFFFDAC1
                      0x00007FFFFFFFD5A8  0x00007FFFFFFFDAD6
                      (gdb) stepcmd
                      0x0000000000400086 in ?? ()
                      => 0x400086:    mov    edx,0xf
                         0x40008b:    lea    rsi,[rip+0x11]        # 0x4000a3
                         0x400092:    push   0x1
                         0x400094:    pop    rdi
                         0x400095:    mov    eax,edi
                      rax            0x0                 0
                      rbx            0x0                 0
                      rcx            0x0                 0
                      rdx            0x0                 0
                      rsi            0x0                 0
                      rdi            0x0                 0
                      rbp            0x7fffffffd558      0x7fffffffd558
                      rsp            0x7fffffffd538      0x7fffffffd538
                      r8             0x0                 0
                      r9             0x0                 0
                      r10            0x0                 0
                      r11            0x0                 0
                      r12            0x0                 0
                      r13            0x0                 0
                      r14            0x0                 0
                      r15            0x0                 0
                      rip            0x400086            0x400086
                      eflags         0x202               [ IF ]
                      cs             0x33                51
                      ss             0x2b                43
                      ds             0x0                 0
                      es             0x0                 0
                      fs             0x0                 0
                      gs             0x0                 0
                      k0             0x0                 0
                      k1             0x0                 0
                      k2             0x0                 0
                      k3             0x0                 0
                      k4             0x0                 0
                      k5             0x0                 0
                      k6             0x0                 0
                      k7             0x0                 0
                      fs_base        0x0                 0
                      gs_base        0x0                 0
                      0x00007FFFFFFFD538  0x0000000000000000
                      0x00007FFFFFFFD540  0x0000000000000000
                      0x00007FFFFFFFD548  0x0000000000000000
                      0x00007FFFFFFFD550  0x0000000000000000
                      0x00007FFFFFFFD558  0xFEDCBA9876543210
                      0x00007FFFFFFFD560  0x0000000000000001
                      0x00007FFFFFFFD568  0x00007FFFFFFFD9CC
                      0x00007FFFFFFFD570  0x0000000000000000
                      0x00007FFFFFFFD578  0x00007FFFFFFFD9F9
                      0x00007FFFFFFFD580  0x00007FFFFFFFDA09
                      (gdb) continue
                      Continuing.
                      [Inferior 1 (process 30131) exited normally]
                      (gdb) q
                    Вот я вам наглядно показываю как действует enter. Как можете видеть сначала я распечатал состояние регистров и стека до выполнения команды
                    ExpandedWrap disabled
                      mov rbp, 0xFEDCBA9876543210

                    И там мы видим 0 в rbp
                    После выполнения команды mov как и ожидалось в rbp появляется 0xFEDCBA9876543210
                    Ну и после команды enter 32, 0 мы видим, что значение rbp изменилось и стало равно rsp - 32.
                    И в стеке у нас появилось место для 32 байт плюс то самое значение из rbp (0xFEDCBA9876543210). Итого в стек положили 40 байт, из которых 8 это старое значение rbp до выполнения команды enter
                    Сообщение отредактировано: macomics -
                      Да? Ну да бог с ним, с этим rbp)
                        Ну можете так же еще заметить, что после enter значение в rbp указывает на адрес в стеке где и лежит предыдущее его же значение.
                        Обратной командой для enter является команда leave эквивалентная последовательности
                        ExpandedWrap disabled
                          mov rsp, rbp
                          pop rbp
                          Да это понятно всё. Я подумал, что это в AMD64 упразднили, ибо не видел, чтобы это использовалось.
                          1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                          0 пользователей:


                          Рейтинг@Mail.ru
                          [ Script execution time: 0,0450 ]   [ 14 queries used ]   [ Generated: 5.07.25, 23:57 GMT ]