2016-12-30 43 views
1

我想授予對ELF二進制文件中所有內存頁的完全權限(讀,寫,執行)。理想情況下,我希望能夠對二進制文件或目標文件進行轉換,就像可以用objcopy更改符號一樣。我還沒有找到一個好辦法來做到這一點。我也可以使用一個解決方案,它涉及在啓動時運行代碼,在每個頁面上調用mprotect,標記爲PROT_READ | PROT_WRITE | PROT_EXEC。我簡單地嘗試了這一點,但是我還沒有找到一個很好的方法來知道哪些頁面被映射,因此哪些頁面需要被編輯爲mprotect使所有頁面可讀/可寫/可執行

動態分配的頁面不需要具有所有權限,只需要在程序啓動時映射的頁面。

+0

既然'ELF'文件格式與語言無關,爲什麼C++標籤呢? –

+0

因爲如果我最終不得不在每一頁上調用'mprotect',我都會用C++來完成。 – IanPudney

回答

3

下面的腳本實現受聘于俄羅斯代碼的回答:

  • 設置RELRO段的p_typePT_NULL
  • FlagsLOADPF_X|PF_W|PF_R

這取決於pyelftoolspython3,可與pip3 install pyelftools安裝。

#!/usr/bin/env python3 

import sys 

from elftools.elf.elffile import ELFFile 
from elftools.elf.descriptions import describe_p_type 

if len(sys.argv) != 2: 
    print("Usage: elf_rwe <elf>") 

name = sys.argv[1] 
with open(name, "rb") as f: 
    elf = ELFFile(f) 

    rwe_offsets = [] 
    relro_offsets = [] 
    for i in range(elf['e_phnum']): 
     program_offset = elf['e_phoff'] + i * elf['e_phentsize'] 
     f.seek(program_offset) 
     program_header = elf.structs.Elf_Phdr.parse_stream(f) 

     if program_header['p_type'] == "PT_LOAD": 
      rwe_offsets.append(program_offset) 
     if program_header['p_type'] == "PT_GNU_RELRO": 
      relro_offsets.append(program_offset) 

    f.seek(0) 
    b = list(f.read()) 

    # Zap RELRO 
    pt_null = 0 
    for off in relro_offsets: 
     b[off] = pt_null 

    # Fix permissions 
    p_flags_offset = 4 
    for off in rwe_offsets: 
     b[off + p_flags_offset] = 0x7 # PF_X|PF_W|PF_R 

with open(name, "wb") as f: 
    f.write(bytes(b)) 
1

我想授予一個ELF二進制完全權限(讀,寫和執行)所有的內存頁。

請注意,某些安全策略(如selinux中的W^X)會阻止您的二進制文件運行。

理想情況下,我希望能夠做到這一點的轉變上的二進制文件,二進制文件或目標文件

運行readelf -Wl。你會看到類似的東西:

$ readelf -Wl /bin/date 

Elf file type is EXEC (Executable file) 
Entry point 0x4021cf 
There are 9 program headers, starting at offset 64 

Program Headers: 
    Type   Offset VirtAddr   PhysAddr   FileSiz MemSiz Flg Align 
    PHDR   0x000040 0x0000000000400040 0x0000000000400040 0x0001f8 0x0001f8 R E 0x8 
    INTERP   0x000238 0x0000000000400238 0x0000000000400238 0x00001c 0x00001c R 0x1 
     [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2] 
    LOAD   0x000000 0x0000000000400000 0x0000000000400000 0x00dde4 0x00dde4 R E 0x200000 
    LOAD   0x00de10 0x000000000060de10 0x000000000060de10 0x0004e4 0x0006b0 RW 0x200000 
    DYNAMIC  0x00de28 0x000000000060de28 0x000000000060de28 0x0001d0 0x0001d0 RW 0x8 
    NOTE   0x000254 0x0000000000400254 0x0000000000400254 0x000044 0x000044 R 0x4 
    GNU_EH_FRAME 0x00cb8c 0x000000000040cb8c 0x000000000040cb8c 0x0002f4 0x0002f4 R 0x4 
    GNU_STACK  0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x10 
    GNU_RELRO  0x00de10 0x000000000060de10 0x000000000060de10 0x0001f0 0x0001f0 R 0x1 

你想要做的又是什麼改變FlagsLOAD段有PF_X|PF_W|PF_R。這些標誌是Elf{32,64}_Phdr表的一部分,表的偏移量存儲在Elf{32,64}_Ehdr(存儲在每個ELF文件的開始處)的e_phoff中。

查看/usr/include/elf.h。解析這裏涉及的固定大小的ELF結構並不複雜。

你是不可能找到任何標準的工具,它會爲你做這個(因爲這是這樣做的一個不尋常的和不安全的事情),但一個程序更改標誌是瑣碎CPythonPerl寫。

P.S.您可能還需要「刪除」RELRO細分受衆羣,您可以將其p_type更改爲PT_NULL

我還沒有發現知道哪些頁面被映射,因此該頁面必須mprotected的好方法。

在Linux上,您可以解析/proc/self/maps以獲取該信息。其他操作系統可能會提供不同的方式來實現相同的目標。