1. 介紹2017年3月,長(zhǎng)亭安全研究實(shí)驗(yàn)室(Chaitin Security Research Lab)參加了Pwn2Own黑客大賽,我作為團(tuán)隊(duì)的一員,一直專注于VMware Workstation" />

国产成人精品无码青草_亚洲国产美女精品久久久久∴_欧美人与鲁交大毛片免费_国产果冻豆传媒麻婆精东

15158846557 在線咨詢 在線咨詢
15158846557 在線咨詢
所在位置: 首頁(yè) > 營(yíng)銷資訊 > 網(wǎng)站運(yùn)營(yíng) > 利用一個(gè)堆溢出漏洞實(shí)現(xiàn)VMware虛擬機(jī)逃逸

利用一個(gè)堆溢出漏洞實(shí)現(xiàn)VMware虛擬機(jī)逃逸

時(shí)間:2023-06-29 04:51:02 | 來(lái)源:網(wǎng)站運(yùn)營(yíng)

時(shí)間:2023-06-29 04:51:02 來(lái)源:網(wǎng)站運(yùn)營(yíng)

利用一個(gè)堆溢出漏洞實(shí)現(xiàn)VMware虛擬機(jī)逃逸:[作者:李小龍(acez),中文翻譯:kelwin]


1. 介紹

2017年3月,長(zhǎng)亭安全研究實(shí)驗(yàn)室(Chaitin Security Research Lab)參加了Pwn2Own黑客大賽,我作為團(tuán)隊(duì)的一員,一直專注于VMware Workstation Pro的破解,并成功在賽前完成了一個(gè)虛擬機(jī)逃逸的漏洞利用。(很不)幸運(yùn)的是,就在Pwn2Own比賽的前一天(3月14日),VMware發(fā)布了一個(gè)新的版本,其中修復(fù)了我們所利用的漏洞。在本文中,我會(huì)介紹我們從發(fā)現(xiàn)漏洞到完成利用的整個(gè)過(guò)程。感謝@kelwin在實(shí)現(xiàn)漏洞利用過(guò)程中給予的幫助,也感謝ZDI的朋友,他們近期也發(fā)布了一篇相關(guān)博客,正是這篇博文促使我們完成本篇writeup。

本文主要由三部分組成:首先我們會(huì)簡(jiǎn)要介紹VMware中的RPCI機(jī)制,其次我們會(huì)描述本文使用的漏洞,最后講解我們是如何利用這一個(gè)漏洞來(lái)繞過(guò)ASLR并實(shí)現(xiàn)代碼執(zhí)行的。

2. VMware RPCI機(jī)制

VMware實(shí)現(xiàn)了多種虛擬機(jī)(下文稱為guest)與宿主機(jī)(下文稱文host)之間的通信方式。其中一種方式是通過(guò)一個(gè)叫做Backdoor的接口,這種方式的設(shè)計(jì)很有趣,guest只需在用戶態(tài)就可以通過(guò)該接口發(fā)送命令。VMware Tools也部分使用了這種接口來(lái)和host通信。我們來(lái)看部分相關(guān)代碼(摘自open-vm-tools中的lib/backdoor/backdoorGcc64.c):

