日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

UEFI 文件类型 .efi (二)

發(fā)布時(shí)間:2023/12/10 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 UEFI 文件类型 .efi (二) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

上一篇博客講了一個(gè)例子關(guān)于在一個(gè)C 程序里如何動(dòng)態(tài)去load 一個(gè)可執(zhí)行文件,并且讓這個(gè)文件能夠跑起來,代碼里有幾處是hard code 寫的,沒有去根據(jù)讀取的可執(zhí)行文件類型去分析它。上篇也說了,如果那個(gè)例子理解透了,那么對于efi 文件加載和執(zhí)行理解起來就不成問題了。

這篇博客介紹一下,efi 文件內(nèi)容。其實(shí)不用去看代碼,也不用怎么翻spec, 看看下面的幾個(gè)圖片,應(yīng)該就會(huì)很清晰,efi 文件的重定位,裝載,執(zhí)行了。

舉個(gè)具體例子看一下吧。我這邊有一個(gè)build 好的efi driver, 文件格式呢是pe32。

先來看看這個(gè)driver 是怎么個(gè)結(jié)構(gòu),我們可以用Windows 下的命令dumpbin /ALL xxx.efi > xx.txt

FILE HEADER VALUES
14C machine (x86)
3 number of sections
0 time date stamp
0 file pointer to symbol table
0 number of symbols
E0 size of optional header
2102 characteristics
Executable
32 bit word machine
DLL

OPTIONAL HEADER VALUES
10B magic # (PE32)
10.00 linker version
4DA0 size of code
4400 size of initialized data
0 size of uninitialized data
240 entry point (00000240)
240 base of code
4FE0 base of data
0 image base (00000000 to 000093DF)
20 section alignment
20 file alignment
0.00 operating system version
0.00 image version
0.00 subsystem version
0 Win32 version
93E0 size of image
240 size of headers
0 checksum
B subsystem (EFI Boot Service Driver)
0 DLL characteristics
0 size of stack reserve
0 size of stack commit
0 size of heap reserve
0 size of heap commit
0 loader flags
10 number of directories
0 [ 0] RVA [size] of Export Directory
0 [ 0] RVA [size] of Import Directory
0 [ 0] RVA [size] of Resource Directory
0 [ 0] RVA [size] of Exception Directory
0 [ 0] RVA [size] of Certificates Directory
8FA0 [ 428] RVA [size] of Base Relocation Directory
0 [ 0] RVA [size] of Debug Directory
0 [ 0] RVA [size] of Architecture Directory
0 [ 0] RVA [size] of Global Pointer Directory
0 [ 0] RVA [size] of Thread Storage Directory
0 [ 0] RVA [size] of Load Configuration Directory
0 [ 0] RVA [size] of Bound Import Directory
0 [ 0] RVA [size] of Import Address Table Directory
0 [ 0] RVA [size] of Delay Import Directory
0 [ 0] RVA [size] of COM Descriptor Directory
0 [ 0] RVA [size] of Reserved Directory

