PageRenderTime 47ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/PyEmu.py

http://pyemu.googlecode.com/
Python | 987 lines | 956 code | 9 blank | 22 comment | 0 complexity | 2663d35cae12c7a6852976ddd6d3546f MD5 | raw file
  1. #!/usr/bin/env python
  2. ########################################################################
  3. #
  4. # PyEmu: scriptable x86 emulator
  5. #
  6. # Cody Pierce - cpierce@tippingpoint.com - 2007
  7. #
  8. # License: None
  9. #
  10. ########################################################################
  11. import sys, os, time, struct, re
  12. sys.path.append(r'C:\Program Files\IDA\python')
  13. from PyCPU import PyCPU
  14. from PyContext import PyContext
  15. from PyMemory import *
  16. from PyOS import *
  17. '''
  18. PyEmu:
  19. The main emulator class. This class implements the public methods
  20. for controlling the emulator. This includes handlers, and initialization.
  21. '''
  22. class PyEmu:
  23. DEBUG = 0
  24. def __init__(self):
  25. # Holds a instance of our PyCPU class
  26. self.cpu = None
  27. # Holds an instance of our PyOS class
  28. self.os = None
  29. # Tells the emulator whether we are emulating
  30. self.emulating = True
  31. # Whether to use a frame pointer for stack offsets
  32. self.frame_pointer = True
  33. # Class members to hold stack and heap limits
  34. self.stack_base = 0x0
  35. self.stack_size = 0x0
  36. self.heap_base = 0x0
  37. self.heap_size = 0x0
  38. # Holds an instance of our PyMemory class
  39. self.memory = ""
  40. # A list of names for public methods
  41. self.register_names = {}
  42. self.stack_variable_names = {}
  43. self.stack_argument_names = {}
  44. # A list of our user handlers for various aspects of emulation
  45. self.mnemonic_handlers = {}
  46. self.opcode_handlers = {}
  47. self.register_handlers = {}
  48. self.pc_handlers = {}
  49. self.exception_handlers = {}
  50. self.interrupt_handlers = {}
  51. self.library_handlers = {}
  52. self.memory_handlers = {}
  53. self.memory_read_handler = None
  54. self.memory_write_handler = None
  55. self.memory_access_handler = None
  56. self.stack_read_handler = None
  57. self.stack_write_handler = None
  58. self.stack_access_handler = None
  59. self.heap_read_handler = None
  60. self.heap_write_handler = None
  61. self.heap_access_handler = None
  62. # Instantiate a CPU for use in the emulator
  63. self.cpu = PyCPU(self)
  64. # Determine which os we are on to instantiate the proper PyOS
  65. if os.name == 'nt':
  66. self.os = PyWindows()
  67. elif os.name == 'posix':
  68. # Yea I realize
  69. self.os = PyLinux()
  70. #
  71. # raise_exception: This method gets called when an exception happens
  72. # Currently we only care about general protection
  73. # faults (invalid memory access). We will throw a
  74. # Python exception when this occurs (I want to change
  75. # this).
  76. #
  77. def raise_exception(self, exception, address):
  78. # User must raise their own exception
  79. if exception in self.exception_handlers:
  80. self.exception_handlers[exception](self, exception, address, self.cpu.EIP)
  81. else:
  82. print "\n"
  83. print "*" * 72
  84. print "* A %s fault has occured at 0x%08x" % (exception, address)
  85. print "*" * 72
  86. self.dump_regs()
  87. self.dump_stack()
  88. raise RuntimeError, "The memory requested was invalid"
  89. return False
  90. #
  91. # debug: A public method for setting global debug levels
  92. #
  93. def debug(self, level):
  94. self.DEBUG = level
  95. # Propigate the debug levels throughout
  96. self.memory.set_debug(level)
  97. self.cpu.set_debug(level)
  98. self.os.set_debug(level)
  99. #
  100. # execute: A public method for executing instructions
  101. #
  102. def execute(self, steps=1, start=0x0, end=0x0):
  103. # If we are called we are emulating
  104. self.emulating = True
  105. self.cpu.counts = {}
  106. # Set the instruction pointer to the user supplied address
  107. if start:
  108. self.cpu.set_register32("EIP", start)
  109. # Set a stopping point if supplied so we can break
  110. if end:
  111. if steps > 1:
  112. while self.cpu.get_register32("EIP") != end and steps:
  113. if not self.emulating: return False
  114. if not self.cpu.execute():
  115. return False
  116. steps -= 1
  117. else:
  118. while self.cpu.get_register32("EIP") != end:
  119. if not self.emulating: return False
  120. if not self.cpu.execute():
  121. return False
  122. else:
  123. if steps >= 1:
  124. for x in range(steps):
  125. if not self.emulating: return False
  126. if not self.cpu.execute():
  127. return False
  128. else:
  129. while self.emulating:
  130. if not self.cpu.execute():
  131. return False
  132. return True
  133. #
  134. # get_register: A public method to retrieve a register for the user
  135. #
  136. def get_register(self, register):
  137. register = register.upper()
  138. # We are smart about the requested register automatically
  139. # determining the proper register size
  140. # 32 bit registers
  141. if re.compile('^E[A-X]{2}$', re.IGNORECASE).match(register):
  142. result = self.cpu.get_register32(register)
  143. # 16 bit registers
  144. elif re.compile('^[ABCD]X$', re.IGNORECASE).match(register):
  145. result = self.cpu.get_register16(register)
  146. # 8 bit registers
  147. elif re.compile('^[ABCD]{1,}[LH]{1}$', re.IGNORECASE).match(register):
  148. result = self.cpu.get_register8(register)
  149. # Segment registers
  150. elif re.compile('^[CSDEFG]{1}S$', re.IGNORECASE).match(register):
  151. result = self.cpu.get_register16(register)
  152. # Flags
  153. elif re.compile('^[CPAZSTIDPR]{1}F$', re.IGNORECASE).match(register) or register in ["IOPL","NT","VM","AC","VIF","VIP","ID"]:
  154. result = self.cpu.get_register8(register)
  155. # Check to make sure the user isnt requesting by name
  156. else:
  157. if register in self.register_names:
  158. result = self.cpu.get_register(self.register_names[register]["name"], self.register_names[register]["size"])
  159. else:
  160. print "[!] Couldnt determine register"
  161. return False
  162. return result
  163. #
  164. # set_register: A public method for setting a registers value
  165. # from a script.
  166. #
  167. def set_register(self, register, value, name=""):
  168. # Make sure its a valid value
  169. if not isinstance(value, int) and not isinstance(value, long):
  170. print "[!] Dont know how to use non-int value %s" % type(value)
  171. return False
  172. register = register.upper()
  173. name = name.upper()
  174. # We are smart about the requested register automatically
  175. # determining the proper register size
  176. # 32 bit registers
  177. if re.compile('^E[A-X]{2}$', re.IGNORECASE).match(register):
  178. if name:
  179. self.register_names[name] = {"name": register, "size": 4}
  180. # Try and set the register
  181. if not self.cpu.set_register32(register, value):
  182. print "[!] Problem setting register"
  183. return False
  184. # 16 bit registers
  185. elif re.compile('^[ABCD]X$', re.IGNORECASE).match(register):
  186. if name:
  187. self.register_names[name] = {"name": register, "size": 2}
  188. # Try and set the register
  189. if not self.cpu.set_register16(register, value):
  190. print "[!] Problem setting register"
  191. return False
  192. # 8 bit registers
  193. elif re.compile('^[ABCD]{1,}[LH]{1}$', re.IGNORECASE).match(register):
  194. if name:
  195. self.register_names[name] = {"name": register, "size": 1}
  196. # Try and set the register
  197. if not self.cpu.set_register8(register, value):
  198. print "[!] Problem setting register"
  199. return False
  200. # Segment registers
  201. elif re.compile('^[CSDEFG]{1}S$', re.IGNORECASE).match(register):
  202. if name:
  203. self.register_names[name] = {"name": register, "size": 2}
  204. # Try and set the register
  205. if not self.cpu.set_register16(register, value):
  206. print "[!] Problem setting register"
  207. return False
  208. # Flags
  209. elif re.compile('^[CPAZSTIDPR]{1}F$', re.IGNORECASE).match(register) or register in ["IOPL","NT","VM","AC","VIF","VIP","ID"]:
  210. if name:
  211. self.register_names[name] = {"name": register, "size": 1}
  212. # Try and set the register
  213. if not self.cpu.set_register8(register, value):
  214. print "[!] Problem setting register"
  215. return False
  216. # Check to make sure the user isnt requesting by name
  217. else:
  218. if name in self.register_names:
  219. # Try and set the register
  220. if not self.cpu.set_register(self.register_names[name]["name"], self.register_names[name]["size"]):
  221. print "[!] Problem setting register"
  222. return False
  223. else:
  224. print "[!] Couldnt determine register size"
  225. return False
  226. return True
  227. #
  228. # get_stack_variable: A public method for setting stack local variables
  229. #
  230. def get_stack_variable(self, offset, size=0):
  231. # Validate the type of argument to determine offset or name
  232. if isinstance(offset, str):
  233. offset = offset.upper()
  234. # Check if we have the name
  235. if offset not in self.stack_variable_names:
  236. print "[!] Couldnt find name %s" % offset
  237. return False
  238. else:
  239. # Retrieve the offset associated
  240. offset = self.stack_variable_names[offset]
  241. elif not isinstance(offset, int) and not isinstance(offset, long):
  242. print "[!] Dont understand %s type" % type(offset)
  243. return False
  244. # If we dont have a size default to a dword
  245. if not size:
  246. size = 4
  247. # Check if we are using frame pointers for offsets
  248. if self.frame_pointer:
  249. address = self.cpu.get_register32("EBP") - offset
  250. else:
  251. address = self.cpu.get_register32("ESP") + offset
  252. # Fetch the address requested from the memory manager
  253. result = self.memory.get_memory(address, size)
  254. # Return the value
  255. return result
  256. #
  257. # set_stack_variable: A public method for setting a local stack variable
  258. #
  259. def set_stack_variable(self, offset, value, size=0, name=""):
  260. # Make sure our offset is a valid type
  261. if not isinstance(offset, int) and not isinstance(offset, long):
  262. print "[!] Offset must be int not %s" % type(offset)
  263. return False
  264. # Automagically determine a size for the supplied string
  265. if isinstance(value, str):
  266. if not size:
  267. size = len(value)
  268. else:
  269. # Truncate the string if necessary
  270. value = value[:size]
  271. elif isinstance(value, int) or isinstance(value, long):
  272. if not size:
  273. size = 4
  274. # If we are setting a name store it in the names list
  275. if name:
  276. name = name.upper()
  277. self.stack_variable_names[name] = offset
  278. # Check for a frame pointer to get the proper offset
  279. if self.frame_pointer:
  280. address = self.cpu.get_register32("EBP") - offset
  281. else:
  282. address = self.cpu.get_register32("ESP") + offset
  283. # Set the value in memory via the memory manager
  284. if not self.set_memory(address, value, size):
  285. print "[!] Failed setting memory @ %x" % (address)
  286. return False
  287. return True
  288. #
  289. # get_stack_argument: A public method to get a functions stack argument
  290. #
  291. def get_stack_argument(self, offset, size=0):
  292. # If we are asking by name check it
  293. if isinstance(offset, str):
  294. offset = offset.upper()
  295. if offset not in self.stack_variable_names:
  296. print "[!] Couldnt find name %s" % offset
  297. return False
  298. else:
  299. # Return the offset associated
  300. offset = self.stack_variable_names[offset]
  301. elif not isinstance(offset, int) and not isinstance(offset, long):
  302. print "[!] Dont understand %s type" % type(offset)
  303. return False
  304. # We only handle dword arguments for now
  305. size = 4
  306. # Check for frame pointer to get the proper stack address
  307. if self.frame_pointer:
  308. address = self.cpu.get_register32("EBP") + offset
  309. else:
  310. address = self.cpu.get_register32("ESP") + offset
  311. # Retrieve the value from memory via the memory manager
  312. result = self.memory.get_memory(address, size)
  313. return result
  314. #
  315. # set_stack_argument: A public method to set up a stack argument
  316. #
  317. def set_stack_argument(self, offset, value, name=""):
  318. # Ensure the offset is proper
  319. if not isinstance(offset, int) and not isinstance(offset, long):
  320. print "[!] Offset must be int not %s" % type(offset)
  321. return False
  322. # Only dword arguments for now
  323. size = 4
  324. # If we have a name we need to get the associated offset
  325. if name:
  326. name = name.upper()
  327. self.stack_variable_names[name] = offset
  328. # Check the frame pointer and get the proper address
  329. if self.frame_pointer:
  330. address = self.cpu.get_register32("EBP") + offset
  331. else:
  332. address = self.cpu.get_register32("ESP") + offset
  333. # Store the value on the stack
  334. if not self.set_memory(address, value, size):
  335. print "[!] Failed setting memory @ %x" % (address)
  336. return False
  337. return True
  338. #
  339. # get_memory: A public method for fetching arbitrary memory
  340. #
  341. def get_memory(self, address, size=0):
  342. if not size:
  343. size = 4
  344. # Fetch the value
  345. result = self.memory.get_memory(address, size)
  346. return result
  347. #
  348. # get_memory_string: A public method to fetch a string from memory
  349. #
  350. def get_memory_string(self, address):
  351. s = ""
  352. x = 0
  353. while True:
  354. b = self.get_memory(address + x, size=1)
  355. if b != 0x00:
  356. s += chr(b)
  357. else:
  358. break
  359. x += 1
  360. return s
  361. #
  362. # set_memory: A public method for setting arbitrary memory
  363. #
  364. def set_memory(self, address, value, size=0):
  365. # If we are using a string calculate the size
  366. if isinstance(value, str):
  367. if not size:
  368. size = len(value)
  369. else:
  370. value = value[:size]
  371. elif isinstance(value, int) or isinstance(value, long):
  372. if not size:
  373. size = 4
  374. else:
  375. print "[!] I dont know what this type is"
  376. return False
  377. # For right now we lower the fault so the user can set arbitraty memory
  378. self.memory.fault = False
  379. # Set the value into memory via the memory manager
  380. if not self.memory.set_memory(address, value, size):
  381. print "[!] Failed setting memory @ %x" % (address)
  382. return False
  383. self.memory.fault = True
  384. return True
  385. #
  386. # get_selector: A public method for fetching a selector from the LDT
  387. #
  388. def get_selector(self, selector):
  389. return self.os.get_selector(selector)
  390. #
  391. # set_register_handler: A public method for setting a custom register
  392. # handler. This allows trapping register touches
  393. #
  394. def set_register_handler(self, register, handler):
  395. # We only allow names via this method
  396. if not isinstance(register, str):
  397. print "[!] Cant understand register of type %s" % type(register)
  398. return False
  399. # Store the handler
  400. register = register.upper()
  401. self.register_handlers[register] = handler
  402. return True
  403. #
  404. # set_mnemonic_handler: A public method for setting a custom mnemonic
  405. # handler. This allows the user to trap on
  406. # execution of a specified mnemonic
  407. #
  408. def set_mnemonic_handler(self, mnemonic, handler):
  409. # We only allow the string representation of the mnemonic
  410. if not isinstance(mnemonic, str):
  411. print "[!] Cant understand mnemonic of type %s" % type(mnemonic)
  412. return False
  413. # Store the handler
  414. mnemonic = mnemonic.upper()
  415. self.mnemonic_handlers[mnemonic] = handler
  416. return True
  417. #
  418. # set_opcode_handler: A public method for setting a custom handler
  419. # for opcodes. This allows a user to trap on
  420. # the specified opcode.
  421. #
  422. def set_opcode_handler(self, opcode, handler):
  423. # We only allow opcodes by integer
  424. if not isinstance(opcode, int) and not isinstance(opcode, long):
  425. print "[!] Cant understand opcode of type %s" % type(opcode)
  426. return False
  427. # Store the handler
  428. self.opcode_handlers[opcode] = handler
  429. return True
  430. #
  431. # set_pc_handler: A public method for setting a custom handler on
  432. # the instruction pointer. A quasi breakpoint
  433. # returning execution to the user at a specified
  434. # address.
  435. #
  436. def set_pc_handler(self, address, handler):
  437. # We only allow integer addresses
  438. if not isinstance(address, int) and not isinstance(address, long):
  439. print "[!] Cant understand address of type %s" % type(address)
  440. return False
  441. # Store the handler
  442. self.pc_handlers[address] = handler
  443. #
  444. # set_exception_handler: A public method for setting a custom
  445. # handler for any exceptions that may happen
  446. # currently we are only handling GP/DE faults
  447. #
  448. def set_exception_handler(self, exception, handler):
  449. # We only allow string values
  450. if not isinstance(exception, str):
  451. print "[!] Cant understand exception of type %s" % type(exception)
  452. return False
  453. # Store the handler
  454. self.exception_handlers[exception] = handler
  455. #
  456. # set_library_handler: A public method for setting a custom
  457. # handler for any import function that
  458. # gets called
  459. #
  460. def set_library_handler(self, function, handler):
  461. # We only allow string values
  462. if not isinstance(function, str):
  463. print "[!] Cant understand function of type %s" % type(function)
  464. return False
  465. # Store the handler
  466. self.library_handlers[function] = handler
  467. #
  468. # set_interrupt_handler: A public method for setting a custom
  469. # handler for any interrupts that may happen
  470. #
  471. def set_interrupt_handler(self, interrupt, handler):
  472. # We only allow int values
  473. if not isinstance(exception, int) and not isinstance(exception, long):
  474. print "[!] Cant understand interrupt of type %s" % type(interrupt)
  475. return False
  476. # Store the handler
  477. self.interrupt_handlers[interrupt] = handler
  478. #
  479. # set_memory_handler: A public method for setting a custom handler
  480. # for specific memory access. This allows a user
  481. # to receive execution when a specified address
  482. # is accessed.
  483. #
  484. def set_memory_handler(self, address, handler):
  485. # We only allow integer addresses
  486. if not isinstance(address, int) and not isinstance(address, long):
  487. print "[!] Cant understand address of type %s" % type(address)
  488. return False
  489. # Store the handler
  490. self.memory_handlers[address] = handler
  491. #
  492. # set_memory_read_handler: A public memory for setting a custom handler
  493. # for *any* read of memory.
  494. #
  495. def set_memory_read_handler(self, handler):
  496. # Store the handler
  497. self.memory_read_handler = handler
  498. return True
  499. #
  500. # set_memory_write_handler: A public memory for setting a custom handler
  501. # for *any* write of memory.
  502. #
  503. def set_memory_write_handler(self, handler):
  504. # Store the handler
  505. self.memory_write_handler = handler
  506. return True
  507. #
  508. # set_memory_access_handler: A public memory for setting a custom handler
  509. # for *any* read or write of memory.
  510. #
  511. def set_memory_access_handler(self, handler):
  512. # Store the handler
  513. self.memory_access_handler = handler
  514. return True
  515. #
  516. # set_stack_read_handler: A public memory for setting a custom handler
  517. # for *any* stack read.
  518. #
  519. def set_stack_read_handler(self, handler):
  520. # Store the handler
  521. self.stack_read_handler = handler
  522. return True
  523. #
  524. # set_stack_write_handler: A public memory for setting a custom handler
  525. # for *any* stack write.
  526. #
  527. def set_stack_write_handler(self, handler):
  528. # Store the handler
  529. self.stack_write_handler = handler
  530. return True
  531. #
  532. # set_stack_access_handler: A public memory for setting a custom handler
  533. # for *any* stack read or write.
  534. #
  535. def set_stack_access_handler(self, handler):
  536. # Store the handler
  537. self.stack_access_handler = handler
  538. return True
  539. #
  540. # set_heap_read_handler: A public memory for setting a custom handler
  541. # for *any* heap read.
  542. #
  543. def set_heap_read_handler(self, handler):
  544. # Store the handler
  545. self.heap_read_handler = handler
  546. return True
  547. #
  548. # set_heap_write_handler: A public memory for setting a custom handler
  549. # for *any* heap write.
  550. #
  551. def set_heap_write_handler(self, handler):
  552. # Store the handler
  553. self.heap_write_handler = handler
  554. return True
  555. #
  556. # set_heap_access_handler: A public memory for setting a custom handler
  557. # for *any* heap read or write.
  558. #
  559. def set_heap_access_handler(self, handler):
  560. # Store the handler
  561. self.heap_access_handler = handler
  562. return True
  563. #
  564. # dump_regs: A public method to dump the regs from the CPU
  565. #
  566. def dump_regs(self):
  567. self.cpu.dump_regs()
  568. #
  569. # dump_stack: A public method to dump the stack from ESP and EBP
  570. #
  571. def dump_stack(self, count=64):
  572. self.cpu.dump_stack(count)
  573. #
  574. # get_disasm: A public method to get a pretty dump of the current
  575. # instruction disassembly
  576. def get_disasm(self):
  577. return self.cpu.get_disasm()
  578. '''
  579. PyDbgPyEmu:
  580. The ugliest class name ever. Really the PyEmu class for handling
  581. PyDbg operation. It is responsible for talking between the
  582. emulator and the real process. This is what the user would instantiate.
  583. '''
  584. class PyDbgPyEmu(PyEmu):
  585. def __init__(self, dbg):
  586. PyEmu.__init__(self)
  587. # Store the pydbg instance
  588. self.dbg = dbg
  589. # Get the memory manager object
  590. self.memory = PyDbgMemory(self, self.dbg)
  591. # Set our context from the real process
  592. self.setup_context()
  593. def setup_context(self):
  594. pcontext = self.dbg.context
  595. emucontext = PyContext()
  596. emucontext.EAX = pcontext.Eax
  597. emucontext.ECX = pcontext.Ecx
  598. emucontext.EDX = pcontext.Edx
  599. emucontext.EBX = pcontext.Ebx
  600. emucontext.ESP = pcontext.Esp
  601. emucontext.EBP = pcontext.Ebp
  602. emucontext.ESI = pcontext.Esi
  603. emucontext.EDI = pcontext.Edi
  604. emucontext.EIP = pcontext.Eip
  605. emucontext.GS = pcontext.SegGs
  606. emucontext.FS = pcontext.SegFs
  607. emucontext.ES = pcontext.SegEs
  608. emucontext.DS = pcontext.SegDs
  609. emucontext.CS = pcontext.SegCs
  610. emucontext.SS = pcontext.SegSs
  611. emucontext.EFLAGS = pcontext.EFlags
  612. # Set up the context in the emulated CPU
  613. self.cpu.set_context(emucontext)
  614. return True
  615. '''
  616. IDAPyEmu:
  617. The purposed class for emulating in IDA Pro. This has to set up
  618. some basic operating environments for the executable. This is what
  619. the user will be instantiating.
  620. '''
  621. class IDAPyEmu(PyEmu):
  622. def __init__(self, stack_base=0x0095f000, stack_size=0x1000, heap_base=0x000a0000, heap_size=0x2000, frame_pointer=True):
  623. PyEmu.__init__(self)
  624. # Store memory limit information
  625. self.stack_base = stack_base
  626. self.stack_size = stack_size
  627. self.heap_base = heap_base
  628. self.heap_size = heap_size
  629. self.frame_pointer = frame_pointer
  630. # Get a memory manager object for IDA
  631. self.memory = IDAMemory(self)
  632. # Load initial thread information
  633. self.setup_os()
  634. # Set up context information
  635. self.setup_context()
  636. #
  637. # setup_os: Adds a new thread based on which OS you are using
  638. #
  639. def setup_os(self):
  640. self.os.initialize(self, self.stack_base, self.stack_base - self.stack_size, self.heap_base, self.heap_base + self.heap_size)
  641. #
  642. # setup_context: Sets the needed stack pointers so we can execute
  643. # properly
  644. #
  645. def setup_context(self):
  646. # Set the registers to a sane starting address
  647. self.cpu.set_register32("EBP", self.stack_base - self.stack_size / 2)
  648. # So heres the difference in starting at the FP save or after
  649. #self.cpu.set_register32("ESP", self.cpu.get_register32("EBP") - 4)
  650. self.cpu.set_register32("ESP", self.cpu.get_register32("EBP"))
  651. # Set some registers to dumb values
  652. self.cpu.EAX = 0x00000001
  653. self.cpu.ECX = 0x00000002
  654. self.cpu.EBX = 0x00000003
  655. self.cpu.EDX = 0x00000004
  656. self.cpu.ESI = 0x00000005
  657. self.cpu.EDI = 0x00000006
  658. # Set up segment registers
  659. self.cpu.CS = 0x001b
  660. self.cpu.SS = 0x0023
  661. self.cpu.DS = 0x0023
  662. self.cpu.ES = 0x0023
  663. self.cpu.FS = 0x003b
  664. self.cpu.GS = 0x0000
  665. return True
  666. '''
  667. PEPyEmu:
  668. The purposed class for emulating from a raw PE executable. This has
  669. to set up some basic operating environments for the executable.
  670. This is what the user will be instantiating.
  671. '''
  672. class PEPyEmu(PyEmu):
  673. def __init__(self, stack_base=0x0095f000, stack_size=0x1000, heap_base=0x000a0000, heap_size=0x2000, frame_pointer=True):
  674. PyEmu.__init__(self)
  675. # PE Specific information
  676. self.entry_point = None
  677. self.image_base = None
  678. self.code_base = None
  679. self.data_base = None
  680. self.sections = {}
  681. # Store memory limit information
  682. self.stack_base = stack_base
  683. self.stack_size = stack_size
  684. self.heap_base = heap_base
  685. self.heap_size = heap_size
  686. self.frame_pointer = frame_pointer
  687. # Get a memory manager object for the PE file
  688. self.memory = PEMemory(self)
  689. # Load initial thread information
  690. self.setup_os()
  691. # Set up context information
  692. self.setup_context()
  693. #
  694. # setup_os: Adds a new thread based on which OS you are using
  695. #
  696. def setup_os(self):
  697. self.os.initialize(self, self.stack_base, self.stack_base - self.stack_size, self.heap_base, self.heap_base + self.heap_size)
  698. #
  699. # setup_context: Sets the needed stack pointers so we can execute
  700. # properly
  701. #
  702. def setup_context(self):
  703. # Set the registers to a sane starting address
  704. self.cpu.set_register32("EBP", self.stack_base - self.stack_size / 2)
  705. # So heres the difference in starting at the FP save or after
  706. #self.cpu.set_register32("ESP", self.cpu.get_register32("EBP") - 4)
  707. self.cpu.set_register32("ESP", self.cpu.get_register32("EBP"))
  708. self.cpu.EAX = 0x00000001
  709. self.cpu.ECX = 0x00000002
  710. self.cpu.EBX = 0x00000003
  711. self.cpu.EDX = 0x00000004
  712. self.cpu.ESI = 0x00000005
  713. self.cpu.EDI = 0x00000006
  714. # Set up segment registers
  715. self.cpu.CS = 0x001b
  716. self.cpu.SS = 0x0023
  717. self.cpu.DS = 0x0023
  718. self.cpu.ES = 0x0023
  719. self.cpu.FS = 0x003b
  720. self.cpu.GS = 0x0000
  721. return True
  722. #
  723. # load: Loads the sections of a binary into the emulator memory
  724. # if you need more control over the loading do it in your
  725. # script ignoring this method.
  726. #
  727. def load(self, exename):
  728. try:
  729. import pefile
  730. except ImportError:
  731. print "[!] Couldnt import pefile"
  732. return False
  733. # Instantiate our pefile object
  734. pe = pefile.PE(exename)
  735. self.image_base = pe.OPTIONAL_HEADER.ImageBase
  736. self.code_base = pe.OPTIONAL_HEADER.ImageBase + pe.OPTIONAL_HEADER.BaseOfCode
  737. self.data_base = pe.OPTIONAL_HEADER.ImageBase + pe.OPTIONAL_HEADER.BaseOfData
  738. self.entry_point = pe.OPTIONAL_HEADER.ImageBase + pe.OPTIONAL_HEADER.AddressOfEntryPoint
  739. if self.DEBUG > 1:
  740. print "[*] Image Base Addr: 0x%08x" % (self.image_base)
  741. print "[*] Code Base Addr: 0x%08x" % (self.code_base)
  742. print "[*] Data Base Addr: 0x%08x" % (self.data_base)
  743. print "[*] Entry Point Addr: 0x%08x\n" % (self.entry_point)
  744. # I need to load the image header first
  745. headerlen = len(pe.header)
  746. if self.DEBUG > 1:
  747. print "[*] Loading header of size %x at %x" % (headerlen, self.image_base)
  748. for x in range(headerlen):
  749. c = pe.header[x]
  750. self.set_memory(self.image_base + x, int(ord(c)), size=1)
  751. # We loop through the sections in our binary returning a list of info
  752. for section in pe.sections:
  753. if self.DEBUG > 1:
  754. print "[*] Loading [%s] data into memory" % section.Name.strip('\x00')
  755. # Get our section address base
  756. sectionbase = self.image_base + section.VirtualAddress
  757. virtualsize = section.Misc_VirtualSize
  758. sectiondata = section.data
  759. sectiondatalen = len(sectiondata)
  760. if self.DEBUG > 1:
  761. print "[*] Base Addr: 0x%08x (vsize: %08x dsize: %08x)" % (sectionbase, virtualsize, sectiondatalen)
  762. # Grab our data bytes from the section
  763. for x in range(sectiondatalen):
  764. c = section.data[x]
  765. self.set_memory(sectionbase + x, int(ord(c)), size=1)
  766. # if we have a section without data lets fill nulls
  767. for x in range(virtualsize - sectiondatalen):
  768. c = "\x00"
  769. self.set_memory(sectionbase + x + sectiondatalen, c, size=1)
  770. # append our section to the class list so the user can access it
  771. self.sections[section.Name.strip('\x00')] = {"base": sectionbase, "vsize": virtualsize, "dsize": sectiondatalen}
  772. #sys.exit()
  773. # We must load import directory
  774. for entry in pe.DIRECTORY_ENTRY_IMPORT:
  775. if self.DEBUG > 1:
  776. print "[*] Adding import from %s" % entry.dll
  777. for imp in entry.imports:
  778. if self.DEBUG > 1:
  779. print '[*] 0x%08x [%20s]' % (imp.address, imp.name)
  780. self.os.add_library(entry.dll, imp.name)
  781. import_address = self.os.get_library_address(imp.name)
  782. if import_address:
  783. self.set_memory(imp.address, import_address, size=4)
  784. return True