久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

pe/elf 文件加殼時的處理

 cwhbox 2012-01-14
                         ==Ph4nt0m Security Team==

                       Issue 0x02, Phile #0x0A of 0x0A


|=---------------------------------------------------------------------------=|
|=----------------------=[  pe/elf 文件加殼時的處理  ]=----------------------=|
|=---------------------------------------------------------------------------=|
|=---------------------------------------------------------------------------=|
|=--------------------------=[      By dummy     ]=--------------------------=|
|=-----------------------=[  <dummy_at_ph4nt0m.org>  ]=----------------------=|
|=---------------------------------------------------------------------------=|

               
前言:

    最初的殼是在感染型的病毒技術(shù)上發(fā)展出來的,加殼目的一般是壓縮或加密。本文主要
就x86平臺下win32 pe和linux elf 加殼程序的實現(xiàn)做簡單介紹和總結(jié),,以自己以前寫相關(guān)
程序做線索敘述,,其中程序源碼是開源的,有興趣的朋友可以繼續(xù)進(jìn)行改進(jìn),。

    ps: 其中有些地方很久沒碰,,可能有地方描述有誤,還請見諒:)

正文:

    -------------------------------------------------------
    slm        x86 win32 r3 pe packer
    mimisys    x86 win32 r0 pe packer
    elfp       x86 linux r3 elf packer
    -------------------------------------------------------

一,、一個殼的組成

    一個完整的殼程序主要由 2 個部分組成 packer 和 loader,。它們具體的作用分別是:

    (1) packer
       
    負(fù)責(zé)將待加殼程序壓縮和加密處理、把loader寫到待加殼程序上,。以slm的pakcer
    為例具體操作包括,,pe有效性判斷、優(yōu)化可壓縮數(shù)據(jù),、壓縮和加密,、添加loader、存放
    加殼參數(shù)和待加殼程序原數(shù)據(jù)(oep等等),、改寫入口點等等,。

    (2) loader
       
    主要工作是解壓或解密被加殼的程序,以slm的loader為例具體的操作包括:獲取自
    身位置,、獲取加殼參數(shù),、進(jìn)行解壓或解密、填充導(dǎo)入表,、重定位,、tls 初始化等等。

二,、slm (x86 win32 r3 pe packer)

資料:
    http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx

工具:
    lordpe    pe 文件格式查看編輯工具
    dumpbin    vc 自帶coff文件格式查看工具
    ollydbg    r3 調(diào)試工具

源碼結(jié)構(gòu):
    ./slm/cm 公共頭文件和模塊
    ./slm/pk    packer 實現(xiàn)
    ./slm/sc    loader 實現(xiàn)

    在做這個時候?qū)?pe 也是剛剛了解,,所以 slm 很多地方現(xiàn)在看來有些問題:)。在第一