只是截取一部分,大概就這個(gè)樣子,我們只關(guān)心加載和執(zhí)行,所以其中

  • entry point
  • image base
  • 重定向表
  • 都在option header 里。所以無論我們的build tool 還是core 去分析這個(gè)driver 找到option header 就可以把需要的信息提取出來。提取出來,我們image 需要重定向,關(guān)于重定向之前也講過,需要分析重定向表,好吧,看看重定向表的信息。

    SECTION HEADER #3.reloc name428 virtual size8FA0 virtual address (00008FA0 to 000093C7)440 size of raw data8FA0 file pointer to raw data (00008FA0 to 000093DF)0 file pointer to relocation table0 file pointer to line numbers0 number of relocations0 number of line numbers 42000040 flagsInitialized DataDiscardableRead OnlyRAW DATA #300008FA0: 00 00 00 00 4C 00 00 00 54 32 6F 32 80 32 85 32 00008FB0: A1 32 B6 33 CC 33 E2 33 F8 33 04 36 2C 36 36 38 00008FC0: 47 38 4D 38 59 38 9C 38 97 39 10 3A 37 3A 52 3A 00008FD0: 57 3A 09 3B 35 3B 95 3B 2D 3C 4C 3C 6B 3C 8A 3C 00008FE0: A9 3C 2B 3E 32 3E E6 3E 4B 3F 5D 3F 00 10 00 00 00008FF0: 68 00 00 00 87 33 D2 33 95 35 9B 35 DE 35 E4 35 00009000: 3A 36 40 36 BA 36 BF 36 12 37 17 37 63 37 69 37 00009010: 8D 37 92 37 AB 37 B1 37 C7 37 CD 37 EA 37 F0 37 00009020: 06 38 0C 38 22 38 28 38 36 38 3B 38 5B 38 61 38 00009030: 77 38 7D 38 91 38 97 38 AB 38 B1 38 CD 38 D5 38 00009040: 33 39 3A 39 BD 39 C3 39 82 3B 4B 3D 25 3F 44 3F // 重定向表的解析BASE RELOCATIONS #30 RVA, 4C SizeOfBlock254 HIGHLOW 000051B026F HIGHLOW 000070B8280 HIGHLOW 00005020285 HIGHLOW 000070BC2A1 HIGHLOW 000070A03B6 HIGHLOW 000052A03CC HIGHLOW 000052B03E2 HIGHLOW 000052C03F8 HIGHLOW 000052D0604 HIGHLOW 00005010

    我們也稍微簡單分析一下這個(gè)可重定向表,我們可以從表頭可以看到這個(gè)表載入內(nèi)存大小是0x428, 并且virtual address 0x8FA0(Image base 0x0000),所以0x8FA0 也可以看成載入內(nèi)存時(shí)候,可重定向表距離image base 偏移是0x8FA0。 OK 找到表了,接下來就是對表的分析了

    00008FA0: 00 00 00 00 4C 00 00 00 54 32 6F 32 80 32 85 32

    重定向表還是按照block 去劃分,每個(gè)block 會(huì)有一個(gè)header ,里面有兩個(gè)內(nèi)容 1 UINT32 RVP, 2 UINT32 blocksize。 從上面的數(shù)據(jù),我們可以得出 RVP 是 0x00000000, blocksize =0x4c ,然后每個(gè)可重定位項(xiàng)是16bits 高4位是類型,低12bit 是偏移。我們可以看到上面的 54 32 就會(huì)解析成,偏移是0x254, 類型是0x03(HIGHLOW)。這個(gè)0x254 需要加上所在Block 的 RVP, 意思就是0x254 + 0x000000 = 0x254,這個(gè)偏移地方需要修改,修改多大,我們的類型是0x03,就是32bit。一起看個(gè)圖片就知道了。兩張圖一個(gè)是重定向后的(左),一個(gè)沒有重定向(右)。

    可以看到偏移0xF4 的位置被修改了,那是Image Base ,被修改成實(shí)際image 載入內(nèi)存的地址。剩下的就是需要重定向位置,我們用可以看到上面需要重定向的位置,有0x254, 0x26F, 等等,我們對著圖片看看,不一樣的地方正好和這些重定向偏移的地址吻合。好了,重定向之后,我們就可以根據(jù)表頭的Entry point 偏移找到入口地址,然后跳入這個(gè)image 里。

    關(guān)于PE 結(jié)構(gòu),它有它方便的一面,也有復(fù)雜的一面,對于學(xué)習(xí)uefi 的同學(xué),PE 結(jié)構(gòu),我們了解這么多,也可以了。其他方面關(guān)于導(dǎo)入表,導(dǎo)出表,動(dòng)態(tài)延時(shí)綁定等等,有興趣自己去找另外的資料研究學(xué)習(xí)。

    看著簡單吧,其實(shí)自己寫還不一定能寫好,因?yàn)橐灿泻芏嗉?xì)節(jié)問題,比如內(nèi)存對齊等等,細(xì)節(jié)的地方只能自己去摸索了,別人講太多都是記不住,程序員還是應(yīng)該務(wù)實(shí)一點(diǎn),寫幾段代碼調(diào)試幾遍。比只看不寫強(qiáng)太多。

    總結(jié)

    以上是生活随笔為你收集整理的UEFI 文件类型 .efi (二)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。