| 582 | |
| 583 | |
| 584 | class CPUID(object): |
| 585 | def __init__(self): |
| 586 | # Figure out if SE Linux is on and in enforcing mode |
| 587 | self.is_selinux_enforcing = False |
| 588 | |
| 589 | # Just return if the SE Linux Status Tool is not installed |
| 590 | if not DataSource.has_sestatus(): |
| 591 | return |
| 592 | |
| 593 | # Figure out if we can execute heap and execute memory |
| 594 | can_selinux_exec_heap = DataSource.sestatus_allow_execheap() |
| 595 | can_selinux_exec_memory = DataSource.sestatus_allow_execmem() |
| 596 | self.is_selinux_enforcing = (not can_selinux_exec_heap or not can_selinux_exec_memory) |
| 597 | |
| 598 | def _asm_func(self, restype=None, argtypes=(), byte_code=[]): |
| 599 | byte_code = bytes.join(b'', byte_code) |
| 600 | address = None |
| 601 | |
| 602 | if DataSource.is_windows: |
| 603 | # Allocate a memory segment the size of the byte code, and make it executable |
| 604 | size = len(byte_code) |
| 605 | MEM_COMMIT = ctypes.c_ulong(0x1000) |
| 606 | PAGE_EXECUTE_READWRITE = ctypes.c_ulong(0x40) |
| 607 | address = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0), ctypes.c_size_t(size), MEM_COMMIT, PAGE_EXECUTE_READWRITE) |
| 608 | if not address: |
| 609 | raise Exception("Failed to VirtualAlloc") |
| 610 | |
| 611 | # Copy the byte code into the memory segment |
| 612 | memmove = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t)(ctypes._memmove_addr) |
| 613 | if memmove(address, byte_code, size) < 0: |
| 614 | raise Exception("Failed to memmove") |
| 615 | else: |
| 616 | # Allocate a memory segment the size of the byte code |
| 617 | size = len(byte_code) |
| 618 | address = ctypes.pythonapi.valloc(size) |
| 619 | if not address: |
| 620 | raise Exception("Failed to valloc") |
| 621 | |
| 622 | # Mark the memory segment as writeable only |
| 623 | if not self.is_selinux_enforcing: |
| 624 | WRITE = 0x2 |
| 625 | if ctypes.pythonapi.mprotect(address, size, WRITE) < 0: |
| 626 | raise Exception("Failed to mprotect") |
| 627 | |
| 628 | # Copy the byte code into the memory segment |
| 629 | if ctypes.pythonapi.memmove(address, byte_code, size) < 0: |
| 630 | raise Exception("Failed to memmove") |
| 631 | |
| 632 | # Mark the memory segment as writeable and executable only |
| 633 | if not self.is_selinux_enforcing: |
| 634 | WRITE_EXECUTE = 0x2 | 0x4 |
| 635 | if ctypes.pythonapi.mprotect(address, size, WRITE_EXECUTE) < 0: |
| 636 | raise Exception("Failed to mprotect") |
| 637 | |
| 638 | # Cast the memory segment into a function |
| 639 | functype = ctypes.CFUNCTYPE(restype, *argtypes) |
| 640 | fun = functype(address) |
| 641 | return fun, address |
no outgoing calls
no test coverage detected
searching dependent graphs…