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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > asp.net >内容正文

asp.net

.NET平台PE结构分析之Metadata(一)

發(fā)布時(shí)間:2024/9/5 asp.net 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 .NET平台PE结构分析之Metadata(一) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

.NET平臺(tái)PE結(jié)構(gòu)分析之Metadata(一)

強(qiáng)命名及其去除

?

?????? 首先,這不是一篇完整的參考,所以并沒(méi)有涉及Metadata的各個(gè)方面,而只是討論了與強(qiáng)命名有關(guān)的部分。所以,在開(kāi)始前,先列出一些參考文獻(xiàn),在閱讀過(guò)程中若遇到問(wèn)題,可以直接從中查閱。

?

兩本書(shū):The Common Language Infrastructure Annotated StandardAddison Wesley

????????????? Inside Microsoft .NET IL AssemblerMicrosoft Corporation

文章:? MS.Net CLR擴(kuò)展PE結(jié)構(gòu)分析? (作者:Flier Lu

????????????? The .NET File Format??????????   (來(lái)自:codeproject.com

當(dāng)然,還有最權(quán)威的Framework SDK的文檔。

?

本文的例子文件:

?

1、什么是強(qiáng)命名(StrongName

?????? 我的理解,強(qiáng)命名類(lèi)似win32平臺(tái)下PE文件的checksum,用來(lái)對(duì)原始文件完整性進(jìn)行驗(yàn)證的。一般有兩個(gè)作用:一是不同版本的相同文件,Strongname是不一樣的,因此可以將其區(qū)分開(kāi);二是防止文件被修改,被修改的文件是無(wú)法運(yùn)行的。第一點(diǎn)我們不關(guān)心,但是第二點(diǎn)就應(yīng)該引起cracker們的注意了。一個(gè)加密非常簡(jiǎn)單的文件,只要改動(dòng)一個(gè)字節(jié)的數(shù)據(jù)(比如jejne)就可以破解,結(jié)果修改了過(guò)后卻無(wú)法運(yùn)行。郁悶啊!因此,在對(duì)有強(qiáng)命名的PE文件修改前,必須去掉其強(qiáng)命名。(太累了,下面一律簡(jiǎn)稱(chēng)SN。)

?

2、怎么給程序加上SN

?????? 這和cracker關(guān)系不大,但是了解一下有好處,至少有個(gè)感性的印象。

?????? 第一步,是生成一個(gè)key文件,命令是:sdk安裝目錄\bin\sn.exe –k strong.snk

?????? 第二步,把strong.snk文件的信息加入到你需要加密的Module當(dāng)中,通常在AssemblyInfo.cs的文件中添加:

?????? [assembly: AssemblyKeyFile(@"完整路徑\strong.snk")]

?????? 然后編譯生成就OK了。這樣,一個(gè)含有SN的文件便生成。可以用我寫(xiě)的工具snView看一下(文件見(jiàn)末尾的pskill.exe,這是我N年前寫(xiě)的一個(gè)查殺進(jìn)程的程序,已被加上SN):

?????? 看一下它的保護(hù)效果,用UD打開(kāi)文件,把末尾的一個(gè)字節(jié)從00改為01,再運(yùn)行。報(bào)錯(cuò),如下:

?

3、去除強(qiáng)命名的兩種方法

?????? 下面介紹去除SN的兩種方法,第一種手動(dòng),第二種自動(dòng)。

?

3.1、反匯編成il代碼,修改后再編譯成exe文件

?????? 這個(gè)方法不多講了,codeproject上有幾篇文章詳細(xì)說(shuō)過(guò):Building Security Awareness in .NET Assemblies : Part 3 - Learn to break strong name .NET Assemblies?,只大概說(shuō)一下過(guò)程。

?

1、? ildasm反匯編

2、? .assembly 這個(gè)assemblyname塊中尋找.publickey,如圖:

?????? 注意,會(huì)搜索到很多.publickeytoken,而且長(zhǎng)度較短。這些都不是該文件(assembly,又叫裝配件)的SN,而不過(guò)是其中的方法/類(lèi)等等的唯一性標(biāo)志。

3、? 刪除選定的部分

包含兩個(gè),一個(gè)是key的值,一個(gè)是.hash algorithm,這是計(jì)算該key的算法。 

4、? 再用ilasm進(jìn)行編譯

ilasm /resource=psill.res pskill.il

?

這時(shí)就可以對(duì)這個(gè)文件進(jìn)行修改了。

BUT,這種方法有兩個(gè)缺點(diǎn):一是麻煩,二是某些文件沒(méi)法反匯編,或反匯編不完全,或反匯編后就無(wú)法再次匯編成功。(特別是混淆過(guò)的程序)

?

3.2、直接在文件上修改

這樣最方便,但是,方便的前提是你知道.NET判斷SN的數(shù)據(jù)及修改方法,這就要牽涉到Metadata了。

原先網(wǎng)上有一個(gè)工具,叫snRemove,不過(guò)不好用,修改完了運(yùn)行不了。這里先紹一個(gè)偶寫(xiě)的工具:snRemover,可以自動(dòng)去除程序中的SN。下載請(qǐng)到http://vxer.cn/hmx

?

?

下面介紹snRemover的原理。什么是Metadata?我們都知道,.NET下運(yùn)行的PE文件類(lèi)似JAVA,不是將指令編譯成機(jī)器代碼,而是編譯成il中間代碼,再在運(yùn)行時(shí)進(jìn)行既時(shí)編譯(JIT)。這樣,用一些軟件可以直接打開(kāi)PE文件,看到類(lèi)名、方法名、指令等等。所有的這些東東,都是Metadata。我們的任務(wù),就是在Metadata中,找到標(biāo)識(shí)SN的地方并修改之。

下面假定你已經(jīng)對(duì)win32平臺(tái)下PE結(jié)構(gòu)有些了解了,講述從簡(jiǎn)。

PE文件中緊跟PE Header的是16個(gè)Data Directory Table,最常見(jiàn)的是第1個(gè)輸出表和第2個(gè)輸入表。而.NET擴(kuò)展的PE結(jié)構(gòu)則由倒數(shù)第二個(gè)表指向,也就是Common Language Runtime header address and size(簡(jiǎn)稱(chēng)CLI),根據(jù)他,我們找到了CLI Header。以pskill.exe為例,CLI HeaderRVA2008,大小是48,算出物理偏移是1008。你現(xiàn)在就可以用UD打開(kāi)pskill.exe跟著我走了。

00001008h: 48 00 00 00 02 00 05 00 10 42 00 00 60 11 00 00 ; H........B..`...

00001018h: 09 00 00 00 04 00 00 06 A8 26 00 00 65 1B 00 00 ; ........?..e...

00001028h: 50 20 00 00 80 00 00 00 00 00 00 00 00 00 00 00 ; P ..€...........

00001038h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................

00001048h: 00 00 00 00 00 00 00 00???????????????????????? ; ........

?

CLI Header的結(jié)構(gòu)如下:

RVA

Field

Contents

0x2008

Cb(結(jié)構(gòu)的大小)

0x48

0x200C

MajorRuntimeVersion

2

0x200E

MinorRuntimeVersion

0

0x2010

MetaData

0x2060

0x2014

Size of the Metadata

0x148 =(RVA of Import Table) – (RVA of MetaData)

0x2018

Flags

1

0x201C

EntryPointToken

0x06000001 (Method #1 in TypeDef table)

0x2020

Resources

0

0x2028

StrongNameSignature

0

0x2030

CodeManagerTable

0

0x2038

VTableFixups

0

0x2040

ExportAddressTableJumps

0

0x2048

ManagedNativeHeader

0

?

這里,出現(xiàn)了兩處和SN有關(guān)的標(biāo)識(shí)。一處是FLAGS,另一處是StrongNameSignature。對(duì)于FLAGS,有這個(gè)標(biāo)志:

COMIMAGE_FLAGS_STRONGNAMESIGNED (0x00000008)?

如果這處標(biāo)志被置位,則認(rèn)為有SN。第二處則指出了SN數(shù)據(jù)的RVA和大小,也就是最開(kāi)始用snView看到的。

修改時(shí),FLAGS標(biāo)志位減去0x00000008,然后把StrongNameSignatureRVASIZE 均填0。運(yùn)行一下試試,還是出錯(cuò)。當(dāng)然,還有一處最重要的地方要修改,我們繼續(xù)。

注意第四項(xiàng)Metadata,他指出了Metadata表的RVA和大小。看一下,pskillMetadataRVA=4210處,也就是物理地址3210處。

00003210h: 42 53 4A 42 01 00 01 00 00 00 00 00 0C 00 00 00 ; BSJB............

00003220h: 76 32 2E 30 2E 35 30 37 32 37 00 00 00 00 05 00 ; v2.0.50727......

00003230h: 6C 00 00 00 7C 05 00 00 23 7E 00 00 E8 05 00 00 ; l...|...#~..?..

00003240h: 80 07 00 00 23 53 74 72 69 6E 67 73 00 00 00 00 ; €...#Strings....

00003250h: 68 0D 00 00 80 01 00 00 23 55 53 00 E8 0E 00 00 ; h...€...#US.?..

00003260h: 10 00 00 00 23 47 55 49 44 00 00 00 F8 0E 00 00 ; ....#GUID...?..

00003270h: 68 02 00 00 23 42 6C6F 62 00 00 00 00 00 00 00 ; h...#Blob.......

00003280h: 02 00 00 01 57 15 02 00 09 01 00 00 00 FA 01 33 ; ....W........?3

00003290h: 00 16 00 00 01 00 00 00 33 00 00 00 02 00 00 00 ; ........3.......

000032a0h: 09 00 00 00 0A 00 00 00 0C 00 00 00 53 00 00 00 ; ............S...

000032b0h: 0D 00 00 00 04 00 00 00 01 00 00 00 05 00 00 00 ; ................

000032c0h: 01 00 00 00 00 00 0A 00 01 00 00 00 00 00 06 00 ; ................

?

看一下文檔中對(duì)Metadata的定義:

Type

Field

Description

DWORD

lSignature

“Magic” signature for physical metadata, currently 0x424A5342

WORD

iMajorVersion

Major version (1 for the first release of the common language runtime)

WORD

iMinorVersion

Minor version (1 for the first release of the common language runtime)

DWORD

iExtraData

Reserved; set to 0

DWORD

iLength

Length of the version string

BYTE[?]

iVersionString

Version string

BYTE

fFlags

Reserved; set to 0

BYTE

?

[padding]

WORD

iStreams

Number of streams

?

第一項(xiàng),Metadata根部的標(biāo)識(shí),ASC碼“BSJB”。這樣,以后我們?cè)趯ふ宜鼤r(shí)就可以直接搜索“BSJB”既可。這里有一點(diǎn)注意,就是ASC碼串VersionString是可變長(zhǎng)度的,結(jié)束后再加一個(gè)fFlags,然后要和4字節(jié)對(duì)齊,也就是padding。這里,我們的版本號(hào)是v2.0.50727,前面iLength指出了長(zhǎng)度是0C(十進(jìn)制的12,已經(jīng)是和4對(duì)齊的了,能整除),因此fFlags的地址就是00003220+0C=0000322C,后一個(gè)字節(jié)為空,又是padding。最后,05 00指出了Number of streams,共有幾個(gè)數(shù)據(jù)流。

Metadata中的數(shù)據(jù)都是存放在各種數(shù)據(jù)流stream里,比較重要的是“#~”和“#Strings”,后者保存了各種名稱(chēng)(比較混淆或者反混淆,就要從這個(gè)流著手,如果有機(jī)會(huì),下次再講),而與SN相關(guān)的則是#~流。它也是所有當(dāng)中最復(fù)雜的。

緊接著上面的數(shù)據(jù),就是各個(gè)流的Header了:

00003230h: 6C 00 00 00 7C 05 00 00 23 7E 00 00 E8 05 00 00 ; l...|...#~..?..

00003240h: 80 07 00 00 23 53 74 72 69 6E 67 73 00 00 00 00 ; €...#Strings....

00003250h: 68 0D 00 00 80 01 00 00 23 55 53 00 E8 0E 00 00 ; h...€...#US.?..

00003260h: 10 00 00 00 23 47 55 49 44 00 00 00 F8 0E 00 00 ; ....#GUID...?..

00003270h: 68 02 00 00 23 42 6C6F 62 00 00 00 00 00 00 00 ; h...#Blob.......

?

這個(gè)結(jié)構(gòu)不難,如下:

Type

Field

Description

DWORD

iOffset

Offset in the file for this stream

DWORD

iSize

Size of the stream in bytes

char[]

rcName

Name of the stream; a zero-terminated ANSI string no longer than seven characters

?

?

我們以#~為例

00003230h: 6C 00 00 00 7C 05 00 00 23 7E 00 00 E8 05 00 00 ; l...|...#~..?..

紅色部分是RVA,相對(duì)于Metadata Root的,藍(lán)色部分是大小,而黑色斜體就是“#~”的ASC碼了。那為什么237E后要加兩個(gè)字節(jié)的0呢?又忘了?因?yàn)樽址c4字節(jié)對(duì)齊。我們來(lái)計(jì)算#~流的實(shí)際物理地址:offset=root + RVA=00003210+6C=0000327C

0000327ch: 00 00 00 00 02 00 00 01 57 15 02 00 09 01 00 00 ; ........W.......

0000328ch: 00 FA 01 33 00 16 00?????????????

?

對(duì)應(yīng)的結(jié)構(gòu)如下:

Size

Field

Description

4 bytes

Reserved

Reserved; set to 0.

1 byte

Major

Major version of the table schema (1 for the first release of the common language runtime).

1 byte

Minor

Minor version of the table schema (0 for the first release of the common language runtime).

1 byte

Heaps

Binary flags indicate the offset sizes to be used within the heaps.

A 4-byte unsigned integer offset is indicated by 0x01 for a string heap, 0x02 for a GUID heap, and 0x04 for a blob heap.

If a flag is not set, the respective heap offset is presumed to be a 2-byte unsigned integer.

?

?

A # stream can also have special flags set: flag 0x20, indicating that the stream contains only changes made during an edit-and-continue session, and flag 0x80, indicating that the metadata might contain items marked as deleted.

1 byte

Rid

Bit count of the maximal record index to all tables of the metadata; calculated at run time (during the metadata stream initialization).

8 bytes

MaskValid

Bit vector of present tables, each bit representing one table (1 if present).

8 bytes

Sorted

Bit vector of sorted tables, each bit representing a respective table (1 if sorted).

?

這里要講一下#~流中各種數(shù)據(jù)的保存形式了。該流中保存的主要是各種表,這些表又定義了Metadata中其它的各種數(shù)據(jù),所以才說(shuō)它重要啊。現(xiàn)在微軟已經(jīng)定義的表有

注意結(jié)構(gòu)中的MaskValid數(shù)據(jù),它是8字節(jié)的,對(duì)應(yīng)2進(jìn)制數(shù)有64位。從最低位開(kāi)始,如果這個(gè)位為1,代表#~流中該表被定義了,如果為0,代表沒(méi)有該表。我們看一下pskill的數(shù)據(jù),為57 15 02 00 09 01 00 00,翻譯為2進(jìn)制為

2進(jìn)制:0000 0000 0000 0000 0000 0001 0000 1001 0000 0000 0000 0010 0001 0101 0101 0111

16進(jìn)制: 0?? 0??? 0?? 0??? 0?? 1??? 0?? 9??? 0?? 0??? 0?? 2??? 1?? 5?? 5??? 7

這樣我們就知道了一共有C個(gè)表被定義了,pskill中存在的表可以用Spices .Net看一下,再與上表對(duì)應(yīng)一下,看看是不是相等:

?

?

同時(shí),我們點(diǎn)擊了第20個(gè)表,AssemblyDef,看到了右邊的數(shù)據(jù)顯示出了PublicKey,那不正是我們要找的SN嗎。

????????????? 接下來(lái)的工作就是計(jì)算AssemblyDef前面表的大小,然后直到找到AssemblyDef為止。剩下的不多講了,可以看codeproject的那篇THE .NET File Format。但是這個(gè)過(guò)程是非常煩索的,我寫(xiě)的強(qiáng)命名去除工具snRemover也沒(méi)有說(shuō)細(xì)的計(jì)算,而是選擇一個(gè)比較偷懶的方法。下面再說(shuō)。我們先來(lái)到AssemblyDef處:

0000376eh: 04 80 00 00 01 00 00 00 05 09 64 5F 01 00 00 00 ; .€........d_....

0000377eh: 46 00 1B 00 00?????? ???????????????????????????; F....

?

來(lái)看一下AssemblyDef的定義:

?

? HashAlgId (a 4-byte constant of type AssemblyHashAlgorithm).

? MajorVersion, MinorVersion, BuildNumber, RevisionNumber

(2-byte constants).

? Flags (a 4-byte bit mask of type AssemblyFlags).

? PublicKey (index into Blob heap).

? Name (index into String heap).

? Culture (index into String heap).

一共有6項(xiàng),其中Flags項(xiàng)有一個(gè)常數(shù)為

afPublicKey = 0x0001,

// The assembly ref holds the full (unhashed) public key.

也就是說(shuō),如果Flags(數(shù)據(jù)中藍(lán)色部分)的第一位被置1,則認(rèn)為它有SN。因此,我們將Flags1,然后將.PublicKey項(xiàng)(黑色斜體部分,指向BLOG中的指針)置0。現(xiàn)在才徹底修改完成。運(yùn)行一下,OK??????

????????????? 偶是怎么定義AssemblyDef的地方的呢?因?yàn)樵摫淼牡谝豁?xiàng)為HashAlgId,目前只有三種可能:00008004,000080030。如果是0,代表沒(méi)有SN。因此直接從#~開(kāi)始,搜索00008004或者00008003,定義既可。但是有失敗的可能,因?yàn)椴荒鼙WCAssemblyDef之前的表中沒(méi)有0000800400008003,那樣的話(huà)就玩完了。不過(guò)我試了那么多程序,暫時(shí)沒(méi)有發(fā)現(xiàn)不能用。等回頭有空再把snRemover改成精確定位吧!

?

?

????????????? 要是你能堅(jiān)持看到這,真得感謝你了,頭暈了吧!我打字都不行了。那就休息一下,下次再講講簡(jiǎn)單的,因?yàn)樽铍y的部分已經(jīng)講完了。

?

?

By:tankaiha [NE365]

2006.04.28

Any bug, report to http://vxer.cn/

?

轉(zhuǎn)載于:https://www.cnblogs.com/cxd4321/archive/2008/06/04/1213313.html

與50位技術(shù)專(zhuān)家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的.NET平台PE结构分析之Metadata(一)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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