Пример #1
0
 def test_write(self):
     """" Tests that the write64 gadget works """
     self.rop.write64(0x1234567887654321, data + 0)
     self.rop.write64(0xDEADBEEF, data + 8)
     self.execute()
     self.assertEqual(u64(self.memory, 0), 0x1234567887654321)
     self.assertEqual(u64(self.memory, 8), 0xDEADBEEF)
Пример #2
0
 def test_set_x8(self):
     """ Tests that setting X8 works """
     self.rop.call(F.setjmp, data + 0, 2, 3, x8=0xB00BBABE)  # setjmp
     self.execute()
     self.assertEqual(u64(self.memory, 1 * 8), 2)
     self.assertEqual(u64(self.memory, 2 * 8), 3)
     self.assertEqual(u64(self.memory, 8 * 8), 0xB00BBABE)
Пример #3
0
 def test_dump_regs(self):
     """ Tests that dumping regs via setjmp works """
     self.rop.call(G.ret, 1, 2, 3, 4, 5, 6, 7, 8)
     self.rop.dump_regs(data, and_store_r0=data + 0x400)
     self.execute()
     self.assertEqual(u64(self.memory, 0x400), 1)  # r0
     for x in range(1, 8):
         self.assertEqual(u64(self.memory, x * 8), x + 1)
Пример #4
0
 def get_bases(self):
     rop = Rop()
     rop.write64(data_base, data_base + 0)
     rop.write64(main_base, data_base + 8)
     rop.write64(wk_base, data_base + 0x10)
     data = self.execute(rop)
     buf_base = u64(data, 0) - 0x10000
     return [buf_base, u64(data, 8)]
Пример #5
0
    def query(self, addr):
        regs = self.fh.svcQueryMemory(data_base, data_base + 0x100, addr, regs=True)
        base =  u64(self.mem, 0)
        size =  u64(self.mem, 8)
        state = u32(self.mem, 0x10)
        attr =  u32(self.mem, 0x14)
        perm =  u64(self.mem, 0x18)
        unk1 =  u32(self.mem, 0x1C)
        unk2 =  u32(self.mem, 0x20)
        unk3 =  u32(self.mem, 0x24)
        pageinfo = regs["x1"] & 0xFFFFFFFF

        perm_str = ''
        perm_str += 'R' if (perm & 1) else ' '
        perm_str += 'W' if (perm & 2) else ' '
        perm_str += 'X' if (perm & 4) else ' '

        type_map = {
            0: 'UNMAPPED',
            1: 'IO',
            2: 'STATIC',
            3: 'CODE RO',
            4: 'CODE RW',
            5: 'HEAP',
            6: 'SHAREDMEM',
            7: 'WEIRDMAP',
            8: 'MODULE RO',
            9: 'MODULE RW',
            0xB: 'MAPPED',
            0xC: 'TLS',
            0xD: 'WEIRDSHARED',
            0xE: 'TRANSFERMEM',
            0xF: 'PROCESS',
            0x10: 'RESERVED'
        }

        attr_str = ''
        if attr & 1:
            attr_str += 'MIRORRED '
        if attr & 2:
            attr_str += '!!UNK!! '
        if attr & 4:
            attr_str += 'DEVICEMAPPED '
        if attr & 8:
            attr_str += 'UNCACHED '

        if state != 0:
            print '[%s] 0x%010x-0x%010x size=0x%010x [%s] %s' % (perm_str, base, base+size-1, size, type_map[state], attr_str)
            if unk1 != 0:
                print '  !!Unk1!!:   0x%x' % unk1
            if unk2 != 0:
                print '  Unk2:   0x%x' % unk2
            if unk3 != 0:
                print '  !!Unk3!!:   0x%x' % unk3
            if pageinfo != 0:
                print '  Info:   0x%x' % pageinfo

        return base + size
