在i386Linux上的程序集中提升BRK



我发现并研究了x86内存访问分段错误,它在我的代码中不起作用。不同之处可能在于,我不使用单独的.text和.data段,而是通过创建自定义ELF头将所有段保留在一个段中。这是否解释了SYS_BRK调用失败的原因?

然后,程序通过使存储器页读取/写入/执行等来继续。我试图找到说明这个问题的最小代码示例。

在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 $ - $$

此处应该使用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

相关内容

  • 没有找到相关文章

最新更新