我正在尝试使用英特尔 AES 指令集实现 AES 加密,在将 xmm 寄存器的内容移动到内存时遇到了一个奇怪的问题。我正在尝试将 %xmm1 的内容移动到 %rsi 中的堆栈地址。这是我的代码:
movdqa (%rdi), %xmm1
movdqa %xmm1, (%rsi)
(%rdi) 的内容按预期移动到 xmm1,但是当将它们移动到 (%rsi) 时,第一个 dword 被清零并且最后一个 dword 不被复制:
(lldb) mem read $rdi -c 0x10
0x7ffeefbff3a0: 30 28 00 00 00 00 00 00 42 42 42 42 41 41 41 41 0(......BBBBAAAA
(lldb) mem read $rsi -c 0x10
0x7ffeefbff2f0: 00 00 00 00 00 00 00 00 20 71 4e 00 00 00 00 00 ........ qN.....
(lldb) s
(lldb) reg read xmm1
xmm1 = {0x30 0x28 0x00 0x00 0x00 0x00 0x00 0x00 0x42 0x42 0x42 0x42 0x41 0x41 0x41 0x41}
(lldb) s
(lldb) mem read $rsi -c 0x10
0x7ffeefbff2f0: 00 00 00 00 00 00 00 00 42 42 42 42 00 00 00 00 ........BBBB....
即使内存是 16 字节对齐的,我也尝试了 movdqu 指令并得到了相同的结果。有谁知道这种行为的原因,或者有解决方法的想法?
这是我的代码,问题出现在 copy_aes_key_schedule 的第 3 行。我正在用 Xcode 编译和调试它。
在 main.c 中:
#include <stdio.h>
extern void encrypt_function_call(uint64_t functionID, uint64_t returnAddress, uint64_t opcodes, uint8_t result[0x10]);
int main(int argc, const char * argv[]) {
// insert code here...
uint32_t encrypted[4];
encrypt_function_call(0xd67f1567, 0x2830, 0x4141414142424242, encrypted);
return 0;
}
在 es 中:
.globl _encrypt_function_call
key_expansion_128:
pshufd $0xff, %xmm2, %xmm2
vpslldq $4, %xmm1, %xmm3
pxor %xmm3, %xmm1
vpslldq $4, %xmm1, %xmm3
pxor %xmm3, %xmm1
vpslldq $4, %xmm1, %xmm3
pxor %xmm3, %xmm1
pxor %xmm2, %xmm1
movdqu %xmm1, (%rcx)
add $0x10, %rcx
ret
copy_aes_key_schedule:
push %rcx
movdqa (%rdi), %xmm1
movdqa %xmm1, (%rsi)
lea 0x10(%rsi), %rcx // Untested from here on
aeskeygenassist $1, %xmm1, %xmm2
call key_expansion_128
aeskeygenassist $2, %xmm1, %xmm2
call key_expansion_128
aeskeygenassist $4, %xmm1, %xmm2
call key_expansion_128
aeskeygenassist $8, %xmm1, %xmm2
call key_expansion_128
aeskeygenassist $0x10, %xmm1, %xmm2
call key_expansion_128
aeskeygenassist $0x20, %xmm1, %xmm2
call key_expansion_128
aeskeygenassist $0x40, %xmm1, %xmm2
call key_expansion_128
aeskeygenassist $0x80, %xmm1, %xmm2
call key_expansion_128
aeskeygenassist $0x1b, %xmm1, %xmm2
call key_expansion_128
aeskeygenassist $0x36, %xmm1, %xmm2
call key_expansion_128
pop %rcx
ret
_encrypt_function_call:
push %rbp
mov %rsp, %rbp
push %r12
push %r13
push %r14
push %r15
mov %rcx, %r15
lea -0x30(%rbp), %r10 // data
mov %rdi, (%r10)
rdrand %r12
mov %r12, 8(%r10)
rdrand %r12d
mov %r12d, 4(%r10)
lea -0x40(%rbp), %rdi // key
mov %rsi, (%rdi)
mov %rdx, 8(%rdi)
lea -0xf0(%rbp), %rsi
call copy_aes_key_schedule
call _abort // untested from here on
movdqu (%r10), %xmm15
movdqu (%rsi), %xmm0
pxor %xmm0, %xmm15
movdqu 0x10(%rsi), %xmm0
aesenc %xmm0, %xmm15
movdqu 0x20(%rsi), %xmm0
aesenc %xmm0, %xmm15
movdqu 0x30(%rsi), %xmm0
aesenc %xmm0, %xmm15
movdqu 0x40(%rsi), %xmm0
aesenc %xmm0, %xmm15
movdqu 0x50(%rsi), %xmm0
aesenc %xmm0, %xmm15
movdqu 0x60(%rsi), %xmm0
aesenc %xmm0, %xmm15
movdqu 0x70(%rsi), %xmm0
aesenc %xmm0, %xmm15
movdqu 0x80(%rsi), %xmm0
aesenc %xmm0, %xmm15
movdqu 0x90(%rsi), %xmm0
aesenc %xmm0, %xmm15
movdqu 0xa0(%rsi), %xmm0
aesenclast %xmm0, %xmm15
movdqu %xmm15, (%r15)
pop %r15
pop %r14
pop %r13
pop %r12
pop %rbp
ret