1
1
import struct
2
2
from collections import namedtuple
3
3
4
- from minidump .minidumpfile import AllocationProtect
5
4
from unicorn import *
6
5
from unicorn .x86_const import *
7
6
8
- def map_unicorn_perms (protect : AllocationProtect ):
7
+ from dumpulator .memory import MemoryProtect
8
+
9
+ def map_unicorn_perms (protect : MemoryProtect ):
9
10
if isinstance (protect , int ):
10
- protect = AllocationProtect (protect )
11
+ protect = MemoryProtect (protect )
12
+ assert isinstance (protect , MemoryProtect )
11
13
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 ,
20
22
}
21
- return mapping . get ( protect , UC_PROT_NONE )
23
+ return mapping [ protect ]
22
24
23
25
24
26
class Registers :
@@ -561,197 +563,3 @@ def __setitem__(self, index, value):
561
563
"Reserved"
562
564
]
563
565
assert 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