<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      謎題:打造極小ELF文件輸出文件(在Linux環境中精簡ELF64文件)

      接前文《謎題:打造極小ELF文件輸出文件(使用匯編語言通過系統調用來實現)》

      在完成了一個232字節的程序后,發現距離186字節的目標還是有一些距離。接下來就要深入研究ELF文件的細節了。

      [root@i-a77ugr2f tmp]# readelf -h open
      ELF Header:
        Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
        Class:                             ELF64
        Data:                              2's complement, little endian
        Version:                           1 (current)
        OS/ABI:                            UNIX - System V
        ABI Version:                       0
        Type:                              EXEC (Executable file)
        Machine:                           Advanced Micro Devices X86-64
        Version:                           0x1
        Entry point address:               0x4000b0
        Start of program headers:          64 (bytes into file)
        Start of section headers:          0 (bytes into file)
        Flags:                             0x0
        Size of this header:               64 (bytes)
        Size of program headers:           56 (bytes)
        Number of program headers:         2
        Size of section headers:           64 (bytes)
        Number of section headers:         0
        Section header string table index: 0

      先通過readelf命令來看一下程序的ELF文件頭信息,這里輸出的信息都是從ELF文件頭中提取得到的。
      需要重點關注一下ELF文件頭(64字節)和程序頭(56*2=112字節)的大小。在64位ELF文件的定義上,文件頭和程序頭的大小是有明確定義的。
      我們可以計算出實際機器指令的大小:總大小-文件頭-程序頭=232-64-112=56字節。而這56字節的指令我們前面已經通過各種技巧進行了最簡化。
      那么,接下里的思路只有兩個:

      1. 想辦法將代碼段中的機器指令填充到ELF頭和程序頭中
      2. 想辦法將程序頭與文件頭進行合并

      如上圖所示,這是前面得到的232字節的ELF可執行文件的16進制內容,并對文件頭和程序頭中的字段進行了標注。(備注參考資料)

      通過查閱相關資料,我們嘗試判斷并驗證哪些字段是無用的。可以通過下面的cutelf.sh腳本,在使用0xff覆蓋一些字節后,觀察程序是否仍能正常運行。

      cutelf.sh
       #!/bin/sh
      test_byte_ff() {
        # modify Ehdr
        seek_lst=({4..15} {20..23} {40..53} {58..63})
        for sk in ${seek_lst[@]}; do
          echo -ne "\xff" | dd of=open bs=1 count=1 seek=${sk} conv=notrunc > /dev/null 2>&1
        done
        # modify Phdr
        seek_lst=({88..95} {112..119} {144..151} {168..175})
        for sk in ${seek_lst[@]}; do
          echo -ne "\xff" | dd of=open bs=1 count=1 seek=${sk} conv=notrunc > /dev/null 2>&1
        done
      }
      test_byte_ff

      經過一番努力,我們知道了在文件頭和程序頭中哪些字節可以被篡改,且不影響程序功能。然后按照思路一,嘗試將代碼段中的機器指令填充到ELF文件頭和程序頭中。
      由于ELF文件頭和程序頭中可以被篡改的字節不是連續的,可以使用匯編指令jmp對應的機器指令0xeb來進行跳轉。0xeb后面可以跟一個字節,表示向后跳轉的字節數。

      [root@i-a77ugr2f tmp]# objdump -d open.o
      open.o:     file format elf64-x86-64
      Disassembly of section .text:
      0000000000000000 <_start>:
         0:   b0 02                   mov    $0x2,%al            # 1
         2:   48 8b 7c 24 10          mov    0x10(%rsp),%rdi     # 2
         7:   0f 05                   syscall                    # 3
         9:   48 89 c7                mov    %rax,%rdi           # 4
         c:   48 31 c0                xor    %rax,%rax           # 5
         f:   be 00 00 00 00          mov    $0x0,%esi           # 6
        14:   66 ba ff ff             mov    $0xffff,%dx         # 7
        18:   0f 05                   syscall                    # 8
        1a:   48 89 c2                mov    %rax,%rdx           # 9
        1d:   48 31 c0                xor    %rax,%rax           # 10
        20:   b0 01                   mov    $0x1,%al            # 11
        22:   48 31 ff                xor    %rdi,%rdi           # 12
        25:   40 b7 01                mov    $0x1,%dil           # 13
        28:   0f 05                   syscall                    # 14
        2a:   48 31 c0                xor    %rax,%rax           # 15
        2d:   b0 03                   mov    $0x3,%al            # 16
        2f:   0f 05                   syscall                    # 17
        31:   b0 3c                   mov    $0x3c,%al           # 18
        33:   0f 05                   syscall                    # 19

      我們通過objdump命令可以從open.o文件中粗略查看,ELF文件的代碼段中機器指令對應的匯編指令。
      再配合jmp的跳轉方案,就可以試著將代碼段中的部分機器指令填充到ELF文件頭和程序頭中了。

      cutelf.sh
      #!/bin/sh
      mv_bytes() {
        # 覆蓋 e_ident[7~13],將0xb0(176)開始的7個字節(第1、2條指令),復制到0x07(7)開始的位置
        dd if=open of=open bs=1 skip=176 count=7 seek=7 conv=notrunc
      
        # 覆蓋 e_ident[14~15],將0x0e(14)開始的兩個字節覆蓋為(eb 04),表示從下一個字節算起,向后跳轉0x04(4)個字節
        echo -ne "\xeb\x04" | dd of=open bs=1 count=2 seek=14 conv=notrunc
      
        # 覆蓋 e_version[0~1],將0xb7(183)開始的2個字節(第3條指令),復制到0x14(20)開始的位置
        dd if=open of=open bs=1 skip=183 count=2 seek=20 conv=notrunc
      
        # 覆蓋 e_version[2~3],將0x16(22)開始的兩個字節覆蓋為(eb 10),表示向后跳轉0x10(16)個字節
        echo -ne "\xeb\x10" | dd of=open bs=1 count=2 seek=22 conv=notrunc
      
        # 覆蓋 e_shoff[0-7], e_flags[0-2],將0xb9(185)開始的11個字節(第4、5、6條指令),復制到0x28(40)開始的位置
        dd if=open of=open bs=1 skip=185 count=11 seek=40 conv=notrunc
      
        # 覆蓋 e_flags[3], e_ehsize[0],將0x33(51)開始的兩個字節覆蓋為(eb 05),表示向后跳轉0x05(5)個字節
        echo -ne "\xeb\x05" | dd of=open bs=1 count=2 seek=51 conv=notrunc
      
        # 覆蓋 e_shentsize, e_shnum,將0xc4(196)開始的4個字節(第7條指令),復制到0x3a(58)開始的位置
        dd if=open of=open bs=1 skip=196 count=4 seek=58 conv=notrunc
      
        # 覆蓋 e_shstrndx,將0x3e(62)開始的兩個字節覆蓋為(eb 18),表示向后跳轉0x18(24)個字節
        echo -ne "\xeb\x18" | dd of=open bs=1 count=2 seek=62 conv=notrunc
      
        # 覆蓋 p_paddr[0~4],將0xc8(200)開始的5個字節(第8、9條指令),復制到0x58(88)開始的位置
        dd if=open of=open bs=1 skip=200 count=5 seek=88 conv=notrunc
      
        # 覆蓋 p_paddr[5~6],將0x5d(93)開始的兩個字節覆蓋為(eb 11),表示向后跳轉0x11(17)個字節
        echo -ne "\xeb\x11" | dd of=open bs=1 count=2 seek=93 conv=notrunc
      
        # 覆蓋 p_align[0~4],將0xcd(205)開始的5個字節(第10、11條指令),復制到0x70(112)開始的位置
        dd if=open of=open bs=1 skip=205 count=5 seek=112 conv=notrunc
      
        # 覆蓋 p_align[5~6],將0x75(117)開始的兩個字節覆蓋為(eb 19),表示向后跳轉0x19(25)個字節
        echo -ne "\xeb\x19" | dd of=open bs=1 count=2 seek=117 conv=notrunc
      
        # 覆蓋 p_paddr[0~5],將0xd2(210)開始的6個字節(第12、13條指令),復制到0x90(144)開始的位置
        dd if=open of=open bs=1 skip=210 count=6 seek=144 conv=notrunc
      
        # 覆蓋 p_paddr[6~7],將0x96(150)開始的兩個字節覆蓋為(eb 10),表示向后跳轉0x10(16)個字節
        echo -ne "\xeb\x10" | dd of=open bs=1 count=2 seek=150 conv=notrunc
      
        # 覆蓋 p_align[0~7] 和后面的代碼段,將0xd8(216)開始的13個字節(第14-19條指令),復制到0xa8(168)開始的位置
        dd if=open of=open bs=1 skip=216 count=48 seek=168 conv=notrunc
      
        # 從0xb5(181)開始截去之后的字節
        dd if=open of=open bs=1 count=1 skip=181 seek=181
      
        # 覆蓋 e_entry[0~1],調整程序入口地址 0x4000b0->0x400007,將0x18(24)的字節修改為0x07
        echo -ne "\x07" | dd of=open bs=1 count=1 seek=24 conv=notrunc
      }
      mv_bytes > /dev/null 2>&1

      以上代碼建議就著上文的圖片一起看,再配合注釋更容易理解。

      [root@i-a77ugr2f tmp]# bash cutelf.sh
      [root@i-a77ugr2f tmp]# ./open /etc/passwd
      # 可以正常輸出
      [root@i-a77ugr2f tmp]# ll open
      -rwxr-xr-x 1 root root 181 Oct 31 00:15 open

      執行cutelf.sh腳本后,就獲得了僅181字節的極小ELF文件,符合謎題要求。

      posted @ 2022-11-08 00:51  Cathon  閱讀(266)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 人人爽人人爽人人爽| 国产精品丝袜一区二区三区| 国产 精品 自在 线免费| 99re6这里有精品热视频| 91精品91久久久久久| 亚洲区一区二区三区精品| 亚洲性美女一区二区三区| 成午夜福利人试看120秒| 国产伦码精品一区二区| 精品久久人人妻人人做精品| 久久香蕉欧美精品| 国产黄色一区二区三区四区| 五月综合网亚洲乱妇久久| 麻豆一区二区中文字幕| 亚洲中文字幕精品第一页| 国产日韩久久免费影院| 久久久久国产精品熟女影院| 日韩在线视频一区二区三区| 亚洲深深色噜噜狠狠网站| 国产视频最新| 欧美老少配性行为| 顶级欧美熟妇xx| 国产精品自拍视频免费看| 爱性久久久久久久久| 亚洲人成色7777在线观看不卡 | 少妇人妻偷人精品免费| 99久久精品国产亚洲精品| 毛茸茸性xxxx毛茸茸毛茸茸| 国产乱对白刺激视频| 青青草原国产AV福利网站| 四虎在线播放亚洲成人| 色悠悠国产在线视频一线| 婷婷四虎东京热无码群交双飞视频| 国产精品九九九一区二区| 精品国产丝袜自在线拍国语| 国产一二三五区不在卡| 日韩高清在线亚洲专区不卡| 大化| 国产乱子影视频上线免费观看| 国产高清一区二区不卡| 四虎永久在线高清免费看|