Writing from text section on text section data

Viewed 138

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.

1 Answers

Yes, another stupid mistake.

I added the write permission at runtime for the .text section. But the code that I inject was in another section, and the used data was so. I just added a PF_W flag in the program header's p_flags field of the corresponding segment and it worked like a charm.

Related