assemblysegmentation-faultx86-64machine-code

Segmentation fault on priting a string in machine code


I'm writing a machine code program to print a string to the terminal in 64-bit Linux. Here is my code:

00000000: 7f45 4c46 0201 0103 0000 0000 0000 0000  .ELF............
00000010: 0200 3e00 0100 0000 7800 4000 0000 0000  ..>.....x.@.....
00000020: 4000 0000 0000 0000 0000 0000 0000 0000  @...............
00000030: 0000 0000 4000 3800 0100 4000 0000 0000  ....@.8...@.....
00000040: 0100 0000 0700 0000 0000 0000 0000 0000  ................
00000050: 0000 4000 0000 0000 0000 4000 0000 0000  ..@.......@.....
00000060: 8e00 0000 0000 0000 8e00 0000 0000 0000  ................
00000070: 0010 0000 0000 0000 48b9 0000 0000 0000  ........H.......
00000080: 0001 bf00 0000 0000 4000 88bb 0000 0000  ........@.......
00000090: 0000 0005 c000 0000 0000 0000 010f 05c7  ................
000000a0: c03c 0000 0048 c7c7 0000 0000 0f05 6865  .<...H........he
000000b0: 6c6c 6f00 0a                             llo..

Here are my machine code translations for the x86-64 assembly instructions:

  1. mov rax, 1 b900 0000 0000 0000 01
  2. mov rsi, input bf00 0000 0000 4000 88
  3. mov rdx, 5 bb00 0000 0000 0000 05
  4. mov rdi, 1 c000 0000 0000 0000 01
  5. syscall 0f05

Here is the assembly program I'm translating for learning:

; print.asm - written in fasm assembly language
format ELF64 executable 3       ; value 3 marks the executable for Linux system
; print
mov rax, 1      ; syscall #1 (write)
mov rsi, input  ; arg1 = msg
mov rdx, 5      ; arg2 = msg length
mov rdi, 1      ; arg3 = 1 (stdout)
syscall
; exit 
mov rax, 60     ; syscall #60 (exit)
mov rdi, 0      ; arg 1 = 0 (OK)
syscall         ; call exit
; data
input db "hello", 0

The executable is named print and on executing it:

$ ./print
Segmentation fault (core dumped)

$ gdb ./print
(gdb) r
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400087 in ?? ()
(gdb) quit

$ readelf -l print

Elf file type is EXEC (Executable file)
Entry point 0x400078
There is 1 program header, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x000000000000008e 0x000000000000008e  RWE    0x1000

$ file print
print: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, no section header

I think I'm getting the segmentation fault at offset 0x00000087. What is the problem and how to figure it out?


Solution

  • You have done the machine code wrong. The very first instruction is already broken. b900 0000 0000 0000 01 is not mov rax, 1 it's mov ecx, 0. Note that the actual program dump has a 48 prefix which makes it mov rcx, 0x100000000000000. Even then it's the wrong register and the value is not adjusted for little endian. That applies for the rest of the instructions as well. Use a disassembler to see what you actually encoded:

    (gdb) x/3i 0x400078
    => 0x400078:    movabs rcx,0x100000000000000
       0x400082:    mov    edi,0x0
       0x400087:    add    BYTE PTR [rax+0x0],al
    

    The first two are just wrong, the third one will fault.