11import struct
22from collections import namedtuple
33
4- from minidump .minidumpfile import AllocationProtect
54from unicorn import *
65from unicorn .x86_const import *
76
8- def map_unicorn_perms (protect : AllocationProtect ):
7+ from dumpulator .memory import MemoryProtect
8+
9+ def map_unicorn_perms (protect : MemoryProtect ):
910 if isinstance (protect , int ):
10- protect = AllocationProtect (protect )
11+ protect = MemoryProtect (protect )
12+ assert isinstance (protect , MemoryProtect )
1113 mapping = {
12- AllocationProtect .PAGE_EXECUTE : UC_PROT_EXEC | UC_PROT_READ ,
13- AllocationProtect .PAGE_EXECUTE_READ : UC_PROT_EXEC | UC_PROT_READ ,
14- AllocationProtect .PAGE_EXECUTE_READWRITE : UC_PROT_ALL ,
15- AllocationProtect .PAGE_EXECUTE_WRITECOPY : UC_PROT_ALL ,
16- AllocationProtect .PAGE_NOACCESS : UC_PROT_NONE ,
17- AllocationProtect .PAGE_READONLY : UC_PROT_READ ,
18- AllocationProtect .PAGE_READWRITE : UC_PROT_READ | UC_PROT_WRITE ,
19- AllocationProtect .PAGE_WRITECOPY : UC_PROT_READ | UC_PROT_WRITE ,
14+ MemoryProtect .PAGE_EXECUTE : UC_PROT_EXEC | UC_PROT_READ ,
15+ MemoryProtect .PAGE_EXECUTE_READ : UC_PROT_EXEC | UC_PROT_READ ,
16+ MemoryProtect .PAGE_EXECUTE_READWRITE : UC_PROT_ALL ,
17+ MemoryProtect .PAGE_EXECUTE_WRITECOPY : UC_PROT_ALL ,
18+ MemoryProtect .PAGE_NOACCESS : UC_PROT_NONE ,
19+ MemoryProtect .PAGE_READONLY : UC_PROT_READ ,
20+ MemoryProtect .PAGE_READWRITE : UC_PROT_READ | UC_PROT_WRITE ,
21+ MemoryProtect .PAGE_WRITECOPY : UC_PROT_READ | UC_PROT_WRITE ,
2022 }
21- return mapping . get ( protect , UC_PROT_NONE )
23+ return mapping [ protect ]
2224
2325
2426class Registers :
@@ -561,197 +563,3 @@ def __setitem__(self, index, value):
561563 "Reserved"
562564]
563565assert len (interrupt_names ) == 32
564-
565-
566-
567- class MemoryManager ():
568- def __init__ (self , uc : Uc ):
569- self ._memory_map = []
570- self ._uc = uc
571-
572- def mem_protect (self , addr , size , perms ):
573- for memory_region in self ._memory_map : # Query parents
574- if addr in memory_region and addr + size in memory_region : # Verify that the memory you are altering is inside a parent memory chunk
575- perms = map_unicorn_perms (perms )
576- memory_region .children .confliction_check (addr ,size ) # Identify if there are any conflictions
577- new_addr , new_size = memory_region .children .mem_protect_correct (addr , size , perms ) # Using the conflictions, correct the memory layout
578- memory_region .children .add_child (ChildMemoryRegion (new_addr ,new_size ,perms , None , memory_region .start ))
579- self ._uc .mem_protect (addr , size , perms )
580- else :
581- print ("MEMORY_MANAGER | Attempted to change write permissions to memory that isn't mapped..." )
582- return
583-
584- def mem_free (self , addr ): # MAJOR : NEED TO MANAGE FREE'ING PARENT MEMORY AND SHRINKING EFFECTED CHILD MEMORY OR DELETING CHILDREN ENTIRELY
585- for memory_region in self ._memory_map :
586- if memory_region .start == addr :
587- self ._memory_map .remove (memory_region ) # NEED TO ADD SELF._UC.MEM_UNMAP(ADDRESS,SIZE) ASSERT SIZE >= 0x1000
588- return
589- return
590-
591- def mem_allocate (self , addr :int , size :int , perms :int = UC_PROT_ALL , comment = None ): # WORKS
592- assert size >= 0x1000
593- if self .check_memory_avail (addr , size ) == True :
594- self ._memory_map .append (ParentMemoryRegion (addr ,size ,perms ,comment ))
595- self ._uc .mem_map (addr , size , perms )
596- return
597- else :
598- print ("MEMORY_MANAGER | There was an attempt to illegally overmap memory from" , addr , "to" , addr + size )
599- return
600-
601- def mem_find (self , addr ): # WORKS
602- for memory_region in self ._memory_map :
603- if addr in memory_region :
604- return memory_region
605- self .mem_error ("MEMORY_MANAGER | Unable to find parent memory for given address..." )
606- return 0
607-
608- def check_memory_avail (self , addr , size ):
609- for memory_region in self ._memory_map :
610- if memory_region .query_parent (addr , size ) == False :
611- return True
612- else :
613- return False
614- return True
615-
616- def write (self , addr , data ):
617- self ._uc .mem_write (addr , data )
618-
619- def read (self , addr , size ):
620- return self ._uc .mem_read (addr , size )
621-
622- def readable_contents (self ):
623- if len (self ._memory_map ):
624- for mem_region in self ._memory_map :
625- print ("MEMORY_MANAGER | There is a parent block which starts at" , mem_region .start , "and ends at" , mem_region .end )
626- else :
627- print ("MEMORY_MANAGER | There is no memory allocated..." )
628-
629- class MemoryRegionChildL :
630- def __init__ (self ):
631- self ._child_mem_list = []
632- self ._conflicting_regions = []
633-
634- def sort (self ):
635- length = len (self ._child_mem_list )
636- for i in range (length - 1 ):
637- for j in range (0 , length - i - 1 ):
638- if self ._child_mem_list [j ] > self ._child_mem_list [j + 1 ]:
639- swapped = True
640- self ._child_mem_list [j ], self ._child_mem_list [j + 1 ] = self ._child_mem_list [j + 1 ], self ._child_mem_list [j ]
641- if not swapped :
642- return
643-
644- def confliction_check (self , addr , size ): # Updates the conflicting memory regions list
645- self ._conflicting_regions = []
646- assert len (self ._conflicting_regions ) == 0 # Make sure that confliction regions is cleared
647- for gen_address in range (addr , addr + size , 0x100 ):
648- for child_mem in self ._child_mem_list :
649- if gen_address in child_mem :
650- self ._conflicting_regions .append (child_mem )
651- return
652-
653- def mem_protect_correct (self , addr , size , perms ):
654- new_addr = addr
655- new_size = size
656- for mem_region in self ._conflicting_regions : #Clear the area for the new write permissions
657- if new_addr not in mem_region and new_addr + new_size not in mem_region : # No need to correct to split this area, it will be overwritten anyway.
658- self .remove_child (mem_region )
659- elif new_addr in mem_region and new_addr + new_size not in mem_region and mem_region .perms != perms : # The start of the region is in the mem_region, but not the end.
660- mod_region = self .find_child (mem_region )
661- mod_region .end = new_addr
662- mod_region .size = mem_region .end - mem_region .start
663- elif new_addr not in mem_region and new_addr + new_size in mem_region and mem_region .perms != perms :
664- mod_region = self .find_child (mem_region )
665- mod_region .start = new_addr + new_size
666- mod_region .size = mem_region .end - mem_region .start
667- elif new_addr in mem_region and new_addr + new_size in mem_region and mem_region .perms != perms :
668- new_region = ChildMemoryRegion (addr + size , mem_region .end - addr + size , mem_region .perms , mem_region .comment , mem_region .start )
669- mod_region = self .find_child (mem_region )
670- mod_region .end = new_addr
671- mod_region .size = mem_region .end - mem_region .start
672- self ._child_mem_list .append (new_region )
673- elif new_addr in mem_region and new_addr + new_size in mem_region and mem_region .perms == perms :
674- return False # The attempted write permissions is within a single child memory block, with the same permissions, its safe to fail the change protection.
675- elif new_addr in mem_region and new_addr + new_size not in mem_region and mem_region .perms == perms :
676- new_addr = mem_region .start
677- new_size += addr - mem_region .start
678- self .remove_child (mem_region )
679- elif new_addr not in mem_region and new_addr + new_size in mem_region and mem_region .perms == perms :
680- new_size += mem_region .end - new_addr + new_size
681- self .remove_child (mem_region )
682- else :
683- print ("MEMORY_REGION_CHILD | Unhandled logic in mem_protect_correct" )
684- return False
685- return new_addr , new_size
686-
687- def add_child (self , memory_region ):
688- self ._child_mem_list .append (memory_region )
689- return
690-
691- def find_child (self , mem_region ):
692- for i , mem in enumerate (self ._child_mem_list ):
693- if mem_region .start == mem .start :
694- return self ._child_mem_list [i ]
695-
696- def remove_child (self , mem_region ):
697- for i , mem in enumerate (self ._child_mem_list ):
698- if mem_region .start == mem .start :
699- del self ._child_mem_list [i ]
700- break
701-
702- def print_contents (self ):
703- for i in self ._child_mem_list :
704- print ("A child memory block starts at" , i .start , "ends at" , i .start + i .size , "with permissions of" , i .perms , "and a comment of" , i .comment )
705-
706- class ChildMemoryRegion :
707- def __init__ (self , start_addr , size , perms , comment = None , alloc_base = None ):
708- self .region = comment
709- self .start = start_addr
710- self .end = self .start + size
711- self .alloc_base = alloc_base
712- self .size = size
713- self .perms = perms
714- self .comment = comment
715-
716- def __gt__ (self , other ):
717- if self .start > other .start :
718- return True
719- return False
720-
721- def __contains__ (self , addr ):
722- if self .start <= addr and addr <= self .end :
723- # print(self.start, "<=",addr, " & ",addr, "<=", self.end)
724- return True
725- else :
726- return False
727-
728- class ParentMemoryRegion :
729- def __init__ (self , start_addr , size , perms , comment = None , alloc_base = None ):
730- self .region = comment
731- self .start = start_addr
732- self .end = self .start + size
733- self .alloc_base = alloc_base
734- self .size = size
735- self .perms = perms
736- self .comment = comment
737- self .children = MemoryRegionChildL ()
738-
739- @property
740- def is_parent (self ):
741- return self .alloc_base is None
742-
743- def __contains__ (self , addr ):
744- if self .start <= addr and addr <= self .end :
745- return True
746- else :
747- return False
748-
749- def query_parent (self , addr , size ):
750- for gen_address in range (addr , addr + size , 0x100 ): # Could change the range step
751- if gen_address in self :
752- return True
753- return False
754-
755- def print_contents (self ):
756- print ("MEMORY_REGION | This block starts at" , self .start , "ends at" , self .end , "with permissions of" , self .perms ,)
757- return
0 commit comments