!sb, !sd, !sq (search physical memory)

Description of '!sb, !sd, !sq' commands in HyperDbg.


!sb : search physical memory as Byte values

!sd : search physical memory as Double-word values (4 bytes)

!sq : search physical memory as Quad-word values (8 bytes)


!sb [StartAddress (hex)] [l Length (hex)] [BytePattern (hex)]

!sd [StartAddress (hex)] [l Length (hex)] [BytePattern (hex)]

!sq [StartAddress (hex)] [l Length (hex)] [BytePattern (hex)]


Searches the physical memory for a special byte(s).


[StartAddress (hex)]

The physical address of where we want to start searching from its address.

[l Length (hex)]

Length of the searching area.

[BytePattern (hex)]

Search for these bytes (pattern).

Process ID doesn't make sense in physical memory. If you specify pid for physical memory, it is ignored.


The following command is used to search for 4156415748starting from 76f010 to 76f010+ffff.

HyperDbg> !sb 76f010 l ffff 41 56 41 57 48 

The following example is used when we want to search for f0cc8549from 9016ADto 9016AD+fff in a different process (process id = 1dd0).

HyperDbg> !sd 9016AD pid 1dd0 l fff f0cc8549 

The following example is used when we want to search for f0cc8549from @rax+@rbx+5to @rax+@rbx+5+fff in a different process (process id = 1dd0).

HyperDbg> !sd @rax+@rbx+5 pid 1dd0 l fff f0cc8549 

The following example is used when we want to search for 0f450000`00c0888b 8b410000`0092b1b7 from 76f010 to 76f010+100.

HyperDbg> !sq 76f010 l 100 0f450000`00c0888b 8b410000`0092b1b7


This function works by calling DeviceIoControl with IOCTL = IOCTL_DEBUGGER_SEARCH_MEMORY, you have to send it in the following structure.

typedef struct _DEBUGGER_SEARCH_MEMORY {

  UINT64 Address;                            // Target adddress to start searching
  UINT64 Length;                             // Length of bytes to search
  UINT32 ProcessId;                          // specifies the process id
  DEBUGGER_SEARCH_MEMORY_TYPE MemoryType;    // Type of memory
  DEBUGGER_SEARCH_MEMORY_BYTE_SIZE ByteSize; // Modification size
  UINT32 CountOf64Chunks;
  UINT32 FinalStructureSize;


The Address is where we want to start searching from its memory, and it can be both a physical address or a virtual address.

ProcessId is the process that we want to modify based on its memory layout (cr3), it can't be null or zero.

MemoryType shows whether the Address is a physical address or a virtual address.

You can see its values in the following enum :


ByteSize shows whether we want to search the target Address in a byte, dword, or qword format.


The above structure is added on top of an array of 64-bit values, which is the new content to the memory.

For example, if you want to search in the memory address of the target for0x90 0x90 then you should provide an array of 0x0000000000000090 and 0x0000000000000090 and append it to the end of the above structure. The count of these chunks is stored at CountOf64Chunks in the above structure and the final buffer that will be sent into the kernel has a size of FinalStructureSize bytes.

Also, you should provide a buffer (size = MaximumSearchResults * sizeof(UINT64)) as the output buffer, so the kernel-mode module will fill this buffer with a 64-bit array or addresses that match our search results.

You can read the result buffer as an UINT64 array, and if you encounter a null entry, then it means there is no other result.


  • You can search for as many bytes as you need in byte, dword, and qword formats. Just add the multiple byte(s) values to the end of the command.

  • In the current implementation of physical memory search, the address should also be available and mapped to the target process's virtual address space.

Physical addresses are not validated in HyperDbg, which means if you access an invalid physical address, then the debuggee halts or crashes.

This command will continue the debuggee for some time (in Debugger Mode). This means that you lose the current context (registers & memory) after executing this command.




Last updated