Пример #6
0
 def test_store_load_ret(self):
     """ Tests that store_ret and load_ret work """
     self.rop.write64(0x8DEADB00B, data)
     self.rop.load_ret(data)
     self.rop.store_ret(data + 8)
     self.rop.load_ret(data + 8)
     self.rop.store_ret(data + 0x50)
     self.execute()
     self.assertEqual(u64(self.memory, 0), 0x8DEADB00B)
     self.assertEqual(u64(self.memory, 8), 0x8DEADB00B)
     self.assertEqual(u64(self.memory, 0x50), 0x8DEADB00B)
Пример #7
0
    def bases(self):
        """ Ok this is done in a kinda roundabout way but whatever """
        rop = Rop()
        rop.write64(data_base, data_base + 0)
        rop.write64(main_base, data_base + 8)
        rop.write64(wk_base, data_base + 0x10)
        data = self.execute(rop)
        buf_base = u64(data, 0) - 0x10000

        print "Static memory: 0x{:x} (You can use it between different calls)".format(buf_base)
        print "Main binary base: 0x{:x}".format(u64(data, 8))
        print "Webkit base: 0x{:x}".format(u64(data, 0x10))
Пример #8
0
def sockserver(host, port, rpc):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind((host, port))
    s.listen(10)

    c, addr = s.accept()
    print(c, addr)
    setup_buf = c.recv(0x1000, socket.MSG_WAITALL)

    data_base = u64(setup_buf, 0)
    main_base = u64(setup_buf, 8)
    wk_base = u64(setup_buf, 0x10)
    sockfd = u64(setup_buf, 0x100)
    print("got data of len 0x{:x}".format(len(setup_buf)))
    print("data: 0x{:x} main: 0x{:x} wk: 0x{:x} sockfd: {}".format(
        data_base, main_base, wk_base, sockfd))

    # NOTE: in this first payload, data_base is at +0x8000
    # See rpc.py for the buf layout
    buf = data_base - 0x8000
    rpc.set_args(sockfd, buf)
    relocs = {
        1: buf + RPC_DYNAMIC_MEM_OFF,
        2: main_base,
        3: wk_base
    }  # 1 = data_base = dynamic mem

    print("--- setup complete ---")
    print("you can run ./client.py now")

    while True:
        rop = rpc.next_payload()
        binary = rop.generate_binary(relocs)
        print("Sending rop len = 0x{:x}".format(len(binary)))
        binary += "\x00" * (RPC_ROP_LEN - len(binary))

        ret = c.send(binary)

        print("Sent 0x{:x}".format(ret))

        data = c.recv(RPC_RESPONSE_LEN, socket.MSG_WAITALL)

        rpc.res_q.put(data)

        # print "Got data: {} len 0x{:x}".format(data, len(data))
        print("Got data len 0x{:x}".format(len(data)))
Пример #9
0
 def awrite(self, data):
     """ automem write: "allocate" memory in data section and write into it """
     while len(data) % 8 != 0:
         data += "\x00"
     mem = self.alloc(len(data))
     for x in range(len(data) / 8):
         self.write64(u64(data, 8 * x), mem + 8 * x)
     return mem
Пример #10
0
 def test_rv_call(self):
     """ Tests that x0 is forwarded properly """
     off = 0x1230
     self.rop.write64(data + off, data)
     self.rop.load_ret(data)
     self.rop.call(F.setjmp, Ret, 1, 2, 3, 4)
     self.execute()
     for x in range(1, 5):
         self.assertEqual(u64(self.memory, off + x * 8), x)