void Backdoor_InOut(Backdoor_proto *myBp) // IN/OUT { uint64 dummy; __asm__ __volatile__(#ifdef __APPLE__ /* * Save %rbx on the stack because the Mac OS GCC doesn't want us to * clobber it - it erroneously thinks %rbx is the PIC register. * (Radar bug 7304232) */ "pushq %%rbx" "/n/t"#endif "pushq %%rax" "/n/t" "movq 40(%%rax), %%rdi" "/n/t" "movq 32(%%rax), %%rsi" "/n/t" "movq 24(%%rax), %%rdx" "/n/t" "movq 16(%%rax), %%rcx" "/n/t" "movq 8(%%rax), %%rbx" "/n/t" "movq (%%rax), %%rax" "/n/t" "inl %%dx, %%eax" "/n/t" /* NB: There is no inq instruction */ "xchgq %%rax, (%%rsp)" "/n/t" "movq %%rdi, 40(%%rax)" "/n/t" "movq %%rsi, 32(%%rax)" "/n/t" "movq %%rdx, 24(%%rax)" "/n/t" "movq %%rcx, 16(%%rax)" "/n/t" "movq %%rbx, 8(%%rax)" "/n/t" "popq (%%rax)" "/n/t"#ifdef __APPLE__ "popq %%rbx" "/n/t"#endif : "=a" (dummy) : "0" (myBp) /* * vmware can modify the whole VM state without the compiler knowing * it. So far it does not modify EFLAGS. --hpreg */ :#ifndef __APPLE__ /* %rbx is unchanged at the end of the function on Mac OS. */ "rbx",#endif "rcx", "rdx", "rsi", "rdi", "memory" );}上面的代碼中出現(xiàn)了一個(gè)很奇怪的指令inl。在通常環(huán)境下(例如Linux下默認(rèn)的I/O權(quán)限設(shè)置),用戶態(tài)程序是無(wú)法執(zhí)行I/O指令的,因?yàn)檫@條指令只會(huì)讓用戶態(tài)程序出錯(cuò)并產(chǎn)生崩潰。而此處這條指令產(chǎn)生的權(quán)限錯(cuò)誤會(huì)被host上的hypervisor捕捉,從而實(shí)現(xiàn)通信。Backdoor所引入的這種從guest上的用戶態(tài)程序直接和host通信的能力,帶來(lái)了一個(gè)有趣的攻擊面,這個(gè)攻擊面正好滿足Pwn2Own的要求:“在這個(gè)類型(指虛擬機(jī)逃逸這一類挑戰(zhàn))中,攻擊必須從guest的非管理員帳號(hào)發(fā)起,并實(shí)現(xiàn)在host操作系統(tǒng)中執(zhí)行任意代碼”。guest將0x564D5868存入$eax,I/O端口號(hào)0x5658或0x5659存儲(chǔ)在$dx中,分別對(duì)應(yīng)低帶寬和高帶寬通信。其它寄存器被用于傳遞參數(shù),例如$ecx的低16位被用來(lái)存儲(chǔ)命令號(hào)。對(duì)于RPCI通信,命令號(hào)會(huì)被設(shè)為BDOOR_CMD_MESSAGE(=30)。文件lib/include/backdoor_def.h中包含了一些支持的backdoor命令列表。host捕捉到錯(cuò)誤后,會(huì)讀取命令號(hào)并分發(fā)至相應(yīng)的處理函數(shù)。此處我省略了很多細(xì)節(jié),如果你有興趣可以閱讀相關(guān)源碼。


2.1 RPCI

遠(yuǎn)程過(guò)程調(diào)用接口RPCI(Remote Procedure Call Interface)是基于前面提到的Backdoor機(jī)制實(shí)現(xiàn)的。依賴這個(gè)機(jī)制,guest能夠向host發(fā)送請(qǐng)求來(lái)完成某些操作,例如,拖放(Drag n Drop)/復(fù)制粘貼(Copy Paste)操作、發(fā)送或獲取信息等等。RPCI請(qǐng)求的格式非常簡(jiǎn)單:<命令> <參數(shù)>。例如RPCI請(qǐng)求info-get guestinfo.ip可以用來(lái)獲取guest的IP地址。對(duì)于每個(gè)RPCI命令,在vmware-vmx進(jìn)程中都有相關(guān)注冊(cè)和處理操作。

需要注意的是有些RPCI命令是基于VMCI套接字實(shí)現(xiàn)的,但此內(nèi)容已超出本文討論的范疇。

3. 漏洞

花了一些時(shí)間逆向各種不同的RPCI處理函數(shù)之后,我決定專注于分析拖放(Drag n Drop,下面簡(jiǎn)稱為DnD)和復(fù)制粘貼(Copy Paste,下面簡(jiǎn)稱為CP)功能。這部分可能是最復(fù)雜的RPCI命令,也是最可能找到漏洞的地方。在深入理解的DnD/CP內(nèi)部工作機(jī)理后,可以很容易發(fā)現(xiàn),在沒(méi)有用戶交互的情況下,這些處理函數(shù)中的許多功能是無(wú)法調(diào)用的。DnD/CP的核心功能維護(hù)了一個(gè)狀態(tài)機(jī),在無(wú)用戶交互(例如拖動(dòng)鼠標(biāo)從host到guest中)情況下,許多狀態(tài)是無(wú)法達(dá)到的。

