Сейчас на форуме: jinoweb (+6 невидимых)

 eXeL@B —› Программирование —› Вопрос по х64 асму
Посл.ответ Сообщение


Ранг: 150.3 (ветеран), 175thx
Активность: 0.160.07
Статус: Участник

Создано: 16 августа 2018 12:30 · Поправил: -=AkaBOSS=-
· Личное сообщение · #1

Приветствую собратьев ассемблерщиков!
Недавно решил поиграться 64 битным асмом, и засыпался на банальнейшем хелловорлде
Code:
  1.   frame
  2.   invoke MessageBoxW, 0, addr txt1, addr txt2, 0
  3.   invoke ExitProcess, 0
  4.   endf


Вроде ж ничего криминального, но программа упорно падает где-то в системных недрах:
Code:
  1. movaps xmmword [rsp+150],  xmm8   ; lpk.dll+1775 exception!


Эксепшен генерится ммх командой, которая ожидает, что записываемый адрес будет кратен 0х10
Таким образом, добавив в начало своей программы выравнивание стэка "and rsp, -16", я от проблемы избавился.

А теперь, собственно, вопрос: как правильно оформлять стек в х64?
Допустим, я вызываю апи функцию, которой нужно передать больше 4ёх аргументов - они пойдут через стэк.
Выравнивать нужно до стековых аргументов, или так, чтобы в итоге только 0x20 фрейм был выравнен?
Какие еще есть грабли, о которых нужно знать, чтобы писать на х64 асме?

[имхо]стандартное соглашение о вызовах - просто жесть дичайшая.
Вместо того, чтобы просто толкать первые четыре аргумента в стэк, они пишутся в регистры,
но вызывающая сторона всё равно должна выделить 0х20 байт в стэке, куда вызванная
функция сохраняет свои аргументы. О чём они, бл***, думали?
[/имхо]



cea1_16.08.2018_EXELAB.rU.tgz - buggy.exe



Ранг: 419.0 (мудрец), 647thx
Активность: 0.460.51
Статус: Участник
"Тибериумный реверсинг"

Создано: 16 августа 2018 12:58 · Поправил: ELF_7719116
· Личное сообщение · #2

Что студийный компиль нагенерил:
Code:
  1. ::MessageBoxW(NULL, L"TEXT", L"HEAD", MB_OK);
  2. 0000000140007940  mov         eax,0  
  3. 0000000140007945  lea         rdx,[string L"\x5400\x4500\x5800\x5400" (014031933Ch)]  
  4. 000000014000794C  lea         rcx,[string L"\x4800\x4500\x4100\x4400" (0140319348h)]  
  5. 0000000140007953  mov         ebx,0  
  6. 0000000140007958  mov         rsi,qword ptr [__imp_MessageBoxW (0140314FD0h)]  
  7. 000000014000795F  mov         qword ptr [rbp+298h],rcx  
  8. 0000000140007966  mov         rcx,rax 
  9. 0000000140007969  mov         rax,qword ptr [rbp+298h]  
  10. 0000000140007970  mov         r8,rax  
  11. 0000000140007973  mov         r9d,ebx  
  12. 0000000140007976  call        rsi  
  13. 0000000140007978  mov         dword ptr [rbp+22Ch],eax

как-бэ fastcall



Ранг: 369.8 (мудрец), 400thx
Активность: 0.390
Статус: Участник

Создано: 16 августа 2018 15:09 · Поправил: ntldr
· Личное сообщение · #3

ELF_7719116 пишет:
как-бэ fastcall

Обычный для x64 calling convention

-=AkaBOSS=- пишет:
Вместо того, чтобы просто толкать первые четыре аргумента в стэк, они пишутся в регистры,
но вызывающая сторона всё равно должна выделить 0х20 байт в стэке, куда вызванная
функция сохраняет свои аргументы. О чём они, бл***, думали?

Вообще-то это очень мудрое решение с точки зрения глобальной оптимизации кода. Стековые фреймы могут быть выделены один раз, функции можно вызывать много раз и разные.
Просто это всё не предназначено чтобы вручную писать на ассемблере. Юзайте си.

-----
PGP key <0x1B6A24550F33E44A>





Ранг: 271.4 (наставник), 331thx
Активность: 0.321.49
Статус: Участник