節(jié)已經(jīng)簡單描述 slm 的工作流程,,下面主要就我當(dāng)初做的時候遇到的問題做一些描述:

    (1) 資源的處理
       
    slm 的資源處理做的比較煩瑣,,當(dāng)初目的是為了把可壓縮資源數(shù)據(jù)歸并到一起,進(jìn)
    行一次壓縮,,不可壓縮單獨存放,。下面簡單介紹一下資源的目錄數(shù)據(jù)格式,詳細(xì)還是看
    看微軟的文檔和相關(guān)源碼:)
       
        從IMAGE_NT_HEADERS.IMAGE_DATA_DIRECTORY[IMAGE_DIRECTORY_ENTRY_RESOURCE]
    取出資源數(shù)據(jù)的地址res_rva,,經(jīng)過轉(zhuǎn)換后第一個結(jié)構(gòu)體是IMAGE_RESOURCE_DIRECTORY

        IMAGE_RESOURCE_DIRECTORY:

            NumberOfIdEntries       目錄下 id 名稱入口項個數(shù)
            NumberOfNamedEntries    目錄下 name 名稱入口項個數(shù)

        緊跟著IMAGE_RESOURCE_DIRECTORY后面是IMAGE_RESOURCE_DIRECTORY_ENTRY結(jié)構(gòu)
    數(shù)組,這個數(shù)組的元素個數(shù)是 NumberOfIdEntries + NumberOfNamedEntries,。

        IMAGE_RESOURCE_DIRECTORY_ENTRY:

            Id                  目錄id,,只有NameIsString非真才有效
            NameIsString        目錄名稱是否是字符串,如果為真NameOffset有效
            NameOffset          目錄名稱串的偏移, 偏移是相對與res_rva*的,。
            DataIsDirectory     如果為真 OffsetToData 有效,,否則OffsetToDirectory
                                有效
            OffsetToData        指向資源數(shù)據(jù),,偏移類型rva
            OffsetToDirectory   指向子目錄,偏移類型rva

        如果目錄入口名稱是字符串,,通過NameOffset獲取PIMAGE_RESOURCE_DIR_STRING_U
    的結(jié)構(gòu)指針,,目錄名是unicode格式,并且不是以零結(jié)尾的字符串,。如果目錄名不是字符
    串而是id, 那么其值在winnt.h 定義,。常見id有RT_ICON、RT_VERSION等等,。

        結(jié)構(gòu)大致簡單描述完了,,有點要注意OffsetToDirectory、OffsetToData修改時要
    進(jìn)行 DWORD 對齊,,否則會出現(xiàn)奇怪的現(xiàn)象,。

    (2) 導(dǎo)入表處理

        從IMAGE_NT_HEADERS.IMAGE_DATA_DIRECTORY[IMAGE_DIRECTORY_ENTRY_IMPORT]
    取出導(dǎo)入表的地址imp_rva,經(jīng)過轉(zhuǎn)換后第一個結(jié)構(gòu)體是IMAGE_IMPORT_DESCRIPTOR,。
       
    IMAGE_IMPORT_DESCRIPTOR:

            Name               指向?qū)?dll 的名稱,,偏移類型 rva
            FirstThunk         指向 IMAGE_THUNK_DATA 結(jié)構(gòu)體,偏移類型 rva
            OriginalFirstThunk 指向FirstThunk 的副本, 可以為空,。偏移類型 rva
       
        導(dǎo)入由IMAGE_IMPORT_DESCRIPTOR結(jié)構(gòu)數(shù)組組成,,數(shù)組長度由一個Name域為空的結(jié)
    構(gòu)表明。
       
        FirstThunk和OriginalFirstThunk都是指向以IMAGE_THUNK_DATA數(shù)組組成的數(shù)據(jù)
    結(jié)構(gòu),,系統(tǒng)的加載器在進(jìn)行導(dǎo)入表填充時,,會把FirstThunk指向的結(jié)構(gòu)修改掉。

    (3) TLS 處理

        這里說的tls是所謂的靜態(tài)tls(在pe文件結(jié)構(gòu)上進(jìn)行實現(xiàn)),,關(guān)于什么是tls可以看看
    《windows 核心編程》線程那章,。
       
        1、tls 是怎樣的

        比如要在vc中聲明一個tls變量需要這樣__declspec(thread) int x = 0;在鏈接
    時這個變量會被鏈接器放入.tls的節(jié)中,。這個節(jié)從外邊看和其他的節(jié)沒有什么不同,,唯
    一的區(qū)別在IMAGE_DATA_DIRECTORY[IMAGE_DIRECTORY_ENTRY_TLS]指向的一個結(jié)構(gòu)會對
    此節(jié)進(jìn)行描述,這個結(jié)構(gòu)是IMAGE_TLS_DIRECTORY,。

        IMAGE_TLS_DIRECTORY:

            StartAddressOfRawData   tls數(shù)據(jù)開始地址類型va
            EndAddressOfRawData     tls數(shù)據(jù)結(jié)束地址類型va
            AddressOfIndex;         tls slot的地址,,默認(rèn)tls slot為0

            AddressOfCallBacks      指向一個PIMAGE_TLS_CALLBACK的數(shù)組,這個數(shù)組
                                    以0結(jié)尾,,每個PIMAGE_TLS_CALLBACK都是va類型
           
            SizeOfZeroFill          數(shù)據(jù)區(qū)需要進(jìn)行清 0 數(shù)據(jù)的大小
            Characteristics
       
        2,、系統(tǒng)加載器怎樣處理exe的tls

            系統(tǒng)加載器在完成重定位和輸入表填充后,就開始處理tls,。如果存在tls_dir,,
    求出tls數(shù)據(jù)的大小EndAddressOfRawData - StartAddressOfRawData +
    SizeOfZeroFill, 按照大小分配一塊內(nèi)存,地址存入(PDWORD)fs:[0x2c] +
    tls_slot, 接著拷貝StartAddressOfRawData -> EndAddressOfRawData之間的數(shù)
    據(jù)到新分配的內(nèi)存中,然后使用SizeOfZeroFill 清零剩下的數(shù)據(jù),,然后進(jìn)行循環(huán)回
    調(diào)AddressOfCallBacks中的函數(shù),,PIMAGE_TLS_CALLBACK函數(shù)和DllMain原型很像,
    只是沒有返回值,。

        3,、系統(tǒng)加載器怎樣處理dll的tls

            首先明確dll是可以使用tls的,,唯一的不同是AddressOfCallBacks調(diào)用方式會
    有些區(qū)別。如果目標(biāo)dll是被靜聽鏈接到其他文件上,在進(jìn)程創(chuàng)建完成時即被加載,,
    那么他的tls callback會觸發(fā),,而LoadLibrary方式加載不會觸發(fā),。

    (4) rva & raw 轉(zhuǎn)換

        pe 文件中許多結(jié)構(gòu)域的指針類型是rva, rva是pe文件由系統(tǒng)加載后,,方法相關(guān)數(shù)
    據(jù)的相對偏移量。而我們進(jìn)行加殼處理時,,是直接map的文件數(shù)據(jù)訪問都是使用文件指
    針,,這就需要rva進(jìn)行轉(zhuǎn)換。(每次做pe相關(guān)工具時,,我都會習(xí)慣寫一個這樣的函數(shù),,現(xiàn)在
    不下10中版本,竟然沒有一個可以保證是正確的 - -)

        下面這個是最新的rva2raw版本,,不保證正確性,。