我決定看一看Pwnfest 2016上被利用的漏洞,該漏洞在這個(gè)VMware安全公告中有所提及。此時(shí)我的idb已經(jīng)標(biāo)上了很多符號(hào),所以很容易就通過(guò)bindiff找到了補(bǔ)丁的位置。下面的代碼是修補(bǔ)之前存在漏洞的函數(shù)(可以看出services/plugins/dndcp/dnddndCPMsgV4.c中有對(duì)應(yīng)源碼,漏洞依然存在于open-vm-tools的git倉(cāng)庫(kù)的master分支當(dāng)中):

static Bool DnDCPMsgV4IsPacketValid(const uint8 *packet, size_t packetSize){ DnDCPMsgHdrV4 *msgHdr = NULL; ASSERT(packet); if (packetSize < DND_CP_MSG_HEADERSIZE_V4) { return FALSE; } msgHdr = (DnDCPMsgHdrV4 *)packet; /* Payload size is not valid. */ if (msgHdr->payloadSize > DND_CP_PACKET_MAX_PAYLOAD_SIZE_V4) { return FALSE; } /* Binary size is not valid. */ if (msgHdr->binarySize > DND_CP_MSG_MAX_BINARY_SIZE_V4) { return FALSE; } /* Payload size is more than binary size. */ if (msgHdr->payloadOffset + msgHdr->payloadSize > msgHdr->binarySize) { // [1] return FALSE; } return TRUE;}Bool DnDCPMsgV4_UnserializeMultiple(DnDCPMsgV4 *msg, const uint8 *packet, size_t packetSize){ DnDCPMsgHdrV4 *msgHdr = NULL; ASSERT(msg); ASSERT(packet); if (!DnDCPMsgV4IsPacketValid(packet, packetSize)) { return FALSE; } msgHdr = (DnDCPMsgHdrV4 *)packet; /* * For each session, there is at most 1 big message. If the received * sessionId is different with buffered one, the received packet is for * another another new message. Destroy old buffered message. */ if (msg->binary && msg->hdr.sessionId != msgHdr->sessionId) { DnDCPMsgV4_Destroy(msg); } /* Offset should be 0 for new message. */ if (NULL == msg->binary && msgHdr->payloadOffset != 0) { return FALSE; } /* For existing buffered message, the payload offset should match. */ if (msg->binary && msg->hdr.sessionId == msgHdr->sessionId && msg->hdr.payloadOffset != msgHdr->payloadOffset) { return FALSE; } if (NULL == msg->binary) { memcpy(msg, msgHdr, DND_CP_MSG_HEADERSIZE_V4); msg->binary = Util_SafeMalloc(msg->hdr.binarySize); } /* msg->hdr.payloadOffset is used as received binary size. */ memcpy(msg->binary + msg->hdr.payloadOffset, packet + DND_CP_MSG_HEADERSIZE_V4, msgHdr->payloadSize); // [2] msg->hdr.payloadOffset += msgHdr->payloadSize; return TRUE;}對(duì)于Version 4的DnD/CP功能,當(dāng)guest發(fā)送分片DnD/CP命令數(shù)據(jù)包時(shí),host會(huì)調(diào)用上面的函數(shù)來(lái)重組guest發(fā)送的DnD/CP消息。接收的第一個(gè)包必須滿足payloadOffset為0,binarySize代表堆上分配的buffer長(zhǎng)度。[1]處的檢查比較了包頭中的binarySize,用來(lái)確保payloadOffset和payloadSize不會(huì)越界。在[2]處,數(shù)據(jù)會(huì)被拷入分配的buffer中。但是[1]處的檢查存在問(wèn)題,它只對(duì)接收的第一個(gè)包有效,對(duì)于后續(xù)的數(shù)據(jù)包,這個(gè)檢查是無(wú)效的,因?yàn)榇a預(yù)期包頭中的binarySize和分片流中的第一個(gè)包相同,但實(shí)際上你可以在后續(xù)的包中指定更大的binarySize來(lái)滿足檢查,并觸發(fā)堆溢出。

所以,該漏洞可以通過(guò)發(fā)送下面的兩個(gè)分片來(lái)觸發(fā):

packet 1{ ... binarySize = 0x100 payloadOffset = 0 payloadSize = 0x50 sessionId = 0x41414141 ... #...0x50 bytes...#}packet 2{ ... binarySize = 0x1000 payloadOffset = 0x50 payloadSize = 0x100 sessionId = 0x41414141 ... #...0x100 bytes...#}有了以上的知識(shí),我決定看看Version 3中的DnD/CP功能中是不是也存在類似的問(wèn)題。令人驚訝的是,幾乎相同的漏洞存在于Version 3的代碼中(這個(gè)漏洞最初通過(guò)逆向分析來(lái)發(fā)現(xiàn),但是我們后來(lái)意識(shí)到v3的代碼也在open-vm-tools的git倉(cāng)庫(kù)中):

Bool DnD_TransportBufAppendPacket(DnDTransportBuffer *buf, // IN/OUT DnDTransportPacketHeader *packet, // IN size_t packetSize) // IN{ ASSERT(buf); ASSERT(packetSize == (packet->payloadSize + DND_TRANSPORT_PACKET_HEADER_SIZE) && packetSize <= DND_MAX_TRANSPORT_PACKET_SIZE && (packet->payloadSize + packet->offset) <= packet->totalSize && packet->totalSize <= DNDMSG_MAX_ARGSZ); if (packetSize != (packet->payloadSize + DND_TRANSPORT_PACKET_HEADER_SIZE) || packetSize > DND_MAX_TRANSPORT_PACKET_SIZE || (packet->payloadSize + packet->offset) > packet->totalSize || //[1] packet->totalSize > DNDMSG_MAX_ARGSZ) { goto error; } /* * If seqNum does not match, it means either this is the first packet, or there * is a timeout in another side. Reset the buffer in all cases. */ if (buf->seqNum != packet->seqNum) { DnD_TransportBufReset(buf); } if (!buf->buffer) { ASSERT(!packet->offset); if (packet->offset) { goto error; } buf->buffer = Util_SafeMalloc(packet->totalSize); buf->totalSize = packet->totalSize; buf->seqNum = packet->seqNum; buf->offset = 0; } if (buf->offset != packet->offset) { goto error; } memcpy(buf->buffer + buf->offset, packet->payload, packet->payloadSize); buf->offset += packet->payloadSize; return TRUE;error: DnD_TransportBufReset(buf); return FALSE;}Version 3的DnD/CP在分片重組時(shí),上面的函數(shù)會(huì)被調(diào)用。此處我們可以在[1]處看到與之前相同的情形,代碼依然假設(shè)后續(xù)分片中的totalSize會(huì)和第一個(gè)分片一致。因此這個(gè)漏洞可以用和之前相同的方法觸發(fā):

packet 1{ ... totalSize = 0x100 payloadOffset = 0 payloadSize = 0x50 seqNum = 0x41414141 ... #...0x50 bytes...#}packet 2{ ... totalSize = 0x1000 payloadOffset = 0x50 payloadSize = 0x100 seqNum = 0x41414141 ... #...0x100 bytes...#}在Pwn2Own這樣的比賽中,這個(gè)漏洞是很弱的,因?yàn)樗皇鞘艿街奥┒吹膯l(fā),而且甚至可以說(shuō)是同一個(gè)。因此,這樣的漏洞在賽前被修補(bǔ)并不驚訝(好吧,也許我們并不希望這個(gè)漏洞在比賽前一天被修復(fù))。對(duì)應(yīng)的VMware安全公告在這里。受到這個(gè)漏洞影響的VMWare Workstation Pro最新版本是12.5.3。

接下來(lái),讓我們看一看這個(gè)漏洞是如何被用來(lái)完成從guest到host的逃逸的!

4. 漏洞利用

為了實(shí)現(xiàn)代碼執(zhí)行,我們需要在堆上覆蓋一個(gè)函數(shù)指針,或者破壞C++對(duì)象的虛表指針。

首先讓我們看一看如何將DnD/CP協(xié)議的設(shè)置為version 3,依次發(fā)送下列RPCI命令即可:

tools.capability.dnd_version 3 tools.capability.copypaste_version 3 vmx.capability.dnd_version vmx.capability.copypaste_version 前兩行消息分別設(shè)置了DnD和Copy/Paste的版本,后續(xù)兩行用來(lái)查詢版本,這是必須的,因?yàn)橹挥胁樵儼姹静艜?huì)真正觸發(fā)版本切換。RPCI命令vmx.capability.dnd_version會(huì)檢查DnD/CP協(xié)議的版本是否已被修改,如果是,就會(huì)創(chuàng)建一個(gè)對(duì)應(yīng)版本的C++對(duì)象。對(duì)于version 3,2個(gè)大小為0xA8的C++對(duì)象會(huì)被創(chuàng)建,一個(gè)用于DnD命令,另一個(gè)用于Copy/Paste命令。

這個(gè)漏洞不僅可以讓我們控制分配的大小和溢出的大小,而且能夠讓我們進(jìn)行多次越界寫(xiě)。理想的話,我們可以用它分配大小為0xA8的內(nèi)存塊,并讓它分配在C++對(duì)象之前,然后利用堆溢出改寫(xiě)C++對(duì)象的vtable指針,使其指向可控內(nèi)存,從而實(shí)現(xiàn)代碼執(zhí)行。

這并非易事,在此之前我們必須解決一些其他問(wèn)題。首先我們需要找到一個(gè)方法來(lái)繞過(guò)ASLR,同時(shí)處理好Windows Low Fragmented Heap。

4.1 繞過(guò)ASLR

一般來(lái)說(shuō),我們需要找到一個(gè)對(duì)象,通過(guò)溢出來(lái)影響它,然后實(shí)現(xiàn)信息泄露。例如破壞一個(gè)帶有長(zhǎng)度或者數(shù)據(jù)指針的對(duì)象,并且可以從guest讀取,然而我們沒(méi)有找到這種對(duì)象。于是我們逆向了更多的RPCI命令處理函數(shù),來(lái)尋找可用的東西。那些成對(duì)的命令特別引人關(guān)注,例如你能用一個(gè)命令來(lái)設(shè)置一些數(shù)據(jù),同時(shí)又能用相關(guān)命令來(lái)取回?cái)?shù)據(jù),最終我們找到的是一對(duì)命令info-set和info-get:

info-set guestinfo.KEY VALUE info-get guestinfo.KEY VALUE是一個(gè)字符串,字符串的長(zhǎng)度可以控制堆上buffer的分配長(zhǎng)度,而且我們可以分配任意多的字符串。但是如何用這些字符串來(lái)泄露數(shù)據(jù)呢?我們可以通過(guò)溢出來(lái)覆蓋結(jié)尾的null字節(jié),讓字符串連接上相鄰的內(nèi)存塊。如果我們能夠在發(fā)生溢出的內(nèi)存塊和DnD或CP對(duì)象之間分配一個(gè)字符串,那么我們就能泄露對(duì)象的vtable地址,從而我們就可以知道vmware-vmx的地址。盡管Windows的LFH堆分配存在隨機(jī)化,但我們能夠分配任意多的字符串,因此可以增加實(shí)現(xiàn)上述堆布局的可能性,但是我們?nèi)匀粺o(wú)法控制溢出buffer后面分配的是DnD還是CP對(duì)象。經(jīng)過(guò)我們的測(cè)試,通過(guò)調(diào)整一些參數(shù),例如分配和釋放不同數(shù)量的字符串,我們可以實(shí)現(xiàn)60%到80%的成功率。

