Assembly x86 brk() call use

后端 未结 4 1804
孤城傲影
孤城傲影 2020-12-10 16:36

i am trying to dynamically allocate memory into the heap and then assign values in those memory addresses. I understand how to allocate the memory but how would i assign for

相关标签:
4条回答
  • 2020-12-10 17:05

    int 80h is only for 32 bit system calls. Use syscall for 64 bit instead.

    Calling sys_brk twice is redundant - in assembly you always know where your program data ends. Simply put a label there and you will have the address.

    Allocating this way memory less than one page is pointless, it will be allocated in blocks of 4KB anyway.

    It is important to be understood - sys_brk is not heap management function. It is low level memory management.

    0 讨论(0)
  • 2020-12-10 17:08

    others have pointed out a few things that are wrong with your code. I would like to add that you would not add 20 bits to the current breakpoint (or 20 bytes like add rbx, 20 actually does), you would simply add 5 bytes.

    Also, your first syscall argument will not be in rbx, it will be in rdi. The 64-bit syscall ABI uses different system call numbers, different registers, and a different instruction (syscall instead of int 0x80) than the 32-bit ABI (which is still available in 64-bit processes). See also the x86 tag wiki for more ABI links.

    Here's how your code should look:

    push rbp
    mov rbp, rsp
    
    ;; sys_brk(0)
    mov   rax, 12         ; 12 is SYS_brk (/usr/include/asm/unistd_64.h)
    mov   rdi, 0          ; rdi for first syscall arg in the 64-bit ABI, not rbx
    syscall               ; syscall, not int 0x80, for the 64-bit ABI
    
    mov   qword [brk_firstLocation], rax
    
    ;; sys_brk(old_break + 5)
    lea   rdi, [rax + 5]  ; add 5 bytes to the break point
    mov   rax, 12
    syscall               ; set the new breakpoint
    

    At this point you can use brk_firstLocation as a pointer to whatever 5 byte struct you want to store on the heap. Here's how you would put values in that memory space:

    mov   rdi, [brk_firstLocation]   ; load the pointer from memory, if you didn't already have it in a register
    
    mov   byte [rdi], 'A'            ; a char at it's first byte
    mov   [rdi+1], ecx               ; a 32-bit value in the last 4 bytes.
    
    0 讨论(0)
  • 2020-12-10 17:17

    As you have done, call once to retrieve the current bottom of heap, then move the top of heap (which is the brk value). However your code is not correct in using the 64-bit register set r.x. If your Linux is 32-bit (as implied by the use of 45 for the syscall number), then you want the 32-bit register set:

    mov eax, 45                            ; brk                                                                                                                                                                                  
    mov ebx, 0                             ; arg 1: 0 = fail returning brk value in rax                                                                                                                               
    int 0x80                               ; syscall
    mov dword ptr [brk_firstLocation], rax ; save result
    mov eax, 45                            ; brk                                                                                                                                                                                  
    mov ebx, 4                             ; arg 1: allocate 4 bytes for a 32-bit int                                                                                                                                
    int 0x80                               ; syscall
    
    mov eax, dword ptr [brk_firstLocation] ; reload rax with allocated memory address.
    mov dword ptr [eax], 42 ; use result: store 42 in newly allocated storage
    

    Of course you can re-load the saved value for re-use as many times as needed.

    0 讨论(0)
  • 2020-12-10 17:18

    There are a number of problems I see:

    • 0x2d is the brk system call on x86 (32 bit); on x86_64 it's 0xc
    • brk sets the end of the data segment; it returns 0 on success and -1 on failure. It does not return "the first position in the heap". That comes from the symbol _end which the linker sets to the end of the uninitialized preallocated data.

    So you want something like:

        mov [brk_firstloaction], _end
        mov rbx, [brk_firstlocation]
        add rbx, 0x14         ; space for 5 dwords (20 bytes)
        mov rax, 12
        int 0x80
    
    0 讨论(0)
提交回复
热议问题