1import angr 2 3from cle.backends.externs.simdata.io_file import io_file_data_for_arch 4 5###################################### 6# fdopen 7# 8# Reference for implementation: 9# glibc-2.25/libio/iofdopen.c 10###################################### 11 12 13def mode_to_flag(mode): 14 # TODO improve this: handle mode = strings 15 if mode[-1] == b'b': # lol who uses windows 16 mode = mode[:-1] 17 all_modes = { 18 b"r" : angr.storage.file.Flags.O_RDONLY, 19 b"r+" : angr.storage.file.Flags.O_RDWR, 20 b"w" : angr.storage.file.Flags.O_WRONLY | angr.storage.file.Flags.O_CREAT, 21 b"w+" : angr.storage.file.Flags.O_RDWR | angr.storage.file.Flags.O_CREAT, 22 b"a" : angr.storage.file.Flags.O_WRONLY | angr.storage.file.Flags.O_CREAT | angr.storage.file.Flags.O_APPEND, 23 b"a+" : angr.storage.file.Flags.O_RDWR | angr.storage.file.Flags.O_CREAT | angr.storage.file.Flags.O_APPEND 24 } 25 if mode not in all_modes: 26 raise angr.SimProcedureError('unsupported file open mode %s' % mode) 27 28 return all_modes[mode] 29 30class fdopen(angr.SimProcedure): 31 #pylint:disable=arguments-differ 32 33 def run(self, fd_int, m_addr): 34 #pylint:disable=unused-variable 35 strlen = angr.SIM_PROCEDURES['libc']['strlen'] 36 37 m_strlen = self.inline_call(strlen, m_addr) 38 m_expr = self.state.memory.load(m_addr, m_strlen.max_null_index, endness='Iend_BE') 39 mode = self.state.solver.eval(m_expr, cast_to=bytes) 40 41 # TODO: handle append and other mode subtleties 42 43 fd = self.state.solver.eval(fd_int) 44 if fd not in self.state.posix.fd: 45 # if file descriptor not found return NULL 46 return 0 47 else: 48 # Allocate a FILE struct in heap 49 malloc = angr.SIM_PROCEDURES['libc']['malloc'] 50 io_file_data = io_file_data_for_arch(self.state.arch) 51 file_struct_ptr = self.inline_call(malloc, io_file_data['size']).ret_expr 52 53 # Write the fd 54 fd_bvv = self.state.solver.BVV(fd, 4 * 8) # int 55 self.state.memory.store(file_struct_ptr + io_file_data['fd'], 56 fd_bvv, 57 endness=self.state.arch.memory_endness) 58 59 return file_struct_ptr 60