下圖總結(jié)了我們構(gòu)建的堆布局情況(Ov代表溢出內(nèi)存塊,S代表String,T代表目標(biāo)對(duì)象)。

我們的策略是:首先分配一些填滿“A”的字符串,然后通過(guò)溢出寫(xiě)入一些“B”,接下來(lái)讀取所有分配的字符串,其中含有“B”的就是被溢出的字符串。這樣我們就找到了一個(gè)字符串可以被用來(lái)讀取泄露的數(shù)據(jù),然后以bucket的內(nèi)存塊大小0xA8的粒度繼續(xù)溢出,每次溢出后都檢查泄露的數(shù)據(jù)。由于DnD和CP對(duì)象的vtable距離vmware-vmx基地址的偏移是固定的,每次溢出后只需要檢查最低一些數(shù)據(jù)位,就能夠判斷溢出是否到達(dá)了目標(biāo)對(duì)象。

4.2 獲取代碼執(zhí)行

現(xiàn)在我們實(shí)現(xiàn)了信息泄露,也能知道溢出的是哪個(gè)C++對(duì)象,接下來(lái)要實(shí)現(xiàn)代碼執(zhí)行。我們需要處理兩種情形:溢出CopyPaste和DnD。需要指出的是能利用的代碼路徑有很多,我們只是選擇了其中一個(gè)。

