To add to @Χpẘ answer, the reverse of the command shouldn't be really hard as debugger extensions DLLs come with symbols (I already reversed one to explain the internal flag of the !heap command).
Note that it is just a quick overview, I haven't perused inside it too much.
According to the !address
documentation the command is located in exts.dll library. The command itself is located in Extension::address
.
There are two commands handled there, a kernel mode (KmAnalyzeAddress
) and a user mode one (UmAnalyzeAddress
).
Inside UmAnalyzeAddress
, the code:
- Parse the command line:
UmParseCommandLine(CmdArgs &,UmFilterData &)
- Check if the process PEB is available
IsTypeAvailable(char const *,ulong *)
with "${$ntdllsym}!_PEB"
- Allocate a std::list of user mode ranges:
std::list<UmRange,std::allocator<UmRange>>::list<UmRange,std::allocator<UmRange>>(void)
- Starts a loop to gather the required information:
UmRangeData::GetWowState(void)
UmMapBuild
UmMapFileMappings
UmMapModules
UmMapPebs
UmMapTebsAndStacks
UmMapHeaps
UmMapPageHeaps
UmMapCLR
UmMapOthers
Finally the results are finally output to screen using UmPrintResults
.
Each of the above function can be simplfied to basic components, e.g. UmFileMappings
has the following central code:
.text:101119E0 push edi ; hFile
.text:101119E1 push offset LibFileName ; "psapi.dll"
.text:101119E6 call ds:LoadLibraryExW(x,x,x)
.text:101119EC mov [ebp+hLibModule], eax
.text:101119F2 test eax, eax
.text:101119F4 jz loc_10111BC3
.text:101119FA push offset ProcName ; "GetMappedFileNameW"
.text:101119FF push eax ; hModule
.text:10111A00 mov byte ptr [ebp+var_4], 1
.text:10111A04 call ds:GetProcAddress(x,x)
Another example, to find each stacks, the code just loops trhough all threads, get their TEB and call:
.text:1010F44C push offset aNttib_stackbas ; "NtTib.StackBase"
.text:1010F451 lea edx, [ebp+var_17C]
.text:1010F457 lea ecx, [ebp+var_CC]
.text:1010F45D call ExtRemoteTyped::Field(char const *)
There is a lot of fetching from _PEB
, _TEB
, _HEAP
and other internal structures so it's not probably doable without going directly through those structures. So, I guess that some of the information returned by !address
are not accessible through usual / common APIs.