三、mimisys (x86 win32 r0 pe packer)

資料:
    Windows Research Kernel
        wrk/base/ntos/mm/sysload.c:MmLoadSystemImage
工具:
    syser     內(nèi)核調(diào)試器,,你也可以選擇其他的r0調(diào)試器
    vmware    如果不想頻繁重啟,,需要一個虛擬機

    文件格式的一些處理參考slm, 這里主要就r0 pe和r3 pe區(qū)別做介紹:

    (1) 節(jié)和頁

        r0空間的內(nèi)存常常很緊張,就導(dǎo)致sys section屬性有幾個特殊地方

        1,、可換出和禁止換出
           
        在內(nèi)存不足時,,系統(tǒng)內(nèi)存管理器,會枚舉已加載的section object, 如果存在
    pageout屬性,,那么系統(tǒng)內(nèi)存管理器就會換出這個節(jié)對應(yīng)的頁(這個節(jié)經(jīng)過系統(tǒng)頁對
    齊后換出內(nèi)存)節(jié)對齊原則VirtualAddress向上,、VirtualSize向下。禁止換出如
    名字所名這個節(jié)將永駐內(nèi)存,。

        2,、節(jié)對齊小于一頁
           
        大多數(shù)sys的節(jié)對齊指數(shù)都是小于一頁,系統(tǒng)加載器在處理這類文件時相當(dāng)很
    簡單,。加載后文件和磁盤上的文件布局基本一致,。當(dāng)節(jié)對齊小于一頁時,
    SizeOfRawData必須大于等于VirtualSize,,即不支持未初始化節(jié),。mimisys通過增
    加SizeOfImage在文件加載后分配一個未初始化的緩沖區(qū),,保證解壓過程。

    (2) checksum校驗

        一句話: 只有正確的checksum sys文件才允許被加載,。

    (3) win2k相關(guān)問題

        win2k的系統(tǒng)加載器和其他nt系統(tǒng)有幾處不同,r3和r0都會有一些區(qū)別,,比如r3 pe
    的必須要有導(dǎo)入表,,否則拒絕加載,r0 pe必須要有重定位信息,,否則也會拒絕加載,。這
    種情況需要構(gòu)造一個空的重定位目錄即可。

        mimisys采取的是合并節(jié),,導(dǎo)致加殼后只剩下兩個節(jié),,第一個節(jié)是loader, 存放
    loader和各種加殼參數(shù),第二個節(jié)是原程序優(yōu)化壓縮后的數(shù)據(jù)(移動重定位,,移動資源等
    等),。兩個節(jié)的屬性都是不允許換出的。

