2016-04-03 94 views
-1

我發現並學習了x86 memory access segmentation fault,它不會在我的代碼中工作。不同之處可能在於我不使用單獨的.text和.data段,而是通過創建自定義ELF標題將所有內容保留在單個段中。這是否解釋了爲什麼SYS_BRK調用失敗?在i386 Linux上升級BRK in assembly

該程序然後繼續通過使內存頁面讀/寫/執行等 我試圖找到說明問題的最小代碼示例。

在kdbg中,示例不起作用,但從命令行啓動時不起作用,因此打印消息。

  cpu 386 
      bits 32 

; System calls used 
%assign  SYS_EXIT 1 
%assign  SYS_WRITE 4 
%assign  SYS_BRK  45 
%assign  SYS_MPROTECT 125 

; flags for SYS_MPROTECT 
%assign  PROT_READ 1 
%assign  PROT_WRITE 2 
%assign  PROT_EXEC 4 

%assign  STDOUT  1 

memstart: org   0x08048000 

ehdr:           ; Elf32_Ehdr (see https://en.wikipedia.org/wiki/Executable_and_Linkable_Format) 
      db  0x7F, "ELF"     ; e_ident[EI_MAG0..EI_MAG03] 
      db  1       ; e_ident[EI_CLASS] 
      db  1       ; e_ident[EI_DATA] 
      db  1       ; e_ident[EI_VERSION] 
      db  0       ; e_ident[EI_OSABI] 
      db  0       ; e_ident[EI_ABIVERSION] 
    times 7 db  0       ; e_ident[EI_PAD] 
      dw  2       ; e_type 
      dw  3       ; e_machine 
      dd  1       ; e_version 
      dd  start      ; e_entry 
      dd  phdr - $$     ; e_phoff 
      dd  0       ; e_shoff 
      dd  0       ; e_flags 
      dw  ehdrsize     ; e_ehsize 
      dw  phdrsize     ; e_phentsize 
      dw  1       ; e_phnum 
      dw  0       ; e_shentsize 
      dw  0       ; e_shnum 
      dw  0       ; e_shstrndx 
ehdrsize equ  $ - ehdr 

phdr:           ; Elf32_Phdr 
      dd  1       ; p_type 
      dd  0       ; p_offset 
      dd  $$       ; p_vaddr 
      dd  $$       ; p_paddr 
      dd  filesize     ; p_filesz 
      dd  filesize     ; p_memsz 
      dd  5       ; p_flags 
      dd  0x1000      ; p_align 
phdrsize equ  $ - phdr 

memsize: dd  16*4096      ; = 16 * 4K pages 
memtop:  dd  0 


start:  ;int  3 
      xor  ebx, ebx     ; find the amount of allocated memory 
      mov  eax, SYS_BRK 
      int  0x80      ; eax contains current memtop 

      sub  eax, memstart    ; got enough memory? 
      test eax, [memsize] 
      ja  memgood 

      mov  eax, memstart    ; raise memory limit to memstart + memsize 
      add  eax, [memsize] 
      mov  ebx, eax 
      mov  ecx, eax     ; save requested memory size in ecx 
      mov  eax, SYS_BRK 
      int  0x80 
      cmp  eax, ecx 
      jne  brk_error     ; raising memory limit failed 

memgood: mov  edx, (PROT_READ | PROT_WRITE | PROT_EXEC) 
      mov  ecx, [memsize]    ; make memory read/write/execute 
      mov  ebx, memstart 
      mov  eax, SYS_MPROTECT 
      int  0x80 
      test eax, eax 
      js  bailout 

      jmp  launch      ; lets start the party 


brk_error: mov  edx, brkelen 
      mov  ecx, brke 
      mov  ebx, STDOUT 
      mov  eax, SYS_WRITE 
      int  0x80 
      jmp  bailout 
brke:  db  'SYS_BRK failed, bye', 10 
brkelen  equ  $ - brke 

bailout: mov  eax, SYS_EXIT 
      xor  ebx, ebx 
      int  0x80 

launch:  mov  edx, succlen 
      mov  ecx, succ 
      mov  ebx, STDOUT 
      mov  eax, SYS_WRITE 
      int  0x80 
      jmp  bailout 
succ:  db  'Success with mem config, bye', 10 
succlen  equ  $ - succ 

filesize equ $ - $$ 
+0

我看到你的答案並驗證它工作。頭部是有規律的,除了有一個單獨的段,所以沒有代碼/數據/ BSS分離。 (哎呀,突然進入帖子)。 我編輯問題以顯示完整的初始化,但這並沒有改變,所以我將這些部分留下。 – LNoor

+1

對不起,(第一次使用者)。我的代碼問題是第二次給BRK打電話。當我在int 128的前面放置一個int 3時,我得到了關於調試器斷點的期望msg。如果我在程序之後放置它永遠不會到達那裏。從控制檯運行時,程序看起來只是掛起。 – LNoor

+0

我已經刪除了我所有的評論,因爲您現在提供了實際的代碼lol –

回答

2

你應該在這裏使用cmp代替test

sub  eax, memstart    ; got enough memory? 
    test eax, [memsize] 
    ja  memgood 

通過SYS_BRK描述的存儲區域開始隨機的0偏移0x02000000可執行文件後,除非地址空間佈局隨機化是禁用的,這是我懷疑你的調試器。您可以使用mmap在指定地址分配內存(除非要覆蓋現有映射,否則不要設置MAP_FIXED)。

但是這整個運動與brkmprotect似乎相當無意義的除了在程序堆棧開始爲指定的ELF頭的內存正好分配,相反,您可以:

phdr:           ; Elf32_Phdr 
      dd  1       ; p_type 
      dd  0       ; p_offset 
      dd  $$       ; p_vaddr 
      dd  $$       ; p_paddr 
      dd  filesize     ; p_filesz 
      dd  16*4096      ; p_memsz 
      dd  7       ; p_flags 
      dd  0x1000      ; p_align 
phdrsize equ  $ - phdr 
+0

謝謝蒂莫西。這可能是一條路。該節目種類的重寫和擴大本身聲稱額外的空間這樣做。我沒有考慮地址空間佈局隨機化。但修改精靈標題和重新啓動應該有所斬斷。 – LNoor

+0

禁用地址空間隨機化被證明是解決方案。所以程序以'setarch $(uname -m)-RL。/ lf'啓動,解決了這個問題。謝謝@蒂莫西。參見[http://stackoverflow.com/questions/5194666/disable-randomization-of-memory-addresses]。 – LNoor