• Kali下使用libheap


    Kali下使用libheap

        在github上,可以libheap用来帮助调试堆溢出。链接见:https://github.com/cloudburst/libheap 但是最后一次更新在一年前了,我直接拿着在Kali 2.0上使用时,会出错,比如:

        我就对其进行了修改,保证可以在Kali 2.0下完美使用,32位和64位都可以使用。我的系统版本:

        以后碰见其它Linux发行版,都可以对其修改。在不同的发行版之间,在malloc_state和malloc_par结构体中,稍微有些区别,只需要下载相应的glibc源码,根据源码对libheap进行修改就可以了。在Kali 64位下,int是4字节,long是8字节,size_t是8字节。修改后的libheap见:

       1 from __future__ import print_function
       2 #modify by wah for kali 2.0
       3 try:
       4     import gdb
       5 except ImportError:
       6     print("Not running inside of GDB, exiting...")
       7     exit()
       8 
       9 import sys
      10 import struct
      11 from os import uname
      12 
      13 # bash color support
      14 color_support = True
      15 if color_support:
      16     c_red      = "33[31m"
      17     c_red_b    = "33[01;31m"
      18     c_green    = "33[32m"
      19     c_green_b  = "33[01;32m"
      20     c_yellow   = "33[33m"
      21     c_yellow_b = "33[01;33m"
      22     c_blue     = "33[34m"
      23     c_blue_b   = "33[01;34m"
      24     c_purple   = "33[35m"
      25     c_purple_b = "33[01;35m"
      26     c_teal     = "33[36m"
      27     c_teal_b   = "33[01;36m"
      28     c_none     = "33[0m"
      29 else:
      30     c_red      = ""
      31     c_red_b    = ""
      32     c_green    = ""
      33     c_green_b  = ""
      34     c_yellow   = ""
      35     c_yellow_b = ""
      36     c_blue     = ""
      37     c_blue_b   = ""
      38     c_purple   = ""
      39     c_purple_b = ""
      40     c_teal     = ""
      41     c_teal_b   = ""
      42     c_none     = ""
      43 c_error  = c_red
      44 c_title  = c_green_b
      45 c_header = c_yellow_b
      46 c_value  = c_blue_b
      47 
      48 ################################################################################
      49 # MALLOC CONSTANTS AND MACROS
      50 ################################################################################
      51 
      52 _machine = uname()[4]
      53 if _machine == "x86_64":
      54     SIZE_SZ = 8
      55 elif _machine in ("i386", "i686"):
      56     SIZE_SZ = 4
      57 
      58 MIN_CHUNK_SIZE    = 4 * SIZE_SZ
      59 MALLOC_ALIGNMENT  = 2 * SIZE_SZ
      60 MALLOC_ALIGN_MASK = MALLOC_ALIGNMENT - 1
      61 MINSIZE           = (MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK
      62 
      63 def chunk2mem(p):
      64     "conversion from malloc header to user pointer"
      65     return (p.address + (2*SIZE_SZ))
      66 
      67 def mem2chunk(mem):
      68     "conversion from user pointer to malloc header"
      69     return (mem - (2*SIZE_SZ))
      70 
      71 def request2size(req):
      72     "pad request bytes into a usable size"
      73 
      74     if (req + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE):
      75         return MINSIZE
      76     else:
      77         return (int(req + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)
      78 
      79 PREV_INUSE     = 1
      80 IS_MMAPPED     = 2
      81 NON_MAIN_ARENA = 4
      82 SIZE_BITS      = (PREV_INUSE|IS_MMAPPED|NON_MAIN_ARENA)
      83 
      84 def prev_inuse(p):
      85     "extract inuse bit of previous chunk"
      86     return (p.size & PREV_INUSE)
      87 
      88 def chunk_is_mmapped(p):
      89     "check for mmap()'ed chunk"
      90     return (p.size & IS_MMAPPED)
      91 
      92 def chunk_non_main_arena(p):
      93     "check for chunk from non-main arena"
      94     return (p.size & NON_MAIN_ARENA)
      95 
      96 def chunksize(p):
      97     "Get size, ignoring use bits"
      98     return (p.size & ~SIZE_BITS)
      99 
     100 def next_chunk(p):
     101     "Ptr to next physical malloc_chunk."
     102     return (p.address + (p.size & ~SIZE_BITS))
     103 
     104 def prev_chunk(p):
     105     "Ptr to previous physical malloc_chunk"
     106     return (p.address - p.prev_size)
     107 
     108 def chunk_at_offset(p, s):
     109     "Treat space at ptr + offset as a chunk"
     110     return malloc_chunk(p.address + s, inuse=False)
     111 
     112 def inuse(p):
     113     "extract p's inuse bit"
     114     return (malloc_chunk(p.address + 
     115             (p.size & ~SIZE_BITS), inuse=False).size & PREV_INUSE)
     116 
     117 def set_inuse(p):
     118     "set chunk as being inuse without otherwise disturbing"
     119     chunk = malloc_chunk((p.address + (p.size & ~SIZE_BITS)), inuse=False)
     120     chunk.size |= PREV_INUSE
     121     chunk.write()
     122 
     123 def clear_inuse(p):
     124     "clear chunk as being inuse without otherwise disturbing"
     125     chunk = malloc_chunk((p.address + (p.size & ~SIZE_BITS)), inuse=False)
     126     chunk.size &= ~PREV_INUSE
     127     chunk.write()
     128 
     129 def inuse_bit_at_offset(p, s):
     130     "check inuse bits in known places"
     131     return (malloc_chunk((p.address + s), inuse=False).size & PREV_INUSE)
     132 
     133 def set_inuse_bit_at_offset(p, s):
     134     "set inuse bits in known places"
     135     chunk = malloc_chunk((p.address + s), inuse=False)
     136     chunk.size |= PREV_INUSE
     137     chunk.write()
     138 
     139 def clear_inuse_bit_at_offset(p, s):
     140     "clear inuse bits in known places"
     141     chunk = malloc_chunk((p.address + s), inuse=False)
     142     chunk.size &= ~PREV_INUSE
     143     chunk.write()
     144 
     145 def bin_at(m, i):
     146     "addressing -- note that bin_at(0) does not exist"
     147     if SIZE_SZ == 4:
     148         offsetof_fd = 0x8
     149         return (gdb.parse_and_eval("&main_arena.bins[%d]" % 
     150             ((i -1) * 2)).cast(gdb.lookup_type('unsigned int')) - offsetof_fd)
     151     elif SIZE_SZ == 8:
     152         offsetof_fd = 0x10
     153         return (gdb.parse_and_eval("&main_arena.bins[%d]" % 
     154             ((i -1) * 2)).cast(gdb.lookup_type('unsigned long')) - offsetof_fd)
     155 
     156 def next_bin(b):
     157     return (b + 1)
     158 
     159 def first(b):
     160     return b.fd
     161 
     162 def last(b):
     163     return b.bk
     164 
     165 NBINS          = 128
     166 NSMALLBINS     = 64
     167 SMALLBIN_WIDTH = MALLOC_ALIGNMENT
     168 MIN_LARGE_SIZE = (NSMALLBINS * SMALLBIN_WIDTH)
     169 
     170 def in_smallbin_range(sz):
     171     "check if size is in smallbin range"
     172     return (sz < MIN_LARGE_SIZE)
     173 
     174 def smallbin_index(sz):
     175     "return the smallbin index"
     176 
     177     if SMALLBIN_WIDTH == 16:
     178         return (sz >> 4)
     179     else:
     180         return (sz >> 3)
     181 
     182 def largebin_index_32(sz):
     183     "return the 32bit largebin index"
     184 
     185     if (sz >> 6) <= 38:
     186         return (56 + (sz >> 6))
     187     elif (sz >> 9) <= 20:
     188         return (91 + (sz >> 9))
     189     elif (sz >> 12) <= 10:
     190         return (110 + (sz >> 12))
     191     elif (sz >> 15) <= 4:
     192         return (119 + (sz >> 15))
     193     elif (sz >> 18) <= 2:
     194         return (124 + (sz >> 18))
     195     else:
     196         return 126
     197 
     198 def largebin_index_64(sz):
     199     "return the 64bit largebin index"
     200 
     201     if (sz >> 6) <= 48:
     202         return (48 + (sz >> 6))
     203     elif (sz >> 9) <= 20:
     204         return (91 + (sz >> 9))
     205     elif (sz >> 12) <= 10:
     206         return (110 + (sz >> 12))
     207     elif (sz >> 15) <= 4:
     208         return (119 + (sz >> 15))
     209     elif (sz >> 18) <= 2:
     210         return (124 + (sz >> 18))
     211     else:
     212         return 126
     213 
     214 def largebin_index(sz):
     215     "return the largebin index"
     216 
     217     if SIZE_SZ == 8:
     218         return largebin_index_64(sz)
     219     else:
     220         return largebin_index_32(sz)
     221 
     222 def bin_index(sz):
     223     "return the bin index"
     224 
     225     if in_smallbin_range(sz):
     226         return smallbin_index(sz)
     227     else:
     228         return largebin_index(sz)
     229 
     230 BINMAPSHIFT = 5
     231 BITSPERMAP  = 1 << BINMAPSHIFT
     232 BINMAPSIZE  = (NBINS / BITSPERMAP)
     233 
     234 def fastbin(ar_ptr, idx):
     235     return ar_ptr.fastbinsY[idx]
     236 
     237 def fastbin_index(sz):
     238     "offset 2 to use otherwise unindexable first 2 bins"
     239     if SIZE_SZ == 8:
     240         return ((sz >> 4) - 2)
     241     else:
     242         return ((sz >> 3) - 2)
     243 
     244 MAX_FAST_SIZE = (80 * SIZE_SZ / 4)
     245 NFASTBINS     = (fastbin_index(request2size(MAX_FAST_SIZE)) + 1)
     246 
     247 FASTCHUNKS_BIT = 0x1
     248 
     249 def have_fastchunks(M):
     250     return ((M.flags & FASTCHUNKS_BIT) == 0)
     251 
     252 def clear_fastchunks(M, inferior=None):
     253     if inferior == None:
     254         inferior = get_inferior()
     255 
     256     M.flags |= FASTCHUNKS_BIT
     257     inferior.write_memory(M.address, struct.pack("<I", M.flags))
     258 
     259 def set_fastchunks(M, inferior=None):
     260     if inferior == None:
     261         inferior = get_inferior()
     262 
     263     M.flags &= ~FASTCHUNKS_BIT
     264     inferior.write_memory(M.address, struct.pack("<I", M.flags))
     265 
     266 NONCONTIGUOUS_BIT = 0x2
     267 
     268 def contiguous(M):
     269     return ((M.flags & NONCONTIGUOUS_BIT) == 0)
     270 
     271 def noncontiguous(M):
     272     return ((M.flags & NONCONTIGUOUS_BIT) != 0)
     273 
     274 def set_noncontiguous(M, inferior=None):
     275     if inferior == None:
     276         inferior = get_inferior()
     277 
     278     M.flags |= NONCONTIGUOUS_BIT
     279     inferior.write_memory(M.address, struct.pack("<I", M.flags))
     280 
     281 def set_contiguous(M, inferior=None):
     282     if inferior == None:
     283         inferior = get_inferior()
     284 
     285     M.flags &= ~NONCONTIGUOUS_BIT
     286     inferior.write_memory(M.address, struct.pack("<I", M.flags))
     287 
     288 def get_max_fast():
     289     return gdb.parse_and_eval("global_max_fast")
     290 
     291 def mutex_lock(ar_ptr, inferior=None):
     292     if inferior == None:
     293         inferior = get_inferior()
     294 
     295     ar_ptr.mutex = 1
     296     inferior.write_memory(ar_ptr.address, struct.pack("<I", ar_ptr.mutex))
     297 
     298 def mutex_unlock(ar_ptr, inferior=None):
     299     if inferior == None:
     300         inferior = get_inferior()
     301 
     302     ar_ptr.mutex = 0
     303     inferior.write_memory(ar_ptr.address, struct.pack("<I", ar_ptr.mutex))
     304 
     305 def get_inferior():
     306     try:
     307         if len(gdb.inferiors()) == 0:
     308             print(c_error + "No gdb inferior could be found." + c_none)
     309             return -1
     310         else:
     311             inferior = gdb.inferiors()[0]
     312             return inferior
     313     except AttributeError:
     314         print(c_error + "This gdb's python support is too old." + c_none)
     315         exit()
     316 
     317 
     318 ################################################################################
     319 class malloc_chunk:
     320     "python representation of a struct malloc_chunk"
     321 
     322     def __init__(self,addr=None,mem=None,size=None,inferior=None,inuse=False,read_data=True):
     323         self.prev_size   = 0
     324         self.size        = 0
     325         self.data        = None
     326         self.fd          = None
     327         self.bk          = None
     328         self.fd_nextsize = None
     329         self.bk_nextsize = None
     330 
     331         if addr == None or addr == 0:
     332             if mem == None:
     333                 sys.stdout.write(c_error)
     334                 print("Please specify a valid struct malloc_chunk address.", end=' ')
     335                 sys.stdout.write(c_none)
     336                 return None
     337 
     338             self.address = None
     339         else:
     340             self.address = addr
     341 
     342         if inferior == None and mem == None:
     343             inferior = get_inferior()
     344             if inferior == -1:
     345                 return None
     346 
     347         if mem == None:
     348             # a string of raw memory was not provided
     349             try:
     350                 if SIZE_SZ == 4:
     351                     mem = inferior.read_memory(addr, 0x8)
     352                 elif SIZE_SZ == 8:
     353                     mem = inferior.read_memory(addr, 0x10)
     354             except TypeError:
     355                 print(c_error + "Invalid address specified." + c_none)
     356                 return None
     357             except RuntimeError:
     358                 print(c_error + "Could not read address 0x%x" % addr + c_none)
     359                 return None
     360         else:
     361             # a string of raw memory was provided
     362             if inuse:
     363                 if (len(mem)!=0x8) and (len(mem)<0x10):
     364                     sys.stdout.write(c_error)
     365                     print("Insufficient memory provided for a malloc_chunk.", end=' ')
     366                     sys.stdout.write(c_none)
     367                     return None
     368                 if len(mem)==0x8 or len(mem)==0x10:
     369                     #header only provided
     370                     read_data = False
     371             else:
     372                 if (len(mem)!=0x18) and (len(mem)<0x30):
     373                     sys.stdout.write(c_error)
     374                     print("Insufficient memory provided for a free chunk.", end=' ')
     375                     sys.stdout.write(c_none)
     376                     return None
     377 
     378         if SIZE_SZ == 4:
     379             (self.prev_size,
     380             self.size) = struct.unpack_from("<II", mem, 0x0)
     381         elif SIZE_SZ == 8:
     382             (self.prev_size,
     383             self.size) = struct.unpack_from("<QQ", mem, 0x0)
     384 
     385         if size == None:
     386             real_size = (self.size & ~SIZE_BITS)
     387         else:
     388             #a size was provided (for a malformed chunk with an invalid size)
     389             real_size = size & ~SIZE_BITS
     390 
     391         if inuse:
     392             if read_data:
     393                 if self.address != None:
     394                     # a string of raw memory was not provided
     395                     try:
     396                         mem = inferior.read_memory(addr, real_size + SIZE_SZ)
     397                     except TypeError:
     398                         print(c_error + "Invalid address specified." + c_none)
     399                         return None
     400                     except RuntimeError:
     401                         print(c_error + "Could not read address 0x%x" % addr 
     402                                 + c_none)
     403                         return None
     404 
     405                 real_size = (real_size - SIZE_SZ) / SIZE_SZ
     406                 if SIZE_SZ == 4:
     407                     self.data = struct.unpack_from("<%dI" % real_size, mem, 0x8)
     408                 elif SIZE_SZ == 8:
     409                     self.data = struct.unpack_from("<%dQ" %real_size, mem, 0x10)
     410 
     411         if not inuse:
     412             if self.address != None:
     413                 # a string of raw memory was not provided
     414                 if inferior != None:
     415                     if SIZE_SZ == 4:
     416                         mem = inferior.read_memory(addr, 0x18)
     417                     elif SIZE_SZ == 8:
     418                         mem = inferior.read_memory(addr, 0x30)
     419 
     420             if SIZE_SZ == 4:
     421                 (self.fd,         
     422                 self.bk,          
     423                 self.fd_nextsize, 
     424                 self.bk_nextsize) = struct.unpack_from("<IIII", mem, 0x8)
     425             elif SIZE_SZ == 8:
     426                 (self.fd,         
     427                 self.bk,          
     428                 self.fd_nextsize, 
     429                 self.bk_nextsize) = struct.unpack_from("<QQQQ", mem, 0x10)
     430 
     431     def write(self, inferior=None):
     432         if self.fd == None and self.bk == None:
     433             inuse = True
     434         else:
     435             inuse = False
     436 
     437         if inferior == None:
     438             inferior = get_inferior()
     439             if inferior == -1:
     440                 return None
     441 
     442         if inuse:
     443             if SIZE_SZ == 4:
     444                 mem = struct.pack("<II", self.prev_size, self.size)
     445                 if self.data != None:
     446                     mem += struct.pack("<%dI" % len(self.data), *self.data)
     447             elif SIZE_SZ == 8:
     448                 mem = struct.pack("<QQ", self.prev_size, self.size)
     449                 if self.data != None:
     450                     mem += struct.pack("<%dQ" % len(self.data), *self.data)
     451         else:
     452             if SIZE_SZ == 4:
     453                 mem = struct.pack("<IIIIII", self.prev_size, self.size, 
     454                         self.fd, self.bk, self.fd_nextsize, self.bk_nextsize)
     455             elif SIZE_SZ == 8:
     456                 mem = struct.pack("<QQQQQQ", self.prev_size, self.size, 
     457                         self.fd, self.bk, self.fd_nextsize, self.bk_nextsize)
     458 
     459         inferior.write_memory(self.address, mem)
     460 
     461     def __str__(self):
     462         if self.prev_size == 0 and self.size == 0:
     463             return ""
     464         elif self.fd == None and self.bk == None:
     465             ret =  "%s%s%x%s%x%s" %                               
     466                     (c_title + "struct malloc_chunk {",           
     467                     c_none + "
    prev_size   = " + c_value + "0x", 
     468                     self.prev_size,                               
     469                     c_none + "
    size        = " + c_value + "0x", 
     470                     self.size, c_none)
     471 
     472             if self.data != None:
     473                 if SIZE_SZ == 4:
     474                     ret += "%s%s%r" %                                       
     475                             ("
    data        = " + c_value + str(self.data), 
     476                             c_none + "
    raw         = " + c_value,          
     477                             struct.pack("<%dI"%len(self.data), *self.data))
     478                 elif SIZE_SZ == 8:
     479                     ret += "%s%s%r" %                                       
     480                             ("
    data        = " + c_value + str(self.data), 
     481                             c_none + "
    raw         = " + c_value,          
     482                             struct.pack("<%dQ"%len(self.data), *self.data))
     483                 ret += c_none
     484 
     485             return ret
     486         else:
     487             return "%s%s%x%s%x%s%lx%s%lx%s%lx%s%lx%s" %           
     488                     (c_title + "struct malloc_chunk {",           
     489                     c_none + "
    prev_size   = " + c_value + "0x", 
     490                     self.prev_size,                               
     491                     c_none + "
    size        = " + c_value + "0x", 
     492                     self.size,                                    
     493                     c_none + "
    fd          = " + c_value + "0x", 
     494                     self.fd,                                      
     495                     c_none + "
    bk          = " + c_value + "0x", 
     496                     self.bk,                                      
     497                     c_none + "
    fd_nextsize = " + c_value + "0x", 
     498                     self.fd_nextsize,                             
     499                     c_none + "
    bk_nextsize = " + c_value + "0x", 
     500                     self.bk_nextsize, c_none)
     501 
     502 ################################################################################
     503 class malloc_state:
     504     "python representation of a struct malloc_state"
     505 
     506     def __init__(self, addr=None, mem=None, inferior=None):
     507         self.mutex          = 0
     508         self.flags          = 0
     509         self.fastbinsY      = 0
     510         self.top            = 0
     511         self.last_remainder = 0
     512         self.bins           = 0
     513         self.binmap         = 0
     514         self.next           = 0
     515     self.next_free      = 0
     516         self.system_mem     = 0
     517         self.max_system_mem = 0
     518 
     519         if addr == None:
     520             if mem == None:
     521                 sys.stdout.write(c_error)
     522                 print("Please specify a struct malloc_state address.")
     523                 sys.stdout.write(c_none)
     524                 return None
     525 
     526             self.address = None
     527         else:
     528             self.address = addr
     529 
     530         if inferior == None and mem == None:
     531             inferior = get_inferior()
     532             if inferior == -1:
     533                 return None
     534 
     535         if mem == None:
     536             # a string of raw memory was not provided
     537             try:
     538                 if SIZE_SZ == 4:
     539                     mem = inferior.read_memory(addr, 0x450)
     540                 elif SIZE_SZ == 8:
     541                     mem = inferior.read_memory(addr, 0x888)
     542             except TypeError:
     543                 print(c_error + "Invalid address specified." + c_none)
     544                 return None
     545             except RuntimeError:
     546                 print(c_error + "Could not read address 0x%x" % addr + c_none)
     547                 return None
     548 
     549         if SIZE_SZ == 4:
     550             (self.mutex,         
     551             self.flags)          = struct.unpack_from("<II", mem, 0x0)
     552             self.fastbinsY       = struct.unpack_from("<10I", mem, 0x8)
     553             (self.top,           
     554             self.last_remainder) = struct.unpack_from("<II", mem, 0x30)
     555 
     556             self.bins            = struct.unpack_from("<254I", mem, 0x38)
     557             self.binmap          = struct.unpack_from("<IIII", mem, 0x430)
     558             (self.next,          
     559         self.next_free,      
     560             self.system_mem,     
     561             self.max_system_mem) = struct.unpack_from("<IIII", mem, 0x440)
     562         elif SIZE_SZ == 8:
     563             (self.mutex,         
     564             self.flags)          = struct.unpack_from("<II", mem, 0x0)
     565             self.fastbinsY       = struct.unpack_from("<10Q", mem, 0x8)
     566             (self.top,           
     567             self.last_remainder) = struct.unpack_from("<QQ", mem, 0x58)
     568             self.bins            = struct.unpack_from("<254Q", mem, 0x68)
     569             self.binmap          = struct.unpack_from("<IIII", mem, 0x858)
     570             (self.next,          
     571         self.next_free,      
     572             self.system_mem,     
     573             self.max_system_mem) = struct.unpack_from("<QQQQ", mem, 0x868)
     574 
     575     def write(self, inferior=None):
     576         if inferior == None:
     577             inferior = get_inferior()
     578             if inferior == -1:
     579                 return None
     580 
     581         if SIZE_SZ == 4:
     582             mem = struct.pack("<275I", self.mutex, self.flags, self.fastbinsY, 
     583                     self.top, self.last_remainder, self.bins, self.binmap, 
     584                     self.next, self.system_mem, self.max_system_mem)
     585         elif SIZE_SZ == 8:
     586             mem = struct.pack("<II266QIIIIQQQ", self.mutex, self.flags, 
     587                     self.fastbinsY, self.top, self.last_remainder, self.bins, 
     588                     self.binmap, self.next, self.system_mem, 
     589                     self.max_system_mem)
     590 
     591         inferior.write_memory(self.address, mem)
     592 
     593     def __str__(self):
     594         return "%s%s%x%s%x%s%s%lx%s%lx%s%s%s%lx%s%lx%s%lx%s" %      
     595                 (c_title + "struct malloc_state {",                 
     596                 c_none + "
    mutex          = " + c_value + "0x",    
     597                 self.mutex,                                         
     598                 c_none + "
    flags          = " + c_value + "0x",    
     599                 self.flags,                                         
     600                 c_none + "
    fastbinsY      = " + c_value + "{...}", 
     601                 c_none + "
    top            = " + c_value + "0x",    
     602                 self.top,                                           
     603                 c_none + "
    last_remainder = " + c_value + "0x",    
     604                 self.last_remainder,                                
     605                 c_none + "
    bins           = " + c_value + "{...}", 
     606                 c_none + "
    binmap         = " + c_value + "{...}", 
     607                 c_none + "
    next           = " + c_value + "0x",    
     608                 self.next,                                          
     609                 c_none + "
    system_mem     = " + c_value + "0x",    
     610                 self.system_mem,                                    
     611                 c_none + "
    max_system_mem = " + c_value + "0x",    
     612                 self.max_system_mem, c_none)
     613 
     614 
     615 ################################################################################
     616 class malloc_par:
     617     "python representation of a struct malloc_par"
     618 
     619     def __init__(self, addr=None, mem=None, inferior=None):
     620         self.trim_threshold   = 0
     621         self.top_pad          = 0
     622         self.mmap_threshold   = 0
     623     self.arena_test       = 0
     624     self.arena_max        = 0
     625         self.n_mmaps          = 0
     626         self.n_mmaps_max      = 0
     627         self.max_n_mmaps      = 0
     628         self.no_dyn_threshold = 0
     629         self.mmapped_mem      = 0
     630         self.max_mmapped_mem  = 0
     631         self.max_total_mem    = 0
     632         self.sbrk_base        = 0
     633 
     634         if addr == None:
     635             if mem == None:
     636                 sys.stdout.write(c_error)
     637                 print("Please specify a struct malloc_par address.")
     638                 sys.stdout.write(c_none)
     639                 return None
     640 
     641             self.address = None
     642         else:
     643             self.address = addr
     644 
     645         if inferior == None and mem == None:
     646             inferior = get_inferior()
     647             if inferior == -1:
     648                 return None
     649 
     650         if mem == None:
     651             # a string of raw memory was not provided
     652             try:
     653                 if SIZE_SZ == 4:
     654                     mem = inferior.read_memory(addr, 0x34)
     655                 elif SIZE_SZ == 8:
     656                     mem = inferior.read_memory(addr, 0x58)
     657             except TypeError:
     658                 print(c_error + "Invalid address specified." + c_none)
     659                 return None
     660             except RuntimeError:
     661                 print(c_error + "Could not read address 0x%x" % addr + c_none)
     662                 return None
     663 
     664         if SIZE_SZ == 4:
     665             (self.trim_threshold, 
     666             self.top_pad,         
     667             self.mmap_threshold,  
     668         self.arena_test,      
     669         self.arena_max,       
     670             self.n_mmaps,         
     671             self.n_mmaps_max,     
     672             self.max_n_mmaps,     
     673             self.no_dyn_threshold,
     674             self.mmapped_mem,     
     675             self.max_mmapped_mem, 
     676             self.max_total_mem,   
     677             self.sbrk_base)       = struct.unpack("<13I", mem)
     678         elif SIZE_SZ == 8:
     679             (self.trim_threshold, 
     680             self.top_pad,         
     681             self.mmap_threshold,  
     682         self.arena_test,      
     683         self.arena_max,       
     684             self.n_mmaps,         
     685             self.n_mmaps_max,     
     686             self.max_n_mmaps,     
     687             self.no_dyn_threshold,
     688             self.mmapped_mem,     
     689             self.max_mmapped_mem, 
     690             self.max_total_mem,   
     691             self.sbrk_base)       = struct.unpack("<5Q4I4Q", mem)
     692 
     693     def __str__(self):
     694         return "%s%s%lx%s%lx%s%lx%s%x%s%x%s%x%s%x%s%lx%s%lx%s%lx%s%lx%s" % 
     695                 (c_title + "struct malloc_par {",                  
     696                 c_none + "
    trim_threshold   = " + c_value + "0x", 
     697                 self.trim_threshold,                               
     698                 c_none + "
    top_pad          = " + c_value + "0x", 
     699                 self.top_pad,                                      
     700                 c_none + "
    mmap_threshold   = " + c_value + "0x", 
     701                 self.mmap_threshold,                               
     702                 c_none + "
    n_mmaps          = " + c_value + "0x", 
     703                 self.n_mmaps,                                      
     704                 c_none + "
    n_mmaps_max      = " + c_value + "0x", 
     705                 self.n_mmaps_max,                                  
     706                 c_none + "
    max_n_mmaps      = " + c_value + "0x", 
     707                 self.max_n_mmaps,                                  
     708                 c_none + "
    no_dyn_threshold = " + c_value + "0x", 
     709                 self.no_dyn_threshold,                             
     710                 c_none + "
    mmapped_mem      = " + c_value + "0x", 
     711                 self.mmapped_mem,                                  
     712                 c_none + "
    max_mmapped_mem  = " + c_value + "0x", 
     713                 self.max_mmapped_mem,                              
     714                 c_none + "
    max_total_mem    = " + c_value + "0x", 
     715                 self.max_total_mem,                                
     716                 c_none + "
    sbrk_base        = " + c_value + "0x", 
     717                 self.sbrk_base,                                    
     718                 c_none)
     719 
     720 
     721 
     722 ################################################################################
     723 # ARENA CONSTANTS AND MACROS
     724 ################################################################################
     725 
     726 HEAP_MIN_SIZE     = 32 * 1024
     727 HEAP_MAX_SIZE     = 1024 * 1024
     728 
     729 def top(ar_ptr):
     730     return ar_ptr.top
     731 
     732 def heap_for_ptr(ptr):
     733     "find the heap and corresponding arena for a given ptr"
     734     return (ptr & ~(HEAP_MAX_SIZE-1))
     735 
     736 
     737 ################################################################################
     738 # GDB PRETTY PRINTERS
     739 ################################################################################
     740 
     741 class malloc_par_printer:
     742     "pretty print the malloc parameters (mp_)"
     743 
     744     def __init__(self, val):
     745         self.val = val
     746 
     747     def to_string(self):
     748         return "%s%s%lx%s%lx%s%lx%s%x%s%x%s%x%s%x%s%lx%s%lx%s%lx%s%lx%s" % 
     749                 (c_title + "struct malloc_par {",                  
     750                 c_none + "
    trim_threshold   = " + c_value + "0x", 
     751                 self.val['trim_threshold'],                        
     752                 c_none + "
    top_pad          = " + c_value + "0x", 
     753                 self.val['top_pad'],                               
     754                 c_none + "
    mmap_threshold   = " + c_value + "0x", 
     755                 self.val['mmap_threshold'],                        
     756                 c_none + "
    n_mmaps          = " + c_value + "0x", 
     757                 self.val['n_mmaps'],                               
     758                 c_none + "
    n_mmaps_max      = " + c_value + "0x", 
     759                 self.val['n_mmaps_max'],                           
     760                 c_none + "
    max_n_mmaps      = " + c_value + "0x", 
     761                 self.val['max_n_mmaps'],                           
     762                 c_none + "
    no_dyn_threshold = " + c_value + "0x", 
     763                 self.val['no_dyn_threshold'],                      
     764                 c_none + "
    mmapped_mem      = " + c_value + "0x", 
     765                 self.val['mmapped_mem'],                           
     766                 c_none + "
    max_mmapped_mem  = " + c_value + "0x", 
     767                 self.val['max_mmapped_mem'],                       
     768                 c_none + "
    max_total_mem    = " + c_value + "0x", 
     769                 self.val['max_total_mem'],                         
     770                 c_none + "
    sbrk_base        = " + c_value + "0x", 
     771                 self.val['sbrk_base'],                             
     772                 c_none)
     773 
     774     def display_string(self):
     775         return "string"
     776 
     777 ################################################################################
     778 class malloc_state_printer:
     779     "pretty print a struct malloc_state (ar_ptr)"
     780 
     781     def __init__(self, val):
     782         self.val = val
     783 
     784     def to_string(self):
     785         return "%s%s%x%s%x%s%s%lx%s%lx%s%s%s%lx%s%lx%s%lx%s" %      
     786                 (c_title + "struct malloc_state {",                 
     787                 c_none + "
    mutex          = " + c_value + "0x",    
     788                 self.val['mutex'],                                  
     789                 c_none + "
    flags          = " + c_value + "0x",    
     790                 self.val['flags'],                                  
     791                 c_none + "
    fastbinsY      = " + c_value + "{...}", 
     792                 c_none + "
    top            = " + c_value + "0x",    
     793                 self.val['top'],                                    
     794                 c_none + "
    last_remainder = " + c_value + "0x",    
     795                 self.val['last_remainder'],                         
     796                 c_none + "
    bins           = " + c_value + "{...}", 
     797                 c_none + "
    binmap         = " + c_value + "{...}", 
     798                 c_none + "
    next           = " + c_value + "0x",    
     799                 self.val['next'],                                   
     800                 c_none + "
    system_mem     = " + c_value + "0x",    
     801                 self.val['system_mem'],                             
     802                 c_none + "
    max_system_mem = " + c_value + "0x",    
     803                 self.val['max_system_mem'],                         
     804                 c_none)
     805 
     806     def display_string(self):
     807         return "string"
     808 
     809 ################################################################################
     810 class malloc_chunk_printer:
     811     "pretty print a struct malloc_chunk"
     812 
     813     def __init__(self, val):
     814         self.val = val
     815 
     816     def to_string(self):
     817         return "%s%s%x%s%x%s%lx%s%lx%s%lx%s%lx%s" %           
     818                 (c_title + "struct malloc_chunk {",           
     819                 c_none + "
    prev_size   = " + c_value + "0x", 
     820                 self.val['prev_size'],                        
     821                 c_none + "
    size        = " + c_value + "0x", 
     822                 self.val['size'],                             
     823                 c_none + "
    fd          = " + c_value + "0x", 
     824                 self.val['fd'],                               
     825                 c_none + "
    bk          = " + c_value + "0x", 
     826                 self.val['bk'],                               
     827                 c_none + "
    fd_nextsize = " + c_value + "0x", 
     828                 self.val['fd_nextsize'],                      
     829                 c_none + "
    bk_nextsize = " + c_value + "0x", 
     830                 self.val['bk_nextsize'],                      
     831                 c_none)
     832 
     833     def display_string(self):
     834         return "string"
     835 
     836 ################################################################################
     837 class heap_info_printer:
     838     "pretty print a struct heap_info"
     839 
     840     def __init__(self, val):
     841         self.val = val
     842 
     843     def to_string(self):
     844         return "%s%s%lx%s%lx%s%lx%s%lx%s" %                     
     845                 (c_title + "struct heap_info {",                
     846                 c_none + "
    ar_ptr        = " + c_value + "0x", 
     847                 self.val['ar_ptr'],                             
     848                 c_none + "
    prev          = " + c_value + "0x", 
     849                 self.val['prev'],                               
     850                 c_none + "
    size          = " + c_value + "0x", 
     851                 self.val['size'],                               
     852                 c_none + "
    mprotect_size = " + c_value + "0x", 
     853                 self.val['mprotect_size'],                      
     854                 c_none)
     855 
     856     def display_string(self):
     857         return "string"
     858 
     859 ################################################################################
     860 def pretty_print_heap_lookup(val):
     861     "Look-up and return a pretty-printer that can print val."
     862 
     863     # Get the type.
     864     type = val.type
     865 
     866     # If it points to a reference, get the reference.
     867     if type.code == gdb.TYPE_CODE_REF:
     868         type = type.target()
     869 
     870     # Get the unqualified type, stripped of typedefs.
     871     type = type.unqualified().strip_typedefs()
     872 
     873     # Get the type name.
     874     typename = type.tag
     875     if typename == None:
     876         return None
     877     elif typename == "malloc_par":
     878         return malloc_par_printer(val)
     879     elif typename == "malloc_state":
     880         return malloc_state_printer(val)
     881     elif typename == "malloc_chunk":
     882         return malloc_chunk_printer(val)
     883     elif typename == "_heap_info":
     884         return heap_info_printer(val)
     885     else:
     886         print(typename)
     887 
     888     # Cannot find a pretty printer.  Return None.
     889     return None
     890 
     891 
     892 ################################################################################
     893 # GDB COMMANDS
     894 ################################################################################
     895 
     896 class print_malloc_stats(gdb.Command):
     897     "print general malloc stats, adapted from malloc.c mSTATs()"
     898 
     899     def __init__(self):
     900         super(print_malloc_stats, self).__init__("print_mstats",
     901                                         gdb.COMMAND_DATA, gdb.COMPLETE_NONE)
     902 
     903     def invoke(self, arg, from_tty):
     904         "Specify an optional arena addr: print_mstats main_arena=0x12345"
     905 
     906         try:
     907             mp         = gdb.selected_frame().read_var('mp_')
     908 
     909             if arg.find("main_arena") == -1:
     910                 main_arena = gdb.selected_frame().read_var('main_arena')
     911                 main_arena_address = main_arena.address
     912             else:
     913                 arg = arg.split()
     914                 for item in arg:
     915                     if item.find("main_arena") != -1:
     916                         if len(item) < 12:
     917                             sys.stdout.write(c_error)
     918                             print("Malformed main_arena parameter")
     919                             sys.stdout.write(c_none)
     920                             return
     921                         else:
     922                             main_arena_address = int(item[11:],16)
     923         except RuntimeError:
     924             sys.stdout.write(c_error)
     925             print("No frame is currently selected.")
     926             sys.stdout.write(c_none)
     927             return
     928         except ValueError:
     929             sys.stdout.write(c_error)
     930             print("Debug glibc was not found.")
     931             sys.stdout.write(c_none)
     932             return
     933 
     934         if main_arena_address == 0:
     935             sys.stdout.write(c_error)
     936             print("Invalid main_arena address (0)")
     937             sys.stdout.write(c_none)
     938             return
     939 
     940         in_use_b = mp['mmapped_mem']
     941         system_b = in_use_b
     942 
     943         arena = 0
     944         while(1):
     945             ar_ptr = malloc_state(main_arena_address)
     946             mutex_lock(ar_ptr)
     947 
     948             sys.stdout.write(c_title)
     949             print("=================================", end=' ')
     950             print("Malloc Stats =================================
    ")
     951             sys.stdout.write(c_none)
     952 
     953             # account for top
     954             avail = chunksize(malloc_chunk(top(ar_ptr), inuse=True, 
     955                     read_data=False))
     956             nblocks = 1
     957 
     958             nfastblocks = 0
     959             fastavail = 0
     960 
     961             # traverse fastbins
     962             for i in range(NFASTBINS):
     963                 p = fastbin(ar_ptr, i)
     964                 while p!=0:
     965                     p = malloc_chunk(p, inuse=False)
     966                     nfastblocks += 1
     967                     fastavail += chunksize(p)
     968                     p = p.fd
     969 
     970             avail += fastavail
     971 
     972             # traverse regular bins
     973             for i in range(1, NBINS):
     974                 b = bin_at(ar_ptr, i)
     975                 p = malloc_chunk(first(malloc_chunk(b,inuse=False)),inuse=False)
     976 
     977                 while p.address != b:
     978                     nblocks += 1
     979                     avail += chunksize(p)
     980                     p = malloc_chunk(first(p), inuse=False)
     981 
     982             sys.stdout.write(c_header)
     983             print("Arena %d:" % arena)
     984             sys.stdout.write(c_none)
     985             print(c_none + "system bytes     = " + 
     986                     c_value + "0x%x" % ar_ptr.system_mem)
     987             print(c_none + "in use bytes     = " + 
     988                     c_value + "0x%x
    " % (ar_ptr.system_mem - avail))
     989 
     990             system_b += ar_ptr.system_mem
     991             in_use_b += (ar_ptr.system_mem - avail)
     992 
     993             mutex_unlock(ar_ptr)
     994             if ar_ptr.next == main_arena_address:
     995                 break
     996             else:
     997                 ar_ptr = malloc_state(ar_ptr.next)
     998                 arena += 1
     999 
    1000         print(c_header + "Total (including mmap):")
    1001         print(c_none + "system bytes     = " + c_value + "0x%x" % system_b)
    1002         print(c_none + "in use bytes     = " + c_value + "0x%x" % in_use_b)
    1003         print(c_none + "max system bytes = " + 
    1004                 c_value + "0x%x" % mp['max_total_mem'])
    1005         print(c_none + "max mmap regions = " + 
    1006                 c_value + "0x%x" % mp['max_n_mmaps'])
    1007         print(c_none + "max mmap bytes   = " + 
    1008                 c_value + "0x%lx" % mp['max_mmapped_mem'] + c_none)
    1009 
    1010 
    1011 ################################################################################
    1012 class heap(gdb.Command):
    1013     "print a comprehensive view of the heap"
    1014 
    1015     def __init__(self):
    1016         super(heap, self).__init__("heap", gdb.COMMAND_DATA, gdb.COMPLETE_NONE)
    1017 
    1018     def invoke(self, arg, from_tty):
    1019         "Usage can be obtained via heap -h"
    1020 
    1021         inferior = get_inferior()
    1022         if inferior == -1:
    1023             return
    1024 
    1025         if arg.find("-h") != -1:
    1026             print(c_title + "==============================", end=' ')
    1027             print("Heap Dump Help ==================================
    " + c_none)
    1028 
    1029             print(c_title + "Options:
    " + c_none)
    1030             print(c_header + "  -a 0x1234" + c_none 
    1031                     + "	Specify an arena address")
    1032             print(c_header + "  -b" + c_none + 
    1033                     "		Print compact bin listing (only free chunks)")
    1034             print(c_header + "  -c" + c_none + 
    1035                     "		Print compact arena listing (all chunks)")
    1036             print(c_header + "  -f [#]" + c_none + 
    1037                     "	Print all fast bins, or only a single fast bin")
    1038             print(c_header + "  -l" + c_none + 
    1039                     "		Print a flat listing of all chunks in an arena")
    1040             print(c_header + "  -s [#]" + c_none + 
    1041                     "	Print all small bins, or only a single small bin
    ")
    1042             return
    1043 
    1044         a_found = f_found = s_found = p_fb = p_sb = p_b = p_l = p_c = 0
    1045         for item in arg.split():
    1046             if a_found == 1:
    1047                 arena_address = int(item,16)
    1048                 a_found = 0
    1049                 continue
    1050             if f_found == 1:
    1051                 f_found = 0
    1052                 try:
    1053                     fb_number = int(item)
    1054                 except:
    1055                     pass
    1056                 continue
    1057             if s_found == 1:
    1058                 s_found = 0
    1059                 try:
    1060                     sb_number = int(item)
    1061                 except:
    1062                     pass
    1063                 continue
    1064             if item.find("-a") != -1:
    1065                 a_found = 1
    1066             if item.find("f") != -1:
    1067                 f_found = 1
    1068                 fb_number = None
    1069                 p_fb = 1
    1070             if item.find("s") != -1:
    1071                 s_found = 1
    1072                 sb_number = None
    1073                 p_sb = 1
    1074             if item.find("b") != -1:
    1075                 p_b = 1
    1076             if item.find("l") != -1:
    1077                 p_l = 1
    1078             if item.find("c") != -1:
    1079                 p_c = 1
    1080 
    1081         if arg.find("-a") == -1:
    1082             try:
    1083                 main_arena = gdb.selected_frame().read_var('main_arena')
    1084                 arena_address = main_arena.address
    1085             except RuntimeError:
    1086                 print(c_error + "No gdb frame is currently selected." + c_none)
    1087                 return
    1088             except ValueError:
    1089                 print(c_error + "Debug glibc was not found, " 
    1090                     "guessing main_arena address via offset from libc." + c_none)
    1091 
    1092                 #find heap by offset from end of libc in /proc
    1093                 libc_end,heap_begin = read_proc_maps(inferior.pid)
    1094 
    1095                 if SIZE_SZ == 4:
    1096                     #__malloc_initialize_hook + 0x20
    1097                     #offset seems to be +0x380 on debug glibc, +0x3a0 otherwise
    1098                     arena_address = libc_end + 0x3a0
    1099                 elif SIZE_SZ == 8:
    1100                     #offset seems to be +0xe80 on debug glibc, +0xea0 otherwise
    1101                     arena_address = libc_end + 0xea0
    1102 
    1103                 if libc_end == -1:
    1104                     print(c_error + "Invalid address read via /proc" + c_none)
    1105                     return
    1106 
    1107         if arena_address == 0:
    1108             print(c_error + "Invalid arena address (0)" + c_none)
    1109             return
    1110         ar_ptr = malloc_state(arena_address)
    1111 
    1112         if len(arg) == 0:
    1113             if ar_ptr.next == 0:
    1114                 print("%s%s %s 0x%x) %s" % (c_error, 
    1115                         "ERROR: No arenas could be correctly guessed.", 
    1116                         "(Nothing was found at", ar_ptr.address, c_none))
    1117                 return
    1118 
    1119             print(c_title + "==================================", end=' ')
    1120             print("Heap Dump ===================================
    " + c_none)
    1121 
    1122             print(c_title + "Arena(s) found:" + c_none)
    1123             try: #arena address obtained via read_var
    1124                 print("	 arena @ 0x%x" % 
    1125                         ar_ptr.address.cast(gdb.lookup_type("unsigned long")))
    1126             except: #arena address obtained via -a
    1127                 print("	 arena @ 0x%x" % ar_ptr.address)
    1128 
    1129             if ar_ptr.address != ar_ptr.next:
    1130         print('no more than one arena')
    1131                 #we have more than one arena
    1132 
    1133                 curr_arena = malloc_state(ar_ptr.next)
    1134                 while (ar_ptr.address != curr_arena.address):
    1135                     print("	 arena @ 0x%x" % curr_arena.address)
    1136                     curr_arena = malloc_state(curr_arena.next)
    1137 
    1138                     if curr_arena.address == 0:
    1139                         print(c_error + 
    1140                            "ERROR: No arenas could be correctly found." + c_none)
    1141                         break #breaking infinite loop
    1142 
    1143             print("")
    1144             return
    1145 
    1146         try:
    1147             fb_base = ar_ptr.address.cast(gdb.lookup_type("unsigned long")) + 8
    1148         except Exception, e:
    1149         print(e)
    1150             fb_base = ar_ptr.address + 8
    1151         if SIZE_SZ == 4:
    1152             try:
    1153                 sb_base=ar_ptr.address.cast(gdb.lookup_type("unsigned long"))+56
    1154             except:
    1155                 sb_base = ar_ptr.address + 56
    1156         elif SIZE_SZ == 8:
    1157             try:
    1158                 sb_base = ar_ptr.address.cast(gdb.lookup_type("unsigned long"))
    1159                         + 104
    1160             except:
    1161                 sb_base = ar_ptr.address + 104
    1162 
    1163         try:
    1164             mp_ = gdb.selected_frame().read_var('mp_')
    1165             mp_address = mp_.address
    1166         except RuntimeError:
    1167             print(c_error + "No gdb frame is currently selected." + c_none)
    1168             return
    1169         except ValueError:
    1170             print(c_error + "Debug glibc was not found, " 
    1171                    "guessing mp_ address via offset from main_arena." + c_none)
    1172 
    1173             if SIZE_SZ == 4:
    1174                 try:
    1175                     mp_address = ar_ptr.address.cast(gdb.lookup_type(
    1176                                                     "unsigned long")) + 0x460
    1177                 except:
    1178                     mp_address = ar_ptr.address + 0x460
    1179             elif SIZE_SZ == 8: #offset 0x880 untested on 64bit
    1180                 try:
    1181                     mp_address = ar_ptr.address.cast(gdb.lookup_type(
    1182                                                     "unsigned long")) + 0x880
    1183                 except:
    1184                     mp_address = ar_ptr.address + 0x460
    1185         sbrk_base = malloc_par(mp_address).sbrk_base
    1186 
    1187         if p_fb:
    1188             print_fastbins(inferior, fb_base, fb_number)
    1189             print("")
    1190         if p_sb:
    1191             print_smallbins(inferior, sb_base, sb_number)
    1192             print("")
    1193         if p_b:
    1194             print_bins(inferior, fb_base, sb_base)
    1195             print("")
    1196         if p_l:
    1197             print_flat_listing(ar_ptr, sbrk_base)
    1198             print("")
    1199         if p_c:
    1200             print_compact_listing(ar_ptr, sbrk_base)
    1201             print("")
    1202 
    1203 
    1204 ############################################################################
    1205 def read_proc_maps(pid):
    1206     '''
    1207     Locate the stack of a process using /proc/pid/maps.
    1208     Will not work on hardened machines (grsec).
    1209     '''
    1210 
    1211     filename = '/proc/%d/maps' % pid
    1212 
    1213     try:
    1214         fd = open(filename)
    1215     except IOError:
    1216         print(c_error + "Unable to open %s" % filename + c_none)
    1217         return -1,-1
    1218 
    1219     found = libc_begin = libc_end = heap_begin = heap_end = 0
    1220     for line in fd:
    1221         if line.find("libc-") != -1:
    1222             fields = line.split()
    1223 
    1224             libc_begin,libc_end = fields[0].split('-')
    1225             libc_begin = int(libc_begin,16)
    1226             libc_end = int(libc_end,16)
    1227         elif line.find("heap") != -1:
    1228             fields = line.split()
    1229 
    1230             heap_begin,heap_end= fields[0].split('-')
    1231             heap_begin = int(heap_begin,16)
    1232             heap_end = int(heap_end,16)
    1233 
    1234     fd.close()
    1235 
    1236     if libc_begin==0 or libc_end==0:
    1237         print(c_error+"Unable to read libc address information via /proc"+c_none)
    1238         return -1,-1
    1239 
    1240     if heap_begin==0 or heap_end==0:
    1241         print(c_error+"Unable to read heap address information via /proc"+c_none)
    1242         return -1,-1
    1243 
    1244     return libc_end,heap_begin
    1245 
    1246 
    1247 ################################################################################
    1248 def print_fastbins(inferior, fb_base, fb_num):
    1249     "walk and print the fast bins"
    1250 
    1251     print(c_title + "===================================", end=' ')
    1252     print("Fastbins ===================================
    " + c_none)
    1253 
    1254     for fb in range(0,NFASTBINS):
    1255         if fb_num != None:
    1256             fb = fb_num
    1257 
    1258         offset = fb_base + fb*SIZE_SZ
    1259         try:
    1260             mem = inferior.read_memory(offset, SIZE_SZ)
    1261             if SIZE_SZ == 4:
    1262                 fd = struct.unpack("<I", mem)[0]
    1263             elif SIZE_SZ == 8:
    1264                 fd = struct.unpack("<Q", mem)[0]
    1265         except RuntimeError:
    1266             print(c_error + " ERROR: Invalid fb addr 0x%lx" % offset + c_none)
    1267             return
    1268 
    1269         print("%s%s%d%s%s0x%08lx%s%s%s0x%08lx%s%s" % 
    1270                 (c_header,"[ fb  ",fb," ] ",c_none,offset,
    1271                  " -> ",c_value,"[ ",fd," ]",c_none), end=' ')
    1272 
    1273         if fd == 0: #fastbin is empty
    1274             print("")
    1275         else:
    1276             fb_size = ((MIN_CHUNK_SIZE) +(MALLOC_ALIGNMENT)*fb)
    1277             print("(%d)" % fb_size)
    1278             chunk = malloc_chunk(fd, inuse=False)
    1279             while chunk.fd != 0:
    1280                 if chunk.fd is None:   # could not read memory section
    1281                     break
    1282                 print("%s%26s0x%08lx%s%s(%d)" % (c_value,"[ ",chunk.fd," ] ",c_none, fb_size))
    1283                 chunk = malloc_chunk(chunk.fd, inuse=False)
    1284 
    1285         if fb_num != None: #only print one fastbin
    1286             return
    1287 
    1288 
    1289 ################################################################################
    1290 def print_smallbins(inferior, sb_base, sb_num):
    1291     "walk and print the small bins"
    1292 
    1293     print(c_title + "===================================", end=' ')
    1294     print("Smallbins ==================================
    " + c_none)
    1295 
    1296     for sb in range(2,NBINS+2,2):
    1297         if sb_num != None and sb_num!=0:
    1298             sb = sb_num*2
    1299 
    1300         offset = sb_base + (sb-2)*SIZE_SZ
    1301         try:
    1302             mem = inferior.read_memory(offset, 2*SIZE_SZ)
    1303             if SIZE_SZ == 4:
    1304                 fd,bk = struct.unpack("<II", mem)
    1305             elif SIZE_SZ == 8:
    1306                 fd,bk = struct.unpack("<QQ", mem)
    1307         except RuntimeError:
    1308             print(c_error + " ERROR: Invalid sb addr 0x%lx" % offset + c_none)
    1309             return
    1310 
    1311         print("%s%s%02d%s%s0x%08lx%s%s%s0x%08lx%s0x%08lx%s%s" % 
    1312                             (c_header,"[ sb ",sb/2," ] ",c_none,offset, 
    1313                             " -> ",c_value,"[ ", fd, " | ", bk, " ] ",  
    1314                             c_none))
    1315 
    1316         while (1):
    1317             if fd == (offset-2*SIZE_SZ):
    1318                 break
    1319 
    1320             chunk = malloc_chunk(fd, inuse=False)
    1321             print("%s%26s0x%08lx%s0x%08lx%s%s" % 
    1322                     (c_value,"[ ",chunk.fd," | ",chunk.bk," ] ",c_none), end=' ')
    1323             print("(%d)" % chunksize(chunk))
    1324 
    1325             fd = chunk.fd
    1326 
    1327         if sb_num != None: #only print one smallbin
    1328             return
    1329 
    1330 
    1331 ################################################################################
    1332 def print_bins(inferior, fb_base, sb_base):
    1333     "walk and print the nonempty free bins, modified from jp"
    1334 
    1335     print(c_title + "==================================", end=' ')
    1336     print("Heap Dump ===================================
    " + c_none)
    1337 
    1338     for fb in range(0,NFASTBINS):
    1339         print_once = True
    1340         p = malloc_chunk(fb_base-(2*SIZE_SZ)+fb*SIZE_SZ, inuse=False)
    1341 
    1342         while (p.fd != 0):
    1343             if p.fd is None:
    1344                 break
    1345 
    1346             if print_once:
    1347                 print_once = False
    1348                 print(c_header + "  fast bin %d   @ 0x%lx" % 
    1349                         (fb,p.fd) + c_none)
    1350             print("    free chunk @ " + c_value + "0x%lx" % p.fd + c_none + 
    1351                   " - size" + c_value, end=' ')
    1352             p = malloc_chunk(p.fd, inuse=False)
    1353             print("0x%lx" % chunksize(p) + c_none)
    1354 
    1355     for i in range(1, NBINS):
    1356         print_once = True
    1357         b = sb_base + i*2*SIZE_SZ - 4*SIZE_SZ
    1358         p = malloc_chunk(first(malloc_chunk(b, inuse=False)), inuse=False)
    1359 
    1360         while p.address != b:
    1361             if print_once:
    1362                 print_once = False
    1363                 if i==1:
    1364                     try:
    1365                         print(c_header + "  unsorted bin @ 0x%lx" % 
    1366                           (b.cast(gdb.lookup_type("unsigned long")) 
    1367                           + 2*SIZE_SZ) + c_none)
    1368                     except:
    1369                         print(c_header + "  unsorted bin @ 0x%lx" % 
    1370                           (b + 2*SIZE_SZ) + c_none)
    1371                 else:
    1372                     try:
    1373                         print(c_header + "  small bin %d @ 0x%lx" %  
    1374                          (i,b.cast(gdb.lookup_type("unsigned long")) 
    1375                          + 2*SIZE_SZ) + c_none)
    1376                     except:
    1377                         print(c_header + "  small bin %d @ 0x%lx" % 
    1378                          (i,b + 2*SIZE_SZ) + c_none)
    1379 
    1380             print(c_none + "    free_chunk @ " + c_value 
    1381                   + "0x%lx " % p.address + c_none        
    1382                   + "- size " + c_value + "0x%lx" % chunksize(p) + c_none)
    1383 
    1384             p = malloc_chunk(first(p), inuse=False)
    1385 
    1386 
    1387 ################################################################################
    1388 def print_flat_listing(ar_ptr, sbrk_base):
    1389     "print a flat listing of an arena, modified from jp and arena.c"
    1390 
    1391     print(c_title + "==================================", end=' ')
    1392     print("Heap Dump ===================================
    " + c_none)
    1393     print("%s%14s%17s%15s%s" % (c_header, "ADDR", "SIZE", "STATUS", c_none))
    1394     print("sbrk_base " + c_value + "0x%lx" % sbrk_base)
    1395 
    1396     p = malloc_chunk(sbrk_base, inuse=True, read_data=False)
    1397 
    1398     while(1):
    1399         print("%schunk     %s0x%-14lx 0x%-10lx%s" % 
    1400                 (c_none, c_value, p.address, chunksize(p), c_none), end=' ')
    1401 
    1402         if p.address == top(ar_ptr):
    1403             print("(top)")
    1404             break
    1405         elif p.size == (0|PREV_INUSE):
    1406             print("(fence)")
    1407             break
    1408 
    1409         if inuse(p):
    1410             print("%s" % "(inuse)")
    1411         else:
    1412             p = malloc_chunk(p.address, inuse=False)
    1413             print("(F) FD %s0x%lx%s BK %s0x%lx%s" % 
    1414                     (c_value, p.fd, c_none,c_value,p.bk,c_none), end=' ')
    1415 
    1416             if ((p.fd == ar_ptr.last_remainder) 
    1417             and (p.bk == ar_ptr.last_remainder) 
    1418             and (ar_ptr.last_remainder != 0)):
    1419                 print("(LR)")
    1420             elif ((p.fd == p.bk) & ~inuse(p)):
    1421                 print("(LC)")
    1422             else:
    1423                 print("")
    1424 
    1425         p = malloc_chunk(next_chunk(p), inuse=True, read_data=False)
    1426 
    1427     print(c_none + "sbrk_end  " + c_value 
    1428             + "0x%lx" % (sbrk_base + ar_ptr.system_mem) + c_none)
    1429 
    1430 
    1431 ################################################################################
    1432 def print_compact_listing(ar_ptr, sbrk_base):
    1433     "print a compact layout of the heap, modified from jp"
    1434 
    1435     print(c_title + "==================================", end=' ')
    1436     print("Heap Dump ===================================" + c_none)
    1437     p = malloc_chunk(sbrk_base, inuse=True, read_data=False)
    1438 
    1439     while(1):
    1440         if p.address == top(ar_ptr):
    1441             sys.stdout.write("|T|
    ")
    1442             break
    1443 
    1444         if inuse(p):
    1445             sys.stdout.write("|A|")
    1446         else:
    1447             p = malloc_chunk(p.address, inuse=False)
    1448 
    1449             if ((p.fd == ar_ptr.last_remainder) 
    1450             and (p.bk == ar_ptr.last_remainder) 
    1451             and (ar_ptr.last_remainder != 0)):
    1452                 sys.stdout.write("|L|")
    1453             else:
    1454                 sys.stdout.write("|%d|" % bin_index(p.size))
    1455 
    1456         p = malloc_chunk(next_chunk(p), inuse=True, read_data=False)
    1457 
    1458 
    1459 ################################################################################
    1460 class print_bin_layout(gdb.Command):
    1461     "dump the layout of a free bin"
    1462 
    1463     def __init__(self):
    1464         super(print_bin_layout, self).__init__("print_bin_layout",
    1465                                         gdb.COMMAND_DATA, gdb.COMPLETE_NONE)
    1466 
    1467     def invoke(self, arg, from_tty):
    1468         "Specify an optional arena addr: print_bin_layout main_arena=0x12345"
    1469 
    1470         if len(arg) == 0:
    1471             sys.stdout.write(c_error)
    1472             print("Please specify the free bin to dump")
    1473             sys.stdout.write(c_none)
    1474             return
    1475 
    1476         try:
    1477             if arg.find("main_arena") == -1:
    1478                 main_arena = gdb.selected_frame().read_var('main_arena')
    1479                 main_arena_address = main_arena.address
    1480             else:
    1481                 arg = arg.split()
    1482                 for item in arg:
    1483                     if item.find("main_arena") != -1:
    1484                         if len(item) < 12:
    1485                             sys.stdout.write(c_error)
    1486                             print("Malformed main_arena parameter")
    1487                             sys.stdout.write(c_none)
    1488                             return
    1489                         else:
    1490                             main_arena_address = int(item[11:],16)
    1491         except RuntimeError:
    1492             sys.stdout.write(c_error)
    1493             print("No frame is currently selected.")
    1494             sys.stdout.write(c_none)
    1495             return
    1496         except ValueError:
    1497             sys.stdout.write(c_error)
    1498             print("Debug glibc was not found.")
    1499             sys.stdout.write(c_none)
    1500             return
    1501 
    1502         if main_arena_address == 0:
    1503             sys.stdout.write(c_error)
    1504             print("Invalid main_arena address (0)")
    1505             sys.stdout.write(c_none)
    1506             return
    1507 
    1508         ar_ptr = malloc_state(main_arena_address)
    1509         mutex_lock(ar_ptr)
    1510 
    1511         sys.stdout.write(c_title)
    1512         print("=================================", end=' ')
    1513         print("Bin Layout ===================================
    ")
    1514         sys.stdout.write(c_none)
    1515 
    1516         b = bin_at(ar_ptr, int(arg))
    1517         p = malloc_chunk(first(malloc_chunk(b, inuse=False)), inuse=False)
    1518         print_once = True
    1519         print_str  = ""
    1520         count      = 0
    1521 
    1522         while p.address != b:
    1523             if print_once:
    1524                 print_once=False
    1525                 print_str += "-->  " + c_value + "[bin %d]" % int(arg) + c_none
    1526                 count += 1
    1527 
    1528             print_str += "  <-->  " + c_value + "0x%lx" % p.address + c_none
    1529             count += 1
    1530             #print_str += "  <-->  0x%lx" % p.address
    1531             p = malloc_chunk(first(p), inuse=False)
    1532 
    1533         if len(print_str) != 0:
    1534             print_str += "  <--"
    1535             print(print_str)
    1536             print("%s%s%s" % ("|"," " * (len(print_str) - 2 - count*12),"|"))
    1537             print("%s" % ("-" * (len(print_str) - count*12)))
    1538         else:
    1539             print("Bin %d empty." % int(arg))
    1540 
    1541         mutex_unlock(ar_ptr)
    1542 
    1543 
    1544 ################################################################################
    1545 class check_house_of_mind(gdb.Command):
    1546     "print and help validate a house of mind layout"
    1547 
    1548     def __init__(self):
    1549         super(check_house_of_mind, self).__init__("check_house_of_mind",
    1550                                         gdb.COMMAND_DATA, gdb.COMPLETE_NONE)
    1551 
    1552     def invoke(self, arg, from_tty):
    1553         """
    1554         Specify the house of mind method and chunk address (p=mem2chunk(mem)):
    1555         check_house_of_mind method=unsortedbin p=0x12345678
    1556         check_house_of_mind method=fastbin p=0x12345678
    1557         """
    1558 
    1559         if arg.find("method") == -1:
    1560             print("Please specify the House of Mind method to use:")
    1561             print("house_of_mind method={unsortedbin, fastbin}")
    1562             return
    1563         elif arg.find("p") == -1:
    1564             print("Please specify the chunk address to use:")
    1565             print("house_of_mind p=0x12345678")
    1566             return
    1567         else:
    1568             arg = arg.split()
    1569             for item in arg:
    1570                 if item.find("method") != -1:
    1571                     if len(item) < 8:
    1572                         sys.stdout.write(c_error)
    1573                         print("Malformed method parameter")
    1574                         print("Please specify the House of Mind method to use:")
    1575                         print("house_of_mind method={unsortedbin, fastbin}")
    1576                         sys.stdout.write(c_none)
    1577                         return
    1578                     else:
    1579                         method = item[7:]
    1580                 if item.find("p") != -1:
    1581                     if len(item) < 11:
    1582                         sys.stdout.write(c_error)
    1583                         print("Malformed chunk parameter")
    1584                         print("Please specify the chunk address to use:")
    1585                         print("house_of_mind p=0x12345678")
    1586                         sys.stdout.write(c_none)
    1587                         return
    1588                     else:
    1589                         p = int(item[2:],16)
    1590 
    1591         sys.stdout.write(c_title)
    1592         print("===============================", end=' ')
    1593         print("House of Mind ==================================
    ")
    1594         sys.stdout.write(c_none)
    1595 
    1596         if method.find("unsorted") != -1:
    1597             self.unsorted_bin_method(p)
    1598         elif method.find("fast") != -1:
    1599             self.fast_bin_method(p)
    1600 
    1601     def unsorted_bin_method(self, p):
    1602         p = malloc_chunk(addr=p, inuse=True, read_data=False)
    1603 
    1604         print(c_none + "Checking chunk p")
    1605         print(c_none + " [*] p = " + c_value + "0x%x" % p.address + c_none)
    1606 
    1607         if p.address < gdb.parse_and_eval("(unsigned int)%d" % -chunksize(p)):
    1608             print(" [*] size does not wrap")
    1609         else:
    1610             print(c_error + " [_] ERROR: p > -size" + c_none)
    1611             return
    1612 
    1613         if chunksize(p) >= MINSIZE:
    1614             print(" [*] size is > minimum chunk size")
    1615         else:
    1616             print(c_error + " [_] ERROR: chunksize(p) < MINSIZE" + c_none)
    1617             return
    1618 
    1619         if chunksize(p) > get_max_fast():
    1620             print(" [*] size is not in fastbin range")
    1621         else:
    1622             print(c_error + " [_] ERROR: size is in fastbin range" + c_none)
    1623             return
    1624 
    1625         if not chunk_is_mmapped(p):
    1626             print(" [*] is_mmapped bit is not set")
    1627         else:
    1628             print(c_error + " [_] ERROR: IS_MMAPPED bit is set" + c_none)
    1629             return
    1630 
    1631         if prev_inuse(p):
    1632             print(" [*] prev_inuse bit is set")
    1633         else:
    1634             print(c_error + " [_] ERROR: PREV_INUSE bit is not set, this will", end=' ')
    1635             print("trigger backward consolidation" + c_none)
    1636 
    1637         if chunk_non_main_arena(p):
    1638             print(" [*] non_main_arena flag is set")
    1639         else:
    1640             print(c_error + " [_] ERROR: p's non_main_arena flag is NOT set")
    1641             return
    1642 
    1643         print(c_none + "
    Checking struct heap_info")
    1644         print(c_none + " [*] struct heap_info = " 
    1645                 + c_value + "0x%x" % heap_for_ptr(p.address))
    1646 
    1647         inferior = get_inferior()
    1648         if inferior == -1:
    1649             return None
    1650 
    1651         try:
    1652             mem = inferior.read_memory(heap_for_ptr(p.address), SIZE_SZ)
    1653             if SIZE_SZ == 4:
    1654                 ar_ptr = struct.unpack("<I", mem)[0]
    1655             elif SIZE_SZ == 8:
    1656                 ar_ptr = struct.unpack("<Q", mem)[0]
    1657         except RuntimeError:
    1658             print(c_error + " [_] ERROR: Invalid heap_info address 0x%x" 
    1659                     % heap_for_ptr(p.address) + c_none)
    1660             return
    1661 
    1662         print(c_none + " [*] ar_ptr = " + c_value + "0x%x" % ar_ptr)
    1663         print(c_none + "
    Checking struct malloc_state")
    1664 
    1665         #test malloc_state address
    1666         try:
    1667             mutex = inferior.read_memory(ar_ptr, SIZE_SZ)
    1668         except RuntimeError:
    1669             print(c_error + " [_] ERROR: Invalid malloc_state address 0x%x" % 
    1670                     ar_ptr + c_none)
    1671             return
    1672 
    1673         av = malloc_state(ar_ptr)
    1674 
    1675         if av.mutex == 0:
    1676             print(c_none + " [*] av->mutex is zero")
    1677         else:
    1678             print(c_error + " [_] ERROR: av->mutex is not zero" + c_none)
    1679             return
    1680 
    1681         if p.address != av.top:
    1682             print(c_none + " [*] p is not the top chunk")
    1683         else:
    1684             print(c_error + " [_] ERROR: p is the top chunk" + c_none)
    1685             return
    1686 
    1687         if noncontiguous(av):
    1688             print(c_none + " [*] noncontiguous_bit is set")
    1689         elif contiguous(av):
    1690             print(c_error + 
    1691                 " [_] ERROR: noncontiguous_bit is NOT set in av->flags" + c_none)
    1692             return
    1693 
    1694         print(" [*] bck = &av->bins[0] = " + c_value + "0x%x" % (ar_ptr+0x38))
    1695 
    1696         if SIZE_SZ == 4:
    1697             print(c_none + " [*] fwd = bck->fd = *(&av->bins[0] + 8) =", end=' ')
    1698         elif SIZE_SZ == 8:
    1699             print(c_none + " [*] fwd = bck->fd = *(&av->bins[0] + 16) =", end=' ')
    1700 
    1701         fwd = inferior.read_memory(ar_ptr + 0x38 + 2*SIZE_SZ, SIZE_SZ)
    1702         if SIZE_SZ == 4:
    1703             fwd = struct.unpack("<I", fwd)[0]
    1704         elif SIZE_SZ == 8:
    1705             fwd = struct.unpack("<Q", fwd)[0]
    1706         print(c_value + "0x%x" % fwd)
    1707 
    1708         if fwd != (ar_ptr+0x38):
    1709             print(c_none + " [!] fwd->bk (0x%x) != bck (0x%x)" % 
    1710                     (fwd, ar_ptr+0x38) + c_error)
    1711             print("     - ERROR: This will prevent this attack on glibc 2.11+", end=' ')
    1712             print(c_none)
    1713 
    1714         print(c_none + "
    Checking following chunks")
    1715         nextchunk = chunk_at_offset(p, chunksize(p))
    1716 
    1717         if prev_inuse(nextchunk):
    1718             print(c_none + " [*] prev_inuse of the next chunk is set")
    1719         else:
    1720             print(c_error + " [_] PREV_INUSE bit of the next chunk is not set" 
    1721                     + c_none)
    1722             return
    1723 
    1724         if chunksize(nextchunk) > 2*SIZE_SZ:
    1725             print(c_none + " [*] nextchunk size is > minimum size")
    1726         else:
    1727             print(c_error + " [_] ERROR: nextchunk size (%d) < %d" % 
    1728                     (chunksize(nextchunk), 2*SIZE_SZ) + c_none)
    1729             return
    1730 
    1731         if chunksize(nextchunk) < av.system_mem:
    1732             print(c_none + " [*] nextchunk size is < av->system_mem")
    1733         else:
    1734             print(c_error + " [_] ERROR: nextchunk size (0x%x) >" % 
    1735                     chunksize(nextchunk), end=' ')
    1736             print("av->system_mem (0x%x)" % av.system_mem + c_none)
    1737             return
    1738 
    1739         if nextchunk.address != av.top:
    1740             print(c_none + " [*] nextchunk != av->top")
    1741         else:
    1742             print(c_error + " [_] ERROR: nextchunk is av->top (0x%x)" % av.top 
    1743                     + c_none)
    1744             return
    1745 
    1746         if inuse_bit_at_offset(nextchunk, chunksize(nextchunk)):
    1747             print(c_none + " [*] prev_inuse bit set on chunk after nextchunk")
    1748         else:
    1749             print(c_error + " [_] ERROR: PREV_INUSE bit of chunk after", end=' ')
    1750             print("nextchunk (0x%x) is not set" % 
    1751                     (nextchunk.address + chunksize(nextchunk)) + c_none)
    1752             return
    1753 
    1754         print(c_header + "
    p (0x%x) will be written to fwd->bk (0x%x)" 
    1755                 % (p.address, fwd+0xC) + c_none)
    1756 
    1757     def fast_bin_method(self, p):
    1758         p = malloc_chunk(addr=p, inuse=True, read_data=False)
    1759 
    1760         print(c_none + "Checking chunk p")
    1761         print(c_none + " [*] p = " + c_value + "0x%x" % p.address + c_none)
    1762 
    1763         if p.address < gdb.parse_and_eval("(unsigned int)%d" % -chunksize(p)):
    1764             print(" [*] size does not wrap")
    1765         else:
    1766             print(c_error + " [_] ERROR: p > -size" + c_none)
    1767             return
    1768 
    1769         if chunksize(p) >= MINSIZE:
    1770             print(" [*] size is >= minimum chunk size")
    1771         else:
    1772             print(c_error + " [_] ERROR: chunksize(p) < MINSIZE" + c_none)
    1773             return
    1774 
    1775         if chunksize(p) < get_max_fast():
    1776             print(" [*] size is in fastbin range")
    1777         else:
    1778             print(c_error + " [_] ERROR: size is not in fastbin range" + c_none)
    1779             return
    1780 
    1781         if chunk_non_main_arena(p):
    1782             print(" [*] non_main_arena flag is set")
    1783         else:
    1784             print(c_error + " [_] ERROR: p's non_main_arena flag is NOT set")
    1785             return
    1786 
    1787         if prev_inuse(p):
    1788             print(" [*] prev_inuse bit is set")
    1789         else:
    1790             print(c_error + " [_] ERROR: PREV_INUSE bit is not set, this will", end=' ')
    1791             print("trigger backward consolidation" + c_none)
    1792 
    1793         print(c_none + "
    Checking struct heap_info")
    1794         print(c_none + " [*] struct heap_info = " 
    1795                 + c_value + "0x%x" % heap_for_ptr(p.address))
    1796 
    1797         inferior = get_inferior()
    1798         if inferior == -1:
    1799             return None
    1800 
    1801         try:
    1802             mem = inferior.read_memory(heap_for_ptr(p.address), SIZE_SZ)
    1803             if SIZE_SZ == 4:
    1804                 ar_ptr = struct.unpack("<I", mem)[0]
    1805             elif SIZE_SZ == 8:
    1806                 ar_ptr = struct.unpack("<Q", mem)[0]
    1807         except RuntimeError:
    1808             print(c_error + " [_] ERROR: Invalid heap_info address 0x%x" 
    1809                     % heap_for_ptr(p.address) + c_none)
    1810             return
    1811 
    1812         print(c_none + " [*] ar_ptr = " + c_value + "0x%x" % ar_ptr)
    1813         print(c_none + "
    Checking struct malloc_state")
    1814 
    1815         #test malloc_state address
    1816         try:
    1817             mutex = inferior.read_memory(ar_ptr, SIZE_SZ)
    1818         except RuntimeError:
    1819             print(c_error + " [_] ERROR: Invalid malloc_state address 0x%x" % 
    1820                     ar_ptr + c_none)
    1821             return
    1822 
    1823         av = malloc_state(ar_ptr)
    1824 
    1825         if av.mutex == 0:
    1826             print(c_none + " [*] av->mutex is zero")
    1827         else:
    1828             print(c_error + " [_] ERROR: av->mutex is not zero" + c_none)
    1829             return
    1830 
    1831         print(c_none + " [*] av->system_mem is 0x%x" % av.system_mem)
    1832 
    1833         print(c_none + "
    Checking following chunk")
    1834         nextchunk = chunk_at_offset(p, chunksize(p))
    1835         print(" [*] nextchunk = " + c_value + "0x%x" % nextchunk.address)
    1836 
    1837         if nextchunk.size > 2*SIZE_SZ:
    1838             print(c_none + " [*] nextchunk size is > 2*SIZE_SZ")
    1839         else:
    1840             print(c_error + " [_] ERROR: nextchunk size is <= 2*SIZE_SZ" +c_none)
    1841             return
    1842 
    1843         if chunksize(nextchunk) < av.system_mem:
    1844             print(c_none + " [*] nextchunk size is < av->system_mem")
    1845         else:
    1846             print(c_error + " [_] ERROR: nextchunk size (0x%x) is >= " % 
    1847                     chunksize(nextchunk), end=' ')
    1848             print("av->system_mem (0x%x)" % (av.system_mem) + c_none)
    1849             return
    1850 
    1851         fb = ar_ptr + (2*SIZE_SZ) + (fastbin_index(p.size)*SIZE_SZ)
    1852         print(c_header + "
    p (0x%x) will be written to fb (0x%x)" 
    1853                 % (p.address, fb) + c_none)
    1854 
    1855 
    1856 ################################################################################
    1857 # INITIALIZE CUSTOM GDB CODE
    1858 ################################################################################
    1859 heap()
    1860 print_malloc_stats()
    1861 print_bin_layout()
    1862 check_house_of_mind()
    1863 gdb.pretty_printers.append(pretty_print_heap_lookup)
    View Code
  • 相关阅读:
    【Django】CSRF token missing or incorrect问题处理
    【Go】Hello World!
    【Element UI】axios 与 request.js配置
    【Element UI】 使用弹窗组件关闭时的传值修改 / 报错:Avoid mutating a prop directly since the value will be overwritten
    【Pyqt5】QT designer与 pycharm的配置
    Python 冒泡排序的优化
    skywalking/8.5部署
    nginx缓存加速笔记
    记拼多多快团团api php 调用接口类
    记拼多多 快团团 php 快团团创建团购接口 增加商品库存接口 规格创建 上传商品图等接口
  • 原文地址:https://www.cnblogs.com/wangaohui/p/5534888.html
Copyright © 2020-2023  润新知