I'm trying to copy a string s1 into s2 in assembly, here's my code:
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"
I got a segfault line 16 (mov [r8], r12b). I've set a breakpoint at this line in gdb, the register r12 well contains 0x62 ('b'), and the registers r8 / r9 contains respectively the addresses of s1 and s2.
Am I doing it wrong? I first thought it was a permission problem, but in my real program (this one is very simplified), I add the write permission to the text section with mprotect (and check that it succeeds).
Note that I know the .data label is in the text section but I have to do it this way.
I commented out a short version for the actual push / pop operations for clarity.
EDIT:
Here's the code that fails, with more context:
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 and r11 are hardcoded values that I replace when I create the segment (Im doing a packer and have to inject code).
Here's an exemple of their content at runtime: (before the matcpy call)
r10 0x401000 4198400
r11 0x215 533
And here's the mappings for of my program:
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/...
More, the program doesn't loops, meaning rax isn't negative (mprotect succeeds).
Note that it's working if I try the same thing in the .data section. Seems it's a permission issue even if I have the write access mode set on my code section.