PE學習筆記(一)

來源:互聯網
上載者:User

PE學習筆記

 PE 的意思就是 Portable Executable(可移植的執行體)。PE檔案結構的總體層次分布圖:
 
 --------------
|DOS MZ Header |
|--------------|
|DOS Stub      |
|--------------|
|PE Header     |
|--------------|
|Section Table |
|--------------|
|Section 1     |
|--------------|
|Section 2     |
|--------------|
|Section ...   |
|--------------|
|Section n     |
 --------------
 
一、PE檔案格式的概要

1.1、DOS MZ Header:
 所有 PE檔案(甚至32位的 DLLs)必須以一個簡單的 DOS MZ Header 開始。有了它,一旦程式在DOS下執行,DOS就能識別出這是有效執行體,然後運行緊隨 MZ Header 之後的 DOS Stub。

1.2、DOS Stub:
 DOS Stub(存根)實際上是個有效 MS-DOS .EXE 或者.COM 程式(如果檔案格式不對會報錯),在不支援 PE檔案格式的作業系統中,它將通過簡單調用中斷21h服務9來顯示字串"This program cannot run in DOS mode"或者根據程式員自己的意圖實現完整的 DOS 代碼。它的大小一般不能確定。利用連結器(linker)的 /STUB:filename 選項可以替換這個程式。

1.3、PE Header:
 緊接著 DOS Stub 的是 PE Header。PE Header 是PE相關結構 IMAGE_NT_HEADERS 的簡稱,其中包含了許多PE裝載器用到的重要域。執行體在支援PE檔案結構的作業系統中執行時,PE裝載器將從 DOS MZ Header (IMAGE_DOS_HEADER)中找到 PE Header 的起始位移量。因而跳過了DOS Stub 直接定位到真正的檔案頭PE Header。

1.4、Section Table:
 PE Header 接下來的數組結構 Section Table (節表)。如果PE檔案裡有5個節,那麼此 Section Table 結構數組內就有5個成員,每個成員包含對應節的屬性、檔案位移量、虛擬位移量等。

1.5、Sections:
 PE檔案的真正內容被劃分成塊,稱之為Section(節)。每個標準節的名字均以圓點開頭。Sections 是以其起始位址來排列,而不是以其字母次序來排列。下面是常見的節名及作用:
 
節名   作用
.arch  最初的構建資訊(Alpha Architecture Information)
.bss   未經初始化的資料
.CRT   C運行期唯讀資料
.data   已經初始化的資料
.debug   調試資訊
.didata  延遲輸入檔案名稱表
.edata  匯出檔案名稱表
.idata  匯入檔案名稱表
.pdata      異常資訊(Exception Information)
.rdata  唯讀初始化資料
.reloc  重定位表資訊
.rsrc  資源
.text   .exe或.dll檔案的可執行代碼
.tls  線程的本機存放區器
.xdata  異常處理表
 
 節的劃分是基於各組資料的共同屬性,而不是邏輯概念。每節是一塊擁有共同屬性的資料,比如代碼/資料、讀/寫等。如果PE檔案中的資料/代碼擁有相同屬性,它們就能被歸入同一節中。節名稱僅僅是個區別不同節的符號而已,類似"data", "code"的命名只為了便於識別,惟有節的屬性設定決定了節的特性和功能。

1.6、裝載一PE檔案的主要步驟:

1.當PE檔案被執行,PE裝載器檢查 DOS MZ Header 裡的 PE Header 位移量。如果找到,則跳轉到 PE Header。
2.PE裝載器檢查 PE Header 的有效性。如果有效,就跳轉到PE Header的尾部。
3.緊跟 PE Header 的是節表。PE裝載器讀取其中的節資訊,並採用檔案對應方法將這些節映射到記憶體,同時付上節表裡指定的節屬性。
4.PE檔案對應入記憶體後,PE裝載器將處理PE檔案中類似 Import Table(匯入表)邏輯部分。

二、DOS MZ Header 和 PE Header

2.1、DOS MZ Header 定義成結構 IMAGE_DOS_HEADER(64位元組) 。結構定義如下:

