【发布时间】:2021-10-05 04:06:11
【问题描述】:
我正在尝试将字符串 s1 复制到汇编中的 s2 中,这是我的代码:
global main
main:
.init:
; push r8, r9, r12, rcx
.strcpy:
lea r8, [rel s1]
lea r9, [rel s2]
mov rcx, 0
.copy:
cmp rcx, 7
je .fini
xor r12, r12
mov r12b, [byte r9]
mov [r8], r12b
inc r8
inc r9
inc rcx
jmp .copy
.fini:
; pop rcx, r12, r9, r8
ret
.data:
s1 db "coucou"
s2 db "bonjour"
我得到了第 16 行的段错误 (mov [r8], r12b)。我在gdb的这一行设置了一个断点,寄存器r12很好包含0x62('b'),寄存器r8/r9分别包含s1和s2的地址.
我做错了吗?我一开始以为是权限问题,但是在我的真实程序中(这个非常简化),我将写入权限添加到mprotect的文本部分(并检查它是否成功)。
请注意,我知道 .data 标签在文本部分,但我必须这样做。
为了清楚起见,我注释掉了实际推送/弹出操作的简短版本。
编辑:
这是失败的代码,包含更多上下文:
global main
;##############################################################################
; Just some macros to avoid heavy push / pop boilerplates in the code
%macro pushx 1-*
%rep %0
push %1
%rotate 1
%endrep
%endmacro
%macro popx 1-*
%rep %0
%rotate -1
pop %1
%endrep
%endmacro
;##############################################################################
main:
.init:
pushx rdi, rsi, rdx, rax, r10, r11
mov r10, 0xff ; base addr of the first page containing the .text section
mov r11, 0xff ; len for mrpotects calls
.addrights:
pushx r10, r11
mov rdi, r10 ;
mov rsi, r11 ;
mov rdx, 7 ; PROT_WRITE | PROT_READ | PROT_EXEC
mov rax, 10 ; sys_mprotect
syscall ;
cmp rax, 0 ; check for return value
jl .err ; infinite loop on error
popx r10, r11
.matcpy:
call matcpy
.removerights:
mov rdi, r10 ;
mov rsi, r11 ;
mov rdx, 5 ; PROT_EXEC | PROT_READ
mov rax, 10 ; sys_mprotect
syscall
.fini:
popx rdi, rsi, rdx, rax, r10, r11
ret
.err:
jmp $
;##############################################################################
.data:
mat dd 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574, \
0x00000000, 0x00000000, 0x00000000, 0x00000000, \
0x00000000, 0x00000000, 0x00000000, 0x00000042, \
0x00000000, 0x00000000, 0x00000042, 0x00000042
cpy dd 0, 0, 0, 0 ,\
0, 0, 0, 0, \
0, 0, 0, 0, \
0, 0, 0, 0
;##############################################################################
matcpy:
.init:
pushx r10, r11, r12, rcx
.code:
lea r10, [rel mat]
lea r11, [rel cpy]
mov rcx, 0
.copy:
cmp rcx, 64
je .fini
xor r12, r12
mov r12b, byte [r10]
mov [r11], r12b
inc r10
inc r11
inc rcx
jmp .copy
.fini:
popx r10, r11, r12, rcx
ret
r10 和 r11 是我在创建段时替换的硬编码值(我正在做一个打包程序并且必须注入代码)。
以下是他们在运行时的内容示例:(在matcpy 调用之前)
r10 0x401000 4198400
r11 0x215 533
这是我的程序的映射:
00400000-00401000 r--p 00000000 00:36 31195213 /mnt/nfs/homes/...
00401000-00402000 rwxp 00001000 00:36 31195213 /mnt/nfs/homes/...
00402000-00403000 r--p 00002000 00:36 31195213 /mnt/nfs/homes/...
00403000-00404000 r--p 00002000 00:36 31195213 /mnt/nfs/homes/...
00404000-00405000 rw-p 00003000 00:36 31195213 /mnt/nfs/homes/...
0c001000-0c002000 r-xp 00005000 00:36 31195213 /mnt/nfs/homes/...
此外,程序不会循环,这意味着rax 不是负数(mprotect 成功)。
请注意,如果我在 .data 部分尝试相同的操作,它会起作用。即使我在代码部分设置了写访问模式,这似乎也是一个权限问题。
【问题讨论】:
-
感谢您的支持。我知道这是一个标签,但我必须写在文本部分的“数据”上(即使它们被解释为指令而不是真实数据)。
-
我应该更仔细地阅读:) 好吧,这个简化的程序没有
mprotect,所以它失败了,因为.text是只读的。尝试显示一个包含mprotect并且仍然失败的不太简化的程序。 -
.text部分不可写。而是将数据放入.data部分。为什么你必须这样做?也许有了一些动力,我也许可以为您提出更好的解决方案。 -
如果您可以调试您的真实程序,只需检查 gdb 中的实际权限即可。好吧,
info proc mappings似乎没有显示它们,因此您需要在外部查看/proc/pid/mappings。 -
我将在几分钟后发布我的实际程序的简化版本,并检查映射
标签: linux string assembly copy x86-64