看雪-課程-加密與解密基礎
July 13, 2020 8:36 PM
學習看雪的加密與解密基礎
1.概述
0 預備知識
1.匯編語言 《王爽匯編》
2.C語言
3.Win32編程,API方式的Windows程序設計。Charles Petzold所著的《Windows程序設計》以C語言為講解平台
1.1起始
關鍵詞:加密、解密、逆向工程、靜態分析、動態分析
從理論上說,幾乎沒有破解不了的保護。對軟件的保護僅僅靠技術是不夠的,最終要靠人們的知識產權意識和法制觀念的進步以及生活水平的提高。如果一種保護技術的強度強到足以讓破解者在軟件的生命周期內無法將其完全破解,這種保護技術就可以說是非常成功的。軟件保護方式的設計應在一開始就作為軟件開發的一部分來考慮,列入開發計划和開發成本中,並在保護強度、成本、易用性之間進行折衷考慮,選擇一個合適的平衡點。
1.2軟件解密技術
通過研究解密技術可以掌握一些Windows系統底層知識.
作為一個合格的程序員,上要能上到需求分析,設計抽象,設計模式等,下要能下到系統核心,熟悉整個系統的底層結構。
學習解密建議掌握:
- 匯編語言一定得學好;
- 至少掌握一門高級語言;
- 握Win32編程,WinSDK程序設計就是API方式的Windows程序設計,學習Windows API將使您更深入地了解Windows工作方式。此類書籍有Charles Petzold著的《Windows程序設計》(以C來講解)。
- 有精力,再看看《Windows核心編程》這類書,相信會使你內力大增的。
- 有了這些基礎,再參考《加密與解密》(第二版)這本書,你將會扣開加解密的大門。
解密技術涉及到了很多的方面,這里只是簡單窺探一下破解者的操作手法――靜態分析技術與動態分析技術。
1.3 靜態分析介紹
高級語言編寫的程序有兩種形式:
- 一種編譯成機器語言在CPU上執行,如Visual C ++、PASCAL等。由於機器語言與匯編語言幾乎是一一對應的,因此可將機器語言轉化成匯編語言,這個過程稱為反匯編(Disassembler)。
- 另一種高級語言是一邊解釋一邊執行的,稱之為解釋性語言。如Visual Basic 3.0/4.0、Visual FoxPro等,這類語言編譯的程序可以被還原成高級語言的原始結構,這個過程稱為反編譯(Decompiler)。
++靜態分析,即從反匯編出來的程序清單上分析程序流程,了解關注模塊完成的功能++
1.反匯編
編譯執行的語言因為直接同CPU的指令集打交道,具有很強的指令依賴性和系統依賴性,但編譯后的程序執行效率要比解釋語言高得多
反匯編工具,如W32Dasm、IDA pro等,將二進制的機器語言反匯編成匯編代碼,在匯編代碼級別上來分析程序的功能
2.反編譯
解釋性語言在編譯期間,它的程序代碼不被直接轉換成計算機識別的二進制代碼,而是只生成一種中間代碼,目的不是讓計算機直接去執行,而只是為了進行先期語法檢查。這些代碼被放置到內存的“數據段”中,運行時由一個解釋器再動態解釋被存放於“數據段”的偽代碼。因此,可以看到很多偽編譯的程序都帶有一個很大的DLL之類的文件,例如Visual Basic、Visual FoxPro、Power Builder、Java等。解釋執行的語言由於其解釋器不需要直接同機器碼打交道,所以實現起來較為簡單,而且便於在不同的平台上面移植。解釋語言編譯的代碼實際上是“變形的源代碼”,只要能理解其對應機制,就能做出反編譯器來。這類語言編譯的程序可以被還原成高級語言的原始結構,這個過程稱為反編譯(Decompiler)。
最新的Microsoft Visual Studio.net也是一種解釋語言,只是將名稱換成“中間語言(Microsoft Intermediate Language)”。如果用W32Dasm反匯編一此類程序,將會看到莫名其妙的代碼,因為它不再是傳統意義上的匯編代碼了,只有用P-code反編譯器才能得到正確的代碼,以從語言助記符上理解程序功能。如支持VB5/VB6 P-code的反編譯器Exdec、WKTVBDE、VBDE,對付最新microsoft .net的反編譯程序LDASM(.NET FRAMEWORK SDK中提供)等。
從靜態上可以了解各個模塊的功能以及整個軟件的編程思路,但是,並不可能真正地了解軟件中各個模塊的技術細節
1.4動態分析介紹
對於被分析的軟件來說,靜態分析只是工作的第一步,動態跟蹤是分析軟件的關鍵所在。所謂動態跟蹤主要是指利用Visual C++自帶的調試器,或系統級調試器SoftICE或TRW2000等,一步一步跟蹤分析。
由於Win32程序內存尋址使用的是相對簡單的平坦尋址模式,並且Win32程序大量調用系統提供的API,而Win32平台上的調試器如SoftICE等恰好有針對API設置斷點的強大功能,因而這些特點都給動態跟蹤破解帶來極大的方便。因為程序的作者用的是高級語言,Windows又是提倡“透明 ”,不希望程序員知道底層的操作 , 而只提供給他們高層的接口, 而相當多的高級函數調用某個一定的底層函數,所以解密者經常在底層函數上下斷點。所以在Windows中,只要Windows的函數被使用,想對任何尋找蛛絲馬跡的人隱藏什么東西是比較困難的。
為什么要對軟件進行動態分析呢?這主要是因為:
1、許多軟件在整體上完成的功能,一般要分解成若干模塊來完成,而且后一模塊在執行時,往往需要使用其前一模塊處理的結果,這一結果我們把它叫中間結果。如果我們只對軟件本身進行靜態地分析,一般是很難分析出這些中間結果的。而只有通過跟蹤執行前一模塊,才能看到這些結果。另外,在程序的運行過程中,往往會在某一地方出現許多分支和轉移,不同的分支和轉移往往需要不同的條件,而這些條件一般是由運行該分支之前的程序來產生的。如果想知道程序運行到該分支的地方時,到底走向哪一分支,不進行動態地跟蹤和分析是不得而知的。
2、有許多軟件在運行時,其最初執行的一段程序往往需要對該軟件的后面各個模塊進行一些初始始化工作,而沒有依賴系統的重定位。
3、有許多加密程序為了阻止非法跟蹤和閱讀,對執行代碼的大部分內容進行了加密變換,而只有很短的一段程序是明文。加密程序運行時,采用了逐塊解密,逐塊執行和方法,首先運行最初的一段明文程序,該程序在運行過程中,不僅要完成阻止跟蹤的任務,而且還要負責對下一塊密碼進行解密。顯然僅對該軟件的密碼部分進行反匯編,不對該軟件動態跟蹤分析,是根本不可能進行解密的。
由於上述原因,在對軟件靜態分析不行的條件下,就要進行動態分析了。
1.5逆向工程
逆向工程(Reverse Engineering)定義為:"the process of analyzing a subject system to identify the system's components and their interrelationships and create representations of the system in another form or at a higher level of abstraction." (Source: Chikofsky and Cross)
如果認為:
“源代碼 → 編譯器 → 可執行程序”的過程是“順向工程”的話;
“可執行程序 → 反編譯器或人工反編譯 → 源代碼”的過程就是逆向工程。
將逆向工程包括的內容可以分為3類:
1.軟件使用限制的去除,或軟件功能的添加
(1) 按照計算機類別,可以分為個人微型計算機、小型機、中型機、大型機等;
(2) 按照操作平台或處理器類型,可以分為windows、MAC、UNIX,x86,risc等
(3) 按照限制類型,可以分為軟件使用時間限制,軟件功能模塊限制、軟件運行條件限制(軟件狗等)、軟件注冊限制等
(4) 可以是軟件功能限制的去除,也可以是軟件功能的添加。
2.軟件源代碼的再獲得或二進制代碼水平的Debug
(1) 按照計算機類別,可以分為個人微型計算機、小型機、中型機、大型機等;
(2) 按照操作平台,可以分為windows、MAC、UNIX等
(3) 按照軟件層次,可以分為普通應用層軟件與操作系統源等。
3.硬件的復制、模擬
坦白地講,現在的逆向工程,真實目的就是為了再利用。據此,個人可以學習別人的編程技術及技巧,公司可以窺探別人的商業軟件秘密,或開發與之兼容的軟件;(二進制代碼層面的)Debug自然也是其中重要的目的之一。
據說,著名的殺毒軟件AVP代碼寫的實在太有條理,因此很容易被分析后“再利用”。有心人不僅可以將其病毒特征庫改頭換面后再推出,也可以利用逆向工程得到AVP某些模塊的源代碼,加入自己開發的產品中。
在《看雪論壇精華5》(www.pediy.com)中,收錄了一篇文章,講述如何利用逆向工程知識為一個多媒體播放軟件去除“靜音”bug的過程。
《Windows圖形編程》(Feng Yuan著,機械工業出版社)一書中,作者花費了2個章節,約100多頁的文字來介紹如何探索windows系統的GDI/DirectDraw內部數據結構,以及如何自制一個apispy來幫助研究。利用類似的方法,你可以自行探索操作系統的奧秘,而不需要別人的講解。不過,由此產生的副作用是系統上的很多bug被發現和利用,最有名的就是“堆棧溢出攻擊”。
利用逆向工程技術還可以使我們對一些軟件進行改造。《程序員雜志》2003.07有文章《編程擴展“記事本”功能》,介紹的就是一例。作者是采用CreateRemoteThread函數遠程鈎入目標程序進程內,達到其目的。而另一些人可能更喜歡直接修改目標程序的一些二進制代碼,從而利用附加的Dll(動態運行庫)。后面一種方法叫做SMC(Self Modifying Code)。我看到有人這樣為Netscape添加按鈕執行“密碼保護”功能;有人為filemon添加了“打開最近文檔”功能......但最著名的,還是改造W32Dasm――一個著名的反匯編工具活動。通過協作,目前的W32Dasm已經能支持中文字符串,能識別VB程序的引入表,能直接對反匯編程序patch,能添加注釋等等,而這一切都是在沒有源代碼情況下,直接在二進制代碼層面完成。
++著名的反編譯器提供商datarescue出品的IDA Pro,提供對30多個家族、幾十種處理器的支持,它支持windows平台上幾乎所有的編譯器++
成為一個“逆向工程”大師,應該具有如下特征:
1.永遠保存好奇心,崇尚自由。這能促使探索;也能抵抗商業利欲的侵襲;有了它,枯燥的代碼世界才有了生氣。
2.勤奮與毅力:“讓我們搞清楚作為一名Cracker最需要具備的基本條件,其實那並不是扎實的匯編功底和編程基礎。你可以完全不懂這些,CRACKING的秘訣就是勤奮+執着!記住並能做到這兩點,你一樣可以變得優秀。”
3.精通至少一門編程語言,不僅僅是Coding,更重要的是編程思想。RAD工具也許是容易學的,但你要明白隱藏在它背后的機制。
4.扎實的匯編功底和系統編程的知識。
5.能發現“美麗”。是的,你能在枯燥的二進制代碼中見到美,那是數學和對稱的美麗。卓越的編譯器優化能力,簡潔而又高效的代碼,都能使你領略到她的存在。
逆向工程的終極網站woodmann上列出那些大師的名字:Matt Pietrek,Jeffrey Richter,John Robbins ......他們的專著是每個程序員都應該閱讀的:《Windows95系統程式設計打奧秘》、《Windows核心編程》、《應用程序調試技術》......
總之,逆向工程應是一門優雅的藝術,而不是低層次者手中粗陋的工具;逆向工程的目的是學習與再利用;它的精神是“自由”。
2 文本字符
2.1 ASCII字符集
++美國信息交換標准碼(ASCII)是一個7位的編碼標准,包括26個小寫字母、26個大寫字母、10個數字、32個符號、33個控制代碼及空格,總共128個代碼。++
由於計算機通常用“字節”(byte)這個8位的存儲單位來進行信息交換,因此不同的計算機廠商對ASCII進行了擴充,增加了128個附加字符,它們的值在127以上的部分是不統一的。例如ANSI、Symbol、OEM等字符集,其中ANSI是系統預設的標准文字存儲格式。
Unicode是ASCII字符編碼的一個擴展,只不過在Windows中用2個字節對其進行編碼,也稱為“寬字符集”(Widechars)。Unicode是一種雙字節編碼機制的字符集,使用0~65535之間的雙字節無符號整數對每個字符進行編碼。在Unicode中,所有的字符都是16位,包括所有的7位ASCII碼都被擴充為16位(注意,高位擴充的是零)。例如,字符串“pediy”的ASCII碼是:
70h 65h 64h 69h 79h
其Unicode碼的十六進制是:
0070h 0065h 0064h 0069h 0079h
Intel處理器在內存中,一個字存入存儲器要占有相繼的2個字節,這個字存放時就按Little-Endian方式存入,即低位字節存入低地址,高位字節存入高地址.
2.2 字節存儲順序
多字節數據是按怎樣的順序存放的呢?
實際情況和CPU有關,微處理機中的存放順序有正序(Big-Endian)和逆序(Little-Endian)之分。
- 常見的Intel體系芯片使用的編碼方式屬於Little-Endian類;
- 某些RISC架構的CPU,如IBM的Power-PC等屬於Big-Endian類。
兩種編碼區別:
- Big-Endian 高位字節存入低地址,低位字節存入高地址,依次排列;
- Little-Endian 低位字節存入低地址,高位字節存入高地址,反序排列。
3 Windows操作系統
3.1 Win32 API函數
API的英文全稱為“Application Programming Interface”(應用程序編程接口)
在Windows程序設計領域發展的初期,Windows程序員能夠使用的編程工具唯有API函數。這些函數提供應用程序運行所需要的窗口管理、圖形設備接口、內存管理等各項服務功能。這些功能以函數庫的形式組織在一起,形成了Windows應用程序編程接口(API),簡稱“Win API”。Win API子系統負責將API調用轉換成Windows操作系統的系統服務調用。所以,可以認為API函數是構築整個Windows框架的基石,它的下面是Windows的操作系統核心,而它的上面則是Windows應用程序
如下圖所示。對應用程序開發人員而言,所看到的Windows操作系統實際上就是Win API,操作系統的其他部分對開發人員來說是完全透明的。
用於16位版本Windows的API(Windows 1.0到Windows 3.1)稱作“Win16”,用於32位版本Windows的API(Windows 9x/NT/2000/XP/2003)稱作“Win32”。64位版本Windows API的名稱和功能基本沒有變化,還是Win32的函數名,只不過是用64位代碼實現的。API函數調用在從Win16到Win32的轉變中保持兼容,並在數量和功能上不斷增強——Windows 1.0支持不到450個函數調用,現在已有幾千個函數。
所有32位版本的Windows都支持Win16 API(以確保和舊的應用程序兼容)和Win32 API(以運行新的應用程序)。非常有趣的是,Windows NT/2000/XP與Windows 9x的工作方式不同。在Windows NT/2000/XP中,Win16函數調用通過一個轉換層被轉化為Win32函數調用,然后被操作系統處理。在Windows 9x中,該操作正好相反:Win32函數調用通過轉換層轉換為Win16位函數調用,再由操作系統處理。
Windows運轉的核心是一個稱作“動態鏈接”的概念。Windows提供了應用程序可利用的豐富的函數調用,這些函數采用動態鏈接庫(即DLL)實現。在Windows 9x中,通常位於WINDOWSSYSTEM子目錄中。在Windows NT/2000/XP中,通常位於系統安裝目錄的SYSTEM和SYSTEM32子目錄中。
在早期,Windows的主要部分只需要在3個動態鏈接庫中實現,代表了Windows的3個主要子系統,分別叫作Kernel、User和GDI。
- Kernel(由16位的KRNL386.EXE和32位的KERNEL32.DLL實現):操作系統核心功能服務,包括進程與線程控制、內存管理、文件訪問等。
- User(由16位的USER.EXE和32位的USER32.DLL實現):負責處理用戶接口,包括鍵盤和鼠標輸入、窗口和菜單管理等。
- GDI(由16位的GDI.EXE和32位的GDI32.DLL實現):圖形設備接口,允許程序在屏幕和打印機上顯示文本和圖形。
- 除了上述模塊以外,Windows還提供了其他DLL以支持另外一些功能,包括++對象安全性、注冊表操作(ADVAPI32.DLL)、通用控件(COMCTL32.DLL)、公共對話框(COMDLG32.DLL)、用戶界面外殼(SHELL32.DLL)、圖形引擎(DIBENG.DLL)和網絡(NETAPI32.DLL)++。
雖然Win API是一個基於C語言的接口,但是Win API中的函數可以由用不同語言編寫的程序調用,只要在調用時遵循調用的規范即可。
Unicode影響着計算機工業的每個部分,對操作系統和編程語言的影響最大。NT系統是使用Unicode標准字符集重新開發的,其系統核心完全是用Unicode函數工作的。如果希望調用任何一個Windows函數並給它傳遞一個ANSI字符串,系統首先要將字符串轉換成Unicode,然后將Unicode傳遞給操作系統。相反,如果希望函數返回ANSI字符,系統就會首先將Unicode字符串轉換成ANSI字符串,然后將結果返回給應用程序。也就是說,在NT架構下,Win32 API能接受Unicode和ASCII兩種字符集,而其內核則只能使用Unicode。所有這些操作對用戶來說都是透明的,但這些字符串的轉換需要占用系統資源。
++在Win32 API函數字符集中,“A”表示ANSI,“W”表示Widechars(即Unicode)。前者就是通常使用的單字節方式,后者是寬字節方式,以方便處理雙字節字符。++用字符串作參數的每個Win32函數在操作系統中都有這兩種方式的版本。例如,編程時使用MessageBox函數,而在USER32.DLL中卻沒有32位MessageBox函數的入口點。實際上,有兩個入口點,一個名為“MessageBoxA”(ANSI版),另一個名為“MessageBoxW”(寬字符版)。幸運的是,程序員通常不必關心這個問題,代碼中只需要使用MessageBox,開發工具中的編譯模塊就會根據設置來決定是采用MessageBoxA還是MessageBoxW。
這個試驗結果表明,MessageBoxExA函數其實是一個替換翻譯層,用於分配內存,並將ANSI字符串轉換成Unicode字符串,系統最終調用Unicode版的MessageBoxExW函數執行。當MessageBoxExW返回時,它便釋放內存緩存。在這個過程中,系統必須執行這些額外的轉換操作,因此,ANSI版的應用程序需要更多的內存,占用更多的CPU資源。而Unicode版的程序在NT架構下的執行效率就高多了。
由於Win32程序大量調用系統提供的API函數,而Win32平台上的調試器(如OllyDbg等)恰好有針對API函數設置斷點的強大功能,因此掌握常用的API函數具體用法會給程序的跟蹤調試帶來極大的方便,詳細的Win32 API參考文檔可以從MSDN中獲得。建議讀者掌握一定的Win32編程知識(如閱讀《Windows程序設計》一書),這會對合理選擇API函數有很大的幫助。
3.2 WOW64
WOW64(Windows-on-Windows 64-bit)是64位Windows操作系統的子系統,可以使大多數32位應用程序在不作修改的情況下運行在64位版本上。
64位版本的Windows,除了帶有64位操作系統應有的系統文件,還帶有32位操作系統應有的系統文件。++Windows的64位系統文件都放在一個叫作“System32”的文件夾中,WindowsSystem32文件夾中包含原生的64位映像文件。為了兼容32位操作系統,還增加了WindowsSysWOW64文件夾,其中是32位的系統文件。++
64位應用程序會加載System32目錄下64位的kernel32.dll、user32.dll和ntdll.dll。32位應用程序加載時,WOW64建立32位ntdll.dll所要求的啟動環境,將CPU模式切換至32位,並開始執行32位加載器,就如同該進程運行在原生的32位系統之上。WOW64會對32位ntdll.dll的調用重定向ntdll.dll(64位),而不是發出原生的32位系統調用指令。WOW64轉換到原生的64位模式,並捕獲與系統調用有關的參數,發出對應的原生64位系統調用。當原生的系統調用返回時,WOW64將任何輸出參數在返回至32位模式之前從64位轉換成32位格式。
++WOW64不支持16位應用程序的執行(32位Windows支持16位應用程序的執行),也不支持加載32位內核模式的設備驅動程序。WOW64進程只能加載32位DLL,不能加載原生的64位DLL。類似的,原生的64位進程不能加載32位的DLL。++
3.3 WIndows消息機制
Windows是一個消息(Message)驅動式系統。Windows消息提供應用程序與應用程序之間、應用程序與Windows系統之間進行通信的手段。應用程序想要實現的功能由消息來觸發,並且靠對消息的響應和處理來完成。
Windows系統中有兩種消息隊列:
- 一種是系統消息隊列;
- 另一種是應用程序消息隊列。
計算機的所有輸入設備由Windows監控。當一個事件發生時,Windows先將輸入的消息放入系統消息隊列中,再將輸入的消息復制到相應的應用程序隊列中,應用程序中的消息循環從它的消息隊列中檢索每個消息並發送給相應的窗口函數。一個事件的發生,到達處理它的窗口函數必須經歷上述過程。值得注意的是消息的非搶先性,即不論事件的急與緩,總是按到達的先后排隊(一些系統消息除外),這就使一些外部實時事件可能得不到及時的處理。
由於Windows本身是由消息驅動的,所以調試程序時跟蹤一個消息會得到相當底層的答案。
常用的Windows消息函數:
(1)SendMessage函數
調用一個窗口的窗口函數,將一條消息發給那個窗口。除非消息處理完畢,否則該函數不會返回。
返回值:由具體的消息決定。如消息投遞成功,則返回“TRUE”(非零)。
LRESULT SendMessage(
HWND hWnd, // 目的窗口的句柄
UINT Msg, // 消息標識符
WPARAM wParam, // 消息的WPARAM域
LPARAM lParam // 消息的LPARAM域
);
(2)WM_COMMAND消息
當用戶從菜單或按鈕中選擇一條命令或者一個控件時發送給它的父窗口,或者當一個快捷鍵被釋放時發送。Visual C++的WINUSER.H文件里定義了WM_COMMAND消息對應的十六進制數是0111h。
返回值:如果應用程序處理這條消息,則返回值為零。
WM_COMMAND
wNotifyCode = HIWORD(wParam); // 通告代碼
wID = LOWORD(wParam); // 菜單條目、控件或快捷鍵的標識符
hwndCtl = (HWND) lParam; // 控件句柄
(3)WM_DESTROY消息
當一個窗口被銷毀時發送。WM_DESTROY消息的十六進制數是02h。
這條消息無參數。
返回值:如果應用程序處理這條消息,則返回值為零。
3.4 虛擬內存
默認情況下,32位Windows操作系統的地址空間在4GB以內。Win32的平坦內存模式使每個進程擁有自己的虛擬空間。對32位進程來說,這個地址空間是4GB,因為32位指針可以擁有00000000h~FFFFFFFFh之間的任何一個值。此時,程序的代碼和數據都放在同一地址空間中,即不必區分代碼段和數據段。
虛擬內存(Virtual Memory)不是真正的內存,它通過映射(Map)的方法使可用的虛擬地址(Virtual Address)達到4GB,每個應用程序可以被分配2GB的虛擬地址,剩下的2GB留給操作系統自用。在Windows NT中,應用程序甚至可有3GB的虛擬地址。Windows是一個分時的多任務操作系統,CPU時間被分成一個個的時間片后分配給不同的程序。在一個時間片里,與這個程序執行無關的內容不會映射到線性地址中。因此,每個程序都有自己的4GB尋址空間,互不干擾。在物理內存中,操作系統和系統DLL代碼需要供每個應用程序調用,所以在所有的時間必須映射。用戶的EXE程序只在自己所屬的時間片內被映射,而用戶DLL則有選擇地被映射。
簡單地說,虛擬內存的實現方法和過程如下。
① 當一個應用程序被啟動時,操作系統就創建一個新進程,並給每個進程分配2GB的虛擬地址(不是內存,只是地址)。
② 虛擬內存管理器將應用程序的代碼映射到那個應用程序的虛擬地址中的某個位置,並把當前所需要的代碼讀取到物理地址中(注意:虛擬地址與應用程序代碼在物理內存中的位置是沒有關系的)。
③ 如果使用動態鏈接庫DLL,DLL也會被映射到進程的虛擬地址空間中,在需要的時候才被讀入物理內存中。
④ 其他項目(例如數據、堆棧等)的空間是從物理內存中分配的,並被映射到虛擬地址空間中。
⑤ 應用程序通過使用它的虛擬地址空間中的地址開始執行,然后虛擬內存管理器把每次的內存訪問映射到物理位置。
看不明白上面的步驟也不要緊,但要明白以下幾點。
- 應用程序是不會直接訪問物理地址的。
- 虛擬內存管理器通過虛擬地址的訪問請求來控制所有的物理地址訪問。
- 每個應用程序都有相互獨立的4GB尋址空間,不同應用程序的地址空間是隔離的。
- DLL程序沒有自己的“私有”空間,它們總是被映射到其他應用程序的地址空間中,作為其他應用程序的一部分運行。因為如果它不和其他程序處於同一個地址空間,應用程序就無法調用它。
使用虛擬內存的好處是:簡化了內存的管理,並可彌補物理內存的不足;可以防止多任務環境下各個應用程序之間的沖突。
++64位Windows操作系統提供16TB的有效尋址空間,其中有一半可用於用戶模式的應用程序。++