Создано: 16 августа 2018 15:14 · Поправил: f13nd
· Личное сообщение · #4

Code:
  1.         sub rsp,0x400
  2.         and rsp,not 31
  3.         invoke MessageBoxW, 0, addr txt1, addr txt2, MB_OK
  4.         invoke ExitProcess, 0
  5.         ret

Идея понятна?
С такой мишурой можно столкнуться и в х32, с Zw* и Nt* функциями.

-----
2 оттенка серого





Ранг: 2014.5 (!!!!), 1278thx
Активность: 1.340.25
Статус: Модератор
retired

Создано: 16 августа 2018 15:25
· Личное сообщение · #5

Есть отличная статья про переход на x64 https://www.codeproject.com/Articles/17263/Moving-to-Windows-Vista-x64
Это стандартная (и единственная) конвенция вызовов в x64. Всяко полезно ознакомиться.

| Сообщение посчитали полезным: ajax, -=AkaBOSS=-, plutos


Ранг: 71.5 (постоянный), 95thx
Активность: 0.10.38
Статус: Участник

Создано: 16 августа 2018 20:02 · Поправил: BlackCode
· Личное сообщение · #6

-=AkaBOSS=-
В х64 необходимо выравнивать стек на 16 байт, в противном случае будут проблемы описанные тобой.
Для решения оной юзаем макрос
Code:
  1.     ; ********************************************
  2.     ; align memory *
  3.     ; reg has the address of the memory to align *
  4.     ; number is the required alignment *
  5.     ; EXAMPLE : memalign esi, 16 *
  6.     ; ********************************************
  7.  
  8.       memalign MACRO reg, number
  9.         add reg, number - 1
  10.         and reg, -number
  11.       ENDM


В начале функции memalign rsp,16




Ранг: 150.3 (ветеран), 175thx
Активность: 0.160.07
Статус: Участник

Создано: 17 августа 2018 08:54
· Личное сообщение · #7

BlackCode, да причину-то я и сам понял, еще до создания темы.
Другое дело что мне было неясно, как при этом поступать с аргументами, которые передаются через стэк. Как выравнивать - до них или после.
Archer дал ссылку на статью, где это проясняется - выделяем фрейм размером <кол-во стековых аргументов>*8+0х20, округляем rsp вниз до 0х10 и стэковые аргументы не толкаем, а вписываем как-то так: mov [rsp+20h], arg5; mov [rsp+28h], arg6; и т.д.
И разумеется, перед каждым таким фреймом нужно сохранять rsp, так как после округления его уже простой математикой не восстановишь.




Ранг: 271.4 (наставник), 331thx
Активность: 0.321.49
Статус: Участник

Создано: 17 августа 2018 08:58
· Личное сообщение · #8

-=AkaBOSS=- пишет:
его уже простой математикой не восстановишь

Инструкцией leave такое округление восстановится само.

-----
2 оттенка серого





Ранг: 150.3 (ветеран), 175thx
Активность: 0.160.07
Статус: Участник

Создано: 17 августа 2018 09:09 · Поправил: -=AkaBOSS=-
· Личное сообщение · #9

f13nd пишет:
Инструкцией leave такое округление восстановится само.

если регистр не был предварительно сохранён - нет

f13nd пишет:
это всяко лучше

ну вообще в целом это уже зависит от того, как и для чего использовать стэк)




Ранг: 271.4 (наставник), 331thx
Активность: 0.321.49
Статус: Участник

Создано: 17 августа 2018 09:15
· Личное сообщение · #10

-=AkaBOSS=- пишет:
если регистр не был предварительно сохранён - нет

это всяко лучше, чем "перед каждым таким фреймом сохранять rsp"

-----
2 оттенка серого





Ранг: 71.5 (постоянный), 95thx
Активность: 0.10.38
Статус: Участник

Создано: 17 августа 2018 11:49
· Личное сообщение · #11

-=AkaBOSS=-

Ты какой компилятор используешь?
Я UASM64, ранее JWASM..
Как правило компилятор сам заботится об сохранении параметров и выделении стека под аргументы.
В заголовке у меня такие параметры
Code:
  1.     .686
  2.     .MMX
  3.     .XMM
  4.     .x64
  5.     option casemap:none
  6.     option frame:auto
  7.     option win64:11
  8.     option evex:1
  9.     option arch:AVX





