def test_findv(): payload = b"".join([ pad.null( pad.null(b"a" * 0x200 + b"pattern", 0x500) + b"pattern2", 0x1000), pad.null( pad.null(b"b" * 0x200 + b"pattern", 0x500) + b"pattern2", 0x1000), b"c" * 0x1000, pad.null( pad.null(b"d" * 0x200 + b"pattern", 0x500) + b"pattern2", 0x1000) ]) regions = [ Region(0x400000, 0x1000, 0, 0, 0, 0), Region(0x401000, 0x1000, 0, 0, 0, 0x1000), Region(0x402000, 0x1000, 0, 0, 0, 0x2000), Region(0x410000, 0x1000, 0, 0, 0, 0x3000), ] p = procmem(payload, regions=regions) assert list(p.findv(b"pattern")) == [ 0x400200, 0x400500, 0x401200, 0x401500, 0x410200, 0x410500 ] assert list(p.findv(b"pattern", 0x401100, 0x405)) == [0x401200] assert list(p.findv(b"pattern", length=0x10300)) == [ 0x400200, 0x400500, 0x401200, 0x401500, 0x410200 ] assert list(p.findv(b"pattern", 0x401508)) == [0x410200, 0x410500] assert list(p.findv(b"pattern", 0x403508)) == [0x410200, 0x410500]
def test_findbytes(): payload = b" " * 0x1000 + pad.null( b"\xffoo\x00bar thisis0test\n hAAAA\xc3\xc0\xc2\xc4\n\n\x10\x2f\x1f\x1a\x1b\x1f\x1d\xbb\xcc\xdd\xff", 0x10000) buf = procmem(payload, base=0x400000) assert list(buf.findbytesv("c? c? c? 0A")) == [0x40101B] assert list(buf.findbytesv(b"1f ?? ?b")) == [0x401022, 0x401025] assert list(buf.findbytesv("?f ?? ?? 00")) == [0x401000, 0x40102A] assert not list(buf.findbytesv(enhex(b"test hAAAA"))) assert list(buf.findbytesv(enhex(b"test\n hAAAA"))) assert list(buf.findbytesv(enhex(b"is"), length=0x100b)) == [0x40100a] assert list(buf.findbytesv(enhex(b"is"), length=0x100d)) == [0x40100a, 0x40100c] assert list(buf.findbytesv(enhex(b"is"), addr=0x40100b, length=0x100d)) == [0x40100c] payload = b"".join( [b"a" * 0x1000, b"b" * 0x1000, b"c" * 0x1000, b"d" * 0x1000]) regions = [ Region(0x400000, 0x1000, 0, 0, 0, 0), Region(0x401000, 0x1000, 0, 0, 0, 0x1000), Region(0x402000, 0x1000, 0, 0, 0, 0x2000), Region(0x410000, 0x1000, 0, 0, 0, 0x3000), ] p = procmem(payload, regions=regions) assert next(p.findbytesv(enhex(b"dddd"))) == 0x410000
def test_patchv(): payload = b"".join( [b"a" * 0x1000, b"b" * 0x1000, b"c" * 0x1000, b"d" * 0x1000]) regions = [ Region(0x400000, 0x1000, 0, 0, 0, 0), Region(0x401000, 0x1000, 0, 0, 0, 0x1000), Region(0x402000, 0x1000, 0, 0, 0, 0x2000), Region(0x410000, 0x1000, 0, 0, 0, 0x3000), ] p = procmem(payload, regions=regions) with pytest.raises( ValueError, match= "Patched bytes range must be contained within single, existing region" ): p.patchv(0x3fffff, b"p" * 16) p.patchv(0x400000, b"p" * 16) assert p.readv(0x400000, 17) == b"p" * 16 + b"a" with pytest.raises( ValueError, match= "Patched bytes range must be contained within single, existing region" ): p.patchv(0x401fff, b"p" * 2)
def test_readv(): payload = b"".join([ b"a" * 0x1000, b"b" * 0x1000, b"c" * 0x1000, b"d" * 0x1000 ]) regions = [ Region(0x400000, 0x1000, 0, 0, 0, 0), Region(0x401000, 0x1000, 0, 0, 0, 0x1000), Region(0x402000, 0x1000, 0, 0, 0, 0x2000), Region(0x410000, 0x1000, 0, 0, 0, 0x3000), ] p = procmem(payload, regions=regions) assert p.readv(0x3fffff, 16) == b"" assert p.readv(0x400000, 16) == b"a" * 16 assert isinstance(p.readv(0x400000, 16), binary_type) assert p.readv(0x400fff, 16) == b"a" + b"b" * 15 assert p.readv(0x400ffe, 0x1100) == b"aa" + (b"b" * 0x1000) + (b"c" * 0xfe) assert p.readv(0x402ffe, 0x1000) == b"cc" assert p.readv(0x402ffe) == b"cc" assert p.readv(0x403000) == b"" assert p.readv(0x401000) == b"b" * 0x1000 + b"c" * 0x1000 assert p.readv(0x40ffff) == b"" assert p.readv(0x410000) == b"d" * 0x1000 assert p.readv(0x410ffe) == b"dd"
def mem(): # aaaaaaa bbbbbbccccccccdddd eeee payload = b"0123456789abcdefghijklmnopqrstuvwxyz" regions = [ Region(0x10000, 7, 0, 0, 0, 1), Region(0x10007, 6, 0, 0, 0, 10), Region(0x10100, 8, 0, 0, 0, 16), Region(0x10108, 4, 0, 0, 0, 24), Region(0x10200, 4, 0, 0, 0, 31) ] # v---0x10000 v---- 0x10100 v-- 0x10200 # VM: .....1234567abcdef..........ghijklmnopqr ..........vwxy....... return procmem(payload, base=0x10000, regions=regions)
def test_single_region(): payload = b"0123456789" regions = [Region(0x10000, 8, 0, 0, 0, 1)] mem = procmem(payload, regions=regions) assert list(mem.iter_regions()) == mem.regions assert list(mem.iter_regions(addr=0xffff)) == mem.regions assert list(mem.iter_regions(addr=0x10000)) == mem.regions assert list(mem.iter_regions(addr=0x10007)) == mem.regions assert list(mem.iter_regions(addr=0x10008)) == [] assert list(mem.iter_regions(offset=0)) == mem.regions assert list(mem.iter_regions(offset=1)) == mem.regions assert list(mem.iter_regions(offset=8)) == mem.regions assert list(mem.iter_regions(offset=9)) == [] assert list(mem.iter_regions(length=0)) == [] assert list(mem.iter_regions(length=1)) == mem.regions assert list(mem.iter_regions(addr=0xffff, length=1)) == [] assert list(mem.iter_regions(addr=0xffff, length=2)) == mem.regions assert list(mem.iter_regions(addr=0xffff, length=0x10)) == mem.regions assert list(mem.iter_regions(addr=0x10007, length=0x10)) == mem.regions assert list(mem.iter_regions(addr=0x10008, length=0x10)) == [] with pytest.raises(ValueError): # ValueError("Don't know how to retrieve length-limited regions with offset from unmapped area") list(mem.iter_regions(offset=0, length=1)) assert list(mem.iter_regions(offset=1, length=1)) == mem.regions
def test_simple_findv(): payload = b"12ab34cd45ef" regions = [ Region(0x10000, 2, 0, 0, 0, 2), Region(0x10002, 2, 0, 0, 0, 6), Region(0x10010, 2, 0, 0, 0, 10) ] p = procmem(payload, regions=regions) assert list(p.findv(b"12")) == [] assert list(p.findv(b"ab")) == [0x10000] assert list(p.findv(b"ab", addr=0x10002)) == [] assert list(p.findv(b"ab34")) == [] assert list(p.findv(b"abcd")) == [0x10000] assert list(p.findv(b"abcdef")) == [] assert list(p.findv(b"cdef")) == [] assert list(p.findv(b"ef")) == [0x10010]
def test_patchv(): payload = b"".join( [b"a" * 0x1000, b"b" * 0x1000, b"c" * 0x1000, b"d" * 0x1000]) regions = [ Region(0x400000, 0x1000, 0, 0, 0, 0), Region(0x401000, 0x1000, 0, 0, 0, 0x1000), Region(0x402000, 0x1000, 0, 0, 0, 0x2000), Region(0x410000, 0x1000, 0, 0, 0, 0x3000), ] p = procmem(payload, regions=regions) with pytest.raises(ValueError, match="Cross-region patching is not supported"): p.patchv(0x3fffff, b"p" * 16) p.patchv(0x400000, b"p" * 16) assert p.readv(0x400000, 17) == b"p" * 16 + b"a" with pytest.raises(ValueError, match="Cross-region patching is not supported"): p.patchv(0x401fff, b"p" * 2)
def test_single_region_trim(): payload = b"0123456789" regions = [Region(0x10000, 8, 0, 0, 0, 1)] mem = procmem(payload, regions=regions) assert list(mem.iter_regions(trim=True)) == mem.regions assert list(mem.iter_regions(addr=0xffff, trim=True)) == mem.regions assert list(mem.iter_regions(addr=0x10000, trim=True)) == mem.regions assert list(mem.iter_regions( addr=0x10007, trim=True)) == [Region(0x10007, 1, 0, 0, 0, 8)] assert list(mem.iter_regions(addr=0x10008, trim=True)) == [] assert list(mem.iter_regions(offset=0, trim=True)) == mem.regions assert list(mem.iter_regions(offset=1, trim=True)) == mem.regions assert list(mem.iter_regions( offset=8, trim=True)) == [Region(0x10007, 1, 0, 0, 0, 8)] assert list(mem.iter_regions(offset=9, trim=True)) == [] assert list(mem.iter_regions(length=0, trim=True)) == [] assert list(mem.iter_regions( length=1, trim=True)) == [Region(0x10000, 1, 0, 0, 0, 1)] assert list(mem.iter_regions(addr=0xffff, length=1, trim=True)) == [] assert list(mem.iter_regions( addr=0xffff, length=2, trim=True)) == [Region(0x10000, 1, 0, 0, 0, 1)] assert list(mem.iter_regions( addr=0xffff, length=8, trim=True)) == [Region(0x10000, 7, 0, 0, 0, 1)] assert list( mem.iter_regions(addr=0x10001, length=4, trim=True)) == [Region(0x10001, 4, 0, 0, 0, 2)] assert list( mem.iter_regions(addr=0x10007, length=0x10, trim=True)) == [Region(0x10007, 1, 0, 0, 0, 8)] assert list(mem.iter_regions(addr=0x10008, length=0x10, trim=True)) == [] with pytest.raises(ValueError): # ValueError("Don't know how to retrieve length-limited regions with offset from unmapped area") list(mem.iter_regions(offset=0, length=1, trim=True)) assert list(mem.iter_regions( offset=1, length=1, trim=True)) == [Region(0x10000, 1, 0, 0, 0, 1)] assert list(mem.iter_regions( offset=4, length=2, trim=True)) == [Region(0x10003, 2, 0, 0, 0, 4)]
def test_procmem_yara(): payload = b"".join( [b"a" * 0x1000, b"b" * 0x1000, b"c" * 0x1000, b"d" * 0x1000]) regions = [ Region(0x400000, 0x1000, 0, 0, 0, 0), Region(0x401000, 0x1000, 0, 0, 0, 0x1000), Region(0x402000, 0x1000, 0, 0, 0, 0x2000), Region(0x410000, 0x1000, 0, 0, 0, 0x3000), ] p = ProcessMemory(payload, regions=regions) ruleset = Yara( name="regions", strings={ "a_series": "a" * 64, "b_series": "b" * 64, "c_series": "c" * 64, "d_series": "d" * 64, "a_and_b": "a" * 64 + "b" * 64, "b_and_c": "b" * 64 + "c" * 64, "c_and_d": "c" * 64 + "d" * 64 }, condition= "$a_series and $b_series and $c_series and $d_series and $a_and_b and ( $b_and_c or $c_and_d )" ) matchp = p.yarap(ruleset) matchv = p.yarav(ruleset) assert matchp assert matchv assert set(matchp.regions.keys()).difference(set( matchv.regions.keys())) == {"c_and_d"} assert [matchv.regions.a_and_b[0], matchv.regions.b_and_c[0]] == [0x400fc0, 0x401fc0] assert matchv.regions.a_series == list(range(0x400000, 0x401000 - 63)) assert matchv.regions.b_series == list(range(0x401000, 0x402000 - 63)) assert matchv.regions.c_series == list(range(0x402000, 0x403000 - 63)) assert matchv.regions.d_series == list(range(0x410000, 0x411000 - 63)) assert matchv.regions.get("a_series") assert not matchv.regions.get("e_series")
def test_regions_multi(mem): # Test simple enum from specified address assert list(mem.iter_regions()) == mem.regions assert list(mem.iter_regions(0x1000)) == mem.regions assert list(mem.iter_regions(0x10000)) == mem.regions assert list(mem.iter_regions(0x10104)) == [ Region(0x10100, 8, 0, 0, 0, 16), Region(0x10108, 4, 0, 0, 0, 24), Region(0x10200, 4, 0, 0, 0, 31) ] assert list(mem.iter_regions(0x10203)) == [Region(0x10200, 4, 0, 0, 0, 31)] assert list(mem.iter_regions(0x10204)) == [] # Test simple enum from specified offset assert list(mem.iter_regions(offset=0)) == mem.regions assert list(mem.iter_regions(offset=10)) == mem.regions[1:] assert list(mem.iter_regions(offset=20)) == mem.regions[2:] assert list( mem.iter_regions(offset=30)) == [Region(0x10200, 4, 0, 0, 0, 31)] assert list(mem.iter_regions(offset=40)) == [] assert list(mem.iter_regions(0xffff, contiguous=True)) == [] assert list(mem.iter_regions(0x10000, contiguous=True)) == [ Region(0x10000, 7, 0, 0, 0, 1), Region(0x10007, 6, 0, 0, 0, 10) ] assert list(mem.iter_regions(0x10002, length=8, contiguous=True, trim=True)) == [ Region(0x10002, 5, 0, 0, 0, 3), Region(0x10007, 3, 0, 0, 0, 10) ] assert list(mem.iter_regions(offset=1, contiguous=True)) == [ Region(0x10000, 7, 0, 0, 0, 1), Region(0x10007, 6, 0, 0, 0, 10) ] assert list(mem.iter_regions(offset=2, length=0x9f)) == [ Region(0x10000, 7, 0, 0, 0, 1), Region(0x10007, 6, 0, 0, 0, 10) ] assert list(mem.iter_regions(offset=2, length=0x100)) == [ Region(0x10000, 7, 0, 0, 0, 1), Region(0x10007, 6, 0, 0, 0, 10), Region(0x10100, 8, 0, 0, 0, 16) ] assert list(mem.iter_regions(offset=2, length=0x100, trim=True)) == [ Region(0x10001, 6, 0, 0, 0, 2), Region(0x10007, 6, 0, 0, 0, 10), Region(0x10100, 1, 0, 0, 0, 16) ]