为什么我无法在自修改代码中单步执行 aeskeygenassist 指令?
Why I cannot single stepping into aeskeygenassist instruction in self-modifying code?
我尝试用汇编语言实现aes128加密,我的最终目标是找出最终值。调试时(使用单步执行),调试器停在 0x8048074
地址。
这里是代码:
global _start
section .text
_start:
pxor xmm2, xmm2
pxor xmm3, xmm3
mov bx, 0x36e5
mov ah, 0x73
roundloop:
shr ax, 7
div bl
mov byte [sdfsdf+5], ah
sdfsdf:
aeskeygenassist xmm1, xmm0, 0x45
pshufd xmm1, xmm1, 0xff
shuffle:
shufps xmm2, xmm0, 0x10
pxor xmm0, xmm2
xor byte [shuffle+3], 0x9c
js short shuffle
pxor xmm0, xmm1
cmp ah, bh
jz short lastround
aesenc xmm3, xmm0
jmp short roundloop
lastround:
aesenclast xmm3, xmm0
ret
调试器卡在这里,我无法single-stepping
到0x804807a
[-------------------------------------code-------------------------------------]
0x804806c <_start+12>: mov ah,0x73
0x804806e <roundloop>: shr ax,0x7
0x8048072 <roundloop+4>: div bl
=> 0x8048074 <roundloop+6>: mov BYTE PTR ds:0x804807f,ah
0x804807a <sdfsdf>: aeskeygenassist xmm1,xmm0,0x45
0x8048080 <sdfsdf+6>: pshufd xmm1,xmm1,0xff
0x8048085 <shuffle>: shufps xmm2,xmm0,0x10
0x8048089 <shuffle+4>: pxor xmm0,xmm2
我正在为 GDB 使用 peda 插件。
编辑:
抱歉,我没有提到错误信息,错误信息是 Segmentation fault
在这个指令 mov BYTE PTR ds:0x804807f,ah
我假设您忘记了 link 和 --omagic
以使 .text 部分可写。
所以mov BYTE PTR ds:0x804807f,ah
段错误,对在aeskeygenassist
之前。你不能在你的程序崩溃后继续单步执行。 (您没有 SIGSEGV 的处理程序,默认操作是终止您的程序)。
当我出于好奇在我的桌面上尝试这个时,我可以想象将行为解释为单步执行 "stuck" 在 aeskeygenassist
之前,如果我忽略段错误消息!!!并且再次尝试说 "the program is no longer running".
来自 GDB 会话:
(gdb) layout reg
(gdb) starti # like run with an implicit breakpoint on the first instruction
(gdb) si
0x0000000000401004 in _start ()
0x0000000000401008 in _start () ## I kept pressing return to repeat the command
0x000000000040100c in _start ()
0x000000000040100e in roundloop ()
0x0000000000401012 in roundloop ()
0x0000000000401014 in roundloop () # the MOV store
Program received signal SIGSEGV, Segmentation fault.
0x0000000000401014 in roundloop () # still pointing at the MOV store
注意 RIP 仍然指向 mov
。 0x8048074
在你的 32 位版本中,0x401014
在我相同来源的 64 位版本中。
来自 ld
手册:
-N
--omagic
Set the text and data sections to be readable and writable. Also, do not page-align the data segment, and disable linking against
shared
libraries. If the output format supports Unix style magic numbers, mark the output as "OMAGIC". Note: Although a writable text
section is
allowed for PE-COFF targets, it does not conform to the format specification published by Microsoft.
如果我 link 使用:
,你的代码对我来说工作正常
nasm -felf64 aes.asm &&
ld --omagic aes.o -o aes
或者,您可以进行 mprotect
系统调用以提供包含此代码的页面 PROT_READ|PROT_WRITE|PROT_EXEC
。
GDB 的 layout reg
反汇编 window 甚至在 aeskeygenassist
的立即数被存储修改后更新反汇编。
另请注意,自修改代码 (SMC) 在现代 x86 上 极其 缓慢。完整 pipeline nuke after every store near instructions being executed。使用汇编宏展开会更好。
此外,您不能从 _start
到 Linux 下 ret
;这不是一个功能。堆栈指针指向 argc
,而不是 return 地址。 使用 int 0x80
对 32 位代码进行 _exit
系统调用。当我说 "works" 时,我的意思是它到达 ret
并且在将 argc
弹出到 RIP 后从地址 1
获取代码时出现段错误。
此外,使用 default rel
用于存储的 RIP 相对寻址;它更紧凑。或者我猜你出于某种原因正在根据你的代码地址构建一个 32 位可执行文件。起初我没有注意到,这就是我测试 64 位可执行文件的原因。幸运的是你正确地使用了标签,并且 aeskeygenassist
在两种模式下的长度相同,所以它仍然有效。
我尝试用汇编语言实现aes128加密,我的最终目标是找出最终值。调试时(使用单步执行),调试器停在 0x8048074
地址。
这里是代码:
global _start
section .text
_start:
pxor xmm2, xmm2
pxor xmm3, xmm3
mov bx, 0x36e5
mov ah, 0x73
roundloop:
shr ax, 7
div bl
mov byte [sdfsdf+5], ah
sdfsdf:
aeskeygenassist xmm1, xmm0, 0x45
pshufd xmm1, xmm1, 0xff
shuffle:
shufps xmm2, xmm0, 0x10
pxor xmm0, xmm2
xor byte [shuffle+3], 0x9c
js short shuffle
pxor xmm0, xmm1
cmp ah, bh
jz short lastround
aesenc xmm3, xmm0
jmp short roundloop
lastround:
aesenclast xmm3, xmm0
ret
调试器卡在这里,我无法single-stepping
到0x804807a
[-------------------------------------code-------------------------------------]
0x804806c <_start+12>: mov ah,0x73
0x804806e <roundloop>: shr ax,0x7
0x8048072 <roundloop+4>: div bl
=> 0x8048074 <roundloop+6>: mov BYTE PTR ds:0x804807f,ah
0x804807a <sdfsdf>: aeskeygenassist xmm1,xmm0,0x45
0x8048080 <sdfsdf+6>: pshufd xmm1,xmm1,0xff
0x8048085 <shuffle>: shufps xmm2,xmm0,0x10
0x8048089 <shuffle+4>: pxor xmm0,xmm2
我正在为 GDB 使用 peda 插件。
编辑:
抱歉,我没有提到错误信息,错误信息是 Segmentation fault
在这个指令 mov BYTE PTR ds:0x804807f,ah
我假设您忘记了 link 和 --omagic
以使 .text 部分可写。
所以mov BYTE PTR ds:0x804807f,ah
段错误,对在aeskeygenassist
之前。你不能在你的程序崩溃后继续单步执行。 (您没有 SIGSEGV 的处理程序,默认操作是终止您的程序)。
当我出于好奇在我的桌面上尝试这个时,我可以想象将行为解释为单步执行 "stuck" 在 aeskeygenassist
之前,如果我忽略段错误消息!!!并且再次尝试说 "the program is no longer running".
来自 GDB 会话:
(gdb) layout reg
(gdb) starti # like run with an implicit breakpoint on the first instruction
(gdb) si
0x0000000000401004 in _start ()
0x0000000000401008 in _start () ## I kept pressing return to repeat the command
0x000000000040100c in _start ()
0x000000000040100e in roundloop ()
0x0000000000401012 in roundloop ()
0x0000000000401014 in roundloop () # the MOV store
Program received signal SIGSEGV, Segmentation fault.
0x0000000000401014 in roundloop () # still pointing at the MOV store
注意 RIP 仍然指向 mov
。 0x8048074
在你的 32 位版本中,0x401014
在我相同来源的 64 位版本中。
来自 ld
手册:
-N
--omagic
Set the text and data sections to be readable and writable. Also, do not page-align the data segment, and disable linking against shared libraries. If the output format supports Unix style magic numbers, mark the output as "OMAGIC". Note: Although a writable text section is allowed for PE-COFF targets, it does not conform to the format specification published by Microsoft.
如果我 link 使用:
,你的代码对我来说工作正常 nasm -felf64 aes.asm &&
ld --omagic aes.o -o aes
或者,您可以进行 mprotect
系统调用以提供包含此代码的页面 PROT_READ|PROT_WRITE|PROT_EXEC
。
GDB 的 layout reg
反汇编 window 甚至在 aeskeygenassist
的立即数被存储修改后更新反汇编。
另请注意,自修改代码 (SMC) 在现代 x86 上 极其 缓慢。完整 pipeline nuke after every store near instructions being executed。使用汇编宏展开会更好。
此外,您不能从 _start
到 Linux 下 ret
;这不是一个功能。堆栈指针指向 argc
,而不是 return 地址。 使用 int 0x80
对 32 位代码进行 _exit
系统调用。当我说 "works" 时,我的意思是它到达 ret
并且在将 argc
弹出到 RIP 后从地址 1
获取代码时出现段错误。
此外,使用 default rel
用于存储的 RIP 相对寻址;它更紧凑。或者我猜你出于某种原因正在根据你的代码地址构建一个 32 位可执行文件。起初我没有注意到,这就是我测试 64 位可执行文件的原因。幸运的是你正确地使用了标签,并且 aeskeygenassist
在两种模式下的长度相同,所以它仍然有效。