Build format string atoms for writing some data at a given address where some bytes are not allowed to appear in addresses (such as nullbytes). This function is simple and does not try to minimize the number of atoms. For example, if there are no bad bytes, it simply returns one at
(address, data, badbytes=frozenset())
| 282 | return AtomWrite(self.start + start, stop - start, (self.integer >> shift) & clip, (self.mask >> shift) & clip) |
| 283 | |
| 284 | def make_atoms_simple(address, data, badbytes=frozenset()): |
| 285 | """ |
| 286 | Build format string atoms for writing some data at a given address where some bytes are not allowed |
| 287 | to appear in addresses (such as nullbytes). |
| 288 | |
| 289 | This function is simple and does not try to minimize the number of atoms. For example, if there are no |
| 290 | bad bytes, it simply returns one atom for each byte: |
| 291 | |
| 292 | >>> pwnlib.fmtstr.make_atoms_simple(0x0, b"abc", set()) |
| 293 | [AtomWrite(start=0, size=1, integer=0x61, mask=0xff), AtomWrite(start=1, size=1, integer=0x62, mask=0xff), AtomWrite(start=2, size=1, integer=0x63, mask=0xff)] |
| 294 | |
| 295 | If there are bad bytes, it will try to bypass by skipping addresses containing bad bytes, otherwise a |
| 296 | RuntimeError will be raised: |
| 297 | |
| 298 | >>> pwnlib.fmtstr.make_atoms_simple(0x61, b'abc', b'\x62') |
| 299 | [AtomWrite(start=97, size=2, integer=0x6261, mask=0xffff), AtomWrite(start=99, size=1, integer=0x63, mask=0xff)] |
| 300 | >>> pwnlib.fmtstr.make_atoms_simple(0x61, b'a'*0x10, b'\x62\x63\x64\x65\x66\x67\x68') |
| 301 | [AtomWrite(start=97, size=8, integer=0x6161616161616161, mask=0xffffffffffffffff), AtomWrite(start=105, size=1, integer=0x61, mask=0xff), AtomWrite(start=106, size=1, integer=0x61, mask=0xff), AtomWrite(start=107, size=1, integer=0x61, mask=0xff), AtomWrite(start=108, size=1, integer=0x61, mask=0xff), AtomWrite(start=109, size=1, integer=0x61, mask=0xff), AtomWrite(start=110, size=1, integer=0x61, mask=0xff), AtomWrite(start=111, size=1, integer=0x61, mask=0xff), AtomWrite(start=112, size=1, integer=0x61, mask=0xff)] |
| 302 | """ |
| 303 | data = bytearray(data) |
| 304 | if not badbytes: |
| 305 | return [AtomWrite(address + i, 1, d) for i, d in enumerate(data)] |
| 306 | |
| 307 | if any(x in badbytes for x in pack(address)): |
| 308 | raise RuntimeError("impossible to avoid a bad byte in starting address %x" % address) |
| 309 | |
| 310 | i = 0 |
| 311 | out = [] |
| 312 | end = address + len(data) |
| 313 | while i < len(data): |
| 314 | candidate = AtomWrite(address + i, 1, data[i]) |
| 315 | while candidate.end < end and any(x in badbytes for x in pack(candidate.end)): |
| 316 | candidate = candidate.union(AtomWrite(candidate.end, 1, data[i + candidate.size])) |
| 317 | |
| 318 | sz = min([s for s in SPECIFIER if s >= candidate.size] + [float("inf")]) |
| 319 | if candidate.start + sz > end: |
| 320 | raise RuntimeError("impossible to avoid badbytes starting after offset %d (address %#x)" % (i, i + address)) |
| 321 | i += candidate.size |
| 322 | candidate = candidate.union(AtomWrite(candidate.end, sz - candidate.size, 0, 0)) |
| 323 | out.append(candidate) |
| 324 | return out |
| 325 | |
| 326 | |
| 327 | def merge_atoms_writesize(atoms, maxsize): |
no test coverage detected