Esempio n. 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)
Esempio n. 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)
Esempio n. 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)
Esempio n. 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)]
Esempio n. 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
Esempio n. 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)
Esempio n. 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))
Esempio n. 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)))
Esempio n. 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
Esempio n. 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)
Esempio n. 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
Esempio n. 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)
Esempio n. 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
Esempio n. 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)
Esempio n. 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)