Assembly x86 brk() call use

喜欢而已 提交于 2019-11-29 07:48:17
JMcCoy

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 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.

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.

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

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!