Ранг: 2014.5 (!!!!), 1278thx
Активность: 1.340.25
Статус: Модератор
retired

Создано: 17 августа 2018 11:49
· Личное сообщение · #12

Leave-это просто автоматизированный аналог mov Xsp,Xbp; pop Xbp. Если в Xbp никто до этого не положил Xsp, будет мусор.
И в x64 фреймы используются достаточно нечасто в скомпилированном коде. В том числе и потому, что никто не делает там and Xsp,imm. А не делает потому, что на входе в функцию стек уже определённым образом выровнен, чем и пользуются.




Ранг: 338.5 (мудрец), 349thx
Активность: 2.112.42
Статус: Участник

Создано: 18 августа 2018 01:24
· Личное сообщение · #13

И из за компилерных фич трассировка ветвлений(backtrace) выполняется через брутфорс адресов

-----
vx




Ранг: 369.8 (мудрец), 400thx
Активность: 0.390
Статус: Участник

Создано: 24 августа 2018 08:34
· Личное сообщение · #14

BlackCode пишет:
UASM64

Не подскажешь поддерживает ли этот компилятор COMDAT сегменты?

-----
PGP key <0x1B6A24550F33E44A>





Ранг: 673.3 (! !), 400thx
Активность: 0.40.31
Статус: Участник
CyberMonk

Создано: 24 августа 2018 12:40 · Поправил: mak
· Личное сообщение · #15

ntldr пишет:
Не подскажешь поддерживает ли этот компилятор COMDAT сегменты?


Ассемблер, UASM64 ешё не компилятор .. поэтому COMDAT в основном не поддерживает, только на уровне самих сегментов, точно так же, как и масм64. Пример для уасм можно посмотреть здесь - --> Link <--

-----
RE In Progress [!] Coding Hazard [!] Stay Clear of this Cube




Ранг: 1.0 (гость)
Активность: 0=0
Статус: Участник

Создано: 14 декабря 2018 20:57
· Личное сообщение · #16

Привет всем мимо проходящим
Также приветствую собратьев ассемблерщиков
Хотел спросить кто в какой программе любит кодить, как вам Sublime Text ?
Вроде как неплохой редактор, с очень удобной подсветкой синтаксиса и прочих плюшек




Ранг: 77.2 (постоянный), 74thx
Активность: 0.190.15
Статус: Участник

Создано: 14 декабря 2018 21:00
· Личное сообщение · #17

HabibQq пишет:
Привет всем мимо проходящим

Дык ,по ходу это ты..



Ранг: 1.0 (гость)
Активность: 0=0
Статус: Участник

Создано: 14 декабря 2018 21:06
· Личное сообщение · #18

HabibQq пишет:
Привет всем мимо проходящим
Также приветствую собратьев ассемблерщиков
Хотел спросить кто в какой программе любит кодить, как вам Sublime Text ?
Вроде как неплохой редактор, с очень удобной подсветкой синтаксиса и прочих плюшек


Мне лично Atom по душе...или Komodo Edit
Подсветка синтаксиса это не самое важное как мне кажется




Ранг: 271.4 (наставник), 331thx
Активность: 0.321.49
Статус: Участник

Создано: 14 декабря 2018 21:12
· Личное сообщение · #19

HabibQq пишет:
Также приветствую собратьев ассемблерщиков

Sublime Text поддерживает следующие форматы:
- C, CPP, H, HPP, INL, CC, D, ERL, DOT, HTML, HS, JAVA, JS, TEX, LISP, LUA, PL, PY, R, SQL, TCL, XML

Жалкая попытка "беспалевной" рекламы. Ну хоть бы тему правильно выбрал куда постить.

-----
2 оттенка серого



 eXeL@B —› Программирование —› Вопрос по х64 асму
:: Ваш ответ
Жирный  Курсив  Подчеркнутый  Перечеркнутый  {mpf5}  Код  Вставить ссылку 
:s1: :s2: :s3: :s4: :s5: :s6: :s7: :s8: :s9: :s10: :s11: :s12: :s13: :s14: :s15: :s16:


Максимальный размер аттача: 500KB.
Ваш логин: german1505 » Выход » ЛС
   Для печати Для печати