4.2.1 覆蓋CopyPaste對(duì)象

對(duì)于CopyPaste對(duì)象,我們可以覆蓋虛表指針,讓它指向我們可控的其他數(shù)據(jù)。我們需要找到一個(gè)指針,指針指向的數(shù)據(jù)是可控并被用做對(duì)象的虛表。為此我們使用了另一個(gè)RPCI命令unity.window.contents.start。這個(gè)命令主要用于Unity模式下,在host上繪制一些圖像。這個(gè)操作可以讓我們往相對(duì)vmware-vmx偏移已知的位置寫(xiě)入一些數(shù)據(jù)。該命令接收的參數(shù)是圖像的寬度和高度,二者都是32位,合并起來(lái)我們就在已知位置獲得了一個(gè)64位的數(shù)據(jù)。我們用它來(lái)作為虛表中的一個(gè)指針,通過(guò)發(fā)送一個(gè)CopyPast命令即可觸發(fā)該虛函數(shù)調(diào)用,步驟如下:

4.2.2 覆蓋DnD對(duì)象

對(duì)于DnD對(duì)象,我們不能只覆蓋vtable指針,因?yàn)樵诎l(fā)生溢出之后vtable會(huì)立馬被訪問(wèn),另一個(gè)虛函數(shù)會(huì)被調(diào)用,而目前我們只能通過(guò)unity圖像的寬度和高度控制一個(gè)qword,所以無(wú)法控制更大的虛表。

