虛擬機器檢測技術攻防
前言
在當今資訊保安領域,特別是惡意軟體分析中,經常需要利用到虛擬機技術,以提高病毒分析過程的安全性以及硬體資源的節約性,因此它在惡意軟體領域中是應用越來越來廣泛。這裡我們所謂的虛擬機(Virtual Machine)是指通過軟體模擬的具有完整硬體系統功能的、執行在一個完全隔離環境中的完整計算機系統。通過虛擬機軟體(比如VMware,Virtual PC ,VirtualBox),你可以在一臺物理計算機上模擬出一臺或多臺虛擬的計算機,這些虛擬機完全就像真正的計算機那樣進行工作,例如你可以安裝作業系統、安裝應用程式、訪問網路資源等等。攻擊者為了提高惡意程式的隱蔽性以及破壞真實主機的成功率,他們都在惡意程式中加入檢測虛擬方法一:通過執行特權指令來檢測虛擬機器
程式碼:
bool IsInsideVMWare() { bool rc = true; __try { __asm { push edx push ecx push ebx mov eax, 'VMXh' mov ebx, 0 // 將ebx設定為非幻數’VMXH’的其它值 mov ecx, 10 // 指定功能號,用於獲取VMWare版本,當它為0x14時用於獲取VMware記憶體大小 mov edx, 'VX' // 埠號 in eax, dx // 從埠dx讀取VMware版本到eax //若上面指定功能號為0x14時,可通過判斷eax中的值是否大於0,若是則說明處於虛擬測試結果:機中 cmp ebx, 'VMXh' // 判斷ebx中是否包含VMware版本’VMXh’,若是則在虛擬機中 setz [rc] // 設定返回值 pop ebx pop ecx pop edx } } __except(EXCEPTION_EXECUTE_HANDLER) //如果未處於VMware中,則觸發此異常 { rc = false; } return rc; }
圖1
如圖1所示,VMDetect成功檢測出VMWare的存在。
方法二:利用IDT基址檢測虛擬機
利用IDT基址檢測虛擬機的方法是一種通用方式,對VMware和Virtual PC均適用。中斷描述符表IDT(Interrupt Descriptor Table)用於查詢處理中斷時所用的軟體函式,它是一個由256項組成的資料,其中每一中斷對應一項函式。為了讀取IDT基址,我們需要通過SIDT指令來讀取IDTR(中斷描述符表暫存器,用於IDT在記憶體中的基址),SIDT指令是以如下格式來儲存IDTR的內容:程式碼:
typedef struct { WORD IDTLimit; // IDT的大小 WORD LowIDTbase; // IDT的低位地址 WORD HiIDTbase; // IDT的高位地址 } IDTINFO;由於只存在一個IDTR,但又存在兩個作業系統,即虛擬機系統和真主機系統。為了防止發生衝突,VMM(虛擬機監控器)必須更改虛擬機中的IDT地址,利用真主機與虛擬機環境中執行sidt指令的差異即可用於檢測虛擬機是否存在。著名的“紅丸”(redpill)正是利用此原理來檢測VMware的。Redpill作者在VMware上發現虛擬機系統上的IDT地址通常位於0xFFXXXXXX,而Virtual PC通常位於0xE8XXXXXX,而在真實主機上正如圖2所示都位於0x80xxxxxx。Redpill僅僅是通過判斷執行SIDT指令後返回的第一位元組是否大於0xD0,若是則說明它處於虛擬機,否則處於真實主機中。Redpill的原始碼甚是精簡,原始碼分析如下:
程式碼:
#include <stdio.h> int main () { unsigned char m[2+4], rpill[] = "\x0f\x01\x0d\x00\x00\x00\x00\xc3"; //相當於SIDT[adrr],其中addr用於儲存IDT地址 *((unsigned*)&rpill[3]) = (unsigned)m; //將sidt[addr]中的addr設為m的地址 ((void(*)())&rpill)(); //執行SIDT指令,並將讀取後IDT地址儲存在陣列m中 printf ("idt base: %#x\n", *((unsigned*)&m[2])); //由於前2位元組為IDT大小,因此從m[2]開始即為IDT地址 if (m[5]>0xd0) printf ("Inside Matrix!\n", m[5]); //當IDT基址大於0xd0xxxxxx時則說明程式處於VMware中 else printf ("Not in Matrix.\n"); return 0; }測試結果如圖2所示:
圖2
利用此IDT檢測的方法存在一個缺陷,由於IDT的值只針對處於正在執行的處理器而言,在單CPU中它是個常量,但當它處於多CPU時就可能會受到影響了,因為每個CPU都有其自己的IDT,這樣問題就自然而然的產生了。針對此問題,Offensive Computing組織成員提出了兩種應對方法,其中一種方法就是利用Redpill反覆地在系統上迴圈執行任務,以此構造出一張當前系統的IDT值變化統計圖,但這會增加CPU負擔;另一種方法就是windows API函式SetThreadAffinityMask()將執行緒限制在單處理器上執行,當執行此測試時只能準確地將執行緒執行環境限制在本地處理器,而對於將執行緒限制在VM處理器上就可能行不通了,因為VM是計劃在各處理器上執行的,VM執行緒在不同的處理器上執行時,IDT值將會發生變化,因此此方法也是很少被使用的。為此,有人提出了使用LDT的檢測方法,它在具有多個CPU的環境下檢測虛擬機明顯優於IDT檢測方法,該方法具體內容參見下節內容。
方法三:利用LDT和GDT的檢測方法
在 《Intel® 64 and IA-32 Architecture Software Developer’s Manual Volume 3A: System Programming Guide》第二章的Vol.3 2-5 一頁(我的Intel開發手冊是2008版的)中對於LDT和GDT的描述如下(以下內容為個人翻譯):在保護模式下,所有的記憶體訪問都要通過全域性描述符表(GDT)或者本地描述符表(LDT)才能進行。這些表包含有段描述符的呼叫入口。各個段描述符都包含有各段的基址,訪問許可權,型別和使用資訊,而且每個段描述符都擁有一個與之相匹配的段選擇子,各個段選擇子都為軟體程式提供一個GDT或LDT索引(與之相關聯的段描述符偏移量),一個全域性/本地標誌(決定段選擇子是指向GDT還是LDT),以及訪問許可權資訊。
若想訪問段中的某一位元組,必須同時提供一個段選擇子和一個偏移量。段選擇子為段提供可訪問的段描述符地址(在GDT 或者LDT 中)。通過段描述符,處理器從中獲取段線上性地址空間裡的基址,而偏移量用於確定位元組地址相對基址的位置。假定處理器在當前許可權級別(CPL)可訪問這個段,那麼通過這種機制就可以訪問在GDT 或LDT 中的各種有效程式碼、資料或者堆疊段,這裡的CPL是指當前可執行程式碼段的保護級別。
……
GDT的線性基址被儲存在GDT暫存器(GDTR)中,而LDT的線性基址被儲存在LDT暫存器(LDTR)中。
由於虛擬機與真實主機中的GDT和LDT並不能相同,這與使用IDT的檢測方法一樣,因此虛擬機必須為它們提供一個“複製體”。關於GDT和LDT的基址可通過SGDT和SLDT指令獲取。虛擬機檢測工具Scoopy suite的作者Tobias Klein經測試發現,當LDT基址位於0x0000(只有兩位元組)時為真實主機,否則為虛擬機,而當GDT基址位於0xFFXXXXXX時說明處於虛擬機中,否則為真實主機。具體實現程式碼如下:
程式碼:
#include <stdio.h> void LDTDetect(void) { unsigned short ldt_addr = 0; unsigned char ldtr[2]; _asm sldt ldtr ldt_addr = *((unsigned short *)&ldtr); printf("LDT BaseAddr: 0x%x\n", ldt_addr); if(ldt_addr == 0x0000) { printf("Native OS\n"); } else printf("Inside VMware\n"); } void GDTDetect(void) { unsigned int gdt_addr = 0; unsigned char gdtr[4]; _asm sgdt gdtr gdt_addr = *((unsigned int *)&gdtr[2]); printf("GDT BaseAddr:0x%x\n", gdt_addr); if((gdt_addr >> 24) == 0xff) { printf("Inside VMware\n"); } else printf("Native OS\n"); } int main(void) { LDTDetect(); GDTDetect(); return 0; }測試結果如圖3所示:
圖3
方法四:基於STR的檢測方法
在保護模式下執行的所有程式在切換任務時,對於當前任務中指向TSS的段選擇器將會被儲存在任務暫存器中,TSS中包含有當前任務的可執行環境狀態,包括通用暫存器狀態,段暫存器狀態,標誌暫存器狀態,EIP暫存器狀態等等,當此項任務再次被執行時,處理器就會其原先儲存的任務狀態。每項任務均有其自己的TSS,而我們可以通過STR指令來獲取指向當前任務中TSS的段選擇器。這裡STR(Store task register)指令是用於將任務暫存器 (TR) 中的段選擇器儲存到目標運算元,目標運算元可以是通用暫存器或記憶體位置,使用此指令儲存的段選擇器指向當前正在執行的任務的任務狀態段 (TSS)。在虛擬機和真實主機之中,通過STR讀取的地址是不同的,當地址等於0x0040xxxx時,說明處於虛擬機中,否則為真實主機。實現程式碼如下:程式碼:
#include <stdio.h> int main(void) { unsigned char mem[4] = {0}; int i; __asm str mem; printf (" STR base: 0x"); for (i=0; i<4; i++) { printf("%02x",mem[i]); } if ( (mem[0]==0x00) && (mem[1]==0x40)) printf("\n INSIDE MATRIX!!\n"); else printf("\n Native OS!!\n"); return 0; }測試結果如圖4所示:
圖4
方法五:基於登錄檔檢測虛擬機
在windows虛擬機中常常安裝有VMware Tools以及其它的虛擬硬體(如網路介面卡、虛擬印表機,USB集線器……),它們都會建立任何程式都可以讀取的windows登錄檔項,因此我們可以通過檢測登錄檔中的一些關鍵字元來判斷程式是否處於虛擬機之中。關於這些登錄檔的位置我們可以通過在登錄檔中搜索關鍵詞“vmware”來獲取,下面是我在VMware下的WinXP中找到的一些登錄檔項:項名:HKEY_CLASSES_ROOT\Applications\VMwareHostOpen.exe
項名:HKEY_CLASSES_ROOT\Installer\Products\C2A6F2EFE6910124C940B2B12CF170FE\ProductName
鍵值“VMware Tools”
項名:HKEY_CLASSES_ROOT\Installer\Products\C2A6F2EFE6910124C940B2B12CF170FE\SourceList\PackageName
鍵值:VMware Tools.msi
項名:HKEY_CURRENT_USER\Printers\DeviceOld
鍵值:_#VMwareVirtualPrinter,winspool,TPVM:
項名:HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\Scsi\Scsi Port 0\Scsi Bus 0\Target Id 0\Logical Unit Id 0\Identifier
鍵值:VMware Virtual IDE Hard Drive
項名:HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\Scsi\Scsi Port 1\Scsi Bus 0\Target Id 0\Logical Unit Id 0\Identifier
鍵值:NECVMWar VMware IDE CDR10
項名:HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Installer\Products\C2A6F2EFE6910124C940B2B12CF170FE\ProductName
鍵值:VMware Tools
項名:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\C2A6F2EFE6910124C940B2B12CF170FE\InstallProperties\DisplayName
鍵值:VMware Tools
項名:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Reinstall\0002\DeviceDesc
鍵值:VMware SVGA II
項名:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards\2\Description
鍵值:VMware Accelerated AMD PCNet Adapter
項名:HKEY_LOCAL_MACHINE\SOFTWARE\VMware, Inc.\VMware Tools
項名:HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class\{4D36E968-E325-11CE-BFC1-08002BE10318}\0000\DriverDesc
鍵值:VMware SVGA II
項名:HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class\{4D36E968-E325-11CE-BFC1-
08002BE10318}\0000\ProviderName
鍵值:VMware, Inc.
項名:HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}\0001\DriverDesc
鍵值:VMware Accelerated AMD PCNet Adapter
項名:HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class\{4D36E97B-E325-11CE-BFC1-08002BE10318}\0000\DriverDesc
鍵值:VMware SCSI Controller
項名:HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Print\Monitors\ThinPrint Print Port Monitor for VMWare
補充另外一處 具體程式碼如下:
- BOOL DetectVM() {
- HKEY hKey;
- char szBuffer[64];
- unsigned long hSize= sizeof(szBuffer) - 1;
- if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\BIOS\\", 0, KEY_READ, &hKey )==ERROR_SUCCESS ) {
- RegQueryValueEx( hKey, "SystemManufacturer", NULL, NULL, (unsigned char *)szBuffer, &hSize );
- if( strstr( szBuffer, "VMWARE" )) {
- RegCloseKey( hKey );
- return TRUE;
- }
- RegCloseKey( hKey );
- }
- return FALSE;
- }
程式碼:
.386 .model flat, stdcall option casemap:none include windows.inc include user32.inc include kernel32.inc include advapi32.inc includelib user32.lib includelib kernel32.lib includelib advapi32.lib .data szCaption db "VMware Detector ",0 szInside db "Inside VMware!",0 szOutside db "Native OS!",0 szSubKey db "software\VMWare, Inc.\VMware tools",0 hKey dd ? .code start: invoke RegOpenKeyEx, HKEY_LOCAL_MACHINE, addr szSubKey, 0,\ KEY_WRITE or KEY_READ, addr hKey .if eax == ERROR_SUCCESS invoke MessageBox, NULL,addr szInside, addr szCaption, MB_OK .else invoke MessageBox, NULL,addr szOutside, addr szCaption, MB_OK .endif invoke RegCloseKey,hKey invoke ExitProcess,NULL end start測試結果如圖5所示:
圖5
方法六:基於時間差的檢測方式
本方法通過執行一段特定程式碼,然後比較這段程式碼在虛擬機和真實主機之中的相對執行時間,以此來判斷是否處於虛擬機之中。這段程式碼我們可以通過RDTSC指令來實現,RDTSC指令是用於將計算機啟動以來的CPU執行週期數存放到EDX:EAX裡面,其中EDX是高位,而EAX是低位。下面我們以xchg ecx, eax 一句指令的執行時間為例,這段指令在我的真實主機windows 7系統上的執行時間為0000001E,如圖6所示:圖6
而該指令在虛擬機WinXP下的執行時間為00000442,如圖7所示:
圖7
兩者之間的執行時間明顯差別很多,在虛擬機中的執行速度遠不如真實主機的,一般情況下,當它的執行時間大於0xFF時,就可以確定它處於虛擬機之中了,因此不難寫出檢測程式,具體實現程式碼如下:
程式碼:
.586p .model flat, stdcall option casemap:none include windows.inc include kernel32.inc include user32.inc includelib kernel32.lib includelib user32.lib .data szTitle db "VMDetect With RDTSC", 0h szInsideVM db "Inside VMware!", 0h szOutsideVM db "Native OS!", 0h .code start: RDTSC xchg ecx, eax RDTSC sub eax, ecx cmp eax, 0FFh jg Detected invoke MessageBox, 0, offset szOutsideVM, offset szTitle, 0 ret Detected: invoke MessageBox, 0, offset szInsideVM, offset szTitle, 0 ret end start測試結果如圖8所示:
圖8
方法七:利用虛擬硬體指紋檢測虛擬機
利用虛擬硬體指紋也可用於檢測虛擬機的存在,比如VMware預設的網絡卡MAC地址字首為“00-05-69,00-0C-29或者00-50-56”,這前3節是由VMware分配的唯一識別符號OUI,以供它的虛擬化介面卡使用。在我的VMWare WinXP下的MAC地址為00-0C-29-5B-D7-67,如圖9所示:圖9
但由於這些可經過修改配置檔案來繞過檢測。另外,還可通過檢測特定的硬體控制器,BIOS,USB控制器,顯示卡,網絡卡等特徵字串進行檢測,這些在前面使用登錄檔檢測方法中已有所涉及。
另外之前在看雪論壇上也有朋友提到通過檢測硬碟Model Number是否含有“vmware”或“virtual”等字樣來實現檢測虛擬機的功能,具體轉載如下:
- 小試 anti vmware
- 今天偶然看到一款綠色版的硬碟專業工具,突然發現可以利用其中的一項功能來實現anti vmware。
- 今日事今日畢,那就在今晚12:00之前把這個想法實現吧,let's go!
- 我的想法就是檢測硬碟的modelnumber,具體什麼是modelnumber自己網上搜吧,反正不是硬碟序列號。難點就是在多種作業系統下都要能起到anti vmware的效果。程式在xp、2k、2003下都可以檢測到vmware的執行。
- 直接貼程式碼了,如果看不懂也沒關係,我也是逆了人家的程式碼寫出來的。Delphi也可以當組合語言開發工具用,難道不是嗎?
- unit Unit1;
- interface
- uses
- Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
- Dialogs, StdCtrls, Buttons;
- type
- TForm1 = class(TForm)
- BitBtn1: TBitBtn;
- procedure BitBtn1Click(Sender: TObject);
- procedure FormClose(Sender: TObject; var Action: TCloseAction);
- private
- { Private declarations }
- public
- { Public declarations }
- end;
- var
- Form1: TForm1;
- hDeviceHandle:Thandle;
- implementation
- {$R *.dfm}
- procedure TForm1.BitBtn1Click(Sender: TObject);
- var
- InBuffer: array[0..$8f] of byte;
- cb:Cardinal;
- tmp:Pchar;
- begin
- hDeviceHandle:=CreateFile('\\.\PHYSICALDRIVE0',$C0000000,$3,nil,OPEN_EXISTING,$8000000,0);
- ZeroMemory(@InBuffer,sizeof(InBuffer));
- asm
- pushad
- lea ebx,InBuffer
- xor ecx,ecx
- mov al,$2c
- MOV [ebx],al
- MOV EAX,$200c0000
- MOV [ebx+4], eax
- mov al,$01
- MOV [ebx+8],al
- mov al,$40
- MOV [ebx+$c],al
- MOV EAX,$0001a5E0
- MOV [ebx+$10], eax
- mov al,$30
- MOV [ebx+$18],al
- mov al,$12
- MOV [ebx+$1c],al
- mov al,$40
- MOV [ebx+$20],al
- add ecx,ebx
- add ecx,$50
- MOV [ebx+$14], ecx
- popad
- end;
- if DeviceIoControl(hDeviceHandle,$4D014,@InBuffer,$50,@InBuffer,$50,cb,nil) then
- begin
- asm
- pushad
- lea ebx,InBuffer
- add ebx,$58
- mov tmp,ebx
- popad
- end; //asm
- if ((pos('vmware',LowerCase(tmp))>0) or (pos('virtual',LowerCase(tmp))>0)) then
-
相關推薦
虛擬機器檢測技術攻防
前言 在當今資訊保安領域,特別是惡意軟體分析中,經常需要利用到虛擬機技術,以提高病毒分析過程的安全性以及硬體資源的節約性,因此它在惡意軟體領域中是應用越來越來廣泛。這裡我們所謂的虛擬機(Virtual Machine)是指通過軟體模擬的具有完整硬體系統功能的、執行在一個完全隔離環境中的完整計算機系統。通
虛擬機檢測技術剖析
net 更多 共享 修改配置文件 cal 端口 目標 cmp bfc 作者:riusksk (泉哥)主頁:http://riusksk.blogbus.com 前言在當今信息安全領域,特別是惡意軟件分析中,經常需要利用到虛擬機技術,以提高病毒分析過程的安全性以及硬件資源的
《深入理解JVM虛擬機器》pdf版電子書+30個總結JVM虛擬機器的技術文排版好(收藏版)
技術書閱讀方法論 一.速讀一遍(最好在1~2天內完成) 人的大腦記憶力有限,在一天內快速看完一本書會在大腦裡留下深刻印象,對於之後複習以及總結都會有特別好的作用。 對於每一章的知識,先閱讀標題,弄懂大概講的是什麼主題,再去快速看一遍,不懂也沒有關係,但是一定要在不懂的
《HTML&CSS設計與構建網站中文版》電子書附下載連結+30個總結JVM虛擬機器的技術文排版好(收藏版)
技術書閱讀方法論 一.速讀一遍(最好在1~2天內完成) 人的大腦記憶力有限,在一天內快速看完一本書會在大腦裡留下深刻印象,對於之後複習以及總結都會有特別好的作用。 對於每一章的知識,先閱讀標題,弄懂大概講的是什麼主題,再去快速看一遍,不懂也沒有關係,但是一定要在不懂的
《HADOOP實戰(第二版中文》電子書附下載連結+30個總結JVM虛擬機器的技術文排版好(收藏版)
技術書閱讀方法論 一.速讀一遍(最好在1~2天內完成) 人的大腦記憶力有限,在一天內快速看完一本書會在大腦裡留下深刻印象,對於之後複習以及總結都會有特別好的作用。 對於每一章的知識,先閱讀標題,弄懂大概講的是什麼主題,再去快速看一遍,不懂也沒有關係,但是一定要在不懂的
《現代作業系統(第三版)中文版》電子書附下載連結+30個總結JVM虛擬機器的技術文排版好(收藏版)
技術書閱讀方法論 一.速讀一遍(最好在1~2天內完成) 人的大腦記憶力有限,在一天內快速看完一本書會在大腦裡留下深刻印象,對於之後複習以及總結都會有特別好的作用。 對於每一章的知識,先閱讀標題,弄懂大概講的是什麼主題,再去快速看一遍,不懂也沒有關係,但是一定要在不懂的
《演算法導論英文版第三版》電子書附下載連結+30個總結JVM虛擬機器的技術文排版好(收藏版)
技術書閱讀方法論 一.速讀一遍(最好在1~2天內完成) 人的大腦記憶力有限,在一天內快速看完一本書會在大腦裡留下深刻印象,對於之後複習以及總結都會有特別好的作用。 對於每一章的知識,先閱讀標題,弄懂大概講的是什麼主題,再去快速看一遍,不懂也沒有關係,但是一定要在不懂的
《演算法圖解》電子書附下載連結+30個總結JVM虛擬機器的技術文排版好(收藏版)
技術書閱讀方法論 一.速讀一遍(最好在1~2天內完成) 人的大腦記憶力有限,在一天內快速看完一本書會在大腦裡留下深刻印象,對於之後複習以及總結都會有特別好的作用。 對於每一章的知識,先閱讀標題,弄懂大概講的是什麼主題,再去快速看一遍,不懂也沒有關係,但是一定要在不懂的
《Java程式設計思想(第4版)》電子書附下載連結+30個總結JVM虛擬機器的技術文排版好(收藏版)
技術書閱讀方法論 一.速讀一遍(最好在1~2天內完成) 人的大腦記憶力有限,在一天內快速看完一本書會在大腦裡留下深刻印象,對於之後複習以及總結都會有特別好的作用。 對於每一章的知識,先閱讀標題,弄懂大概講的是什麼主題,再去快速看一遍,不懂也沒有關係,但是一定要在不懂的
《Java核心技術 卷II 高階特性 第9版(中文)》電子書附下載連結+30個總結JVM虛擬機器的技術文排版好(收藏版)
技術書閱讀方法論 一.速讀一遍(最好在1~2天內完成) 人的大腦記憶力有限,在一天內快速看完一本書會在大腦裡留下深刻印象,對於之後複習以及總結都會有特別好的作用。 對於每一章的知識,先閱讀標題,弄懂大概講的是什麼主題,再去快速看一遍,不懂也沒有關係,但是一定要在不懂的
《Java核心技術 卷 基礎知識 原書第9版》電子書附下載連結+30個總結JVM虛擬機器的技術文排版好(收藏版)
技術書閱讀方法論 一.速讀一遍(最好在1~2天內完成) 人的大腦記憶力有限,在一天內快速看完一本書會在大腦裡留下深刻印象,對於之後複習以及總結都會有特別好的作用。 對於每一章的知識,先閱讀標題,弄懂大概講的是什麼主題,再去快速看一遍,不懂也沒有關係,但是一定要在不懂的
《JAVA併發程式設計實踐中文完整版》電子書附下載連結+30個總結JVM虛擬機器的技術文排版好(收藏版)
技術書閱讀方法論 一.速讀一遍(最好在1~2天內完成) 人的大腦記憶力有限,在一天內快速看完一本書會在大腦裡留下深刻印象,對於之後複習以及總結都會有特別好的作用。 對於每一章的知識,先閱讀標題,弄懂大概講的是什麼主題,再去快速看一遍,不懂也沒有關係,但是一定要在不懂的
《Java併發程式設計的藝術》電子書附下載連結+30個總結JVM虛擬機器的技術文排版好(收藏版)
技術書閱讀方法論 一.速讀一遍(最好在1~2天內完成) 人的大腦記憶力有限,在一天內快速看完一本書會在大腦裡留下深刻印象,對於之後複習以及總結都會有特別好的作用。 對於每一章的知識,先閱讀標題,弄懂大概講的是什麼主題,再去快速看一遍,不懂也沒有關係,但是一定要在不懂的
《Java效能調優指南》電子書附下載連結+30個總結JVM虛擬機器的技術文排版好(收藏版)
技術書閱讀方法論 一.速讀一遍(最好在1~2天內完成) 人的大腦記憶力有限,在一天內快速看完一本書會在大腦裡留下深刻印象,對於之後複習以及總結都會有特別好的作用。 對於每一章的知識,先閱讀標題,弄懂大概講的是什麼主題,再去快速看一遍,不懂也沒有關係,但是一定要在不懂的
《Eective Java 第二版 中文版》電子書附下載連結+30個總結JVM虛擬機器的技術文排版好(收藏版)
技術書閱讀方法論 一.速讀一遍(最好在1~2天內完成) 人的大腦記憶力有限,在一天內快速看完一本書會在大腦裡留下深刻印象,對於之後複習以及總結都會有特別好的作用。 對於每一章的知識,先閱讀標題,弄懂大概講的是什麼主題,再去快速看一遍,不懂也沒有關係,但是一定要在不懂的
《Netty權威指南(第2版)》電子書附下載連結+30個總結JVM虛擬機器的技術文排版好(收藏版)
技術書閱讀方法論 一.速讀一遍(最好在1~2天內完成) 人的大腦記憶力有限,在一天內快速看完一本書會在大腦裡留下深刻印象,對於之後複習以及總結都會有特別好的作用。 對於每一章的知識,先閱讀標題,弄懂大概講的是什麼主題,再去快速看一遍,不懂也沒有關係,但是一定要在不懂的
《HTML&CSS設計與構建網站中文版》電子書附下載連結和30個總結JVM虛擬機器的技術文排版好(收藏版)
技術書閱讀方法論 一.速讀一遍(最好在1~2天內完成) 人的大腦記憶力有限,在一天內快速看完一本書會在大腦裡留下深刻印象,對於之後複習以及總結都會有特別好的作用。 對於每一章的知識,先閱讀標題,弄懂大概講的是什麼主題,再去快速看一遍,不懂也沒有關係,但是一定要在不懂的
《深入理解JVM虛擬機器》pdf版電子書附下載連結+30個總結JVM虛擬機器的技術文排版好(收藏版)
技術書閱讀方法論 一.速讀一遍(最好在1~2天內完成) 人的大腦記憶力有限,在一天內快速看完一本書會在大腦裡留下深刻印象,對於之後複習以及總結都會有特別好的作用。 對於每一章的知識,先閱讀標題,弄懂大概講的是什麼主題,再去快速看一遍,不懂也沒有關係,但是一定要在不懂的
《計算機網路(第7版)謝希仁》電子書附下載連結+30個總結JVM虛擬機器的技術文排版好(收藏版)
技術書閱讀方法論 一.速讀一遍(最好在1~2天內完成) 人的大腦記憶力有限,在一天內快速看完一本書會在大腦裡留下深刻印象,對於之後複習以及總結都會有特別好的作用。 對於每一章的知識,先閱讀標題,弄懂大概講的是什麼主題,再去快速看一遍,不懂也沒有關係,但是一定要在不懂的
《Spring MVC學習指南(第2版)》電子書附下載連結和30個總結JVM虛擬機器的技術文排版好(收藏版)
技術書閱讀方法論 一.速讀一遍(最好在1~2天內完成) 人的大腦記憶力有限,在一天內快速看完一本書會在大腦裡留下深刻印象,對於之後複習以及總結都會有特別好的作用。 對於每一章的知識,先閱讀標題,弄懂大概講的是什麼主題,再去快速看一遍,不懂也沒有關係,但是一定要在不懂的