typedef struct _IMAGE_DOS_HEADER {      // DOS .EXE Header
    WORD   e_magic;                     // Magic number
    WORD   e_cblp;                      // Bytes on last page of file
    WORD   e_cp;                        // Pages in file
    WORD   e_crlc;                      // Relocations
    WORD   e_cparhdr;                   // Size of Header in paragraphs
    WORD   e_minalloc;                  // Minimum extra paragraphs needed
    WORD   e_maxalloc;                  // Maximum extra paragraphs needed
    WORD   e_ss;                        // Initial (relative) SS value
    WORD   e_sp;                        // Initial SP value
    WORD   e_csum;                      // Checksum
    WORD   e_ip;                        // Initial IP value
    WORD   e_cs;                        // Initial (relative) CS value
    WORD   e_lfarlc;                    // File address of relocation table
    WORD   e_ovno;                      // Overlay number
    WORD   e_res[4];                    // Reserved words
    WORD   e_oemid;                     // OEM identifier (for e_oeminfo)
    WORD   e_oeminfo;                   // OEM information; e_oemid specific
    WORD   e_res2[10];                  // Reserved words
    LONG   e_lfanew;                    // File address of new exe Header
  } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
 
IMAGE_DOS_HEADER 結構的e_lfanew成員就是指向 PE Header 的 RVA。e_magic 包含字串"MZ"。

2.2、PE Header 實際就是一個 IMAGE_NT_HEADERS 結構。定義如下:

typedef struct _IMAGE_NT_HEADERS {
    DWORD Signature;
    IMAGE_FILE_HEADER FileHeader;
    IMAGE_OPTIONAL_HEADER OptionalHeader;
} IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS;

 IMAGE_NT_HEADERS 結構成員含義:

1.Signature:一DWORD 類型,值為50h, 45h, 00h, 00h(PE/0/0)。如果IMAGE_NT_HEADERS的Signature域值等於"PE/0/0",那麼就是有效PE檔案。Microsoft定義了常量IMAGE_NT_SIGNATURE供我們使用,定義如下:

#define IMAGE_DOS_SIGNATURE                 0x5A4D      // MZ
#define IMAGE_OS2_SIGNATURE                 0x454E      // NE
#define IMAGE_OS2_SIGNATURE_LE              0x454C      // LE
#define IMAGE_VXD_SIGNATURE                 0x454C      // LE
#define IMAGE_NT_SIGNATURE                  0x00004550  // PE00

2.FileHeader:該結構域包含了關於PE檔案物理分布的資訊,比如節數目、檔案執行機器等。

3.OptionalHeader:該結構域包含了關於PE檔案邏輯分布的資訊,雖然網域名稱有"可選"字樣,但實際上本結構總是存在的。

2.3、檢驗PE檔案的有效性步驟總結如下:

1.首先檢驗檔案頭部第一個字的值是否等於 IMAGE_DOS_SIGNATURE,是則 DOS MZ Header 有效。
2.一旦證明檔案的 DOS Header 有效後,就可用e_lfanew來定位 PE Header 了。
3.比較 PE Header 的第一個字的值是否等於 IMAGE_NT_HEADER。如果前後兩個值都匹配,那我們就認為該檔案是一個有效PE檔案。

 下面將通過一個VC++ 6.0的例子來檢驗PE檔案的有效性:

 我們首先調用開啟檔案通用對話方塊(GetOpenFileName),選擇開啟一個檔案並映射到記憶體(CreateFile,CreateFileMapping、MapViewOfFile等),獲得目標檔案大小(m_buffer = new unsigned char[m_size];)。然後擷取目標檔案的頭2個位元組(((unsigned short*)m_buffer)[0];),看是否為"MZ"。如果相同,獲得目標檔案PE header的位置(((unsigned int*)(2*m_buffer + 0x3c));), 與0x00004550(PE)比較。由此驗證PE有效性。

三、File Header(檔案頭)

 File Header(IMAGE_FILE_HEADER)包含在PE Header(IMAGE_NT_HEADERS)裡面,其結構定義:

typedef struct _IMAGE_FILE_HEADER {
    WORD Machine;
    WORD NumberOfSections;
    DWORD TimeDateStamp;
    DWORD PointerToSymbolTable;
    DWORD NumberOfSymbols;
    WORD SizeOfOptionalHeader;
    WORD Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

 IMAGE_FILE_HEADER 結構成員含義:

1.Machine:該檔案運行所要求的CPU。對於Intel平台,該值是IMAGE_FILE_MACHINE_I386 (14Ch)。我們嘗試了LUEVELSMEYER的pe.txt聲明的14Dh和14Eh,但Windows不能正確執行。

一些CPU識別碼的定義:

Intel I386    0x14C
Intel i860    0x14D
MIPS R300    0x162
MIPS R400    0x166
DEC Alpha AXP   0x184
Power PC    0x1F0(little endian)
Motorola 68000   0x268
PA RISC    0x290(Precision Architecture)

#define IMAGE_FILE_MACHINE_UNKNOWN           0
#define IMAGE_FILE_MACHINE_I386              0x014c  // Intel 386.
#define IMAGE_FILE_MACHINE_R3000             0x0162  // MIPS little-endian, 0x160 big-endian
#define IMAGE_FILE_MACHINE_R4000             0x0166  // MIPS little-endian
#define IMAGE_FILE_MACHINE_R10000            0x0168  // MIPS little-endian
#define IMAGE_FILE_MACHINE_WCEMIPSV2         0x0169  // MIPS little-endian WCE v2
#define IMAGE_FILE_MACHINE_ALPHA             0x0184  // Alpha_AXP
#define IMAGE_FILE_MACHINE_POWERPC           0x01F0  // IBM PowerPC Little-Endian
#define IMAGE_FILE_MACHINE_SH3               0x01a2  // SH3 little-endian
#define IMAGE_FILE_MACHINE_SH3E              0x01a4  // SH3E little-endian
#define IMAGE_FILE_MACHINE_SH4               0x01a6  // SH4 little-endian
#define IMAGE_FILE_MACHINE_ARM               0x01c0  // ARM Little-Endian
#define IMAGE_FILE_MACHINE_THUMB             0x01c2
#define IMAGE_FILE_MACHINE_IA64              0x0200  // Intel 64
#define IMAGE_FILE_MACHINE_MIPS16            0x0266  // MIPS
#define IMAGE_FILE_MACHINE_MIPSFPU           0x0366  // MIPS
#define IMAGE_FILE_MACHINE_MIPSFPU16         0x0466  // MIPS
#define IMAGE_FILE_MACHINE_ALPHA64           0x0284  // ALPHA64
#define IMAGE_FILE_MACHINE_AXP64             IMAGE_FILE_MACHINE_ALPHA64

2.NumberOfSections:檔案的節數目。如果我們要在檔案中增加或刪除一個節,就需要修改這個值。

3.TimeDateStamp:檔案建立日期和時間。其格式是自從1969年12 月31 日4:00 P.M. 之後的總秒數。據我計算,0xFFFFFFFFh是136.19251950152207001522070015221 年。

4.PointerToSymbolTable:COFF 符號表格的位移位置。此域只對COFF 除錯資訊有用。

5.NumberOfSymbols:COFF 符號表格中的符號個數。

6.SizeOfOptionalHeade:指示緊隨本結構之後的 Optional Header(IMAGE_OPTIONAL_HEADER)結構大小,必須為有效值。

7.Chracteristics:關於本檔案資訊的標記。一些比較重要的性質如下:

0x0001 檔案中沒有重定位(relocation)
0x0002 檔案是一個可執行程式exe(也就是說不是OBJ 或LIB)
0x2000 檔案是dll,不是exe。

 一般情況下,如果要遍曆節表就得使用 NumberOfSections,其它的幾個域作用不大。
 

四、Optional Header

4.1、RVA 及其相關概念:

 RAV 代表相對虛擬位址。RVA是虛擬空間中到參考點的一段距離。RVA就是類似檔案位移量的東西。當然它是相對虛擬空間裡的一個地址,而不是檔案頭部。舉例說明,如果PE檔案裝入虛擬位址(VA)空間的400000h處,且進程從虛址401000h開始執行,我們可以說進程執行起始地址在RVA 1000h。每個RVA都是相對於模組的起始VA的。虛址(VA)0x401000h - 基址(BA)0x400000h = RVA 0x1464h。基址(Base Address)用來描述被映射到記憶體中的exe或者dll的起始位置。

 為什麼PE檔案格式要用到RVA呢? 這是為了減少PE裝載器的負擔。因為每個模組都有可能被重載到任何虛擬位址空間,如果讓PE裝載器修正每個重定位項,這肯定是個夢魘。相反,如果所有重定位項都使用RVA,那麼PE裝載器就不必操心那些東西了: 它只要將整個模組重定位到新的起始VA。這就象相對路徑和絕對路徑的概念: RVA類似相對路徑,VA就象絕對路徑。

 在PE檔案中大多數地址多是RVAs 而 RVAs只有當PE檔案被PE裝載器裝入記憶體後才有意義。如果直接將檔案對應到記憶體而不是通過PE裝載器載入,則不能直接使用那些RVAs。必須先將那些RVAs轉換成檔案位移量。

4.2、Optional Header 結構是 IMAGE_NT_HEADERS 中的最後成員。包含了PE檔案的邏輯分布資訊。該結構共有31個域,一些是很關鍵,另一些不太常用。其結構定義:

typedef struct _IMAGE_OPTIONAL_HEADER {
    WORD    Magic;
    BYTE    MajorLinkerVersion;
    BYTE    MinorLinkerVersion;
    DWORD   SizeOfCode;
    DWORD   SizeOfInitializedData;
    DWORD   SizeOfUninitializedData;
    DWORD   AddressOfEntryPoint;
    DWORD   BaseOfCode;
    DWORD   BaseOfData;
    DWORD   ImageBase;
    DWORD   SectionAlignment;
    DWORD   FileAlignment;
    WORD    MajorOperatingSystemVersion;
    WORD    MinorOperatingSystemVersion;
    WORD    MajorImageVersion;
    WORD    MinorImageVersion;
    WORD    MajorSubsystemVersion;
    WORD    MinorSubsystemVersion;
    DWORD   Win32VersionValue;
    DWORD   SizeOfImage;
    DWORD   SizeOfHeaders;
    DWORD   CheckSum;
    WORD    Subsystem;
    WORD    DllCharacteristics;
    DWORD   SizeOfStackReserve;
    DWORD   SizeOfStackCommit;
    DWORD   SizeOfHeapReserve;
    DWORD   SizeOfHeapCommit;
    DWORD   LoaderFlags;     DWORD   NumberOfRvaAndSizes;
    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;

 IMAGE_OPTIONAL_HEADER 結構成員含義:
 
1.Magic:用來定義 image 的狀態

0x0107(IMAGE_ROM_OPTIONAL_HDR_MAGIC):一個 ROM image
0x010B(IMAGE_NT_OPTIONAL_HDR_MAGIC): 一個正常的(一般的)EXE image。大部份可攜式執行檔都含此值。

2.MajorLinkerVersion、MinorLinkerVersion:產生此PE檔案的連結器的版本。以十進位而非十六進位表示。例如2.23 版。

3.SizeOfCode:所有code section 的總和大小。大部分程式只有一個 code section,所以此域通常就是 .text section 的大小。
4.SizeOfInitializedData:所有包含初始化內容的 sections(但不包括 code section)的總和大小。似乎不包括 initialized data sections 在內。

5.SizeOfUninitializedData:所有需要PE裝載器將記憶體位址空間賦予它但是卻不佔用硬碟空間的所有 sections 的大小總和。這些 sections 在程式啟動時並不需要特別內容,所以導致 Uninitialized Data 這種叫法。為初始化的內容通常放在 .bss section 中。

6.AddressOfEntryPoint:這是PE檔案開始執行的位置。這是一個RVA,通常會落在 .text section.此域適用於 exe 或 dll。

7.BaseOfCode:一個RVA,表示程式中的 code section 從何開始。code section 通常在 data section 之前,在PE 表頭之後。微軟連結器所產生的exes 中,此值通常為0x1000。Borland 的TLINK32則通常指定此值為0x10000。因為預設情況下TLINK時以64k為對齊粒度的,而MS用的是4k。

8.BaseOfData:一個RVA,表示程式中的 data section 從何開始。data section 一般位於code section 和 PE 表頭之後。
 
9.ImageBase:PE檔案的優先裝載地址(Base Address)。比如,如果該值是400000h,PE裝載器將嘗試把檔案裝到虛擬位址空間的400000h處。字眼"優先"表示若該地址地區已被其他模組佔用,那PE裝載器會選用其他空閑地址。

10.SectionAlignment:記憶體中節對齊的粒度。例如,如果該值是4096 (1000h),那麼每節的起始地址必須是4096的倍數。若第一節從401000h開始且大小是10個位元組,則下一節必定從402000h開始,即使401000h和402000h之間還有很多空間沒被使用。

11.FileAlignment:檔案中節對齊的粒度。例如,如果該值是(200h),,那麼每節的起始地址必須是512的倍數。若第一節從檔案位移量200h開始且大小是10個位元組,則下一節必定位於位移量400h,即使位移量512和1024之間還有很多空間沒被使用或定義。預設值就是0x200h。

12.MajorOperatingSystemVersion/MinorOperatingSystemVersion:使用此可執行程式的作業系統的最小版本。WIN32程式的這兩個域通常指定為1.0。

13.MajorSubsystemVersion/MinorSubsystemVersion:WIN32子系統版本。若PE檔案是專門為WIN32設計的,該子系統版本必定是4.0否則對話方塊不會有3維立體感。

14.MajorImageVersion/MinorImageVersion:使用者自訂的域,允許你擁有不同版本的exe或dll。可以利用連結器的 /VERSION 選項設定其值。例如:LINK /VERSION:2.0 myobj.obj。

15.Reserved1:似乎總是0。

16.SizeOfImage:記憶體中整個PE映像體的尺寸。它是所有頭和節經過節對齊處理後的大小。也就是從image base 開始,直到最後一個 section為止。最後一個section 的尾端必需是SectionAlignment 的倍數。
 
17.SizeOfHeaders:所有頭 + 節表的大小,也就等於檔案尺寸減去檔案中所有節的尺寸。可以以此值作為PE檔案第一節的檔案位移量。

18.CheckSum:此程式的一個CRC 校正和。PE中此域通常被忽略並被設為0。然而,所有的driver DLLs、所有在開機時載入的DLLs、以及server DLLs 都必須有一個合法的 CheckSum。其演算法可以在IMAGEHLP.DLL中獲得。IMAGEHLP.DLL 的代碼可以在WIN32 SDK中找到。

19.Subsystem:用來識別PE檔案屬於哪個子系統。對於大多數Win32程式,只有兩類值: Windows GUI 和 Windows CUI (控制台)。WINNT.h中定義如下:

#define IMAGE_SUBSYSTEM_UNKNOWN          0  Unknown subsystem.
#define IMAGE_SUBSYSTEM_NATIVE           1  不需要子系統(例如驅動程式)
#define IMAGE_SUBSYSTEM_WINDOWS_GUI      2  在Windows GUI 子系統中運行
#define IMAGE_SUBSYSTEM_WINDOWS_CUI      3  在Windows 字元模式子系統中運行(也就是console 應用程式)
#define IMAGE_SUBSYSTEM_OS2_CUI          5  在OS/2 字元模式子系統中運行(也就是OS/2 1.x 應用程式)
#define IMAGE_SUBSYSTEM_POSIX_CUI        7  在Posix 字元模式子系統中運行
#define IMAGE_SUBSYSTEM_NATIVE_WINDOWS   8  一個Win9x驅動
#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI   9  在Win CE 子系統中運行

20.DllCharacteristics:一組標誌位,用來指出dll的初始化函數(例如 DllMain)在什麼環境下被調用。這個值總是0,但是作業系統會在四種情況發生式調用dll的初始化函數。此值的四個值的意義如下:

0x0001:當DLL被載入一個進程的地址空間時
0x0002:當一個線程結束時
0x0004:但一個線程開始時
0x0008:當DLL退出時
0x2000:一個WDM驅動

21.SizeOfStackReserve:線程初始堆棧的保留大小。然而並不是所有的這些記憶體都被系統指定。此值預設為0x100000(1MB)。如果你的程式中調用CreateThread 並指定其堆棧大小為0,獲得的線程就有一個與此值相同大小的堆棧。

22.SizeOfStackCommit:一開始就被指定給執行線程初始堆棧的記憶體數量。微軟的連結器預設此值為0x1000(一個page),Borland 的TLINK32把它設為0x2000(兩個page)。

23.SizeOfHeapReserve:保留給最初的進程堆(process heap)的虛擬記憶體數量。這個堆的控制代碼可以利用GetProcessHeap 獲得。並不是所有的這些記憶體都被指定。

24.SizeOfHeapCommit:一開始就被指定給進程堆(process heap)的記憶體數量。此值預設為0x1000個位元組(位元組)。

25.LoaderFlags:Debug用。可能作用:
a.在開始這個進程之前引發一個中斷?
b.在進程被載入之後引發一個除錯器執行?

26.NumberOfRvaAndSizes:在DataDirectory(下一個域)數組的成員結構個數。目前的工具總是把此值設為16。

27.DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]:一個IMAGE_DATA_DIRECTORY 結構數組。每個結構給出一個重要資料結構的RVA。數組的第一個元素代表 Exported Function Table(如果有的話)的地址和大小,第二個元素代表Imported Function Table 的地址和大小,依此類推。下面是其順序的完整列表:

// Directory Entries
#define IMAGE_DIRECTORY_ENTRY_EXPORT   0  // Export Directory
#define IMAGE_DIRECTORY_ENTRY_IMPORT   1  // Import Directory
#define IMAGE_DIRECTORY_ENTRY_RESOURCE   2  // Resource Directory
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION  3  // Exception Directory
#define IMAGE_DIRECTORY_ENTRY_SECURITY   4  // Security Directory
#define IMAGE_DIRECTORY_ENTRY_BASERELOC  5  // Base Relocation Table
#define IMAGE_DIRECTORY_ENTRY_DEBUG   6  // Debug Directory
#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT  7  // Description String
#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR  8  // Machine Value (MIPS GP)
#define IMAGE_DIRECTORY_ENTRY_TLS    9  // TLS Directory
#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG  10 // Load Configuration Directory
#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT  11 // Bound Import Directory in headers
#define IMAGE_DIRECTORY_ENTRY_IAT    12 // Import Address Table

96/112   8  Export Table Export Table address and size.
104/120  8  Import Table Import Table address and size
112/128  8  Resource Table Resource Table address and size.
120/136  8  Exception Table Exception Table address and size.
128/144  8  Certificate Table Attribute Certificate Table address and size.
136/152  8  Base Relocation Table Base Relocation Table address and size.
144/160  8  Debug Debug data starting address and size.
152/168  8  Architecture Architecture-specific data address and size.
160/176  8  Global Ptr Relative virtual address of the value to be stored in the global pointer register. Size member of this structure must be set to 0.
168/184  8  TLS Table Thread Local Storage (TLS) Table address and size.
176/192  8  Load Config Table Load Configuration Table address and size.
184/200  8  Bound Import Bound Import Table address and size.
192/208  8  IAT Import Address Table address and size.
200/216  8  Delay Import Descriptor Address and size of the Delay Import Descriptor.
208/224  8  COM+ Runtime Header COM+ Runtime Header address and size
216/232  8  Reserved

                           rivershan原創於2003.1.18

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.