讓我們看一看DnD和CP對(duì)象的結(jié)構(gòu),總結(jié)如下(一些類似的結(jié)構(gòu)可以在open-vm-tools中找到,但是在vmware-vmx中會(huì)略有區(qū)別):

DnD_CopyPaste_RpcV3{ void * vtable; ... uint64_t ifacetype; RpcUtil{ void * vtable; RpcBase * mRpc; DnDTransportBuffer{ uint64_t seqNum; uint8_t * buffer; uint64_t totalSize; uint64_t offset; ... } ... }}RpcBase{ void * vtable; ...}我們?cè)诖耸÷粤私Y(jié)構(gòu)中很多與本文無(wú)關(guān)的屬性。對(duì)象中有個(gè)指針指向另一個(gè)C++對(duì)象RpcBase,如果我們能用一個(gè)可控?cái)?shù)據(jù)的指針的指針覆蓋mRpc這個(gè)域,那我們就控制了RpcBase的vtable。對(duì)此我們可以繼續(xù)使用unity.window.contents.start命令來(lái)來(lái)控制mRpc,該命令的另一個(gè)參數(shù)是imgsize,這個(gè)參數(shù)代表分配的圖像buffer的大小。這個(gè)buffer分配出來(lái)后,它的地址會(huì)存在vmware-vmx的固定偏移處。我們可以使用命令unity.window.contents.chunk來(lái)填充buffer的內(nèi)容。步驟如下:

P.S:vmware-vmx進(jìn)程中有一個(gè)可讀可寫(xiě)可執(zhí)行的內(nèi)存頁(yè)(至少在版本12.5.3中存在)。

4.3 穩(wěn)定性討論

正如前面提及的,因?yàn)閃indows LFH堆的隨機(jī)化,當(dāng)前的exploit無(wú)法做到100%成功率。不過(guò)可以嘗試下列方法來(lái)提高成功率:

4.4 演示效果


演示視頻:

VMware workstation 12.5.3逃逸演示—在線播放—優(yōu)酷網(wǎng),視頻高清在線觀看http://v.youku.com/v_show/id_XMjg3MjcwMzU4MA==.html?spm=a2h3j.8428770.3416059.1

5. 感想與總結(jié)

“No pwn no fun”,如果你想?yún)⒓覲wn2Own這樣的比賽,你就需要準(zhǔn)備多個(gè)漏洞,或者找到高質(zhì)量的漏洞。

6. 我是廣告

對(duì)安全研究、安全研發(fā)感興趣的朋友歡迎投簡(jiǎn)歷到hr@chaitin.com。

關(guān)鍵詞:實(shí)現(xiàn),虛擬,漏洞,利用,逃逸

74
73
25
news

版權(quán)所有? 億企邦 1997-2025 保留一切法律許可權(quán)利。

為了最佳展示效果,本站不支持IE9及以下版本的瀏覽器,建議您使用谷歌Chrome瀏覽器。 點(diǎn)擊下載Chrome瀏覽器
關(guān)閉