四,、elfp (x86 linux r3 elf packer)

資料:
    Tool Interface Standard (TIS) Executable and Linking Format
        http://www./ftp/manuals/tools/elf.pdf
    毛德操 《漫談內(nèi)核兼容》8,9 ELF映像的裝入
        http://linux./jszl.asp?docid=132762762
        http://linux./jszl.asp?docid=133617926
    linux 內(nèi)核源碼
        linux/fs/binfmt_elf.c:load_elf_binary

工具:
    objdump    進(jìn)行elf文件格式的結(jié)構(gòu)查看
               http://www./software/binutils/binutils.html
               
    ald        匯編級調(diào)試器,,gdb無法調(diào)試沒有調(diào)試信息文件的。
               http://ald./
   
    elfp是在magiclinux完成的linux elf文件壓縮殼,。

    elf的格式是linux下主要的可執(zhí)行文件格式,,它也是在coff上基礎(chǔ)上設(shè)計的,所以它和
pe文件的格式很相似,,下面的敘述過程中會和 pe 文件以對比形式進(jìn)行描述,。

    elf文件的第一個數(shù)據(jù)結(jié)構(gòu)是以Elf32_Ehdr開始

    typedef struct
    {
      unsigned char e_ident[EI_NIDENT];     /* Magic number and other info */
      Elf32_Half    e_type;                 /* Object file type */
      Elf32_Half    e_machine;              /* Architecture */
      Elf32_Word    e_version;              /* Object file version */
      Elf32_Addr    e_entry;                /* Entry point virtual address */
      Elf32_Off     e_phoff;                /* Program header table file offset */
      Elf32_Off     e_shoff;                /* Section header table file offset */
      Elf32_Word    e_flags;                /* Processor-specific flags */
      Elf32_Half    e_ehsize;               /* ELF header size in bytes */
      Elf32_Half    e_phentsize;            /* Program header table entry size */
      Elf32_Half    e_phnum;                /* Program header table entry count */
      Elf32_Half    e_shentsize;            /* Section header table entry size */
      Elf32_Half    e_shnum;                /* Section header table entry count */
      Elf32_Half    e_shstrndx;             /* Section header string table index */
    } Elf32_Ehdr;

    e_ident        在 elf.h 中對應(yīng)的 ELFMAG 宏,長度是四個字節(jié)
    e_entry        入口點映像偏移(映像偏移即 pe 中所說的 rva)
    e_phoff        Elf32_Phdr 數(shù)組的文件偏移
    e_shoff        Elf32_Shdr 數(shù)組的文件偏移
    e_ehsize       Elf32_Ehdr 結(jié)構(gòu)的大小
    e_phentsize    Elf32_Phdr 結(jié)構(gòu)大小
    e_phnum        Elf32_Phdr 數(shù)組成員個數(shù)
    e_shentsize    Elf32_Shdr 結(jié)構(gòu)大小
    e_shnum        Elf32_Shdr 數(shù)組成員個數(shù)
   
    在Elf32_Ehdr之后即Elf32_Phdr數(shù)組,,Elf32_Phdr的地址通過Elf32_Ehdr.e_ehsize來
