x86-64モード用の呼び出し規約では、浮動小数点数の受け渡しは
xMM0
などのレジスタを用います. メモリとxMM0
系のレジスタ間で値を転送する命令(MOVAPS
やMOVAPD
など)は、メモリ上の値が16バイト境界に配置されていることを要求します.
コンパイラは、関数呼び出し時のスタックポインタが16バイト整列されていることを前提に,MOVAPS
やMOVAPD
命令を発行します. また、他の関数を呼び出すときには必ずスタックポインタが16バイト整列するように調整する責任があります.
(http://uchan.hateblo.jp/entry/2018/02/16/232029)
CTFにおいては
0x10
の境界にないとき、system
等がmovaps
が原因で失敗する為、ret
で揃える事がある.
なぜ0x10
か
0x10
の倍数のアドレスにrsp
がある前提で命令があり, 0x8
刻みでスタックはずれていく為([1])、奇数回数のret
で0x10
に揃ってエラーが吐かなくなる.
[1]x86-64 モードのプログラミングではスタックのアライメントに気を付けよう http://uchan.hateblo.jp/entry/2018/02/16/232029
[2]
https://twitter.com/Nperair/status/1215939993299869699
[3]
https://twitter.com/Nperair/status/1215941227700318208