Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Searching memory including unknown values

Tags:

windbg

In WinDbg I can search the memory for bytes using the s command, e.g.

s 0012ff40 L?2000 48 65 6c 6c 6f

Is there also a way to include unknown bytes in the search sequence, e.g.

s 0012ff40 L?2000 48 65 ?? ?? ?? 6c 6f

where ?? is a byte with an arbitrary value?

Idea

How about doing ((memory XOR 48 65 00 00 00 6c 6f) AND FF FF 00 00 00 FF FF) and compare that against 00 00 00 00 00 00 00? But I don't know how to do that in WinDbg either.

like image 724
Thomas Weller Avatar asked Jan 06 '14 13:01

Thomas Weller


2 Answers

Am not sure if the search command supports wild card. But you can use .foreach command, to achieve what you want.

Here is a sample that i used to search a memory pattern such as ff ?? 00

.foreach (hit {s -[1]b 00007ffabc520000 L100 ff }) {db hit L3; s ${hit}+2 L1 00}

Here is a brief description of how it works :

NOTE - Open up the debugger help from windbg to get complete documentation. That is within Windbg, Help | Contents

{s -[1]b 00007ffabc520000 L100 ff }

Use -[1] flag with s, so that only the memory address is given as the output.

s ${hit}+2 L1 00

For each hit, pass that memory address to the next search command. Increase the memory by the number of bytes that you want to skip and mention the last part of search pattern.

db hit L3

From the memory that has the beginning of the patter, dump the entire length. This is just to confirm that we are getting the right results!

Hope this helps. In case you need further clarification, i can try to provide that as well.

like image 154
Player Avatar answered Jan 04 '23 14:01

Player


We can use pykd to achieve this. Find the downloads linked from PyKD Wiki or PyKD Downloads. When using WinDbg Preview, copy the DLLs into

%LOCALAPPDATA%\DBG\EngineExtensions

for 64 bit or

%LOCALAPPDATA%\DBG\EngineExtensions32

for 32 Bit.

Since this is only the WinDbg extension, you also need the Python module as well:

pip install pykd

Use the power of Python to do what WinDbg can't do. Save the following script in a good place for WinDbg, i.e. in a short path without spaces.

from pykd import *
import sys
import re
import struct

if len(sys.argv)<4:
    print("Wildcard search for memory")
    print("Usage:", sys.argv[0], "<address> <length> <pattern> [-v]", sep=" ")
    print("      <address>: Memory address where searching begins.")
    print("                 This can be a WinDbg expression like ntdll!NtCreateThreadEx.")
    print("      <length> : Number of bytes that will be considered as the haystack.")
    print("      <pattern>: Bytes that you're looking for. May contain ?? for unknown bytes.")
    print("      [-v]     : (optional) Verbose output")
    print()
    print("Examples:")
    print("     ", sys.argv[0], "00770000 L50 01 02 03 ?? 05")
    print("         will find 01 02 03 04 05 or 01 02 03 FF 05, if present in memory")
    sys.exit(0)

verbose = False
if sys.argv[-1][0:2] == "-v":
    verbose = True

if verbose:
    for n in range(1, len(sys.argv)):
        print(f"param {n}: " + sys.argv[n])

address = expr(sys.argv[1])
if verbose: print("Start address:", "0x{:08x}".format(address), sep=" ")

length = sys.argv[2]
length = length.replace("L?","") # consider large address range syntax
length = length.replace("L","") # consider address range syntax
length = expr(length)
if verbose: print("Length:", "0n"+str(length), "bytes", sep=" ")

regex = b""
for n in range(3, len(sys.argv) - 1 if verbose else 0):
    if sys.argv[n] == "??":
        regex += bytes(".", "ascii")
    else:
        char = struct.pack("B", expr(sys.argv[n]))
        if char == b".":
            regex += struct.pack("B", ord("\\"))
        regex += char
if verbose: print("Regex:", regex, sep=" ")

memorycontent = loadBytes(address, length)
if verbose: print("Memory:", memorycontent, sep=" ")

result = re.search(regex, bytes(memorycontent))
print("Found:", ' '.join("0x{:02x}".format(x) for x in result.group(0)), "at address", "0x{:08x}".format(address+result.start()))

The script constructs a Regex for a Bytes object. It uses . for the wildcard and escapes literal . to \..

Let's prepare a proper sample in WinDbg:

0:006> .dvalloc 1000
Allocated 1000 bytes starting at 00900000
0:000> eu 0x00900000 "Test.with.regex"
0:000> db 0x00900000 L0n30
00900000  54 00 65 00 73 00 74 00-2e 00 77 00 69 00 74 00  T.e.s.t...w.i.t.
00900010  68 00 2e 00 72 00 65 00-67 00 65 00 78 00        h...r.e.g.e.x.

Load the PyKD extension, so we'll be able to run the script:

0:006> .load pykd

and run the script:

0:000> !py d:\debug\scripts\memwild.py 00900000 L10 2e ?? 77
Found: 0x2e 0x00 0x77 at address 0x00900008
like image 30
Thomas Weller Avatar answered Jan 04 '23 12:01

Thomas Weller