Пример #11
0
    def call(self, func, *args, **kwargs):
        if type(func) in [str, unicode]:
            if func in self.funcs:
                func = self.funcs[func]
            else:
                raise RuntimeError("unknown function {}".format(func))

        return_regs = kwargs.get("regs", False)
        if "regs" in kwargs:
            del kwargs["regs"]

        args = list(args)

        rop = Rop()
        for x, arg in enumerate(args):
            if type(arg) is str:
                args[x] = rop.awrites(arg)

        rop.call(func, *args, **kwargs)

        r0_off = RPC_RESPONSE_LEN - 8
        jmp_buf_off = RPC_RESPONSE_LEN - 0x1000
        # if user asked for return_regs, we use setjmp to retrieve them
        # this is useful for syscalls because they can return values in multiple regs
        if return_regs:
            rop.dump_regs(data_base + jmp_buf_off,
                          and_store_r0=data_base + r0_off)
        else:
            # NB: we store return address as the last qword that switch replies to us, to ensure minimum conflicts with other code
            rop.store_ret(data_base + r0_off)

        data = self.ch.execute(rop)
        self.ch.mem = data

        ret = u64(data, r0_off)

        if return_regs:
            regs = {"x0": ret}  # this one's special
            for x in range(1, 31):
                regs["x{}".format(x)] = u64(data, jmp_buf_off + 8 * x)

            return regs

        return ret
Пример #12
0
	def test_func_call(self):
		""" Tests that chaining functions works, and arguments are passed properly """
		self.rop.call(F.setjmp, data + 0, 0x1111111111, 0x2222222222, 0x3333333333, 0x4444444444) # setjmp
		self.rop.write64(0xDEAD, data + 0x50)
		self.rop.call(F.setjmp, data + 0x100, 0x8, 0x7, 0x6, 0x5) # setjmp
		self.execute()
		self.assertEqual(u64(self.memory, 0x8), 0x1111111111)
		self.assertEqual(u64(self.memory, 0x10), 0x2222222222)
		self.assertEqual(u64(self.memory, 0x18), 0x3333333333)
		self.assertEqual(u64(self.memory, 0x20), 0x4444444444)
		self.assertEqual(u64(self.memory, 0x50), 0xDEAD)
		self.assertEqual(u64(self.memory, 0x108), 0x8)
		self.assertEqual(u64(self.memory, 0x110), 0x7)
		self.assertEqual(u64(self.memory, 0x118), 0x6)
		self.assertEqual(u64(self.memory, 0x120), 0x5)
Пример #13
0
    def space(self):
        maps = []

        cur = 0
        while cur < 2 ** 64:
            regs = self.fh.svcQueryMemory(data_base, data_base + 0x100, cur, regs=True)
            base = u64(self.mem, 0)
            size = u64(self.mem, 8)
            perm = u64(self.mem, 0x18)
            state = u64(self.mem, 0x10)
            pageinfo = regs["x1"] & 0xFFFFFFFF # or at self.mem + 0x100

            maps.append({
                'base': base,
                'size': size,
                'perm': perm,
                'state': state,
                'pageinfo': pageinfo
            })
            cur += size

        return maps
Пример #14
0
    def list_dir(self, path, recursive=False, dump_files=False, host_path="", prefix=""):
        if dump_files:
            os.mkdir(host_path)
        ret = self.fh.OpenDirectory(data_base, path, 3)
        if ret != 0:
            print "failed to open '{0}', error={1}=0x{1:x}".format(path, ret)
            return
        handle = u64(self.mem, 0)
        while True:
            self.fh.ReadDirectory(data_base, data_base + 0x200, handle, 1)
            ret = u64(self.mem, 0)
            if ret != 1:
                break

            entry = self.mem[0x200:0x200 + 0x310]
            is_file = u32(entry, 0x304) & 1
            name = c_str(entry, 0)
            print "{}{}{}".format(prefix, name, "/" if not is_file else "")
            fullpath = "{}/{}".format(path, name)
            if dump_files and is_file:
                self.dump_file(fullpath, os.path.join(host_path, name))
            if recursive and not is_file and ('emoji' not in name):
                self.list_dir(fullpath, recursive, dump_files, os.path.join(host_path, name), prefix + "-")
        self.fh.CloseDirectory(handle)
Пример #15
0
 def test_v8_call(self):
     """ Tests that calling with a lot of args works """
     self.rop.call(F.setjmp, data + 0, 2, 3, 4, 5, 6, 7, 8)  # setjmp
     self.execute()
     for x in range(1, 8):
         self.assertEqual(u64(self.memory, x * 8), x + 1)