確定,。Elf32_Ehdr數(shù)組(或叫段表),你可以把phdr看做pe的節(jié)表,。

    typedef struct
    {
      Elf32_Word    p_type;            /* Segment type */
      Elf32_Off     p_offset;        /* Segment file offset */
      Elf32_Addr    p_vaddr;        /* Segment virtual address */
      Elf32_Addr    p_paddr;        /* Segment physical address */
      Elf32_Word    p_filesz;        /* Segment size in file */
      Elf32_Word    p_memsz;        /* Segment size in memory */
      Elf32_Word    p_flags;        /* Segment flags */
      Elf32_Word    p_align;        /* Segment alignment */
    } Elf32_Phdr;
   
    p_type    描述這個段的加載行為屬性
    p_offset  段數(shù)據(jù)在文件中偏移,,類似pe節(jié)中的PointerToRawData
    p_vaddr   段數(shù)據(jù)加載后在映像中偏移, 類似pe節(jié)中的VirtualAddress
    p_filesz  段數(shù)據(jù)在文件中大小,類型pe節(jié)中的SizeOfRawData
    p_memsz   段數(shù)據(jù)加載后在映像中大小,,類型pe節(jié)中的VirtualSize
    p_flags   描述這個段的內(nèi)存屬性,,類似pe節(jié)中的節(jié)屬性
    p_align   段對齊粒度

    p_type主要的類型有

        PT_LOAD      這個段需要裝載到內(nèi)存中
        PT_PHDR      這個段存放的是Elf32_Phdr數(shù)組
        PT_INTERP    這個段存放一個解釋器名,請求系統(tǒng)加載器把映像裝載需求轉(zhuǎn)給這
             個解釋器,,關(guān)于elf的解釋器問題,,可以理解為windows下ntdll裝載
     pe文件,elf文件的解釋器主要負(fù)責(zé)重定位,、導(dǎo)入表填充等操作

    p_flags 主要類型有

        PF_X         這個段可執(zhí)行
        PF_W         這個段可寫
        PF_R         這個段可讀

    在Elf32_Ehdr(段表)之后便是Elf32_Shdr數(shù)組(節(jié)表),,你可能到這里很奇怪了,,怎么這
個叫節(jié)表?如果你熟悉pe應(yīng)該知道節(jié)表對pe文件的重要性,,但這個可不是pe中的那個節(jié)表,,你
應(yīng)該把它看做nt header中data_dir[]結(jié)構(gòu),加載器或調(diào)試器等工具會通過節(jié)名確定節(jié)具體
用途,,比如存儲調(diào)試信息,、版本信息、字符串表等等,、elfp在加殼過程會丟棄節(jié)表,。

    下面簡單講講elfp的loader處理過程(加殼過程很簡單),在一個elf文件被加載后,,它的
入口點在執(zhí)行之前,,堆棧中會由系統(tǒng)加載器push的一些參數(shù)。

    //  堆棧結(jié)構(gòu):
    //  +-------------------+
    //  |   return address  |        返回地址
    //  +-------------------+
    //  |   argc            |        參數(shù)個數(shù)
    //  +-------------------+
    //  |   argv[?], NULL   |        參數(shù)表,,以 NULL 結(jié)尾
    //  +-------------------+
    //  |   envp[?], NULL   |        環(huán)境表,,以 NULL 結(jié)尾
    //  +-------------------+
    //  |   auxv[?]         |        中文不知道叫什么它,這個主要是給解釋器使用,
    //  +-------------------+        存放這個elf的相關(guān)信息如果被加殼程序需要解
                                     釋器,,你需要重寫正確填寫這個參數(shù),,讓解釋器可
     以正確的找到相關(guān)數(shù)據(jù)的地址。
                                    
    elfp殼loader的執(zhí)行流程大致如下:

        申請內(nèi)存-->把每個段解壓到指定的地址上-->獲取被加殼程序原始信息-->檢查原
    始段表,、重寫 auxv-->加載解釋器-->調(diào)用解釋器

    關(guān)于 elf 的解釋器,,可以參考資料鏈接上的文字,那里比我描述的完整,。

五,、附錄

[1]
本文代碼
    ./pstzine_0A_01.zip

-EOF-

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多