/firmware_slap/command_injection.py

https://github.com/ChrisTheCoolHut/Firmware_Slap · Python · 112 lines · 93 code · 14 blank · 5 comment · 28 complexity · e10a019f4e8423bd746045dfbed9871c MD5 · raw file

  1. import angr
  2. import string
  3. import claripy
  4. import IPython
  5. class SystemLibc(angr.procedures.libc.system.system):
  6. def check_exploitable(self, cmd):
  7. # cmd is a pointer to a string
  8. value = self.state.memory.load(cmd)
  9. # We can't interact with raw bitvectors as potential system candidates
  10. if 'claripy.ast.bv.BV' in str(type(cmd)):
  11. return False
  12. clarip = cmd.to_claripy()
  13. location = self.state.solver.eval(clarip)
  14. value_length = int("0x" + str(value.length), 16)
  15. symbolic_list = [
  16. self.state.memory.load(
  17. self.state.se.eval(clarip, cast_to=int) +
  18. x).get_byte(0).symbolic for x in range(value_length)
  19. ]
  20. position = 0
  21. count = 0
  22. greatest_count = 0
  23. prev_item = symbolic_list[0]
  24. for i in range(1, len(symbolic_list)):
  25. if symbolic_list[i] and symbolic_list[i] == symbolic_list[i - 1]:
  26. count = count + 1
  27. if (count > greatest_count):
  28. greatest_count = count
  29. position = i - count
  30. else:
  31. if (count > greatest_count):
  32. greatest_count = count
  33. position = i - 1 - count
  34. # previous position minus greatest count
  35. count = 0
  36. if greatest_count >= len("`reboot`"):
  37. val_loc = self.state.memory.load(location + position,
  38. len("`reboot`"))
  39. if self.state.satisfiable(
  40. extra_constraints=[val_loc == "`reboot`"]):
  41. self.state.add_constraints(val_loc == "`reboot`")
  42. self.state.globals['exploitable'] = True
  43. self.state.globals['commandInjection'] = True
  44. self.state.globals['cmd'] = "`reboot`"
  45. self.state.globals['val_addr'] = location
  46. self.state.globals['val_offset'] = location + position
  47. # self.state.globals['val_str'] = val_str
  48. elif greatest_count >= len("`ls`"):
  49. val_loc = self.state.memory.load(location + position, len("`ls`"))
  50. if self.state.satisfiable(extra_constraints=[val_loc == "`ls`"]):
  51. self.state.add_constraints(val_loc == "`ls`")
  52. self.state.globals['exploitable'] = True
  53. self.state.globals['commandInjection'] = True
  54. self.state.globals['cmd'] = "`ls`"
  55. self.state.globals['val_addr'] = location
  56. self.state.globals['val_offset'] = location + position
  57. # self.state.globals['val_str'] = val_str
  58. def check_for_constraint(self):
  59. actions = [x for x in self.state.history.actions]
  60. for action in actions:
  61. if type(
  62. action
  63. ) == angr.state_plugins.sim_action.SimActionData and action.actual_value is not None:
  64. value_str = self.state.se.eval(action.actual_value,
  65. cast_to=bytes).decode(
  66. 'utf-8', 'ignore')
  67. value_print_str = ''.join(
  68. (c if c in string.printable else '' for c in value_str))
  69. value_hex = hex(self.state.se.eval(action.actual_value))
  70. value_address = str(action.actual_addrs).replace(
  71. "[", "").replace("]", "").replace("L", "")
  72. value_address = int(value_address)
  73. if "`ls`" in value_str or "`reboot`" in value_str:
  74. return (True, value_str, value_address)
  75. for x, y, z in self.state.globals['args']:
  76. value_str = self.state.se.eval(z, cast_to=bytes).decode(
  77. 'utf-8', 'ignore')
  78. value_print_str = ''.join(
  79. (c if c in string.printable else '' for c in value_str))
  80. value_hex = hex(self.state.se.eval(z))
  81. value_address = str(action.actual_addrs).replace("[", "").replace(
  82. "]", "").replace("L", "")
  83. value_address = int(value_address)
  84. if "`ls`" in value_str or "`reboot`" in value_str:
  85. return (True, value_str, value_address)
  86. return (False, None, None)
  87. def constrain_control(self,
  88. state,
  89. symbolic_variable,
  90. start_loc,
  91. select_string="`ls`"):
  92. for i in range(len(select_string)):
  93. current_byte = state.memory.load(start_loc + i).get_byte(0)
  94. state.add_constraints(
  95. claripy.Or(claripy.And(select_string[i] == current_byte)))
  96. def run(self, cmd):
  97. self.check_exploitable(cmd)
  98. return super(type(self), self).run(cmd)