├── .gitignore ├── BitFieldAnalyzer.h ├── CmdExt.cpp ├── CmdExt.h ├── CmdInterface.h ├── CmdList.cpp ├── CmdList.h ├── LICENSE ├── MemoryAnalyzer.cpp ├── MemoryAnalyzer.h ├── README.md ├── dbgdata.cpp ├── dbgdata.h ├── demos ├── helloworld_viz_5494_ntdll!LdrInitializeThunk.svg ├── helloworld_viz_5494_ntdll!RtlUserThreadStart.svg ├── helloworld_viz_6710_ntdll!RtlUserThreadStart.svg ├── helloworld_viz_forest.svg ├── page_00000052182ff8f0_link.svg ├── page_00000052182ff8f0_link.svgmem_access_0x217c6446670_8.svg ├── page_00000052182ff8f0_link.svgmem_access_0x217c6446680_8.svg ├── page_00000052182ff8f0_link.svgmem_access_0x217c64533f0_8.svg ├── page_00000052182ff8f0_link.svgmem_access_0x217c6454420_8.svg ├── page_00000052182ff8f0_link.svgmem_access_0x217c6456720_8.svg ├── page_00000052182ff8f0_link.svgmem_access_0x217c64568a0_8.svg ├── page_00000052182ff8f0_link.svgmem_access_0x217c645a090_8.svg ├── page_00000052182ff8f0_link.svgmem_access_0x217c645b3b0_8.svg ├── page_00000052182ff8f0_link.svgmem_access_0x217c645b3fd_8.svg ├── page_00000052182ff8f0_link.svgmem_access_0x217c645c9b0_8.svg ├── page_00000052182ff8f0_link.svgmem_access_0x217c645ca50_8.svg ├── page_00000052`182ff730_1.svg ├── page_00000052`182ff8f0_2.svg └── page_00000060a11ff000.svg ├── dk.def ├── dk.sln ├── dk.vcxproj ├── dk.vcxproj.filters ├── dk.vcxproj.user ├── dml.cpp ├── dml.h ├── engextcpp.cpp ├── handle.cpp ├── handle.h ├── heap.cpp ├── heap.h ├── hexsvg.cpp ├── hexsvg.h ├── list.cpp ├── list.h ├── memory.cpp ├── memory.h ├── model.cpp ├── model.h ├── module.cpp ├── module.h ├── object.cpp ├── object.h ├── page.cpp ├── page.h ├── pe.cpp ├── pe.h ├── pool.cpp ├── pool.h ├── process.cpp ├── process.h ├── session.cpp ├── session.h ├── stack.cpp ├── stack.h ├── svg ├── Coordinates.h └── SvgElements.h ├── thread.cpp ├── thread.h ├── token.cpp ├── token.h ├── ttd └── TTD.hpp ├── ttd_cmd.cpp ├── ttd_cmd.h ├── type.cpp ├── type.h ├── usermode.cpp └── usermode.h /.gitignore: -------------------------------------------------------------------------------- 1 | .vs/ 2 | x64/ 3 | -------------------------------------------------------------------------------- /BitFieldAnalyzer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | class CBitFieldAnalyzer 11 | { 12 | public: 13 | CBitFieldAnalyzer() 14 | {} 15 | 16 | CBitFieldAnalyzer( 17 | __in const map& definitions 18 | ) 19 | { 20 | for (auto it = definitions.begin(); 21 | it != definitions.end(); 22 | it++) 23 | { 24 | m_definitions[it->first] = it->second; 25 | } 26 | } 27 | 28 | CBitFieldAnalyzer( 29 | __in map&& definitions 30 | ) 31 | :m_definitions(move(definitions)) 32 | { 33 | } 34 | 35 | string 36 | GetText( 37 | __in const uint32_t compound, 38 | __in bool pureText = false 39 | ) 40 | { 41 | stringstream ss; 42 | if (!pureText) 43 | ss << "0x" << hex << noshowbase << setw(8) << setfill('0') << compound << "("; 44 | 45 | for (auto it = m_definitions.begin(); 46 | it != m_definitions.end(); 47 | it++) 48 | { 49 | if (it->first & compound) 50 | ss << it->second << ","; 51 | } 52 | 53 | if (!pureText) 54 | ss << ")"; 55 | 56 | return ss.str(); 57 | } 58 | 59 | private: 60 | map m_definitions; 61 | }; 62 | -------------------------------------------------------------------------------- /CmdExt.cpp: -------------------------------------------------------------------------------- 1 | #include "CmdExt.h" 2 | #include "CmdList.h" 3 | 4 | #include 5 | 6 | ExtExtension* g_ExtInstancePtr = CCmdExt::Instance(); 7 | 8 | CCmdExt::CCmdExt() 9 | { 10 | ExtSetDllMain::ExtSetDllMain(CmdListMain); 11 | } 12 | 13 | bool CCmdExt::is_reg(string & str) 14 | { 15 | static vector regs{ { 16 | "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rsp", "rbp", "rip", 17 | "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "r16" 18 | } }; 19 | 20 | return find(regs.begin(), regs.end(), str.c_str()) != regs.end(); 21 | } 22 | 23 | void CCmdExt::dk(void) 24 | { 25 | try 26 | { 27 | string raw_args = GetRawArgStr(); 28 | vector args; 29 | for (size_t i = 0, j = 0; i <= raw_args.size(); i++) 30 | { 31 | if (raw_args[i] == ' ' || i == raw_args.size()) 32 | { 33 | if (i > j) 34 | args.push_back(string(raw_args, j, i - j)); 35 | 36 | j = i+1; 37 | } 38 | } 39 | 40 | if (!args.empty()) 41 | { 42 | string cmd = args[0]; 43 | 44 | if (CMD_LIST->IsValidCmd(cmd)) 45 | CMD_LIST->HandleCmd(cmd, args); 46 | else 47 | { 48 | Out("Not valid command: !dk %s! Try following commands:\n", cmd.c_str()); 49 | 50 | for (auto cmd : CMD_LIST->GetValidCommands()) 51 | { 52 | Out("\t!dk %s\n", cmd.c_str()); 53 | } 54 | } 55 | } 56 | else 57 | { 58 | Err("Invalid parameters\n"); 59 | } 60 | } 61 | FC; 62 | } 63 | 64 | CCmdExt::~CCmdExt() 65 | { 66 | } 67 | 68 | 69 | size_t CCmdExt::reg(size_t reg) 70 | { 71 | try 72 | { 73 | DEBUG_VALUE reg_val = { 0, }; 74 | m_Registers->GetValue((ULONG)reg, ®_val); 75 | 76 | return reg_val.I64; 77 | } 78 | FC; 79 | 80 | return 0; 81 | } 82 | 83 | size_t CCmdExt::getSymbolAddr(const char* name) 84 | { 85 | size_t addr = 0; 86 | try 87 | { 88 | m_Symbols->GetOffsetByName(name, &addr); 89 | } 90 | FC; 91 | return addr; 92 | } 93 | 94 | tuple CCmdExt::getAddrSymbol(size_t addr) 95 | { 96 | string name; 97 | ULONG64 disp = 0; 98 | try 99 | { 100 | char* symbol = nullptr; 101 | ULONG len = 0; 102 | if (S_OK == m_Symbols->GetNameByOffset(addr, symbol, 0, &len, 0)) 103 | { 104 | symbol = new (nothrow) char[len]; 105 | 106 | if (symbol != nullptr && 107 | S_OK == m_Symbols->GetNameByOffset(addr, symbol, len, &len, &disp)) 108 | name = symbol; 109 | 110 | if (symbol != nullptr) 111 | delete[] symbol; 112 | } 113 | } 114 | FC; 115 | return make_tuple(name, disp); 116 | } 117 | 118 | size_t CCmdExt::reg_of(const char* reg_v) 119 | { 120 | #define REG_RAX 0 121 | #define REG_RCX 1 122 | #define REG_RDX 2 123 | #define REG_RBX 3 124 | #define REG_RSP 4 125 | #define REG_RBP 5 126 | #define REG_RSI 6 127 | #define REG_RDI 7 128 | #define REG_R8 8 129 | #define REG_R9 9 130 | #define REG_R10 10 131 | #define REG_R11 11 132 | #define REG_R12 12 133 | #define REG_R13 13 134 | #define REG_R14 14 135 | #define REG_R15 15 136 | #define REG_RIP 16 137 | 138 | static map regs_map{ 139 | {"rip", REG_RIP}, {"rbp", REG_RBP}, {"rsp", REG_RSP}, 140 | {"rax", REG_RAX}, {"rbx", REG_RBX}, {"rcx", REG_RCX}, {"rdx", REG_RDX}, 141 | {"rsi", REG_RSI}, {"rdi", REG_RDI}, 142 | {"r8", REG_R8},{ "r9", REG_R9 },{ "r10", REG_R10 },{ "r11", REG_R11 }, 143 | { "r12", REG_R12 },{ "r13", REG_R13 },{ "r14", REG_R14 },{ "r15", REG_R15 } 144 | }; 145 | 146 | uint32_t index = 0; 147 | if (m_Registers->GetIndexByName(reg_v, (PULONG)&index) == S_OK) 148 | { 149 | return reg(index); 150 | } 151 | 152 | if (regs_map.find(reg_v) == regs_map.end()) 153 | return 0; 154 | 155 | return reg(regs_map[reg_v]); 156 | 157 | #undef REG_RAX 158 | #undef REG_RCX 159 | #undef REG_RDX 160 | #undef REG_RBX 161 | #undef REG_RSP 162 | #undef REG_RBP 163 | #undef REG_RSI 164 | #undef REG_RDI 165 | #undef REG_R8 166 | #undef REG_R9 167 | #undef REG_R10 168 | #undef REG_R11 169 | #undef REG_R12 170 | #undef REG_R13 171 | #undef REG_R14 172 | #undef REG_R15 173 | #undef REG_RIP 174 | } 175 | 176 | bool CCmdExt::valid_addr(size_t addr) 177 | { 178 | bool valid = true; 179 | try 180 | { 181 | read(addr); 182 | } 183 | catch (ExtException) 184 | { 185 | valid = false; 186 | } 187 | 188 | return valid; 189 | } 190 | 191 | wstring CCmdExt::readUnicodeString(size_t addr) 192 | { 193 | wstring name; 194 | try 195 | { 196 | ExtRemoteTyped us("(nt!_UNICODE_STRING*)@$extin", addr); 197 | size_t name_addr = us.Field("Buffer").GetLongPtr(); 198 | size_t name_len = us.Field("Length").GetUshort(); 199 | wchar_t* obj_name_buf = new wchar_t[name_len / 2 + 1]; 200 | memset(obj_name_buf, 0, (name_len / 2 + 1) * sizeof(wchar_t)); 201 | if (S_OK == EXT_D_IDebugDataSpaces->ReadVirtual(name_addr, obj_name_buf, (ULONG)name_len, NULL)) 202 | name = obj_name_buf; 203 | 204 | delete[] obj_name_buf; 205 | } 206 | FC; 207 | 208 | return name; 209 | } 210 | 211 | string CCmdExt::size2str(size_t value) 212 | { 213 | string str(""); 214 | try 215 | { 216 | size_t k_size = value / 1024; 217 | size_t m_size = k_size / 1024; 218 | size_t g_size = m_size / 1024; 219 | size_t t_size = g_size / 1024; 220 | 221 | stringstream ss; 222 | 223 | /*ss << showbase << hex; 224 | 225 | if (t_size != 0) 226 | ss << setw(6) << t_size << " T "; 227 | 228 | if (g_size != 0) 229 | ss << setw(6) << g_size - t_size * 1024 << " G "; 230 | 231 | if (m_size != 0) 232 | ss << setw(6) << m_size - g_size * 1024 << " M "; 233 | 234 | if (k_size != 0) 235 | ss << setw(6) << k_size - m_size * 1024 << " K "; 236 | 237 | ss << value - k_size * 1024; 238 | 239 | ss << endl;*/ 240 | ss << noshowbase << dec; 241 | 242 | if (t_size != 0) 243 | ss << setw(6) << t_size << " T "; 244 | 245 | if (g_size != 0) 246 | ss << setw(6) << g_size - t_size * 1024 << " G "; 247 | 248 | if (m_size != 0) 249 | ss << setw(6) << m_size - g_size * 1024 << " M "; 250 | 251 | if (k_size != 0) 252 | ss << setw(6) << k_size - m_size * 1024 << " K "; 253 | 254 | ss << value - k_size * 1024; 255 | 256 | //ss << endl; 257 | 258 | str = ss.str(); 259 | } 260 | FC; 261 | 262 | return str; 263 | } 264 | 265 | HRESULT CCmdExt::x(string cmd) 266 | { 267 | try 268 | { 269 | return m_Control->Execute(DEBUG_OUTCTL_ALL_CLIENTS, cmd.c_str(), DEBUG_EXECUTE_ECHO); 270 | } 271 | FC; 272 | 273 | return S_FALSE; 274 | } 275 | 276 | size_t CCmdExt::getIntArg(vector& args, size_t idx, size_t default_val) 277 | { 278 | if (idx < 0 || idx >= args.size()) 279 | return default_val; 280 | 281 | stringstream ss; 282 | 283 | ss << nouppercase << args[idx]; 284 | 285 | string arg = ss.str(); 286 | 287 | if (is_reg(arg)) 288 | { 289 | return reg_of(arg.c_str()); 290 | } 291 | 292 | if (arg.size() == 17 && arg[8] == '`') 293 | { 294 | for (size_t i = 8; i < 17; i++) 295 | arg[i] = arg[i + 1]; 296 | arg.resize(16); 297 | } 298 | else if (arg.size() == 19 && arg[10] == '`' && arg[0] == '0' && (arg[1] == 'x' || arg[1] == 'X')) 299 | { 300 | for (size_t i = 10; i < 19; i++) 301 | arg[i] = arg[i + 1]; 302 | arg.resize(18); 303 | } 304 | 305 | bool b_hex = true; 306 | if (arg[0] == '0') 307 | { 308 | if (arg[1] == 'n' || arg[1] == 'N') 309 | { 310 | arg = arg.substr(2); 311 | b_hex = false; 312 | } 313 | else if (arg[1] == 'x' || arg[1] == 'X') 314 | { 315 | arg = arg.substr(2); 316 | b_hex = true; 317 | } 318 | } 319 | 320 | try 321 | { 322 | size_t val = strtoull(arg.c_str(), nullptr, b_hex ? 16 : 10); 323 | if (val == 0) 324 | return default_val; 325 | 326 | return val; 327 | } 328 | catch (exception) 329 | { 330 | Err("Invalid conversion!\n"); 331 | } 332 | 333 | return default_val; 334 | } 335 | 336 | ExtCommandDesc g_dk_desc( 337 | "dk", 338 | (ExtCommandMethod)&CCmdExt::dk, 339 | "Customized command line parse entry", 340 | "{{custom}}"); 341 | 342 | extern "C" 343 | HRESULT 344 | CALLBACK 345 | dk( 346 | __in PDEBUG_CLIENT client, 347 | __in_opt PCSTR args) 348 | { 349 | if (!g_Ext.IsSet()) 350 | { 351 | return E_UNEXPECTED; 352 | } 353 | return g_Ext->CallCommand(&g_dk_desc, client, args); 354 | } 355 | -------------------------------------------------------------------------------- /CmdExt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | #include 11 | 12 | #define INITGUID 13 | #define EXT_CLASS CCmdExt 14 | #include 15 | 16 | #define s_CmdExt CCmdExt::Instance() 17 | 18 | #define EXT_F_READ s_CmdExt->read 19 | #define EXT_F_WRITE s_CmdExt->write 20 | #define EXT_F_READX s_CmdExt->readX 21 | #define EXT_F_EXEC s_CmdExt->x 22 | #define EXT_F_IntArg s_CmdExt->getIntArg 23 | #define EXT_F_ValidAddr s_CmdExt->valid_addr 24 | #define EXT_F_Sym2Addr s_CmdExt->getSymbolAddr 25 | #define EXT_F_Addr2Sym s_CmdExt->getAddrSymbol 26 | #define EXT_F_REG s_CmdExt->reg 27 | #define EXT_F_REG_OF s_CmdExt->reg_of 28 | #define EXT_F_IS_IN_RANGE s_CmdExt->is_in_range 29 | #define EXT_F_Size2Str s_CmdExt->size2str 30 | #define EXT_F_READ_USTR s_CmdExt->readUnicodeString 31 | #define EXT_F_THROW s_CmdExt->ThrowRemote 32 | 33 | #define EXT_F_OUT s_CmdExt->Out 34 | #define EXT_F_ERR s_CmdExt->Err 35 | #define EXT_F_DML s_CmdExt->Dml 36 | #define EXT_F_STR_OUT s_CmdExt->out_str 37 | #define EXT_F_STR_ERR s_CmdExt->err_str 38 | #define EXT_F_STR_DML s_CmdExt->dml_str 39 | #define EXT_F_DML_LINK s_CmdExt->DmlCmdLink 40 | #define EXT_F_DML_EXEC s_CmdExt->DmlCmdExec 41 | 42 | #define EXT_D_IDebugAdvanced s_CmdExt->m_Advanced 43 | #define EXT_D_IDebugClient s_CmdExt->m_Client 44 | #define EXT_D_IDebugControl s_CmdExt->m_Control 45 | #define EXT_D_IDebugDataSpaces s_CmdExt->m_Data 46 | #define EXT_D_IDebugRegisters s_CmdExt->m_Registers 47 | #define EXT_D_IDebugSymbols s_CmdExt->m_Symbols 48 | #define EXT_D_IDebugSystemObjects s_CmdExt->m_System 49 | #define EXT_D_IDebugAdvanced2 s_CmdExt->m_Advanced2 50 | #define EXT_D_IDebugAdvanced3 s_CmdExt->m_Advanced3 51 | #define EXT_D_IDebugClient2 s_CmdExt->m_Client2 52 | #define EXT_D_IDebugClient3 s_CmdExt->m_Client3 53 | #define EXT_D_IDebugClient4 s_CmdExt->m_Client4 54 | #define EXT_D_IDebugClient5 s_CmdExt->m_Client5 55 | #define EXT_D_IDebugControl2 s_CmdExt->m_Control2 56 | #define EXT_D_IDebugControl3 s_CmdExt->m_Control3 57 | #define EXT_D_IDebugControl4 s_CmdExt->m_Control4 58 | #define EXT_D_IDebugControl5 s_CmdExt->m_Control5 59 | #define EXT_D_IDebugControl6 s_CmdExt->m_Control6 60 | #define EXT_D_IDebugDataSpaces2 s_CmdExt->m_Data2 61 | #define EXT_D_IDebugDataSpaces3 s_CmdExt->m_Data3 62 | #define EXT_D_IDebugDataSpaces4 s_CmdExt->m_Data4 63 | #define EXT_D_IDebugRegisters2 s_CmdExt->m_Registers2 64 | #define EXT_D_IDebugSymbols2 s_CmdExt->m_Symbols2 65 | #define EXT_D_IDebugSymbols3 s_CmdExt->m_Symbols3 66 | #define EXT_D_IDebugSystemObjects2 s_CmdExt->m_System2 67 | #define EXT_D_IDebugSystemObjects3 s_CmdExt->m_System3 68 | #define EXT_D_IDebugSystemObjects4 s_CmdExt->m_System4 69 | 70 | #define DML_CMD "" 72 | #define DML_END "" 73 | 74 | #define WDML_CMD "" 76 | #define WDML_END "" 77 | 78 | #define HEX_ADDR(addr) hex << showbase << setfill('0') << setw(18) << addr << setfill(' ') 79 | #define WHEX_ADDR(addr) hex << showbase << setfill(L'0') << setw(18) << addr << setfill(L' ') 80 | #define HEX_DATA hex << showbase << setfill(' ') << setw(18) 81 | #define WHEX_DATA hex << showbase << setfill(L' ') << setw(18) 82 | 83 | #define FC \ 84 | catch (ExtException& e) \ 85 | { \ 86 | EXT_F_ERR("[ERROR] %s %s %d %s\n", __FILE__, __FUNCTION__, __LINE__, e.GetMessage()); \ 87 | } \ 88 | catch (exception& e) \ 89 | { \ 90 | EXT_F_ERR("[ERROR] %s %s %d %s\n", __FILE__, __FUNCTION__, __LINE__, e.what()); \ 91 | } 92 | 93 | class CCmdExt 94 | : public ExtExtension 95 | { 96 | public: 97 | static CCmdExt* Instance() 98 | { 99 | static CCmdExt s_cmd_ext; 100 | return &s_cmd_ext; 101 | } 102 | 103 | CCmdExt(); 104 | ~CCmdExt(); 105 | 106 | void dk(void); 107 | 108 | size_t reg(size_t reg); 109 | 110 | size_t reg_of(const char* reg); 111 | 112 | bool is_reg(string& str); 113 | 114 | size_t getSymbolAddr(const char* name); 115 | 116 | tuple getAddrSymbol(size_t addr); 117 | 118 | bool valid_addr(size_t addr); 119 | 120 | size_t getIntArg(vector& args, size_t idx, size_t default_val); 121 | 122 | template 123 | inline bool is_in_range(T value, T min, T max) 124 | { 125 | return value >= min && value < max; 126 | } 127 | 128 | template 129 | T read(size_t addr); 130 | 131 | template 132 | T readX(size_t addr); 133 | 134 | template 135 | void write(size_t addr, T data); 136 | 137 | string size2str(size_t value); 138 | 139 | wstring readUnicodeString(size_t addr); 140 | 141 | HRESULT x(string cmd); 142 | 143 | void out_str(stringstream& ss) 144 | { 145 | Out(ss.str().c_str()); 146 | } 147 | 148 | void dml_str(stringstream& ss) 149 | { 150 | Dml(ss.str().c_str()); 151 | } 152 | 153 | void err_str(stringstream& ss) 154 | { 155 | Err(ss.str().c_str()); 156 | } 157 | }; 158 | 159 | template 160 | inline T CCmdExt::read(size_t addr) 161 | { 162 | T ret = 0; 163 | if (S_OK != m_Data->ReadVirtual(addr, &ret, sizeof(T), NULL)) 164 | ThrowRemote(E_ACCESSDENIED, "Fail to read memory"); 165 | 166 | return ret; 167 | } 168 | 169 | template 170 | inline T CCmdExt::readX(size_t addr) 171 | { 172 | T ret = 0; 173 | if (S_OK != m_Data->ReadPhysical(addr, &ret, sizeof(T), NULL)) 174 | ThrowRemote(E_ACCESSDENIED, "Fail to read memory"); 175 | 176 | return ret; 177 | } 178 | 179 | template 180 | inline void CCmdExt::write(size_t addr, T data) 181 | { 182 | if (S_OK != m_Data->WriteVirtual(addr, &data, sizeof(T), NULL)) 183 | ThrowRemote(E_ACCESSDENIED, "Fail to write memory"); 184 | } 185 | 186 | -------------------------------------------------------------------------------- /CmdInterface.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | using CmdHandler = void (*)(vector& args); 9 | 10 | #define DECLARE_CMD(x) void cmd_##x(vector& args); 11 | #define DEFINE_CMD(x) void cmd_##x(vector& args) 12 | #define CMD_HANDLER(x) cmd_##x -------------------------------------------------------------------------------- /CmdList.cpp: -------------------------------------------------------------------------------- 1 | #include "dbgdata.h" 2 | #include "process.h" 3 | #include "token.h" 4 | #include "object.h" 5 | #include "type.h" 6 | #include "module.h" 7 | #include "dml.h" 8 | #include "thread.h" 9 | #include "memory.h" 10 | #include "handle.h" 11 | #include "page.h" 12 | #include "pool.h" 13 | #include "session.h" 14 | #include "list.h" 15 | #include "stack.h" 16 | #include "pe.h" 17 | #include "clfs.h" 18 | #include "ttd_cmd.h" 19 | #include "usermode.h" 20 | #include "heap.h" 21 | 22 | #include "model.h" 23 | 24 | #include "CmdList.h" 25 | #include 26 | 27 | void RegisterCmdHandlers() 28 | { 29 | CMD_LIST->RegisterCmdHandler("dbgdata", CMD_HANDLER(dbgdata)); 30 | CMD_LIST->RegisterCmdHandler("pses", CMD_HANDLER(pses)); 31 | CMD_LIST->RegisterCmdHandler("kill", CMD_HANDLER(kill)); 32 | CMD_LIST->RegisterCmdHandler("process", CMD_HANDLER(process)); 33 | CMD_LIST->RegisterCmdHandler("ps_flags", CMD_HANDLER(ps_flags)); 34 | CMD_LIST->RegisterCmdHandler("sid", CMD_HANDLER(sid)); 35 | CMD_LIST->RegisterCmdHandler("token", CMD_HANDLER(token)); 36 | CMD_LIST->RegisterCmdHandler("add_privilege", CMD_HANDLER(add_privilege)); 37 | CMD_LIST->RegisterCmdHandler("obj", CMD_HANDLER(obj)); 38 | CMD_LIST->RegisterCmdHandler("gobj", CMD_HANDLER(gobj)); 39 | CMD_LIST->RegisterCmdHandler("obj_dir", CMD_HANDLER(obj_dir)); 40 | CMD_LIST->RegisterCmdHandler("types", CMD_HANDLER(types)); 41 | CMD_LIST->RegisterCmdHandler("lmu", CMD_HANDLER(lmu)); 42 | CMD_LIST->RegisterCmdHandler("lmk", CMD_HANDLER(lmk)); 43 | CMD_LIST->RegisterCmdHandler("lm", CMD_HANDLER(lm)); 44 | CMD_LIST->RegisterCmdHandler("load_dml", CMD_HANDLER(dml)); 45 | CMD_LIST->RegisterCmdHandler("threads", CMD_HANDLER(threads)); 46 | CMD_LIST->RegisterCmdHandler("size", CMD_HANDLER(size)); 47 | CMD_LIST->RegisterCmdHandler("va_regions", CMD_HANDLER(va_regions)); 48 | CMD_LIST->RegisterCmdHandler("page", CMD_HANDLER(page)); 49 | CMD_LIST->RegisterCmdHandler("pages", CMD_HANDLER(pages)); 50 | CMD_LIST->RegisterCmdHandler("hole", CMD_HANDLER(hole)); 51 | CMD_LIST->RegisterCmdHandler("vad", CMD_HANDLER(vad)); 52 | CMD_LIST->RegisterCmdHandler("regs", CMD_HANDLER(regs)); 53 | CMD_LIST->RegisterCmdHandler("as_qword", CMD_HANDLER(as_qword)); 54 | CMD_LIST->RegisterCmdHandler("tpool", CMD_HANDLER(tpool)); 55 | CMD_LIST->RegisterCmdHandler("poolhdr", CMD_HANDLER(poolhdr)); 56 | CMD_LIST->RegisterCmdHandler("pool", CMD_HANDLER(as_qword)); 57 | CMD_LIST->RegisterCmdHandler("bigpool", CMD_HANDLER(bigpool)); 58 | CMD_LIST->RegisterCmdHandler("poolrange", CMD_HANDLER(poolrange)); 59 | CMD_LIST->RegisterCmdHandler("pooltrack", CMD_HANDLER(pooltrack)); 60 | CMD_LIST->RegisterCmdHandler("poolmetrics", CMD_HANDLER(poolmetrics)); 61 | CMD_LIST->RegisterCmdHandler("free_pool", CMD_HANDLER(free_pool)); 62 | CMD_LIST->RegisterCmdHandler("as_mem", CMD_HANDLER(as_mem)); 63 | CMD_LIST->RegisterCmdHandler("ex_mem", CMD_HANDLER(ex_mem)); 64 | CMD_LIST->RegisterCmdHandler("page_2_svg", CMD_HANDLER(page_2_svg)); 65 | CMD_LIST->RegisterCmdHandler("sessions", CMD_HANDLER(sessions)); 66 | CMD_LIST->RegisterCmdHandler("sessionpool", CMD_HANDLER(sessionpool)); 67 | CMD_LIST->RegisterCmdHandler("args", CMD_HANDLER(args)); 68 | CMD_LIST->RegisterCmdHandler("handle_table", CMD_HANDLER(handle_table)); 69 | CMD_LIST->RegisterCmdHandler("khandles", CMD_HANDLER(khandles)); 70 | CMD_LIST->RegisterCmdHandler("link", CMD_HANDLER(link)); 71 | CMD_LIST->RegisterCmdHandler("flink", CMD_HANDLER(flink)); 72 | CMD_LIST->RegisterCmdHandler("kall", CMD_HANDLER(kall)); 73 | CMD_LIST->RegisterCmdHandler("pkall", CMD_HANDLER(pkall)); 74 | CMD_LIST->RegisterCmdHandler("memcpy", CMD_HANDLER(memcpy)); 75 | CMD_LIST->RegisterCmdHandler("peguid", CMD_HANDLER(peguid)); 76 | CMD_LIST->RegisterCmdHandler("ls_model", CMD_HANDLER(ls_model)); 77 | CMD_LIST->RegisterCmdHandler("ls_sessions", CMD_HANDLER(ls_sessions)); 78 | CMD_LIST->RegisterCmdHandler("ls_processes", CMD_HANDLER(ls_processes)); 79 | CMD_LIST->RegisterCmdHandler("ls_threads", CMD_HANDLER(ls_threads)); 80 | CMD_LIST->RegisterCmdHandler("ls_modules", CMD_HANDLER(ls_modules)); 81 | CMD_LIST->RegisterCmdHandler("ls_handles", CMD_HANDLER(ls_handles)); 82 | CMD_LIST->RegisterCmdHandler("ps_ttd", CMD_HANDLER(ps_ttd)); 83 | CMD_LIST->RegisterCmdHandler("session_ttd", CMD_HANDLER(session_ttd)); 84 | CMD_LIST->RegisterCmdHandler("ttd_calls", CMD_HANDLER(ttd_calls)); 85 | CMD_LIST->RegisterCmdHandler("ttd_mem_access", CMD_HANDLER(ttd_mem_access)); 86 | CMD_LIST->RegisterCmdHandler("ttd_mem_use", CMD_HANDLER(ttd_mem_use)); 87 | CMD_LIST->RegisterCmdHandler("cur_context", CMD_HANDLER(cur_context)); 88 | CMD_LIST->RegisterCmdHandler("exec", CMD_HANDLER(exec)); 89 | CMD_LIST->RegisterCmdHandler("mobj", CMD_HANDLER(mobj)); 90 | CMD_LIST->RegisterCmdHandler("mobj_at", CMD_HANDLER(mobj_at)); 91 | CMD_LIST->RegisterCmdHandler("call", CMD_HANDLER(call)); 92 | CMD_LIST->RegisterCmdHandler("ccall", CMD_HANDLER(ccall)); 93 | CMD_LIST->RegisterCmdHandler("ldttd", CMD_HANDLER(ldttd)); 94 | CMD_LIST->RegisterCmdHandler("dump_ttd_events", CMD_HANDLER(dump_ttd_events)); 95 | CMD_LIST->RegisterCmdHandler("usearch_astr", CMD_HANDLER(usearch_astr)); 96 | CMD_LIST->RegisterCmdHandler("usearch_ustr", CMD_HANDLER(usearch_ustr)); 97 | CMD_LIST->RegisterCmdHandler("usearch_bytes", CMD_HANDLER(usearch_bytes)); 98 | CMD_LIST->RegisterCmdHandler("usearch_addr", CMD_HANDLER(usearch_addr)); 99 | CMD_LIST->RegisterCmdHandler("uaddr_ref_disp", CMD_HANDLER(uaddr_ref_disp)); 100 | CMD_LIST->RegisterCmdHandler("uaddr_ref_by", CMD_HANDLER(uaddr_ref_by)); 101 | CMD_LIST->RegisterCmdHandler("uaddr_ref_tree", CMD_HANDLER(uaddr_ref_tree)); 102 | CMD_LIST->RegisterCmdHandler("uaddr_analyze2", CMD_HANDLER(uaddr_analyze2)); 103 | CMD_LIST->RegisterCmdHandler("uaddr_analyze", CMD_HANDLER(uaddr_analyze)); 104 | CMD_LIST->RegisterCmdHandler("uaddr_analyze_svg", CMD_HANDLER(uaddr_analyze_svg)); 105 | CMD_LIST->RegisterCmdHandler("ustacks", CMD_HANDLER(ustacks)); 106 | CMD_LIST->RegisterCmdHandler("uregs", CMD_HANDLER(uregs)); 107 | CMD_LIST->RegisterCmdHandler("heap_ssum", CMD_HANDLER(heap_ssum)); 108 | CMD_LIST->RegisterCmdHandler("heap_bysize", CMD_HANDLER(heap_bysize)); 109 | CMD_LIST->RegisterCmdHandler("heap_oversize", CMD_HANDLER(heap_oversize)); 110 | } 111 | 112 | BOOL __stdcall CmdListMain(HANDLE Instance, ULONG Reason, PVOID Reserved) 113 | { 114 | switch (Reason) 115 | { 116 | case DLL_PROCESS_ATTACH: 117 | RegisterCmdHandlers(); 118 | break; 119 | case DLL_PROCESS_DETACH: 120 | break; 121 | } 122 | return TRUE; 123 | } 124 | 125 | vector CCmdList::GetValidCommands() 126 | { 127 | vector valid_cmds; 128 | 129 | for (auto cmd : m_cmd_hanlders) 130 | valid_cmds.push_back(cmd.first); 131 | 132 | return valid_cmds; 133 | } 134 | -------------------------------------------------------------------------------- /CmdList.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "CmdInterface.h" 9 | 10 | using namespace std; 11 | 12 | BOOL WINAPI CmdListMain( 13 | HANDLE Instance, ULONG Reason, PVOID Reserved); 14 | 15 | #define CMD_LIST CCmdList::Instance() 16 | 17 | class CCmdList 18 | { 19 | public: 20 | static CCmdList* Instance() 21 | { 22 | static CCmdList s_cmd_list; 23 | return &s_cmd_list; 24 | } 25 | 26 | void RegisterCmdHandler(string cmd_name, CmdHandler cmd_handler) 27 | { 28 | m_cmd_hanlders[cmd_name] = cmd_handler; 29 | } 30 | 31 | bool IsValidCmd(string cmd_name) 32 | { 33 | return m_cmd_hanlders.find(cmd_name) != m_cmd_hanlders.end(); 34 | } 35 | 36 | void HandleCmd(string cmd_name, vector& args) 37 | { 38 | m_cmd_hanlders[cmd_name](args); 39 | } 40 | 41 | vector GetValidCommands(); 42 | 43 | private: 44 | map m_cmd_hanlders; 45 | }; 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Daniel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MemoryAnalyzer.cpp: -------------------------------------------------------------------------------- 1 | #include "model.h" 2 | #include "MemoryAnalyzer.h" 3 | #include "CmdExt.h" 4 | #include "CmdList.h" 5 | 6 | #include 7 | #include 8 | 9 | 10 | size_t CMemoryAnalyzer::is_in_cur_stack(size_t addr) 11 | { 12 | auto cur_callstacks = DK_GET_CURSTACK(); 13 | 14 | for (auto& callstack : cur_callstacks) 15 | { 16 | if (addr <= callstack[3] && addr >= callstack[4]) 17 | { 18 | return callstack[0]; 19 | } 20 | } 21 | 22 | return -1; 23 | } 24 | 25 | bool CMemoryAnalyzer::is_local(size_t addr) 26 | { 27 | if (addr >= m_addr && addr < m_addr + m_len) 28 | return true; 29 | 30 | return false; 31 | } 32 | 33 | string CMemoryAnalyzer::get_symbol(size_t addr) 34 | { 35 | auto sym = EXT_F_Addr2Sym(addr); 36 | if (get<0>(sym).empty()) 37 | return ""; 38 | 39 | stringstream ss; 40 | 41 | ss << get<0>(sym) << "+0x" << hex << get<1>(sym); 42 | 43 | return ss.str(); 44 | } 45 | 46 | tuple CMemoryAnalyzer::is_heap(size_t addr) 47 | { 48 | for (auto& entry : m_heap) 49 | { 50 | if (addr >= entry.res_id && addr < entry.res_id + entry.size) 51 | { 52 | return make_tuple(entry.res_id, entry.size); 53 | } 54 | } 55 | 56 | return make_tuple(0, 0);; 57 | } 58 | 59 | void CMemoryAnalyzer::analyze() 60 | { 61 | map notes; 62 | uint64_t* qwords = (uint64_t*)m_data.data(); 63 | 64 | for (auto i = 0; i < m_len / 8; i++) 65 | { 66 | uint64_t qw = *(qwords + i); 67 | if (is_local(qw)) 68 | { 69 | m_ptr2locals[i * 8] = qw - m_addr; 70 | } 71 | 72 | auto frame_num = is_in_cur_stack(qw); 73 | if (frame_num != -1) 74 | { 75 | m_ptr2stacks[i * 8] = frame_num; 76 | } 77 | 78 | auto sym = get_symbol(qw); 79 | if (!sym.empty()) 80 | { 81 | m_ptr2syms[i * 8] = make_tuple(sym, qw); 82 | } 83 | 84 | auto heap_entry = is_heap(qw); 85 | if (get<1>(heap_entry) != 0) 86 | { 87 | m_ptr2heaps[i * 8] = make_tuple(qw, get<0>(heap_entry), get<1>(heap_entry)); 88 | } 89 | } 90 | } 91 | 92 | map CMemoryAnalyzer::get_ptr2local() 93 | { 94 | return m_ptr2locals; 95 | } 96 | 97 | map CMemoryAnalyzer::get_ptr2stack() 98 | { 99 | return m_ptr2stacks; 100 | } 101 | 102 | map> CMemoryAnalyzer::get_ptr2sym() 103 | { 104 | return m_ptr2syms; 105 | } 106 | 107 | map> CMemoryAnalyzer::get_ptr2heap() 108 | { 109 | return m_ptr2heaps; 110 | } 111 | -------------------------------------------------------------------------------- /MemoryAnalyzer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | class CMemoryAnalyzer 10 | { 11 | public: 12 | CMemoryAnalyzer(string data, size_t addr, size_t len) 13 | :m_data(data) 14 | ,m_addr(addr) 15 | , m_len(len) 16 | { 17 | if (m_data.size() < m_len) 18 | m_len = m_data.size(); 19 | 20 | m_heap = DK_GET_HEAP(); 21 | } 22 | 23 | size_t is_in_cur_stack(size_t addr); 24 | 25 | bool is_local(size_t addr); 26 | 27 | string get_symbol(size_t addr); 28 | 29 | tuple is_heap(size_t addr); 30 | 31 | void analyze(); 32 | 33 | map get_ptr2local(); 34 | map get_ptr2stack(); 35 | map> get_ptr2sym(); 36 | map> get_ptr2heap(); 37 | 38 | private: 39 | string m_data; 40 | size_t m_addr; 41 | size_t m_len; 42 | 43 | map m_ptr2locals; 44 | map m_ptr2stacks; 45 | map> m_ptr2syms; 46 | map> m_ptr2heaps; 47 | 48 | vector m_heap; 49 | }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dk WinDbg extension 2 | 3 | # Summary 4 | 5 | dk is the enhanced refactored version of [tokenext](https://github.com/long123king/tokenext). The goal is to improve the readability and extensibility, as well as to leverage the powerful [Debugger Data Model](https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/data-model-cpp-overview) and [Time Travel Debugging](https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/time-travel-debugging-overview). SVG document will be generated for an intuitive visualization in certain circumstances. 6 | 7 | Run ***!dk help*** for supported command list. 8 | 9 | Check page_2_svg demos: 10 | 1. [Initial version](https://raw.githubusercontent.com/long123king/dk/main/demos/page_00000060a11ff000.svg) 11 | 2. [Add pointers to local buffer(in green), pointers to symbols(in red)](https://raw.githubusercontent.com/long123king/dk/main/demos/page_00000052%60182ff730_1.svg) 12 | 3. [Add pointers to heap allocations(in blue)](https://raw.githubusercontent.com/long123king/dk/main/demos/page_00000052%60182ff8f0_2.svg) 13 | 4. [Add heap allocation changing history, blue rects are clickable](https://raw.githubusercontent.com/long123king/dk/main/demos/page_00000052182ff8f0_link.svg) 14 | 15 | Run following commands to generate callstack forest visualization in svg format(small projects only!), demos for helloworld project can be found [here](https://raw.githubusercontent.com/long123king/dk/main/demos/helloworld_viz_forest.svg). (Click interaction on svg is blocked by browsers, try it locally) 16 | 17 | ``` 18 | 0:001> !dk ldttd 19 | 0:001> !dk dump_ttd_events d:\helloworld_viz 20 | ``` 21 | 22 | 23 | 24 | # Reference 25 | 26 | 1. [TTD.hpp](https://github.com/commial/ttd-bindings/blob/master/TTD/TTD.hpp) from [Bindings for Microsoft WinDBG TTD](https://github.com/commial/ttd-bindings) 27 | 28 | # How to start a new WinDbg C++ extension? 29 | 30 | ## 1. Add Windows Kits related folder to Visual Studio project setting: 31 | 32 | ``` xml 33 | 34 | 35 | ...... 36 | 37 | C:\Program Files (x86)\Windows Kits\10\Debuggers\inc;$(IncludePath) 38 | C:\Program Files (x86)\Windows Kits\10\Debuggers\lib\x64;$(LibraryPath) 39 | 40 | 41 | C:\Program Files (x86)\Windows Kits\10\Debuggers\inc;$(IncludePath) 42 | C:\Program Files (x86)\Windows Kits\10\Debuggers\lib\x64;$(LibraryPath) 43 | 44 | ...... 45 | 46 | ``` 47 | 48 | ## 2. Include engextcpp.cpp from C:\Program Files (x86)\Windows Kits\10\Debuggers\inc to Visual Studio project, and make the following changes: 49 | 50 | ```diff 51 | diff -r C:\Program Files (x86)\Windows Kits\10\Debuggers\inc\engextcpp.cpp C:\Users\dk\source\repos\dk\engextcpp.cpp 52 | 248c248 53 | < m_OptionChars = "/-"; 54 | --- 55 | > m_OptionChars = const_cast("/-"); 56 | 286c286 57 | < PSTR Value = ""; 58 | --- 59 | > PSTR Value = const_cast(""); 60 | 2673c2673 61 | < BufferChars > 0) 62 | --- 63 | > *BufferChars > 0) 64 | 65 | ``` 66 | 67 | ## 3. Define exported symbols in dk.def file, and don't forget the 4 default exports: 68 | 69 | ```configuration 70 | DebugExtensionInitialize 71 | DebugExtensionUninitialize 72 | DebugExtensionNotify 73 | help 74 | ``` 75 | 76 | -------------------------------------------------------------------------------- /dbgdata.cpp: -------------------------------------------------------------------------------- 1 | #include "dbgdata.h" 2 | #include 3 | #include "CmdExt.h" 4 | 5 | size_t readDbgDataAddr(ULONG index) 6 | { 7 | size_t addr_field = 0; 8 | EXT_D_IDebugDataSpaces->ReadDebuggerData(index, &addr_field, sizeof(size_t), NULL); 9 | return addr_field; 10 | } 11 | 12 | 13 | DEFINE_CMD(dbgdata) 14 | { 15 | EXT_F_OUT("Debugger Data:\n"); 16 | EXT_F_OUT("%30s 0x%0I64x\n", "kernel base", 17 | readDbgDataAddr(DEBUG_DATA_KernBase)); 18 | 19 | EXT_F_OUT("%30s 0x%0I64x\n", "BreakpointWithStatusInstruction.", 20 | readDbgDataAddr(DEBUG_DATA_BreakpointWithStatusAddr)); 21 | 22 | EXT_F_OUT("%30s 0x%0I64x\n", "KiCallUserMode.", 23 | readDbgDataAddr(DEBUG_DATA_KiCallUserModeAddr)); 24 | 25 | EXT_F_OUT("%30s 0x%0I64x\n", "KeUserCallbackDispatcher.", 26 | readDbgDataAddr(DEBUG_DATA_KeUserCallbackDispatcherAddr)); 27 | 28 | EXT_F_OUT("%30s 0x%0I64x\n", "PsLoadedModuleList.", 29 | readDbgDataAddr(DEBUG_DATA_PsLoadedModuleListAddr)); 30 | 31 | EXT_F_OUT("%30s 0x%0I64x\n", "PsActiveProcessHead.", 32 | readDbgDataAddr(DEBUG_DATA_PsActiveProcessHeadAddr)); 33 | 34 | EXT_F_OUT("%30s 0x%0I64x\n", "PspCidTable.", 35 | readDbgDataAddr(DEBUG_DATA_PspCidTableAddr)); 36 | 37 | EXT_F_OUT("%30s 0x%0I64x\n", "ExpSystemResourcesList.", 38 | readDbgDataAddr(DEBUG_DATA_ExpSystemResourcesListAddr)); 39 | 40 | EXT_F_OUT("%30s 0x%0I64x\n", "ExpPagedPoolDescriptor.", 41 | readDbgDataAddr(DEBUG_DATA_ExpPagedPoolDescriptorAddr)); 42 | 43 | EXT_F_OUT("%30s 0x%0I64x\n", "ExpNumberOfPagedPools.", 44 | readDbgDataAddr(DEBUG_DATA_ExpNumberOfPagedPoolsAddr)); 45 | 46 | EXT_F_OUT("%30s 0x%0I64x\n", "KeTimeIncrement.", 47 | readDbgDataAddr(DEBUG_DATA_KeTimeIncrementAddr)); 48 | 49 | EXT_F_OUT("%30s 0x%0I64x\n", "KeBugCheckCallbackListHead.", 50 | readDbgDataAddr(DEBUG_DATA_KeBugCheckCallbackListHeadAddr)); 51 | 52 | EXT_F_OUT("%30s 0x%0I64x\n", "KiBugCheckData.", 53 | readDbgDataAddr(DEBUG_DATA_KiBugcheckDataAddr)); 54 | 55 | EXT_F_OUT("%30s 0x%0I64x\n", "IopErrorLogListHead.", 56 | readDbgDataAddr(DEBUG_DATA_IopErrorLogListHeadAddr)); 57 | 58 | EXT_F_OUT("%30s 0x%0I64x\n", "ObpRootDirectoryObject.", 59 | readDbgDataAddr(DEBUG_DATA_ObpRootDirectoryObjectAddr)); 60 | 61 | EXT_F_OUT("%30s 0x%0I64x\n", "ObpTypeObjectType.", 62 | readDbgDataAddr(DEBUG_DATA_ObpTypeObjectTypeAddr)); 63 | 64 | EXT_F_OUT("%30s 0x%0I64x\n", "MmSystemCacheStart.", 65 | readDbgDataAddr(DEBUG_DATA_MmSystemCacheStartAddr)); 66 | 67 | EXT_F_OUT("%30s 0x%0I64x\n", "MmSystemCacheEnd.", 68 | readDbgDataAddr(DEBUG_DATA_MmSystemCacheEndAddr)); 69 | 70 | EXT_F_OUT("%30s 0x%0I64x\n", "MmSystemCacheWs.", 71 | readDbgDataAddr(DEBUG_DATA_MmSystemCacheWsAddr)); 72 | 73 | EXT_F_OUT("%30s 0x%0I64x\n", "MmPfnDatabase.", 74 | readDbgDataAddr(DEBUG_DATA_MmPfnDatabaseAddr)); 75 | 76 | EXT_F_OUT("%30s 0x%0I64x\n", "MmSystemPtesStart.", 77 | readDbgDataAddr(DEBUG_DATA_MmSystemPtesStartAddr)); 78 | 79 | EXT_F_OUT("%30s 0x%0I64x\n", "MmSystemPtesEnd.", 80 | readDbgDataAddr(DEBUG_DATA_MmSystemPtesEndAddr)); 81 | 82 | EXT_F_OUT("%30s 0x%0I64x\n", "MmSubsectionBase.", 83 | readDbgDataAddr(DEBUG_DATA_MmSubsectionBaseAddr)); 84 | 85 | EXT_F_OUT("%30s 0x%0I64x\n", "MmNumberOfPagingFiles.", 86 | readDbgDataAddr(DEBUG_DATA_MmNumberOfPagingFilesAddr)); 87 | 88 | EXT_F_OUT("%30s 0x%0I64x\n", "MmLowestPhysicalPage.", 89 | readDbgDataAddr(DEBUG_DATA_MmLowestPhysicalPageAddr)); 90 | 91 | EXT_F_OUT("%30s 0x%0I64x\n", "MmHighestPhysicalPage.", 92 | readDbgDataAddr(DEBUG_DATA_MmHighestPhysicalPageAddr)); 93 | 94 | EXT_F_OUT("%30s 0x%0I64x\n", "MmNumberOfPhysicalPages.", 95 | readDbgDataAddr(DEBUG_DATA_MmNumberOfPhysicalPagesAddr)); 96 | 97 | EXT_F_OUT("%30s 0x%0I64x\n", "MmMaximumNonPagedPoolInBytes.", 98 | readDbgDataAddr(DEBUG_DATA_MmMaximumNonPagedPoolInBytesAddr)); 99 | 100 | EXT_F_OUT("%30s 0x%0I64x\n", "MmNonPagedSystemStart.", 101 | readDbgDataAddr(DEBUG_DATA_MmNonPagedSystemStartAddr)); 102 | 103 | EXT_F_OUT("%30s 0x%0I64x\n", "MmNonPagedPoolStart.", 104 | readDbgDataAddr(DEBUG_DATA_MmNonPagedPoolStartAddr)); 105 | 106 | EXT_F_OUT("%30s 0x%0I64x\n", "MmNonPagedPoolEnd.", 107 | readDbgDataAddr(DEBUG_DATA_MmNonPagedPoolEndAddr)); 108 | 109 | EXT_F_OUT("%30s 0x%0I64x\n", "MmPagedPoolStart.", 110 | readDbgDataAddr(DEBUG_DATA_MmPagedPoolStartAddr)); 111 | 112 | EXT_F_OUT("%30s 0x%0I64x\n", "MmPagedPoolEnd.", 113 | readDbgDataAddr(DEBUG_DATA_MmPagedPoolEndAddr)); 114 | 115 | EXT_F_OUT("%30s 0x%0I64x\n", "MmPagedPoolInfo.", 116 | readDbgDataAddr(DEBUG_DATA_MmPagedPoolInformationAddr)); 117 | 118 | EXT_F_OUT("%30s 0x%0I64x\n", "MmSizeOfPagedPoolInBytes.", 119 | readDbgDataAddr(DEBUG_DATA_MmSizeOfPagedPoolInBytesAddr)); 120 | 121 | EXT_F_OUT("%30s 0x%0I64x\n", "MmTotalCommitLimit.", 122 | readDbgDataAddr(DEBUG_DATA_MmTotalCommitLimitAddr)); 123 | 124 | EXT_F_OUT("%30s 0x%0I64x\n", "MmTotalCommittedPages.", 125 | readDbgDataAddr(DEBUG_DATA_MmTotalCommittedPagesAddr)); 126 | 127 | EXT_F_OUT("%30s 0x%0I64x\n", "MmSharedCommit.", 128 | readDbgDataAddr(DEBUG_DATA_MmSharedCommitAddr)); 129 | 130 | EXT_F_OUT("%30s 0x%0I64x\n", "MmDriverCommit.", 131 | readDbgDataAddr(DEBUG_DATA_MmDriverCommitAddr)); 132 | 133 | EXT_F_OUT("%30s 0x%0I64x\n", "MmProcessCommit.", 134 | readDbgDataAddr(DEBUG_DATA_MmProcessCommitAddr)); 135 | 136 | EXT_F_OUT("%30s 0x%0I64x\n", "MmPagedPoolCommit.", 137 | readDbgDataAddr(DEBUG_DATA_MmPagedPoolCommitAddr)); 138 | 139 | EXT_F_OUT("%30s 0x%0I64x\n", "MmExtendedCommit..", 140 | readDbgDataAddr(DEBUG_DATA_MmExtendedCommitAddr)); 141 | 142 | EXT_F_OUT("%30s 0x%0I64x\n", "MmZeroedPageListHead.", 143 | readDbgDataAddr(DEBUG_DATA_MmZeroedPageListHeadAddr)); 144 | 145 | EXT_F_OUT("%30s 0x%0I64x\n", "MmFreePageListHead.", 146 | readDbgDataAddr(DEBUG_DATA_MmFreePageListHeadAddr)); 147 | 148 | EXT_F_OUT("%30s 0x%0I64x\n", "MmStandbyPageListHead.", 149 | readDbgDataAddr(DEBUG_DATA_MmStandbyPageListHeadAddr)); 150 | 151 | EXT_F_OUT("%30s 0x%0I64x\n", "MmModifiedPageListHead.", 152 | readDbgDataAddr(DEBUG_DATA_MmModifiedPageListHeadAddr)); 153 | 154 | EXT_F_OUT("%30s 0x%0I64x\n", "MmModifiedNoWritePageListHead.", 155 | readDbgDataAddr(DEBUG_DATA_MmModifiedNoWritePageListHeadAddr)); 156 | 157 | EXT_F_OUT("%30s 0x%0I64x\n", "MmAvailablePages.", 158 | readDbgDataAddr(DEBUG_DATA_MmAvailablePagesAddr)); 159 | 160 | EXT_F_OUT("%30s 0x%0I64x\n", "MmResidentAvailablePages.", 161 | readDbgDataAddr(DEBUG_DATA_MmResidentAvailablePagesAddr)); 162 | 163 | EXT_F_OUT("%30s 0x%0I64x\n", "PoolTrackTable.", 164 | readDbgDataAddr(DEBUG_DATA_PoolTrackTableAddr)); 165 | 166 | EXT_F_OUT("%30s 0x%0I64x\n", "NonPagedPoolDescriptor.", 167 | readDbgDataAddr(DEBUG_DATA_NonPagedPoolDescriptorAddr)); 168 | 169 | EXT_F_OUT("%30s 0x%0I64x\n", "MmHighestUserAddress.", 170 | readDbgDataAddr(DEBUG_DATA_MmHighestUserAddressAddr)); 171 | 172 | EXT_F_OUT("%30s 0x%0I64x\n", "MmSystemRangeStart.", 173 | readDbgDataAddr(DEBUG_DATA_MmSystemRangeStartAddr)); 174 | 175 | EXT_F_OUT("%30s 0x%0I64x\n", "MmUserProbeAddress.", 176 | readDbgDataAddr(DEBUG_DATA_MmUserProbeAddressAddr)); 177 | 178 | EXT_F_OUT("%30s 0x%0I64x\n", "KdPrintDefaultCircularBuffer.", 179 | readDbgDataAddr(DEBUG_DATA_KdPrintCircularBufferAddr)); 180 | 181 | EXT_F_OUT("%30s 0x%0I64x\n", "KdPrintDefaultCircularBuffer", 182 | readDbgDataAddr(DEBUG_DATA_KdPrintCircularBufferEndAddr)); 183 | 184 | EXT_F_OUT("%30s 0x%0I64x\n", "KdPrintWritePointer.", 185 | readDbgDataAddr(DEBUG_DATA_KdPrintWritePointerAddr)); 186 | 187 | EXT_F_OUT("%30s 0x%0I64x\n", "KdPrintRolloverCount.", 188 | readDbgDataAddr(DEBUG_DATA_KdPrintRolloverCountAddr)); 189 | 190 | EXT_F_OUT("%30s 0x%0I64x\n", "MmLoadedUserImageList.", 191 | readDbgDataAddr(DEBUG_DATA_MmLoadedUserImageListAddr)); 192 | } 193 | -------------------------------------------------------------------------------- /dbgdata.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CmdInterface.h" 4 | #include 5 | 6 | DECLARE_CMD(dbgdata) 7 | 8 | size_t readDbgDataAddr(ULONG index); 9 | -------------------------------------------------------------------------------- /demos/helloworld_viz_6710_ntdll!RtlUserThreadStart.svg: -------------------------------------------------------------------------------- 1 | 33 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | ( 2f3:d - 38a:74 ) ntdll!RtlUserThreadStart 248 | ( 2f3:d - 38a:74 ) KERNEL32!BaseThreadInitThunk 249 | ( 2f3:d - 38a:74 ) ntdll!TppWorkerThread 250 | ( 2f3:d - 371:2e ) ntdll!TppWorkpExecuteCallback 251 | ( 2f3:d - 371:12 ) ntdll!LdrpWorkCallback 252 | ( 2f3:d - 36a:6 ) ntdll!LdrpProcessWork 253 | ( 2f3:d - 35a:a3 ) ntdll!LdrpSnapModule 254 | ( 2f3:d - 35a:6b ) ntdll!LdrpDoPostSnapWork 255 | ( 0:0 - 2f3:0 ) ntdll!NtProtectVirtualMemory 256 | ( 2f3:d - 35a:5a ) ntdll!LdrpHandleTlsData 257 | ( 2f3:26 - 2f3:89 ) ntdll!RtlpImageDirectoryEntryToDataEx 258 | ( 2f3:3e - 2f3:6c ) ntdll!RtlImageNtHeaderEx 259 | ( 2f3:94 - 318:5 ) ntdll!RtlAcquireSRWLockExclusive 260 | ( 318:1d - 318:1d ) ntdll!RtlAllocateHeap 261 | ( 318:77 - 322:9a ) ntdll!RtlpAllocateHeapInternal 262 | ( 318:77 - 322:7f ) ntdll!RtlpLowFragHeapAllocFromContext 263 | ( 322:21 - 322:54 ) ntdll!RtlpLfhFindClearBitAndSet 264 | ( 322:ad - 340:167 ) ntdll!LdrpAllocateTlsEntry 265 | ( 322:be - 322:be ) ntdll!RtlAllocateHeap 266 | ( 322:118 - 340:9a ) ntdll!RtlpAllocateHeapInternal 267 | ( 322:118 - 340:7f ) ntdll!RtlpLowFragHeapAllocFromContext 268 | ( 340:21 - 340:54 ) ntdll!RtlpLfhFindClearBitAndSet 269 | ( 340:b0 - 340:146 ) ntdll!LdrpAcquireTlsIndex 270 | ( 340:c0 - 340:139 ) ntdll!RtlFindClearBitsAndSet 271 | ( 340:114 - 340:12e ) ntdll!RtlSetBits 272 | ( 340:19c - 340:19c ) ntdll!RtlAllocateHeap 273 | ( 340:1f6 - 346:9a ) ntdll!RtlpAllocateHeapInternal 274 | ( 340:1f6 - 346:7f ) ntdll!RtlpLowFragHeapAllocFromContext 275 | ( 346:21 - 346:54 ) ntdll!RtlpLfhFindClearBitAndSet 276 | ( 346:a9 - 346:b3 ) ntdll!memcpy 277 | ( 346:d1 - 346:d1 ) ntdll!RtlAllocateHeap 278 | ( 346:12b - 348:9a ) ntdll!RtlpAllocateHeapInternal 279 | ( 346:12b - 348:7f ) ntdll!RtlpLowFragHeapAllocFromContext 280 | ( 348:21 - 348:54 ) ntdll!RtlpLfhFindClearBitAndSet 281 | ( 348:a9 - 348:b3 ) ntdll!memcpy 282 | ( 348:d0 - 34a:0 ) ntdll!NtSetInformationProcess 283 | ( 34a:24 - 350:2 ) ntdll!RtlReleaseSRWLockExclusive 284 | ( 350:9 - 35a:41 ) ntdll!RtlFreeHeap 285 | ( 350:1e - 35a:3a ) ntdll!RtlpFreeHeapInternal 286 | ( 350:6b - 350:70 ) ntdll!RtlGetCurrentServiceSessionId 287 | ( 35a:24 - 35a:2c ) ntdll!RtlpHpStackLoggingEnabled 288 | ( 35a:4b - 35a:51 ) ntdll!_security_check_cookie 289 | ( 35a:5e - 35a:62 ) ntdll!LdrControlFlowGuardEnforcedWithExportSuppression 290 | ( 35a:72 - 35a:85 ) ntdll!LdrpLogDllState 291 | ( 35a:93 - 35a:99 ) ntdll!_security_check_cookie 292 | ( 35a:aa - 365:7 ) ntdll!RtlEnterCriticalSection 293 | ( 365:12 - 366:8 ) ntdll!RtlLeaveCriticalSection 294 | ( 366:d - 36a:0 ) ntdll!NtSetEvent 295 | ( 36a:a - 36c:7 ) ntdll!RtlEnterCriticalSection 296 | ( 36c:13 - 371:8 ) ntdll!RtlLeaveCriticalSection 297 | ( 371:37 - 383:41 ) ntdll!TppCallbackEpilog 298 | ( 371:45 - 371:9c ) ntdll!TppCallbackCheckThreadAfterCallback 299 | ( 371:69 - 371:78 ) ntdll!TppCheckForTransactions 300 | ( 371:8f - 371:95 ) ntdll!_security_check_cookie 301 | ( 37c:1c - 383:3 ) ntdll!guard_xfg_dispatch_icall_nop 302 | ( 383:b - 383:2e ) ntdll!memset$thunk$772440563353939046 303 | ( 383:31 - 383:37 ) ntdll!_security_check_cookie 304 | ( 38a:19 - 38a:67 ) ntdll!memset$thunk$772440563353939046 305 | ( 38a:74 - 38a:74 ) ntdll!NtWaitForWorkViaWorkerFactory 306 | 307 | 308 | 309 | -------------------------------------------------------------------------------- /demos/helloworld_viz_forest.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 5494 ( 10:3 - 4b:1e ) ntdll!LdrInitializeThunk 19 | 5494 ( 4d:8 - a80:10c ) ntdll!RtlUserThreadStart 20 | 6710 ( 2f3:d - 38a:74 ) ntdll!RtlUserThreadStart 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /demos/page_00000052182ff8f0_link.svgmem_access_0x217c64533f0_8.svg: -------------------------------------------------------------------------------- 1 | ( 286:2b - 286:2b ) 0x00000217c64533f0, size: 0x8 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 00 29 | 00 30 | 00 31 | 00 32 | 00 33 | 00 34 | 00 35 | 00 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | F0 65 | 33 66 | 45 67 | C6 68 | 17 69 | 02 70 | 00 71 | 00 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | [ 0 ] ntdll!LdrpLoadDependentModuleInternal+0xc5f 133 | [ 1 ] ntdll!LdrpLoadDependentModuleA+0x146 134 | [ 2 ] ntdll!LdrpMapAndSnapDependency+0x1d3 135 | [ 3 ] ntdll!LdrpMapDllWithSectionHandle+0x1bc 136 | [ 4 ] ntdll!LdrpMapDllNtFileName+0x19b 137 | [ 5 ] ntdll!LdrpMapDllFullPath+0xe0 138 | [ 6 ] ntdll!LdrpProcessWork+0x77 139 | [ 7 ] ntdll!LdrpLoadDllInternal+0x1a0 140 | [ 8 ] ntdll!LdrpLoadDll+0xb0 141 | [ 9 ] ntdll!LdrLoadDll+0xfa 142 | [ a ] KERNELBASE!LoadLibraryExW+0x172 143 | [ b ] ucrtbased!try_load_library_from_system_directory+0x1c 144 | [ c ] ucrtbased!try_get_module+0x59 145 | [ d ] ucrtbased!try_get_first_available_module+0x40 146 | [ e ] ucrtbased!try_get_proc_address_from_first_available_module+0x22 147 | [ f ] ucrtbased!try_get_function+0x74 148 | [ 10 ] ucrtbased!try_get_AppPolicyGetProcessTerminationMethod+0x2a 149 | [ 11 ] ucrtbased!__acrt_AppPolicyGetProcessTerminationMethodInternal+0xe 150 | [ 12 ] ucrtbased!`__acrt_get_process_end_policy'::`2'::process_end_policy_properties...... 151 | [ 13 ] ucrtbased!get_win_policy<`__acrt_get_process_end_policy'::`2'::process_end...... 152 | [ 14 ] ucrtbased!__acrt_get_process_end_policy+0xb 153 | [ 15 ] ucrtbased!should_call_terminate_process+0x9 154 | [ 16 ] ucrtbased!exit_or_terminate_process+0xd 155 | [ 17 ] ucrtbased!common_exit+0x85 156 | [ 18 ] ucrtbased!exit+0x16 157 | [ 19 ] helloworld!__scrt_common_main_seh+0x147 158 | [ 1a ] helloworld!__scrt_common_main+0xe 159 | [ 1b ] helloworld!mainCRTStartup+0xe 160 | [ 1c ] KERNEL32!BaseThreadInitThunk+0x1d 161 | [ 1d ] ntdll!RtlUserThreadStart+0x28 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | -------------------------------------------------------------------------------- /demos/page_00000052182ff8f0_link.svgmem_access_0x217c645ca50_8.svg: -------------------------------------------------------------------------------- 1 | ( 97:30 - 97:30 ) 0x00000217c645ca40, size: 0x20 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 00 29 | 00 30 | 00 31 | 00 32 | 00 33 | 00 34 | 00 35 | 00 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 00 65 | 00 66 | 00 67 | 00 68 | 00 69 | 00 70 | 00 71 | 00 72 | 73 | ( 98:f5 - 98:f5 ) 0x00000217c645ca50, size: 0x8 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 00 101 | 00 102 | 00 103 | 00 104 | 00 105 | 00 106 | 00 107 | 00 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | A0 137 | 68 138 | 45 139 | C6 140 | 17 141 | 02 142 | 00 143 | 00 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | [ 0 ] ntdll!memset+0x81 230 | [ 1 ] ntdll!RtlpAllocateHeap+0x826 231 | [ 2 ] ntdll!RtlpAllocateHeapInternal+0x6c9 232 | [ 3 ] ntdll!LdrpAllocateModuleEntry+0x38 233 | [ 4 ] ntdll!LdrpAllocatePlaceHolder+0xce 234 | [ 5 ] ntdll!LdrpFindOrPrepareLoadingModule+0x98 235 | [ 6 ] ntdll!LdrpLoadDllInternal+0x182 236 | [ 7 ] ntdll!LdrpLoadDll+0xb0 237 | [ 8 ] ntdll!LdrLoadDll+0xfa 238 | [ 9 ] KERNELBASE!LoadLibraryExW+0x172 239 | [ a ] ucrtbased!try_load_library_from_system_directory+0x1c 240 | [ b ] ucrtbased!try_get_module+0x59 241 | [ c ] ucrtbased!try_get_first_available_module+0x40 242 | [ d ] ucrtbased!try_get_proc_address_from_first_available_module+0x22 243 | [ e ] ucrtbased!try_get_function+0x74 244 | [ f ] ucrtbased!try_get_AppPolicyGetProcessTerminationMethod+0x2a 245 | [ 10 ] ucrtbased!__acrt_AppPolicyGetProcessTerminationMethodInternal+0xe 246 | [ 11 ] ucrtbased!`__acrt_get_process_end_policy'::`2'::process_end_policy_properties...... 247 | [ 12 ] ucrtbased!get_win_policy<`__acrt_get_process_end_policy'::`2'::process_end...... 248 | [ 13 ] ucrtbased!__acrt_get_process_end_policy+0xb 249 | [ 14 ] ucrtbased!should_call_terminate_process+0x9 250 | [ 15 ] ucrtbased!exit_or_terminate_process+0xd 251 | [ 16 ] ucrtbased!common_exit+0x85 252 | [ 17 ] ucrtbased!exit+0x16 253 | [ 18 ] helloworld!__scrt_common_main_seh+0x147 254 | [ 19 ] helloworld!__scrt_common_main+0xe 255 | [ 1a ] helloworld!mainCRTStartup+0xe 256 | [ 1b ] KERNEL32!BaseThreadInitThunk+0x1d 257 | [ 1c ] ntdll!RtlUserThreadStart+0x28 258 | [ 0 ] ntdll!LdrpAllocateModuleEntry+0xc9 259 | [ 1 ] ntdll!LdrpAllocatePlaceHolder+0xce 260 | [ 2 ] ntdll!LdrpFindOrPrepareLoadingModule+0x98 261 | [ 3 ] ntdll!LdrpLoadDllInternal+0x182 262 | [ 4 ] ntdll!LdrpLoadDll+0xb0 263 | [ 5 ] ntdll!LdrLoadDll+0xfa 264 | [ 6 ] KERNELBASE!LoadLibraryExW+0x172 265 | [ 7 ] ucrtbased!try_load_library_from_system_directory+0x1c 266 | [ 8 ] ucrtbased!try_get_module+0x59 267 | [ 9 ] ucrtbased!try_get_first_available_module+0x40 268 | [ a ] ucrtbased!try_get_proc_address_from_first_available_module+0x22 269 | [ b ] ucrtbased!try_get_function+0x74 270 | [ c ] ucrtbased!try_get_AppPolicyGetProcessTerminationMethod+0x2a 271 | [ d ] ucrtbased!__acrt_AppPolicyGetProcessTerminationMethodInternal+0xe 272 | [ e ] ucrtbased!`__acrt_get_process_end_policy'::`2'::process_end_policy_properties:...... 273 | [ f ] ucrtbased!get_win_policy<`__acrt_get_process_end_policy'::`2'::process_end_...... 274 | [ 10 ] ucrtbased!__acrt_get_process_end_policy+0xb 275 | [ 11 ] ucrtbased!should_call_terminate_process+0x9 276 | [ 12 ] ucrtbased!exit_or_terminate_process+0xd 277 | [ 13 ] ucrtbased!common_exit+0x85 278 | [ 14 ] ucrtbased!exit+0x16 279 | [ 15 ] helloworld!__scrt_common_main_seh+0x147 280 | [ 16 ] helloworld!__scrt_common_main+0xe 281 | [ 17 ] helloworld!mainCRTStartup+0xe 282 | [ 18 ] KERNEL32!BaseThreadInitThunk+0x1d 283 | [ 19 ] ntdll!RtlUserThreadStart+0x28 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | -------------------------------------------------------------------------------- /dk.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | 3 | DebugExtensionInitialize 4 | DebugExtensionUninitialize 5 | DebugExtensionNotify 6 | help 7 | dk 8 | -------------------------------------------------------------------------------- /dk.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.3.32901.215 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dk", "dk.vcxproj", "{9BE137F8-D34F-49B5-A28F-299E1E4175B9}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {9BE137F8-D34F-49B5-A28F-299E1E4175B9}.Debug|x64.ActiveCfg = Debug|x64 17 | {9BE137F8-D34F-49B5-A28F-299E1E4175B9}.Debug|x64.Build.0 = Debug|x64 18 | {9BE137F8-D34F-49B5-A28F-299E1E4175B9}.Debug|x86.ActiveCfg = Debug|Win32 19 | {9BE137F8-D34F-49B5-A28F-299E1E4175B9}.Debug|x86.Build.0 = Debug|Win32 20 | {9BE137F8-D34F-49B5-A28F-299E1E4175B9}.Release|x64.ActiveCfg = Release|x64 21 | {9BE137F8-D34F-49B5-A28F-299E1E4175B9}.Release|x64.Build.0 = Release|x64 22 | {9BE137F8-D34F-49B5-A28F-299E1E4175B9}.Release|x86.ActiveCfg = Release|Win32 23 | {9BE137F8-D34F-49B5-A28F-299E1E4175B9}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {EA008400-53DD-4A7E-9DC1-ECBE161D93DA} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /dk.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {9be137f8-d34f-49b5-a28f-299e1e4175b9} 25 | dk 26 | 10.0 27 | 28 | 29 | 30 | DynamicLibrary 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | DynamicLibrary 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | DynamicLibrary 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | DynamicLibrary 50 | false 51 | v143 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | C:\Program Files (x86)\Windows Kits\10\Debuggers\inc;$(IncludePath) 75 | C:\Program Files (x86)\Windows Kits\10\Debuggers\lib\x64;$(LibraryPath) 76 | 77 | 78 | C:\Program Files (x86)\Windows Kits\10\Debuggers\inc;$(IncludePath) 79 | C:\Program Files (x86)\Windows Kits\10\Debuggers\lib\x64;$(LibraryPath) 80 | 81 | 82 | 83 | Level3 84 | true 85 | WIN32;_DEBUG;DK_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 86 | true 87 | Use 88 | pch.h 89 | 90 | 91 | Windows 92 | true 93 | false 94 | dk.def 95 | 96 | 97 | 98 | 99 | Level3 100 | true 101 | true 102 | true 103 | WIN32;NDEBUG;DK_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 104 | true 105 | Use 106 | pch.h 107 | 108 | 109 | Windows 110 | true 111 | true 112 | true 113 | false 114 | dk.def 115 | 116 | 117 | 118 | 119 | Level3 120 | true 121 | _DEBUG;DK_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 122 | true 123 | NotUsing 124 | 125 | 126 | 127 | stdcpp20 128 | /D _HAS_STD_BYTE=0 %(AdditionalOptions) 129 | 130 | 131 | Windows 132 | true 133 | false 134 | dbgeng.lib;%(AdditionalDependencies) 135 | dk.def 136 | 137 | 138 | 139 | 140 | Level3 141 | true 142 | true 143 | true 144 | NDEBUG;DK_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 145 | true 146 | NotUsing 147 | 148 | 149 | 150 | 151 | 152 | stdcpp20 153 | /D _HAS_STD_BYTE=0 %(AdditionalOptions) 154 | 155 | 156 | Windows 157 | true 158 | true 159 | true 160 | false 161 | dbgeng.lib;%(AdditionalDependencies) 162 | dk.def 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | -------------------------------------------------------------------------------- /dk.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {5710774f-bf32-4d83-842c-25ffd7d9c66c} 6 | 7 | 8 | {6bc1dfff-2fa6-4336-862c-9451bcef05e0} 9 | 10 | 11 | {942d0222-94c1-47b2-8975-107dd3908f7f} 12 | 13 | 14 | {d312d52b-59d0-478c-a757-c8540705c401} 15 | 16 | 17 | {38dd1604-e5c6-4db2-beed-4136dde7ffb3} 18 | 19 | 20 | {8caf07d9-039b-41ee-bc5d-005a15295e26} 21 | 22 | 23 | {650b1d8a-baa8-4963-843b-65c5fa975433} 24 | 25 | 26 | 27 | 28 | CmdList 29 | 30 | 31 | Cmds 32 | 33 | 34 | framework 35 | 36 | 37 | Cmds 38 | 39 | 40 | Cmds 41 | 42 | 43 | framework 44 | 45 | 46 | Cmds 47 | 48 | 49 | Cmds 50 | 51 | 52 | Cmds 53 | 54 | 55 | Cmds 56 | 57 | 58 | Cmds 59 | 60 | 61 | CmdList 62 | 63 | 64 | Cmds 65 | 66 | 67 | Cmds 68 | 69 | 70 | Cmds 71 | 72 | 73 | Cmds 74 | 75 | 76 | Cmds 77 | 78 | 79 | Cmds 80 | 81 | 82 | Cmds 83 | 84 | 85 | Cmds 86 | 87 | 88 | SVG 89 | 90 | 91 | SVG 92 | 93 | 94 | Cmds 95 | 96 | 97 | ttd 98 | 99 | 100 | ttd 101 | 102 | 103 | Utility 104 | 105 | 106 | alpha 107 | 108 | 109 | alpha 110 | 111 | 112 | SVG 113 | 114 | 115 | 116 | 117 | Cmds 118 | 119 | 120 | framework 121 | 122 | 123 | framework 124 | 125 | 126 | CmdList 127 | 128 | 129 | Cmds 130 | 131 | 132 | Cmds 133 | 134 | 135 | Cmds 136 | 137 | 138 | Cmds 139 | 140 | 141 | Cmds 142 | 143 | 144 | Cmds 145 | 146 | 147 | Cmds 148 | 149 | 150 | Cmds 151 | 152 | 153 | Cmds 154 | 155 | 156 | Cmds 157 | 158 | 159 | Cmds 160 | 161 | 162 | Cmds 163 | 164 | 165 | Cmds 166 | 167 | 168 | Cmds 169 | 170 | 171 | Cmds 172 | 173 | 174 | Cmds 175 | 176 | 177 | ttd 178 | 179 | 180 | Utility 181 | 182 | 183 | alpha 184 | 185 | 186 | alpha 187 | 188 | 189 | SVG 190 | 191 | 192 | 193 | 194 | framework 195 | 196 | 197 | -------------------------------------------------------------------------------- /dk.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | C:\Program Files\WindowsApps\Microsoft.WinDbg_1.2210.3001.0_x64__8wekyb3d8bbwe\amd64\EngHost.exe 5 | true 6 | WindowsLocalDebugger 7 | 8 | -------------------------------------------------------------------------------- /dml.cpp: -------------------------------------------------------------------------------- 1 | #include "dml.h" 2 | #include "CmdExt.h" 3 | #include "CmdList.h" 4 | 5 | #include 6 | 7 | using namespace std; 8 | 9 | DEFINE_CMD(dml) 10 | { 11 | if (args.size() < 2) 12 | EXT_F_ERR("Usage: !dk load_dml \n"); 13 | 14 | show_dml(args[1]); 15 | } 16 | 17 | void show_dml(string dml_path) 18 | { 19 | try 20 | { 21 | ifstream ifs(dml_path); 22 | 23 | if (ifs.good()) 24 | { 25 | string content; 26 | 27 | while (getline(ifs, content)) 28 | { 29 | content.push_back('\n'); 30 | 31 | EXT_F_DML(content.c_str()); 32 | } 33 | } 34 | } 35 | FC; 36 | } -------------------------------------------------------------------------------- /dml.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CmdInterface.h" 4 | 5 | DECLARE_CMD(dml) 6 | 7 | void show_dml(string dml_path); -------------------------------------------------------------------------------- /handle.cpp: -------------------------------------------------------------------------------- 1 | #include "model.h" 2 | #include "handle.h" 3 | #include "CmdExt.h" 4 | #include "CmdList.h" 5 | #include "object.h" 6 | 7 | #include 8 | 9 | #pragma warning( disable : 4244) 10 | 11 | CHandleTable::CHandleTable( 12 | __in size_t levels, 13 | __in size_t l1Addr, 14 | __in size_t handleCount) 15 | :m_levels(levels) 16 | , m_l1Addr(l1Addr) 17 | , m_handleCount(handleCount) 18 | { 19 | } 20 | 21 | 22 | CHandleTable::~CHandleTable() 23 | { 24 | } 25 | 26 | void 27 | CHandleTable::traverse( 28 | __in function callback 29 | ) 30 | { 31 | if (0 == m_levels) 32 | { 33 | uint8_t* this_page = new uint8_t[0x1000]; 34 | if (S_OK == g_ExtInstancePtr->m_Data->ReadVirtual(m_l1Addr, this_page, 0x1000, NULL)) 35 | { 36 | for (size_t i = 0; i < 256 && m_handleCount > 0; i++) 37 | { 38 | size_t entry = *(size_t*)(this_page + i * 0x10); 39 | size_t access = *(size_t*)(this_page + i * 0x10 + 0x08); 40 | 41 | callback(entry, access); 42 | m_handleCount--; 43 | } 44 | } 45 | 46 | delete[] this_page; 47 | 48 | //for (size_t i = 0; i < 256 && m_handleCount > 0; i++) 49 | //{ 50 | // size_t entry = 0; 51 | // size_t access = 0; 52 | // 53 | // if (g_ExtInstancePtr && 54 | // S_OK == g_ExtInstancePtr->m_Data->ReadVirtual(m_l1Addr + i * 0x10, &entry, sizeof(size_t), NULL) && 55 | // S_OK == g_ExtInstancePtr->m_Data->ReadVirtual(m_l1Addr + i * 0x10 + 0x08, &access, sizeof(size_t), NULL) && 56 | // callback(entry, access)) 57 | // m_handleCount--; 58 | // 59 | //} 60 | } 61 | else 62 | { 63 | uint8_t* this_page = new uint8_t[0x1000]; 64 | if (S_OK == g_ExtInstancePtr->m_Data->ReadVirtual(m_l1Addr, this_page, 0x1000, NULL)) 65 | { 66 | for (size_t i = 0; i < 512; i++) 67 | { 68 | size_t next_level_addr = *(size_t*)(this_page + i * 0x08); 69 | 70 | CHandleTable next_level_table(m_levels - 1, next_level_addr, m_handleCount); 71 | next_level_table.traverse(callback); 72 | m_handleCount = next_level_table.remained(); 73 | if (m_handleCount == 0) 74 | break; 75 | } 76 | } 77 | 78 | delete[] this_page; 79 | 80 | //for (size_t i = 0; i < 512; i++) 81 | //{ 82 | // size_t next_level_addr = 0; 83 | // if (g_ExtInstancePtr && 84 | // S_OK == g_ExtInstancePtr->m_Data->ReadVirtual(m_l1Addr + i * 0x08, &next_level_addr, sizeof(size_t), NULL)) 85 | // { 86 | // //size_t processed_count = i * 256 * (1 << ((m_levels - 1 >= 0 ? m_levels - 1 : 0) * 8)); 87 | // CHandleTable next_level_table(m_levels - 1, next_level_addr, m_handleCount); 88 | // next_level_table.traverse(callback); 89 | // m_handleCount = next_level_table.remained(); 90 | // if (m_handleCount == 0) 91 | // break; 92 | // } 93 | //} 94 | } 95 | } 96 | 97 | void dump_handle_table(size_t handle_table_addr) 98 | { 99 | size_t table_code = 0; 100 | size_t handle_count = 0; 101 | 102 | try 103 | { 104 | ExtRemoteTyped handle_table("(nt!_HANDLE_TABLE*)@$extin", handle_table_addr); 105 | table_code = handle_table.Field("TableCode").GetLongPtr(); 106 | 107 | size_t freelist_count = EXT_F_READ(EXT_F_Sym2Addr("nt!ExpFreeListCount")); 108 | 109 | if (freelist_count == 0) 110 | { 111 | auto free_list1 = handle_table.Field("FreeLists").ArrayElement(0); 112 | handle_count = free_list1.Field("HandleCount").GetUlong(); 113 | } 114 | else 115 | { 116 | for (auto i = 0; i < freelist_count; i++) 117 | { 118 | auto free_listN = handle_table.Field("FreeLists").ArrayElement(i); 119 | handle_count += free_listN.Field("HandleCount").GetUlong(); 120 | } 121 | } 122 | } 123 | FC; 124 | 125 | size_t level = table_code & 0x00000000000000FF; 126 | size_t l1_addr = table_code & 0xFFFFFFFFFFFFFF00; 127 | 128 | CHandleTable handle_table(level, l1_addr, handle_count); 129 | 130 | EXT_F_OUT("\n[dk:] handle table addr: 0x%016X, level: %d, handle count: 0x%016X\n", l1_addr, level, handle_count); 131 | 132 | //Out("HandleTable : 0x%I64x, count: 0x%08x, level: 0x%08x\n", handle_table_addr, handle_count, level); 133 | //Out("%-18s %-18s %-10s %-10s %-4s %-20s %s\n", "object_table_entry", "object_header_addr", "access", "handle", "type", "type_name", "object_name"); 134 | size_t handle_value = 0; 135 | handle_table.traverse([&handle_value](size_t entry, size_t access) { 136 | //static size_t handle_value = 0; 137 | bool bRet = false; 138 | 139 | if ((entry & 0x01) != 0 && 140 | (entry & 0x8000000000000000) != 0) 141 | { 142 | size_t addr = ((entry >> 0x10) | 0xFFFF000000000000) & 0xFFFFFFFFFFFFFFF0; 143 | 144 | if (EXT_F_ValidAddr(addr)) 145 | { 146 | try 147 | { 148 | ExtRemoteTyped obj_header("(nt!_OBJECT_HEADER*)@$extin", addr); 149 | uint8_t r_index = real_index(obj_header.Field("TypeIndex").GetUchar(), addr); 150 | 151 | wstring obj_name = dump_obj_name(addr); 152 | wstring type_name = getTypeName(r_index); 153 | 154 | string str_type_name(type_name.begin(), type_name.end()); 155 | string str_obj_name(obj_name.begin(), obj_name.end()); 156 | 157 | stringstream ss; 158 | 159 | ss << hex << showbase 160 | << setw(18) << entry << " "; 161 | 162 | ss << "" << setw(18) << addr << " " 165 | << "detail " 166 | << setw(10) << access << " " 167 | << hex << setw(8) << handle_value << /*(" << setw(8) << dec << noshowbase << handle_value << hex << showbase << ")*/" " 168 | << setw(20) << str_type_name << " [" << setw(4) << (uint16_t)r_index << "] "; 169 | 170 | if (obj_name.empty() && type_name == L"File") 171 | { 172 | wstring file_name = dump_file_name(addr + 0x30); 173 | string str_file_name(file_name.begin(), file_name.end()); 174 | 175 | ss << str_file_name; 176 | } 177 | else 178 | ss << str_obj_name; 179 | 180 | ss << endl; 181 | 182 | EXT_F_DML(ss.str().c_str()); 183 | } 184 | FC; 185 | } 186 | else 187 | EXT_F_OUT("----> Invalid addr at 0x%0I64x\n", addr); 188 | 189 | bRet = true; 190 | } 191 | 192 | handle_value += 4; 193 | 194 | return bRet; 195 | }); 196 | } 197 | 198 | DEFINE_CMD(handle_table) 199 | { 200 | if (!DK_MODEL_ACCESS->isKernelmode() || args.size() < 2) 201 | { 202 | EXT_F_OUT("Usage: !dk handle_table \nKernel-Mode Only\n"); 203 | return; 204 | } 205 | 206 | size_t handle_table_addr = EXT_F_IntArg(args, 1, 0); 207 | dump_handle_table(handle_table_addr); 208 | } 209 | 210 | DEFINE_CMD(khandles) 211 | { 212 | if (!DK_MODEL_ACCESS->isKernelmode()) 213 | { 214 | EXT_F_OUT("Usage: !dk khandles\nKernel-Mode Only\n"); 215 | return; 216 | } 217 | dump_kernel_handle_table(); 218 | } 219 | 220 | void dump_kernel_handle_table() 221 | { 222 | try 223 | { 224 | size_t kernel_handle_table_addr = EXT_F_Sym2Addr("nt!ObpKernelHandleTable"); 225 | dump_handle_table(EXT_F_READ(kernel_handle_table_addr)); 226 | } 227 | FC 228 | } 229 | 230 | void dump_process_handle_table(size_t process_addr) 231 | { 232 | try 233 | { 234 | ExtRemoteTyped curr_eprocess("(nt!_EPROCESS*)@$extin", process_addr); 235 | size_t handle_table_addr = curr_eprocess.Field("ObjectTable").GetLongPtr(); 236 | dump_handle_table(handle_table_addr); 237 | } 238 | FC 239 | } -------------------------------------------------------------------------------- /handle.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CmdInterface.h" 4 | #include 5 | 6 | DECLARE_CMD(handle_table); 7 | DECLARE_CMD(khandles); 8 | 9 | class CHandleTable 10 | { 11 | public: 12 | CHandleTable( 13 | __in size_t levels, 14 | __in size_t l1Addr, 15 | __in size_t handleCount); 16 | ~CHandleTable(); 17 | 18 | void 19 | traverse( 20 | __in function callback 21 | ); 22 | 23 | size_t 24 | remained() 25 | { 26 | return m_handleCount; 27 | } 28 | 29 | private: 30 | size_t m_levels; 31 | size_t m_l1Addr; 32 | size_t m_handleCount; 33 | }; 34 | 35 | void dump_kernel_handle_table(); 36 | void dump_process_handle_table(size_t process_addr); -------------------------------------------------------------------------------- /heap.cpp: -------------------------------------------------------------------------------- 1 | #include "model.h" 2 | #include "heap.h" 3 | #include "CmdExt.h" 4 | #include "CmdList.h" 5 | 6 | 7 | DEFINE_CMD(heap_ssum) 8 | { 9 | if (!DK_MODEL_ACCESS->isUsermode()) 10 | { 11 | EXT_F_OUT("Usage: !dk heap_ssum\nUser Mode Only\n"); 12 | return; 13 | } 14 | 15 | heap_ssum(); 16 | } 17 | 18 | DEFINE_CMD(heap_bysize) 19 | { 20 | if (!DK_MODEL_ACCESS->isUsermode() || args.size() < 2) 21 | { 22 | EXT_F_OUT("Usage: !dk heap_bysize \nUser Mode Only\n"); 23 | return; 24 | } 25 | 26 | size_t size = EXT_F_IntArg(args, 1, 0); 27 | 28 | heap_by_size(size); 29 | } 30 | 31 | DEFINE_CMD(heap_oversize) 32 | { 33 | if (!DK_MODEL_ACCESS->isUsermode() || args.size() < 2) 34 | { 35 | EXT_F_OUT("Usage: !dk heap_oversize \nUser Mode Only\n"); 36 | return; 37 | } 38 | 39 | size_t size = EXT_F_IntArg(args, 1, 0); 40 | 41 | heap_over_size(size); 42 | } 43 | 44 | void heap_ssum() 45 | { 46 | CHeapSummary::GetInstance()->dump_size_summary(); 47 | } 48 | 49 | void heap_by_size(size_t size) 50 | { 51 | CHeapSummary::GetInstance()->dump_size(size); 52 | } 53 | 54 | void heap_over_size(size_t size) 55 | { 56 | CHeapSummary::GetInstance()->dump_size_over(size); 57 | } 58 | 59 | CHeapSummary::CHeapSummary() 60 | { 61 | Analyze(); 62 | } 63 | 64 | CHeapSummary::~CHeapSummary() 65 | { 66 | } 67 | 68 | void CHeapSummary::Analyze() 69 | { 70 | EXT_F_OUT("analyzing all process heaps, it may take time, please wait in patience...\n"); 71 | 72 | string cmd = "!heap -s -a -v"; 73 | 74 | auto results = DK_X_CMD(cmd); 75 | for (auto& result : results) 76 | { 77 | if (result.size() > 0x66 && result[1] == '0') 78 | { 79 | if (result[0] == '.') 80 | result = result.substr(1); 81 | 82 | add_chunk(result); 83 | } 84 | } 85 | } 86 | 87 | void CHeapSummary::add_chunk(string& line) 88 | { 89 | size_t addr = 0; 90 | size_t size = 0; 91 | 92 | addr = stoull(line.c_str(), nullptr, 16); 93 | //addr = stoull(line.substr(0, 16), nullptr, 16); 94 | size = stoull(line.c_str() + line.find_first_not_of(' ', 0x48), nullptr, 16); 95 | //size = stoull(line.substr(line.find_first_not_of(' ', 0x48)), nullptr, 16); 96 | 97 | //auto flag_str = line.substr(0x66); 98 | 99 | //if (*flag_str.rbegin() == '\n') 100 | // flag_str.resize(flag_str.size() - 1); 101 | 102 | //if (m_chunks.find(addr) == m_chunks.end()) 103 | // m_chunks[addr] = make_unique(size, flag_str); 104 | 105 | if (m_size_map.find(size) == m_size_map.end()) 106 | m_size_map[size] = set(); 107 | 108 | m_size_map[size].insert(addr); 109 | } 110 | 111 | void CHeapSummary::dump_size_summary() 112 | { 113 | for (auto it : m_size_map) 114 | { 115 | stringstream ss; 116 | ss << "[+] " << hex << showbase << it.first << " : " 117 | << it.second.size() << " chunks" << endl; 118 | 119 | //for (auto itt : it.second) 120 | //{ 121 | // ss << " [-] " << hex << showbase << itt << endl; 122 | //} 123 | 124 | //ss << endl; 125 | 126 | EXT_F_STR_OUT(ss); 127 | } 128 | } 129 | 130 | void CHeapSummary::dump_size(size_t size) 131 | { 132 | auto it = m_size_map.find(size); 133 | if (it != m_size_map.end()) 134 | { 135 | stringstream ss; 136 | ss << "[+] " << hex << showbase << it->first << " : " 137 | << it->second.size() << " chunks" << endl; 138 | 139 | for (auto itt : it->second) 140 | { 141 | ss << " [-] " << hex << showbase << itt << endl; 142 | } 143 | 144 | ss << endl; 145 | 146 | EXT_F_STR_OUT(ss); 147 | } 148 | } 149 | 150 | void CHeapSummary::dump_size_over(size_t size) 151 | { 152 | for (auto it : m_size_map) 153 | { 154 | if (it.first >= size) 155 | { 156 | stringstream ss; 157 | ss << "[+] " << hex << showbase << it.first << " : " 158 | << it.second.size() << " chunks" << endl; 159 | 160 | for (auto itt : it.second) 161 | { 162 | ss << " [-] " << hex << showbase << itt << endl; 163 | } 164 | 165 | ss << endl; 166 | 167 | EXT_F_STR_OUT(ss); 168 | } 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /heap.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CmdInterface.h" 4 | 5 | #include 6 | #include 7 | 8 | DECLARE_CMD(heap_ssum) 9 | DECLARE_CMD(heap_bysize) 10 | DECLARE_CMD(heap_oversize) 11 | 12 | void heap_ssum(); 13 | void heap_by_size(size_t size); 14 | void heap_over_size(size_t size); 15 | 16 | class CChunkInfo 17 | { 18 | public: 19 | CChunkInfo(size_t _size, string _flags) 20 | :size(_size) 21 | , flags(_flags) 22 | { 23 | } 24 | 25 | size_t size; 26 | string flags; 27 | }; 28 | 29 | class CHeapSummary 30 | { 31 | public: 32 | static CHeapSummary* GetInstance() 33 | { 34 | static CHeapSummary s_instance; 35 | return &s_instance; 36 | } 37 | 38 | CHeapSummary(); 39 | ~CHeapSummary(); 40 | 41 | void Analyze(); 42 | 43 | void add_chunk(string& line); 44 | 45 | void dump_size_summary(); 46 | 47 | void dump_size(size_t size); 48 | void dump_size_over(size_t size); 49 | 50 | private: 51 | //map> m_chunks; 52 | map> m_size_map; 53 | }; 54 | -------------------------------------------------------------------------------- /hexsvg.cpp: -------------------------------------------------------------------------------- 1 | #include "hexsvg.h" 2 | #include 3 | 4 | CHexSvg::CHexSvg(size_t boxes_per_row) 5 | :m_boxes_per_row(boxes_per_row) 6 | { 7 | if (m_boxes_per_row < 4) 8 | m_boxes_per_row = 4; 9 | 10 | m_m = make_shared( 11 | m_boxes_per_row, 12 | m_row_header_width, 13 | m_colum_header_height, 14 | m_row_height, 15 | m_column_width); 16 | } 17 | 18 | CHexSvg::~CHexSvg() 19 | { 20 | } 21 | 22 | string CHexSvg::add_text(size_t row, size_t column, string content) 23 | { 24 | return format(R"({})", 25 | m_font_size, 26 | m_font_family, 27 | row * m_row_height, 28 | column * m_column_width, 29 | content); 30 | } 31 | 32 | void CHexSvg::set_address(size_t addr) 33 | { 34 | m_init_address = addr; 35 | } 36 | 37 | void CHexSvg::set_bitmap(bool b_bitmap) 38 | { 39 | m_show_bits = b_bitmap; 40 | } 41 | 42 | void CHexSvg::set_ascii(bool b_ascii) 43 | { 44 | m_show_ascii = b_ascii; 45 | } 46 | 47 | void CHexSvg::set_auto_color(bool b_auto_color) 48 | { 49 | m_auto_color = b_auto_color; 50 | } 51 | 52 | void CHexSvg::set_legend(bool b_legend) 53 | { 54 | m_show_legend = b_legend; 55 | } 56 | 57 | void CHexSvg::add_byte(uint8_t value, string color) 58 | { 59 | if (m_auto_color) 60 | { 61 | color = auto_calc_color(value); 62 | m_boxes.push_back( 63 | make_shared(format("{:02X}", value), 64 | m_offset, 1, true, color)); 65 | m_offset += 1; 66 | } 67 | } 68 | 69 | void CHexSvg::add_word(uint16_t value, string color) 70 | { 71 | m_boxes.push_back( 72 | make_shared(format("{:04X}", value), 73 | m_offset, 2, true, color)); 74 | m_offset += 2; 75 | } 76 | 77 | void CHexSvg::add_dword(uint32_t value, string color) 78 | { 79 | m_boxes.push_back( 80 | make_shared(format("{:08X}", value), 81 | m_offset, 4, true, color)); 82 | m_offset += 4; 83 | } 84 | 85 | void CHexSvg::add_qword(uint64_t value, string color) 86 | { 87 | if (m_boxes_per_row >= 8) 88 | { 89 | m_boxes.push_back( 90 | make_shared(format("{:016X}", value), 91 | m_offset, 8, true, color)); 92 | m_offset += 8; 93 | } 94 | } 95 | 96 | void CHexSvg::add_buffer(string buffer, string color) 97 | { 98 | for (auto ch : buffer) 99 | { 100 | if (m_auto_color) 101 | { 102 | auto auto_color = auto_calc_color(ch); 103 | m_boxes.push_back(make_shared( 104 | format("{:02X}", (unsigned char)ch), 105 | m_offset, 1, true, auto_color)); 106 | } 107 | else 108 | { 109 | m_boxes.push_back(make_shared( 110 | format("{:02X}", (unsigned char)ch), 111 | m_offset, 1, true, color)); 112 | } 113 | 114 | m_offset += 1; 115 | } 116 | } 117 | 118 | void CHexSvg::add_legend(string color, string note) 119 | { 120 | m_legends[color] = note; 121 | } 122 | 123 | void CHexSvg::generate_row_header() 124 | { 125 | size_t rows = (m_offset + m_boxes_per_row - 1) / m_boxes_per_row; 126 | for (size_t i = 0; i < rows; i++) 127 | { 128 | auto [x, y, width, height] = m_m->get_row_header(i); 129 | m_row_header_content << format(R"({})", 130 | m_font_size, 131 | m_font_family, 132 | x + width / 2, 133 | y + (height + m_font_size) / 2, 134 | format("0x{:016X}", m_init_address + i * m_boxes_per_row) 135 | ); 136 | } 137 | } 138 | 139 | void CHexSvg::generate_column_header() 140 | { 141 | for (size_t i = 0; i < m_boxes_per_row; i++) 142 | { 143 | auto [x, y, width, height] = m_m->get_column_header(i); 144 | m_column_header_content << format(R"({})", 145 | m_font_family, 146 | m_font_family, 147 | x + width / 2, 148 | y + (height + m_font_size) / 2, 149 | format("{:X}", i)); 150 | } 151 | } 152 | 153 | void CHexSvg::generate_framework() 154 | { 155 | for (auto& box : m_boxes) 156 | { 157 | m_framework_content << box->gen_framework_bg(m_m); 158 | } 159 | 160 | for (auto& box : m_boxes) 161 | { 162 | m_framework_content << box->gen_framework_separator(m_m); 163 | } 164 | 165 | auto [x, y, width, height] = m_m->get_column_header(m_boxes_per_row - 1); 166 | 167 | size_t rows = (m_offset + m_boxes_per_row - 1) / m_boxes_per_row; 168 | 169 | for (size_t i = 0; i < rows; i++) 170 | { 171 | auto [x, y, width, height] = m_m->get_row_framework(i); 172 | m_framework_content << format(R"()", 173 | x, 174 | y, 175 | height, 176 | width); 177 | } 178 | } 179 | 180 | void CHexSvg::generate_text() 181 | { 182 | for (auto& box : m_boxes) 183 | { 184 | m_content << box->gen_text(m_m); 185 | } 186 | } 187 | 188 | void CHexSvg::generate_svg_headers() 189 | { 190 | auto [x1, y1, width1, height1] = m_m->get_column_header(m_boxes_per_row - 1); 191 | auto [x2, y2, width2, height2] = m_m->get_cell(m_offset, 1); 192 | 193 | size_t canvas_width = x1 + width1; 194 | size_t canvas_height = y2 + height2; 195 | 196 | if (m_show_legend) 197 | canvas_width += (10 * width2); 198 | 199 | m_svg_headers << format(R"( 200 | )", 203 | canvas_width, 204 | canvas_height); 205 | } 206 | 207 | void CHexSvg::generate_bitmap() 208 | { 209 | for (auto& box : m_boxes) 210 | { 211 | m_bitmap_content << box->gen_bitmap(m_m); 212 | } 213 | } 214 | 215 | void CHexSvg::generate_ascii() 216 | { 217 | for (auto& box : m_boxes) 218 | { 219 | m_ascii_content << box->gen_ascii(m_m); 220 | } 221 | } 222 | 223 | void CHexSvg::generate_legend() 224 | { 225 | auto [_x, _y, _width, _height] = m_m->get_cell(7, 1); 226 | 227 | auto x = _x + 2 * _width; 228 | auto y = _y + _height; 229 | auto width = 7 * _width; 230 | auto height = (m_legends.size() + 2) * _height; 231 | 232 | m_legend_content << format(R"()", 233 | x, y, height, width); 234 | 235 | size_t i = 0; 236 | for (auto& it : m_legends) 237 | { 238 | m_legend_content << format(R"()", 239 | x + _width, 240 | y + (1 + i) * _height, 241 | _height, 242 | _width, 243 | it.first); 244 | 245 | m_legend_content << format(R"({})", 246 | m_font_size, 247 | m_font_family, 248 | x + 4 * _width + _width / 2, 249 | y + (1 + i) * _height + (_height + m_font_size) / 2, 250 | it.second); 251 | 252 | i++; 253 | } 254 | } 255 | 256 | string CHexSvg::generate() 257 | { 258 | generate_column_header(); 259 | generate_row_header(); 260 | generate_framework(); 261 | generate_text(); 262 | generate_svg_headers(); 263 | if (m_show_bits) 264 | generate_bitmap(); 265 | 266 | if (m_show_ascii) 267 | generate_ascii(); 268 | 269 | if (m_show_legend) 270 | generate_legend(); 271 | 272 | string svg_content; 273 | 274 | svg_content += m_svg_headers.str(); 275 | svg_content += m_row_header_content.str(); 276 | svg_content += m_column_header_content.str(); 277 | svg_content += m_framework_content.str(); 278 | svg_content += m_content.str(); 279 | svg_content += m_bitmap_content.str(); 280 | svg_content += m_ascii_content.str(); 281 | svg_content += m_legend_content.str(); 282 | svg_content += m_svg_trailers; 283 | 284 | return svg_content; 285 | } 286 | 287 | string CHexSvg::auto_calc_color(uint8_t b) 288 | { 289 | auto highlights = CSvgTheme::GetInstance()->get_highlight(); 290 | auto trivials = CSvgTheme::GetInstance()->get_trivial(); 291 | 292 | if (b == 0) 293 | return highlights[0]; 294 | else if (b >= 0x30 && b <= 0x39) 295 | return highlights[1]; 296 | else if (b >= 0x41 && b <= 0x5A) 297 | return highlights[2]; 298 | else if (b >= 0x61 && b <= 0x7A) 299 | return highlights[3]; 300 | else if (b < 0x80) 301 | return highlights[4]; 302 | else if (b < 0xF0) 303 | return highlights[5]; 304 | else 305 | return trivials[0]; 306 | } 307 | 308 | CHexSvgMetrics::CHexSvgMetrics(size_t bpr, size_t rhw, size_t chh, size_t rh, size_t cw) 309 | :m_boxes_per_row(bpr) 310 | ,m_row_header_width(rhw) 311 | ,m_column_header_height(chh) 312 | ,m_row_height(rh) 313 | ,m_column_width(cw) 314 | { 315 | } 316 | 317 | CHexSvgMetrics::~CHexSvgMetrics() 318 | { 319 | } 320 | 321 | tuple CHexSvgMetrics::get_cell(size_t offset, size_t span) 322 | { 323 | size_t row = offset / m_boxes_per_row; 324 | size_t column = offset % m_boxes_per_row; 325 | 326 | if (column + span > m_boxes_per_row) 327 | { 328 | span = m_boxes_per_row - column; 329 | } 330 | 331 | return make_tuple(m_row_header_width + column * m_column_width, 332 | m_column_header_height + row * m_row_height, 333 | m_column_width * span, 334 | m_row_height); 335 | } 336 | 337 | tuple CHexSvgMetrics::get_row_header(size_t row) 338 | { 339 | return make_tuple(0, 340 | m_column_header_height + row * m_row_height, 341 | m_row_header_width, 342 | m_row_height); 343 | } 344 | 345 | tuple CHexSvgMetrics::get_row_framework(size_t row) 346 | { 347 | return make_tuple(m_row_header_width, 348 | m_column_header_height + row * m_row_height, 349 | m_column_width * m_boxes_per_row, 350 | m_row_height); 351 | } 352 | 353 | tuple CHexSvgMetrics::get_column_header(size_t column) 354 | { 355 | return make_tuple(m_row_header_width + column * m_column_width, 356 | 0, 357 | m_column_width, 358 | m_column_header_height); 359 | } 360 | 361 | CHexBox::CHexBox(string value, size_t offset, size_t span, bool solid_outline, string fill_color, size_t font_size, string font_family) 362 | :m_value(value) 363 | ,m_span(span) 364 | ,m_solid_outline(solid_outline) 365 | ,m_fill_color(fill_color) 366 | ,m_offset(offset) 367 | ,m_font_size(font_size) 368 | ,m_font_family(font_family) 369 | { 370 | } 371 | 372 | CHexBox::~CHexBox() 373 | { 374 | } 375 | 376 | string CHexBox::gen_framework_bg(shared_ptr m) 377 | { 378 | auto [x, y, width, height] = m->get_cell(m_offset, m_span); 379 | 380 | return format(R"()", 381 | x, 382 | y, 383 | width, 384 | height, 385 | m_fill_color); 386 | } 387 | 388 | string CHexBox::gen_framework_separator(shared_ptr m) 389 | { 390 | auto [x, y, width, height] = m->get_cell(m_offset, m_span); 391 | 392 | return format(R"()", 393 | x+width, 394 | y, 395 | x+width, 396 | y+height, 397 | m_solid_outline? R"(stroke-dasharray="1,3")" : ""); 398 | } 399 | 400 | string CHexBox::gen_text(shared_ptr m) 401 | { 402 | auto [x, y, width, height] = m->get_cell(m_offset, m_span); 403 | 404 | return format(R"({})", 405 | m_font_size, 406 | m_font_family, 407 | x + width/2, 408 | y + (height + m_font_size)/2, 409 | m_font_size/8, 410 | m_value); 411 | } 412 | 413 | string CHexBox::gen_bitmap(shared_ptr m) 414 | { 415 | auto [x, y, width, height] = m->get_cell(m_offset, m_span); 416 | 417 | if (m_span > 8) 418 | return ""; 419 | 420 | size_t total_grids = m_span * 8; 421 | size_t grid_width = width / total_grids; 422 | 423 | size_t int_value = stoull(m_value, nullptr, 16); 424 | 425 | string bitmap_svg = ""; 426 | for (size_t i = 0; i < total_grids; i++) 427 | { 428 | bitmap_svg += format(R"()", 429 | x + (total_grids - i - 1) * grid_width, 430 | y, 431 | grid_width, 432 | grid_width, 433 | (((1 << i) & int_value) != 0)? "#e0e0e0":"#606060"); 434 | } 435 | 436 | return bitmap_svg; 437 | } 438 | 439 | string CHexBox::gen_ascii(shared_ptr m) 440 | { 441 | auto [x, y, width, height] = m->get_cell(m_offset, m_span); 442 | 443 | string ascii_text = ""; 444 | 445 | size_t int_value = stoull(m_value, nullptr, 16); 446 | for (size_t i = 0; i < m_span; i++) 447 | { 448 | char ch = (int_value & 0xFF); 449 | if (ch == '<') 450 | ascii_text += "<"; 451 | else if (ch == '>') 452 | ascii_text += ">"; 453 | else if (ch == '&') 454 | ascii_text += "&"; 455 | else if (ch >= ' ' && ch <= '~') 456 | ascii_text += ch; 457 | else 458 | ascii_text += '.'; 459 | 460 | int_value = int_value >> 8; 461 | } 462 | 463 | //reverse(ascii_text.begin(), ascii_text.end()); 464 | 465 | return format(R"({})", 466 | m_font_size / 2, 467 | m_font_family, 468 | x + width - m_font_size / 8, 469 | y + height - m_font_size / 8, ascii_text); 470 | } 471 | -------------------------------------------------------------------------------- /hexsvg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | class CSvgTheme 12 | { 13 | public: 14 | static CSvgTheme* GetInstance() 15 | { 16 | static CSvgTheme s_instance; 17 | return &s_instance; 18 | } 19 | 20 | CSvgTheme() 21 | { 22 | initialize(); 23 | } 24 | 25 | ~CSvgTheme() 26 | { 27 | } 28 | 29 | void initialize() 30 | { 31 | for (size_t i = 1; i < 7; i++) 32 | { 33 | stringstream ss; 34 | ss << "#"; 35 | for (size_t j = 0; j < 3; j++) 36 | { 37 | if ((i & (1 << j)) != 0) 38 | ss << "f0"; 39 | else 40 | ss << "a0"; 41 | } 42 | m_highlight_colors.push_back(ss.str()); 43 | } 44 | 45 | 46 | m_trivial_colors.push_back("#f0f0f0"); 47 | m_trivial_colors.push_back("#a0a0a0"); 48 | m_trivial_colors.push_back("#808080"); 49 | m_trivial_colors.push_back("#404040"); 50 | } 51 | 52 | vector get_highlight() 53 | { 54 | return m_highlight_colors; 55 | } 56 | 57 | vector get_trivial() 58 | { 59 | return m_trivial_colors; 60 | } 61 | 62 | private: 63 | vector m_highlight_colors; 64 | vector m_trivial_colors; 65 | }; 66 | 67 | class CHexSvgMetrics 68 | { 69 | public: 70 | CHexSvgMetrics(size_t bpr, size_t rhw, size_t chh, size_t rh, size_t cw); 71 | ~CHexSvgMetrics(); 72 | 73 | tuple get_cell(size_t offset, size_t span); 74 | 75 | tuple get_row_header(size_t row); 76 | tuple get_row_framework(size_t row); 77 | tuple get_column_header(size_t column); 78 | private: 79 | size_t m_boxes_per_row; 80 | size_t m_row_header_width; 81 | size_t m_column_header_height; 82 | size_t m_row_height; 83 | size_t m_column_width; 84 | }; 85 | 86 | class CHexBox 87 | { 88 | public: 89 | CHexBox(string value, size_t offset, size_t span=1, bool solid_outline = true, 90 | string fill_color="#a0ffa0", size_t font_size = 16, 91 | string font_family = "monospace" 92 | ); 93 | ~CHexBox(); 94 | 95 | string gen_framework_bg(shared_ptr m); 96 | string gen_framework_separator(shared_ptr m); 97 | string gen_text(shared_ptr m); 98 | string gen_bitmap(shared_ptr m); 99 | string gen_ascii(shared_ptr m); 100 | 101 | private: 102 | string m_value; 103 | size_t m_span; 104 | size_t m_offset; 105 | size_t m_font_size; 106 | 107 | bool m_solid_outline; 108 | string m_fill_color; 109 | 110 | string m_font_family; 111 | }; 112 | 113 | class CHexSvg 114 | { 115 | public: 116 | CHexSvg(size_t boxes_per_row = 16); 117 | ~CHexSvg(); 118 | 119 | string add_text(size_t row, size_t column, string content); 120 | void set_address(size_t addr); 121 | void set_bitmap(bool b_bitmap); 122 | void set_ascii(bool b_ascii); 123 | void set_auto_color(bool b_auto_color); 124 | void set_legend(bool b_legend); 125 | 126 | void add_byte(uint8_t value, string color = "#a0ffa0"); 127 | void add_word(uint16_t value, string color = "#a0ffa0"); 128 | void add_dword(uint32_t value, string color = "#a0ffa0"); 129 | void add_qword(uint64_t value, string color = "#a0ffa0"); 130 | 131 | void add_buffer(string buffer, string color = "#a0ffa0"); 132 | 133 | void add_legend(string color, string note); 134 | 135 | void generate_row_header(); 136 | void generate_column_header(); 137 | void generate_framework(); 138 | void generate_text(); 139 | void generate_svg_headers(); 140 | void generate_bitmap(); 141 | void generate_ascii(); 142 | void generate_legend(); 143 | 144 | string generate(); 145 | 146 | string auto_calc_color(uint8_t b); 147 | 148 | 149 | private: 150 | size_t m_boxes_per_row; 151 | 152 | bool m_buffer_as_bytes{ true }; 153 | bool m_show_bits{ true }; 154 | bool m_show_ascii{ true }; 155 | bool m_auto_color{ false }; 156 | bool m_show_legend{ true }; 157 | 158 | size_t m_address{ 0 }; 159 | 160 | size_t m_font_size{ 16 }; 161 | size_t m_init_address{ 0 }; 162 | size_t m_offset{ 0 }; 163 | 164 | vector> m_boxes; 165 | 166 | shared_ptr m_m; 167 | 168 | size_t m_row_header_width{ 200 }; 169 | size_t m_colum_header_height{ 40 }; 170 | size_t m_row_height{ 30 }; 171 | size_t m_column_width{ 40 }; 172 | 173 | string m_font_family{ "monospace" }; 174 | string m_svg_trailers{R"()"}; 175 | 176 | stringstream m_svg_headers; 177 | stringstream m_row_header_content; 178 | stringstream m_column_header_content; 179 | stringstream m_content; 180 | stringstream m_framework_content; 181 | stringstream m_bitmap_content; 182 | stringstream m_ascii_content; 183 | stringstream m_svg_text; 184 | stringstream m_legend_content; 185 | 186 | map m_legends; 187 | 188 | }; -------------------------------------------------------------------------------- /list.cpp: -------------------------------------------------------------------------------- 1 | #include "list.h" 2 | #include "CmdExt.h" 3 | #include "CmdList.h" 4 | 5 | #include 6 | 7 | DEFINE_CMD(link) 8 | { 9 | size_t head = EXT_F_IntArg(args, 1, 0); 10 | dig_link(head); 11 | } 12 | DEFINE_CMD(flink) 13 | { 14 | size_t head = EXT_F_IntArg(args, 1, 0); 15 | size_t entry = EXT_F_IntArg(args, 2, 0); 16 | dig_link(head, entry); 17 | } 18 | 19 | void dig_link(size_t head) 20 | { 21 | try 22 | { 23 | size_t addr = head; 24 | if (EXT_F_ValidAddr(addr)) 25 | { 26 | size_t head = addr; 27 | for (size_t i = 0; i < 0x400; i++) 28 | { 29 | addr = dig_link(addr, head, head, i * 0x400, 0x400); 30 | 31 | if (addr == 0) 32 | return; 33 | } 34 | 35 | EXT_F_OUT("\t[[ Too long list, unable to dump all ]]\n"); 36 | } 37 | else 38 | { 39 | EXT_F_OUT(" --> 0x%I64x\n", addr); 40 | } 41 | } 42 | FC; 43 | } 44 | 45 | void dig_link(size_t head, size_t entry) 46 | { 47 | try 48 | { 49 | size_t addr = head; 50 | if (EXT_F_ValidAddr(addr)) 51 | { 52 | for (size_t i = 0; i < 0x100; i++) 53 | { 54 | addr = dig_link(addr, head, entry, i * 0x1000, 0x1000); 55 | 56 | if (addr == 0) 57 | return; 58 | } 59 | 60 | EXT_F_OUT("\t[[ Too long list, unable to dump all ]]\n"); 61 | } 62 | else 63 | { 64 | EXT_F_OUT(" --> 0x%I64x\n", addr); 65 | } 66 | } 67 | FC; 68 | } 69 | 70 | size_t dig_link(size_t addr, size_t head, size_t entry, size_t index, size_t count) 71 | { 72 | try 73 | { 74 | stringstream ss; 75 | for (size_t i = 0; i < count; i++) 76 | { 77 | if (!EXT_F_ValidAddr(addr)) 78 | { 79 | ss << "\t[[ broken link at " 80 | << HEX_ADDR(addr) 81 | << " ]]\n"; 82 | 83 | EXT_F_OUT(ss.str().c_str()); 84 | return 0; 85 | } 86 | 87 | size_t flink = EXT_F_READ(addr); 88 | size_t blink = EXT_F_READ(addr + 8); 89 | 90 | ss << hex << showbase << setfill(' ') << setw(10) << i + index 91 | << " [ " 92 | << HEX_ADDR(flink) 93 | << " , " 94 | << HEX_ADDR(blink) 95 | << " ] \n"; 96 | 97 | 98 | if (flink == entry/* || blink == head*/) 99 | { 100 | ss << "\t[ found entry " 101 | << HEX_ADDR(addr) 102 | << " ]\n"; 103 | 104 | EXT_F_OUT(ss.str().c_str()); 105 | return 0; 106 | } 107 | 108 | if (flink == head/* || blink == head*/) 109 | { 110 | ss << "\t[ finished " 111 | << HEX_ADDR(addr) 112 | << " ]\n"; 113 | 114 | EXT_F_OUT(ss.str().c_str()); 115 | return 0; 116 | } 117 | 118 | addr = flink; 119 | } 120 | 121 | ss << "\t[[ ... next " << count << " entries ... ]]\n"; 122 | 123 | EXT_F_OUT(ss.str().c_str()); 124 | 125 | return addr; 126 | } 127 | FC; 128 | 129 | return addr; 130 | } -------------------------------------------------------------------------------- /list.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CmdInterface.h" 4 | 5 | DECLARE_CMD(link) 6 | DECLARE_CMD(flink) 7 | 8 | 9 | void dig_link(size_t addr); 10 | 11 | void dig_link(size_t addr, size_t head); 12 | 13 | size_t dig_link(size_t addr, size_t head, size_t entry, size_t index, size_t count); -------------------------------------------------------------------------------- /memory.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CmdInterface.h" 4 | 5 | #include 6 | 7 | DECLARE_CMD(size) 8 | DECLARE_CMD(va_regions) 9 | DECLARE_CMD(regs) 10 | DECLARE_CMD(as_qword) 11 | DECLARE_CMD(as_mem) 12 | DECLARE_CMD(ex_mem) 13 | DECLARE_CMD(args) 14 | DECLARE_CMD(vad) 15 | DECLARE_CMD(memcpy) 16 | DECLARE_CMD(page_2_svg) 17 | 18 | void dump_size(size_t value); 19 | void dump_args(); 20 | void dump_regs(); 21 | void analyze_qword(size_t value); 22 | void analyze_mem(size_t start, size_t len, size_t offset = 0); 23 | void extract_mem(size_t start, size_t len, size_t offset = 0); 24 | bool like_kaddr(size_t addr); 25 | 26 | bool in_curr_stack(size_t addr); 27 | string va_region_name(size_t addr); 28 | bool in_paged_pool(size_t addr); 29 | bool in_non_paged_pool(size_t addr); 30 | bool in_small_pool_page(size_t addr); 31 | tuple as_kcode(size_t addr); 32 | tuple as_ucode(size_t addr); 33 | tuple as_small_pool(size_t addr); 34 | tuple as_large_pool(size_t addr); 35 | string dump_plain_qword(size_t curr_qword); 36 | 37 | void init_va_regions(); 38 | void dump_va_regions(); 39 | 40 | void dump_vad(size_t root_addr); 41 | void visit_vad(size_t vad_node_addr); 42 | 43 | void do_memcpy(size_t src_addr, size_t dst_addr, size_t count); 44 | 45 | void page_to_svg(size_t addr, string svg_filename); 46 | 47 | void mem_access_to_svg(size_t start_addr, size_t end_addr, string mode, string svg_filename); 48 | 49 | -------------------------------------------------------------------------------- /model.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "CmdInterface.h" 18 | #pragma warning( disable : 4244) 19 | 20 | #define DK_COM_PTR Microsoft::WRL::ComPtr 21 | 22 | class CIModelObjectRefLogger 23 | { 24 | public: 25 | CIModelObjectRefLogger(IModelObject* raw_object, string tag); 26 | ~CIModelObjectRefLogger(); 27 | 28 | uint32_t ref_count() 29 | { 30 | if (m_raw_object != nullptr) 31 | { 32 | uint32_t* raw_ptr = (uint32_t*)m_raw_object; 33 | return *(raw_ptr + 3); 34 | } 35 | return 0; 36 | } 37 | 38 | private: 39 | IModelObject* m_raw_object; 40 | string m_tag; 41 | }; 42 | 43 | //#define DK_DBG 44 | 45 | #ifdef DK_DBG 46 | #define LOG_DEFINE_MGR vector> g_log_mgr; 47 | #define LOG_OBJ(mobj, tag) mobj;g_log_mgr.emplace_back(make_shared(mobj.Get(), tag)); 48 | #define DK_DBG_MGET_POBJ(mobj, key) CModelAccess::Instance()->get_pobj(mobj, key) 49 | #define DK_MGET_POBJ(mobj, key) LOG_OBJ(DK_DBG_MGET_POBJ(mobj, key), key); 50 | #define LOG_UNDEF_MGR g_log_mgr.clear(); 51 | #else 52 | #define LOG_DEFINE_MGR 53 | #define LOG_OBJ(mobj, tag) 54 | #define DK_MGET_POBJ CModelAccess::Instance()->get_pobj 55 | #define LOG_UNDEF_MGR 56 | #endif 57 | 58 | #define DK_MODEL_ACCESS CModelAccess::Instance() 59 | #define DK_MOBJ_PTR DK_COM_PTR 60 | 61 | #define DK_DUMP(type) CModelAccess::Instance()->dump_##type 62 | 63 | #define DK_MGET_PVAL CModelAccess::Instance()->get_pvalue 64 | #define DK_MGET_VAL CModelAccess::Instance()->get_value 65 | #define DK_MGET_POS CModelAccess::Instance()->get_pos 66 | #define DK_MGET_KIND CModelAccess::Instance()->get_kind 67 | #define DK_MGET_MODL CModelAccess::Instance()->get_module 68 | #define DK_MGET_SESN CModelAccess::Instance()->get_session 69 | #define DK_MGET_PROC CModelAccess::Instance()->get_process 70 | #define DK_MGET_THRD CModelAccess::Instance()->get_thread 71 | #define DK_X_CMD CModelAccess::Instance()->execute_cmd 72 | #define DK_SEEK_TO CModelAccess::Instance()->seek_to 73 | #define DK_GET_CURSTACK CModelAccess::Instance()->get_current_callstack 74 | #define DK_DUMP_CURSTACK CModelAccess::Instance()->dump_current_callstack 75 | #define DK_GET_CURPOS CModelAccess::Instance()->get_current_pos 76 | #define DK_GET_CURTID CModelAccess::Instance()->get_current_tid 77 | #define DK_GET_HEAP CModelAccess::Instance()->get_heap_memory 78 | #define DK_GET_MEM_ACCESS CModelAccess::Instance()->get_mem_access 79 | 80 | DECLARE_CMD(ls_model) 81 | DECLARE_CMD(ls_sessions) 82 | DECLARE_CMD(ls_processes) 83 | DECLARE_CMD(ls_threads) 84 | DECLARE_CMD(ls_modules) 85 | DECLARE_CMD(ls_handles) 86 | DECLARE_CMD(ps_ttd) 87 | DECLARE_CMD(session_ttd) 88 | DECLARE_CMD(ttd_calls) 89 | DECLARE_CMD(ttd_mem_access) 90 | DECLARE_CMD(ttd_mem_use) 91 | DECLARE_CMD(cur_context) 92 | DECLARE_CMD(exec) 93 | DECLARE_CMD(mobj) 94 | DECLARE_CMD(mobj_at) 95 | DECLARE_CMD(call) 96 | DECLARE_CMD(ccall) 97 | 98 | string BSTR2str(BSTR bstr); 99 | 100 | typedef struct _ttd_heap_memory 101 | { 102 | string function; 103 | tuple pos{ 0, 0 }; 104 | uint32_t thread_id{ 0 }; 105 | uint64_t res_id{ 0 }; 106 | uint64_t res_new_id{ 0 }; 107 | uint64_t size{ 0 }; 108 | }ttd_heap_memory; 109 | 110 | typedef struct _ttd_mem_access 111 | { 112 | string access_type; 113 | uint64_t ip_addr; 114 | uint64_t addr; 115 | uint64_t size; 116 | uint64_t value; 117 | uint64_t overwritten_value; 118 | uint64_t thread_id; 119 | uint64_t event_type; 120 | tuple start_pos{ 0, 0 }; 121 | tuple end_pos{ 0, 0 }; 122 | }ttd_mem_access; 123 | 124 | class CModelAccess 125 | { 126 | public: 127 | static CModelAccess* Instance() 128 | { 129 | static CModelAccess s_instance; 130 | return &s_instance; 131 | } 132 | 133 | CModelAccess(); 134 | 135 | vector> ls(string model_path); 136 | 137 | vector> enum_keyvalues(DK_MOBJ_PTR& mobj); 138 | 139 | vector> enum_keys(DK_MOBJ_PTR& mobj); 140 | 141 | void visit_root(); 142 | 143 | DK_MOBJ_PTR get_session(size_t session_id); 144 | 145 | DK_MOBJ_PTR get_process(size_t session_id, size_t process_id); 146 | 147 | DK_MOBJ_PTR get_thread(size_t session_id, size_t process_id, size_t thread_id); 148 | 149 | public: 150 | vector> iterate(DK_MOBJ_PTR& mobj); 151 | 152 | DK_MOBJ_PTR path2mobj(string path); 153 | 154 | DK_MOBJ_PTR at(DK_MOBJ_PTR& mobj, size_t index); 155 | 156 | ModelObjectKind get_kind(DK_MOBJ_PTR& mobj); 157 | 158 | template 159 | T get_pvalue(DK_MOBJ_PTR& mobj, string key); 160 | 161 | template 162 | T get_value(DK_MOBJ_PTR& mobj); 163 | 164 | DK_MOBJ_PTR get_pobj(DK_MOBJ_PTR& mobj, string key); 165 | 166 | DK_MOBJ_PTR get_pobj_tree(DK_MOBJ_PTR& mobj, string key); 167 | 168 | DK_MOBJ_PTR get_mobj_tree(string key); 169 | 170 | tuple get_pos(DK_MOBJ_PTR& mobj, string key); 171 | 172 | tuple get_module(DK_MOBJ_PTR& mobj); 173 | 174 | DK_MOBJ_PTR create_str_intrinsic_obj(string str); 175 | 176 | template 177 | DK_MOBJ_PTR create_int_intrinsic_obj(T val); 178 | 179 | DK_MOBJ_PTR call(DK_MOBJ_PTR mobj, DK_MOBJ_PTR context, vector args); 180 | 181 | DK_MOBJ_PTR assert_obj(DK_MOBJ_PTR& mobj); 182 | 183 | bool isUsermode() { 184 | return m_usermode; 185 | }; 186 | bool isKernelmode() { 187 | return m_kernelmode; 188 | }; 189 | bool isTTD() { 190 | return m_ttdmode; 191 | }; 192 | bool isDump() { 193 | return m_dumpmode; 194 | }; 195 | bool isLive() { 196 | return m_livemode; 197 | }; 198 | bool isNT() { 199 | return m_nt; 200 | }; 201 | string dumpFilename(){ 202 | return m_dump_filename; 203 | } 204 | 205 | string dump_frame(DK_MOBJ_PTR frame); 206 | 207 | string dump_thread(DK_MOBJ_PTR thread); 208 | 209 | string dump_process(DK_MOBJ_PTR process); 210 | 211 | string dump_stack(DK_MOBJ_PTR stack); 212 | 213 | string dump_current_callstack(); 214 | 215 | string dump_module(DK_MOBJ_PTR module); 216 | 217 | string dump_session(DK_MOBJ_PTR session); 218 | 219 | string dump_handle(DK_MOBJ_PTR handle); 220 | 221 | string dump_event(DK_MOBJ_PTR event); 222 | 223 | string dump_call_result(DK_MOBJ_PTR call_result); 224 | 225 | string dump_heap_memory(DK_MOBJ_PTR heap_memory); 226 | 227 | vector get_heap_memory(); 228 | 229 | string dump_mem_access_result(DK_MOBJ_PTR mem_access_result); 230 | 231 | string dump_mem_use_result(DK_MOBJ_PTR mem_use_result); 232 | 233 | vector> get_current_callstack(); 234 | 235 | void seek_to(uint64_t seq, uint64_t step); 236 | 237 | string dump_mobj(DK_MOBJ_PTR mobj, bool b_show_children = true, string mobj_path = ""); 238 | 239 | vector execute_cmd(string command); 240 | 241 | uint64_t get_current_tid(); 242 | 243 | vector get_mem_access(uint64_t start_addr, uint64_t end_addr, string mode); 244 | 245 | DK_MOBJ_PTR get_current_session(); 246 | DK_MOBJ_PTR get_current_process(); 247 | DK_MOBJ_PTR get_current_thread(); 248 | DK_MOBJ_PTR get_current_stack(); 249 | DK_MOBJ_PTR get_current_frame(); 250 | tuple get_current_pos(); 251 | 252 | private: 253 | IHostDataModelAccess* m_model_access{ nullptr }; 254 | IDataModelManager* m_model_mgr{ nullptr }; 255 | IDebugHost* m_debug_host{ nullptr }; 256 | 257 | static map s_map_kind_name; 258 | static map s_map_vt_name; 259 | 260 | bool m_usermode = { false }; 261 | bool m_kernelmode = { false }; 262 | bool m_ttdmode = { false }; 263 | bool m_dumpmode = { false }; 264 | bool m_livemode = { false }; 265 | bool m_nt = { false }; 266 | 267 | string m_dump_filename; 268 | 269 | public: 270 | DK_MOBJ_PTR m_debugger; 271 | 272 | DK_MOBJ_PTR m_cur_proc; 273 | DK_MOBJ_PTR m_cur_thread; 274 | DK_MOBJ_PTR m_cur_session; 275 | 276 | vector> m_sessions; 277 | }; 278 | -------------------------------------------------------------------------------- /module.cpp: -------------------------------------------------------------------------------- 1 | #include "module.h" 2 | #include "CmdList.h" 3 | #include "CmdExt.h" 4 | #include "object.h" 5 | #include "dbgdata.h" 6 | 7 | DEFINE_CMD(lmu) 8 | { 9 | dump_user_modules(); 10 | } 11 | 12 | DEFINE_CMD(lmk) 13 | { 14 | dump_kernel_modules(); 15 | } 16 | 17 | DEFINE_CMD(lm) 18 | { 19 | dump_modules(); 20 | } 21 | 22 | void dump_user_modules() 23 | { 24 | ExtRemoteTypedList lm_list = ExtNtOsInformation::GetUserLoadedModuleList(); 25 | 26 | for (lm_list.StartHead(); lm_list.HasNode(); lm_list.Next()) 27 | { 28 | ExtRemoteTyped lm = lm_list.GetTypedNode(); 29 | size_t name_addr = lm_list.GetNodeOffset() + lm.GetFieldOffset("FullDllName"); 30 | size_t dll_base = lm.Field("DllBase").GetUlong64(); 31 | EXT_F_OUT(L"0x%0I64x %s\n", dll_base, EXT_F_READ_USTR(name_addr).c_str()); 32 | } 33 | } 34 | 35 | void dump_kernel_modules() 36 | { 37 | 38 | ExtRemoteTypedList klm_list = ExtNtOsInformation::GetKernelLoadedModuleList(); 39 | 40 | for (klm_list.StartHead(); klm_list.HasNode(); klm_list.Next()) 41 | { 42 | ExtRemoteTyped lm = klm_list.GetTypedNode(); 43 | size_t name_addr = klm_list.GetNodeOffset() + lm.GetFieldOffset("FullDllName"); 44 | size_t dll_base = lm.Field("DllBase").GetUlong64(); 45 | EXT_F_OUT(L"0x%0I64x %s\n", dll_base, EXT_F_READ_USTR(name_addr).c_str()); 46 | } 47 | } 48 | 49 | void dump_modules() 50 | { 51 | try 52 | { 53 | size_t lm_head_addr = readDbgDataAddr(DEBUG_DATA_PsLoadedModuleListAddr); 54 | 55 | ExtRemoteTypedList modules_list(lm_head_addr, "nt!_LDR_DATA_TABLE_ENTRY", "InLoadOrderLinks"); 56 | for (modules_list.StartHead(); modules_list.HasNode(); modules_list.Next()) 57 | { 58 | auto module = modules_list.GetTypedNode(); 59 | size_t module_addr = modules_list.GetNodeOffset(); 60 | 61 | size_t base_addr = module.Field("DllBase").GetUlongPtr(); 62 | wstring full_name = EXT_F_READ_USTR(module_addr + module.GetFieldOffset("FullDllName")); 63 | wstring base_name = EXT_F_READ_USTR(module_addr + module.GetFieldOffset("BaseDllName")); 64 | size_t entry = module.Field("EntryPoint").GetUlongPtr(); 65 | uint32_t size = module.Field("SizeOfImage").GetUlong(); 66 | 67 | EXT_F_OUT(L"0x%I64x [0x%016x] 0x%I64x %20s %s\n", base_addr, size, entry, base_name.c_str(), full_name.c_str()); 68 | } 69 | } 70 | FC; 71 | } -------------------------------------------------------------------------------- /module.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CmdInterface.h" 4 | 5 | DECLARE_CMD(lmu) 6 | DECLARE_CMD(lmk) 7 | DECLARE_CMD(lm) 8 | 9 | void dump_user_modules(); 10 | void dump_kernel_modules(); 11 | void dump_modules(); -------------------------------------------------------------------------------- /object.cpp: -------------------------------------------------------------------------------- 1 | #include "object.h" 2 | #include "CmdList.h" 3 | #include "CmdExt.h" 4 | #include "dbgdata.h" 5 | #include "token.h" 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #pragma warning( disable : 4244) 12 | 13 | using namespace std; 14 | 15 | size_t g_header_cookie_addr = 0; 16 | size_t g_type_index_table_addr = 0; 17 | size_t g_ob_header_cookie = 0; 18 | 19 | map g_type_name_map; 20 | 21 | string 22 | getObjectStructByName( 23 | string type_name 24 | ) 25 | { 26 | string struct_name = ""; 27 | if (type_name == "Token") 28 | return "nt!_TOKEN"; 29 | else if (type_name == "Process") 30 | return "nt!_EPROCESS"; 31 | else if (type_name == "Thread") 32 | return "nt!_ETHREAD"; 33 | else if (type_name == "Directory") 34 | return "nt!_OBJECT_DIRECTORY"; 35 | else if (type_name == "Section") 36 | return "nt!_SECTION"; 37 | else if (type_name == "Mutant") 38 | return "nt!_KMUTANT"; 39 | else if (type_name == "Semaphore") 40 | return "nt!_KSEMAPHORE"; 41 | else if (type_name == "Event") 42 | return "nt!_KEVENT"; 43 | else if (type_name == "TmTx") 44 | return "nt!_KTRANSACTION"; 45 | else if (type_name == "TmTm") 46 | return "nt!_KTM"; 47 | else if (type_name == "TmRm") 48 | return "nt!_KRESOURCEMANAGER"; 49 | else if (type_name == "Timer") 50 | return "nt!_KTIMER"; 51 | else if (type_name == "Job") 52 | return "nt!_EJOB"; 53 | //else if (type_name == "Key") 54 | // generic_mask_str += getKeySpecificAccess(specific_mask, pureText); 55 | //else if (type_name == "TmEn") 56 | // generic_mask_str += getEnlistSpecificAccess(specific_mask, pureText); 57 | //else if (type_name == "IoCompletion") 58 | // generic_mask_str += getIoCSpecificAccess(specific_mask, pureText); 59 | else if (type_name == "File") 60 | return "nt!_FILE_OBJECT"; 61 | 62 | return "nt!_FILE_OBJECT"; 63 | } 64 | 65 | DEFINE_CMD(obj) 66 | { 67 | size_t obj_addr = EXT_F_IntArg(args, 1, 0); 68 | 69 | dump_obj(obj_addr); 70 | } 71 | 72 | DEFINE_CMD(gobj) 73 | { 74 | size_t root_obj_dir_addr = readDbgDataAddr(DEBUG_DATA_ObpRootDirectoryObjectAddr); 75 | if (root_obj_dir_addr == 0) 76 | return; 77 | 78 | try 79 | { 80 | dump_obj_dir(EXT_F_READ(root_obj_dir_addr), 0, true); 81 | } 82 | FC; 83 | } 84 | 85 | DEFINE_CMD(obj_dir) 86 | { 87 | size_t addr = EXT_F_IntArg(args, 1, 0); 88 | dump_obj_dir(addr, 0, true); 89 | } 90 | 91 | uint8_t real_index(size_t type_index, size_t obj_hdr_addr) 92 | { 93 | if (g_header_cookie_addr == 0 && g_ob_header_cookie == 0 && g_type_index_table_addr == 0) 94 | { 95 | if (S_OK != EXT_D_IDebugSymbols->GetOffsetByName("nt!ObHeaderCookie", &g_header_cookie_addr) || 96 | S_OK != EXT_D_IDebugDataSpaces->ReadVirtual(g_header_cookie_addr, &g_ob_header_cookie, sizeof(uint8_t), NULL)) 97 | { 98 | EXT_F_ERR("Fail to get the offset of nt!ObHeaderCookie\n"); 99 | return 0; 100 | } 101 | 102 | if (S_OK != EXT_D_IDebugSymbols->GetOffsetByName("nt!ObTypeIndexTable", &g_type_index_table_addr)) 103 | { 104 | EXT_F_ERR("Fail to get the offset of nt!ObTypeIndexTable\n"); 105 | return 0; 106 | } 107 | } 108 | 109 | uint8_t byte_2nd_addr = uint8_t(obj_hdr_addr >> 8); 110 | return (uint8_t)(type_index ^ g_ob_header_cookie ^ byte_2nd_addr); 111 | } 112 | 113 | void dump_obj(size_t obj_addr, bool b_simple) 114 | { 115 | try 116 | { 117 | ExtRemoteTyped obj_hdr("(nt!_OBJECT_HEADER*)@$extin", obj_addr); 118 | //obj_hdr.OutFullValue(); 119 | 120 | uint8_t r_index = real_index(obj_hdr.Field("TypeIndex").GetUchar(), obj_addr); 121 | size_t sdr_addr = obj_hdr.Field("SecurityDescriptor").GetLongPtr() & 0xFFFFFFFFFFFFFFF0; 122 | 123 | wstring obj_name = dump_obj_name(obj_addr); 124 | wstring type_name = getTypeName(r_index); 125 | 126 | string str_type_name(type_name.begin(), type_name.end()); 127 | string str_obj_name(obj_name.begin(), obj_name.end()); 128 | 129 | stringstream ss; 130 | 131 | ss << hex << showbase; 132 | 133 | ss << DML_CMD << "dt " << getObjectStructByName(str_obj_name) << " " << HEX_ADDR(obj_addr + 0x30) 134 | << DML_TEXT << "dt" 135 | << DML_END 136 | << " " 137 | << noshowbase << dec << setfill(' '); 138 | 139 | ss << "" << setw(18) << obj_addr << " " 142 | << setw(20) << str_type_name << " [" << setw(4) << (uint16_t)r_index << "] "; 143 | 144 | if (obj_name.empty() && type_name == L"File") 145 | { 146 | wstring file_name = dump_file_name(obj_addr + 0x30); 147 | string str_file_name(file_name.begin(), file_name.end()); 148 | 149 | ss << str_file_name; 150 | } 151 | else 152 | ss << str_obj_name; 153 | 154 | ss << endl; 155 | 156 | if (!b_simple) 157 | { 158 | 159 | uint8_t info_mask = obj_hdr.Field("InfoMask").GetUchar(); 160 | 161 | size_t mask2off_table_addr = EXT_F_Sym2Addr("nt!ObpInfoMaskToOffset"); 162 | uint8_t offset = EXT_F_READ(mask2off_table_addr + info_mask); 163 | 164 | size_t opt_hdr_start = obj_addr - offset; 165 | 166 | if (info_mask & 0x10) 167 | { 168 | ExtRemoteTyped ob_opt_info("(nt!_OBJECT_HEADER_PROCESS_INFO*)@$extin", opt_hdr_start); 169 | 170 | ss << string(25, '-') << setw(30) << "[ process info : " 171 | << hex << showbase 172 | << "" 175 | << opt_hdr_start 176 | << "" 177 | << " ]" << string(25, '-') << endl; 178 | 179 | size_t proc_addr = ob_opt_info.Field("ExclusiveProcess").GetUlongPtr(); 180 | 181 | ss << "Process: " << proc_addr << "" << endl; 182 | 183 | opt_hdr_start += 0x10; 184 | } 185 | 186 | if (info_mask & 0x08) 187 | { 188 | ExtRemoteTyped ob_opt_info("(nt!_OBJECT_HEADER_QUOTA_INFO*)@$extin", opt_hdr_start); 189 | 190 | ss << string(25, '-') << setw(30) << "[ quota info : " 191 | << hex << showbase 192 | << "" 195 | << opt_hdr_start 196 | << "" 197 | << " ]" << string(25, '-') << endl; 198 | 199 | uint32_t page_charge = ob_opt_info.Field("PagedPoolCharge").GetUlong(); 200 | uint32_t npage_charge = ob_opt_info.Field("NonPagedPoolCharge").GetUlong(); 201 | uint32_t sd_charge = ob_opt_info.Field("SecurityDescriptorCharge").GetUlong(); 202 | 203 | ss << setw(40) << "Paged Pool Charge: " << page_charge << endl 204 | << setw(40) << "Non-Paged Pool Charge: " << npage_charge << endl 205 | << setw(40) << "Security Descrptor Charge: " << sd_charge << endl; 206 | 207 | opt_hdr_start += 0x20; 208 | } 209 | 210 | if (info_mask & 0x04) 211 | { 212 | ExtRemoteTyped ob_opt_info("(nt!_OBJECT_HEADER_HANDLE_INFO*)@$extin", opt_hdr_start); 213 | 214 | ss << string(25, '-') << setw(30) << "[ handle info : " 215 | << hex << showbase 216 | << "" 219 | << opt_hdr_start 220 | << "" 221 | << " ]" << string(25, '-') << endl; 222 | 223 | opt_hdr_start += 0x10; 224 | } 225 | 226 | if (info_mask & 0x02) 227 | { 228 | ExtRemoteTyped ob_opt_info("(nt!_OBJECT_HEADER_NAME_INFO*)@$extin", opt_hdr_start); 229 | wstring obj_name = EXT_F_READ_USTR(obj_addr - offset + ob_opt_info.GetFieldOffset("Name")); 230 | 231 | wstring type_name = getTypeName(real_index(obj_hdr.Field("TypeIndex").GetUchar(), obj_addr)); 232 | if (type_name == L"SymbolicLink") 233 | { 234 | obj_name += L" --> "; 235 | obj_name += dump_sym_link(obj_addr); 236 | } 237 | 238 | ss << string(25, '-') << setw(30) << "[ name info : " 239 | << hex << showbase 240 | << "" 243 | << opt_hdr_start 244 | << "" 245 | << " ]" << string(25, '-') << endl; 246 | 247 | size_t dir_addr = ob_opt_info.Field("Directory").GetUlongPtr(); 248 | 249 | if (dir_addr != 0) 250 | { 251 | ss << "Parent Directory: " << dir_addr << " " 252 | << "\t\tdetail " 253 | << "\t\tlistdir" 254 | << endl; 255 | } 256 | 257 | opt_hdr_start += 0x20; 258 | } 259 | 260 | if (info_mask & 0x01) 261 | { 262 | ExtRemoteTyped ob_opt_info("(nt!_OBJECT_HEADER_CREATOR_INFO*)@$extin", opt_hdr_start); 263 | 264 | ss << string(25, '-') << setw(30) << "[ creator info : " 265 | << hex << showbase 266 | << "" 269 | << opt_hdr_start 270 | << "" 271 | << " ]" << string(25, '-') << endl; 272 | 273 | size_t proc_addr = ob_opt_info.Field("CreatorUniqueProcess").GetUlongPtr(); 274 | 275 | ss << "Creator: " << proc_addr << "" << endl; 276 | 277 | opt_hdr_start += 0x20; 278 | } 279 | 280 | ss << string(25, '-') << setw(30) << "[ security descriptor : " 281 | << hex << showbase 282 | << "" 285 | << sdr_addr 286 | << "" 287 | << " ]" << string(25, '-') << endl; 288 | } 289 | 290 | EXT_F_DML(ss.str().c_str()); 291 | 292 | if (!b_simple && sdr_addr != 0) 293 | dump_sdr(sdr_addr, str_type_name); 294 | 295 | } 296 | FC; 297 | } 298 | 299 | void 300 | dump_obj_dir( 301 | size_t obj_dir_addr, 302 | size_t level, 303 | bool recurse) 304 | { 305 | if (obj_dir_addr == 0) 306 | return; 307 | 308 | try 309 | { 310 | /*ExtRemoteTyped obj_hdr("(nt!_OBJECT_HEADER*)@$extin", obj_hdr_addr); 311 | uint8_t info_mask = obj_hdr.Field("InfoMask").GetUchar(); 312 | size_t obj_dir_addr = 0; 313 | if (info_mask & 0x02) 314 | { 315 | size_t mask2off_table_addr = getSymbolAddr("nt!ObpInfoMaskToOffset"); 316 | uint8_t offset = read(mask2off_table_addr + (info_mask & 3)); 317 | 318 | ExtRemoteTyped ob_type_entry("(nt!_OBJECT_HEADER_NAME_INFO*)@$extin", obj_hdr_addr - offset); 319 | obj_dir_addr = ob_type_entry.Field("Directory").GetUlongPtr(); 320 | }*/ 321 | 322 | //size_t obj_dir_addr = obj_hdr_addr + 0x30; 323 | if (obj_dir_addr == 0) 324 | return; 325 | 326 | stringstream ss; 327 | 328 | dump_obj(obj_dir_addr - 0x30); 329 | 330 | EXT_F_OUT(string(60, '=').append("\n").c_str()); 331 | 332 | for (size_t i = 0; i < 37; i++) 333 | { 334 | size_t entry = EXT_F_READ(obj_dir_addr + 8 * i); 335 | if (!EXT_F_ValidAddr(entry)) 336 | continue; 337 | if (entry == obj_dir_addr) 338 | continue; 339 | 340 | while (EXT_F_ValidAddr(entry)) 341 | { 342 | size_t obj_addr = EXT_F_READ(entry + 8); 343 | if (EXT_F_ValidAddr(obj_addr - 0x30)) 344 | { 345 | ExtRemoteTyped obj_hdr("(nt!_OBJECT_HEADER*)@$extin", obj_addr - 0x30); 346 | wstring wstr_type_name = getTypeName(real_index(obj_hdr.Field("TypeIndex").GetUchar(), obj_addr - 0x30)); 347 | string type_name(wstr_type_name.begin(), wstr_type_name.end()); 348 | string tab(level * 4, ' '); 349 | tab += "->"; 350 | 351 | ss.str(""); 352 | 353 | ss << tab << showbase << hex << setw(4) << i 354 | << " [" << setw(20) << type_name << "] "; 355 | 356 | wstring wstr_file_name = dump_file_name(obj_addr - 0x30); 357 | wstring wstr_obj_name = dump_obj_name(obj_addr - 0x30); 358 | 359 | if (type_name == "File") 360 | ss << setw(50) << string(wstr_file_name.begin(), wstr_file_name.end()); 361 | else 362 | ss << setw(50) << string(wstr_obj_name.begin(), wstr_obj_name.end()); 363 | 364 | ss << " " << obj_addr - 0x30 << " "; 365 | 366 | if (type_name == "Directory") 367 | ss << " detail listdir" << endl; 368 | else 369 | ss << " detail" << endl; 370 | 371 | EXT_F_DML(ss.str().c_str()); 372 | 373 | /*if (type_name == "Device") 374 | { 375 | ExtRemoteTyped dev_obj("(nt!_DEVICE_OBJECT*)@$extin", obj_addr); 376 | size_t dev_sd = dev_obj.Field("SecurityDescriptor").GetPtr(); 377 | dump_sdr(dev_sd); 378 | Out("-------------------------------------------------------------------------------\n"); 379 | }*/ 380 | 381 | /*if (type_name == L"File") 382 | Out(L"%s%02x %20s %s\n", tab.c_str(), i, type_name.c_str(), dump_file_name(obj_addr - 0x30).c_str()); 383 | else 384 | Out(L"%s%02x %20s %s\n", tab.c_str(), i, type_name.c_str(), dump_obj_name(obj_addr - 0x30).c_str()); 385 | */ 386 | //dump_obj(obj_addr-0x30, true); 387 | 388 | /* if (recurse && type_name == "Directory") 389 | dump_obj_dir(obj_addr-0x30, level+1); */ 390 | } 391 | size_t next = EXT_F_READ(entry); 392 | if (next == entry) 393 | break; 394 | entry = next; 395 | } 396 | } 397 | } 398 | FC; 399 | } 400 | 401 | wstring dump_obj_name(size_t obj_hdr_addr) 402 | { 403 | wstring obj_name; 404 | 405 | try 406 | { 407 | ExtRemoteTyped obj_hdr("(nt!_OBJECT_HEADER*)@$extin", obj_hdr_addr); 408 | uint8_t info_mask = obj_hdr.Field("InfoMask").GetUchar(); 409 | if (info_mask & 0x02) 410 | { 411 | size_t mask2off_table_addr = EXT_F_Sym2Addr("nt!ObpInfoMaskToOffset"); 412 | uint8_t offset = EXT_F_READ(mask2off_table_addr + (info_mask & 3)); 413 | 414 | ExtRemoteTyped ob_type_entry("(nt!_OBJECT_HEADER_NAME_INFO*)@$extin", obj_hdr_addr - offset); 415 | obj_name = EXT_F_READ_USTR(obj_hdr_addr - offset + ob_type_entry.GetFieldOffset("Name")); 416 | 417 | wstring type_name = getTypeName(real_index(obj_hdr.Field("TypeIndex").GetUchar(), obj_hdr_addr)); 418 | if (type_name == L"SymbolicLink") 419 | { 420 | obj_name += L" --> "; 421 | obj_name += dump_sym_link(obj_hdr_addr); 422 | } 423 | } 424 | } 425 | FC; 426 | 427 | return obj_name; 428 | } 429 | 430 | wstring dump_file_name(size_t file_obj_addr) 431 | { 432 | try 433 | { 434 | ExtRemoteTyped file_obj("(nt!_FILE_OBJECT*)@$extin", file_obj_addr); 435 | return EXT_F_READ_USTR(file_obj_addr + file_obj.GetFieldOffset("FileName")); 436 | } 437 | FC; 438 | 439 | return L""; 440 | } 441 | 442 | 443 | wstring getTypeName(size_t index) 444 | { 445 | if (g_type_name_map.find((uint8_t)index) == g_type_name_map.end()) 446 | { 447 | size_t type_entry_addr = 0; 448 | if (S_OK == EXT_D_IDebugDataSpaces->ReadVirtual(g_type_index_table_addr + index * 0x08, &type_entry_addr, sizeof(size_t), NULL)) 449 | { 450 | ExtRemoteTyped ob_type_entry("(nt!_OBJECT_TYPE*)@$extin", type_entry_addr); 451 | g_type_name_map[(uint8_t)index] = EXT_F_READ_USTR(type_entry_addr + ob_type_entry.GetFieldOffset("Name")); 452 | } 453 | } 454 | 455 | if (g_type_name_map.find((uint8_t)index) != g_type_name_map.end()) 456 | return g_type_name_map[(uint8_t)index]; 457 | 458 | return L""; 459 | } 460 | 461 | wstring dump_sym_link(size_t addr) 462 | { 463 | wstring obj_name; 464 | 465 | try 466 | { 467 | ExtRemoteTyped obj_sym_link("(nt!_OBJECT_SYMBOLIC_LINK*)@$extin", addr + 0x30); 468 | obj_name = EXT_F_READ_USTR(addr + 0x30 + obj_sym_link.GetFieldOffset("LinkTarget")); 469 | } 470 | FC; 471 | 472 | return obj_name; 473 | } 474 | -------------------------------------------------------------------------------- /object.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CmdInterface.h" 4 | 5 | DECLARE_CMD(obj) 6 | DECLARE_CMD(gobj) 7 | DECLARE_CMD(obj_dir) 8 | 9 | void dump_obj(size_t obj_addr, bool b_simple = false); 10 | void dump_obj_dir(size_t obj_hdr_addr, size_t level = 0, bool recurse = false); 11 | uint8_t real_index(size_t type_index, size_t obj_hdr_addr); 12 | 13 | wstring dump_obj_name(size_t obj_hdr_addr); 14 | wstring dump_file_name(size_t file_obj_addr); 15 | 16 | wstring getTypeName(size_t index); 17 | wstring dump_sym_link(size_t addr); -------------------------------------------------------------------------------- /page.cpp: -------------------------------------------------------------------------------- 1 | #include "page.h" 2 | #include "CmdExt.h" 3 | #include "CmdList.h" 4 | #include "process.h" 5 | 6 | #include 7 | 8 | DEFINE_CMD(page) 9 | { 10 | size_t addr = EXT_F_IntArg(args, 1, 0); 11 | dump_page_info(addr); 12 | } 13 | 14 | DEFINE_CMD(pages) 15 | { 16 | size_t addr = EXT_F_IntArg(args, 1, 0); 17 | dump_pages_around(addr); 18 | } 19 | 20 | DEFINE_CMD(hole) 21 | { 22 | size_t rsp_addr = EXT_F_IntArg(args, 1, 0); 23 | dump_hole(rsp_addr); 24 | } 25 | 26 | // 27 | //void CTokenExt::dump_page_info(size_t addr) 28 | //{ 29 | // size_t pxe_index = (addr >> 39) & 0x1FF; 30 | // size_t ppe_index = (addr >> 30) & 0x1FF; 31 | // size_t pde_index = (addr >> 21) & 0x1FF; 32 | // size_t pte_index = (addr >> 12) & 0x1FF; 33 | // size_t offset = addr & 0xFFF; 34 | // 35 | // stringstream ss; 36 | // 37 | // size_t cr3 = get_cr3(); 38 | // 39 | // PTE64 pxe(readX(cr3 + pxe_index * 8)); 40 | // PTE64 ppe(pxe.valid()? readX(pxe.PFN() + ppe_index * 8) : 0); 41 | // PTE64 pde(ppe.valid()? readX(ppe.PFN() + pde_index * 8) : 0); 42 | // PTE64 pte(pde.valid()? readX(pde.PFN() + pte_index * 8) : 0); 43 | // 44 | // size_t paddr = pte.PFN(); 45 | // 46 | // ss << hex << showbase 47 | // << "PXE: Valid=" << (pxe.valid() ? "Y" : "n") << ", Index=" << setw(6) << pxe_index << ", PFN=" << setw(18) << pxe.PFN() << ", Flags=" << pxe.str() << endl 48 | // << "PPE: Valid=" << (ppe.valid() ? "Y" : "n") << ", Index=" << setw(6) << ppe_index << ", PFN=" << setw(18) << ppe.PFN() << ", Flags=" << ppe.str() << endl 49 | // << "PDE: Valid=" << (pde.valid() ? "Y" : "n") << ", Index=" << setw(6) << pde_index << ", PFN=" << setw(18) << pde.PFN() << ", Flags=" << pde.str() << endl 50 | // << "PTE: Valid=" << (pte.valid() ? "Y" : "n") << ", Index=" << setw(6) << pte_index << ", PFN=" << setw(18) << pte.PFN() << ", Flags=" << pte.str() << endl 51 | // << "Virtual Address: " << setw(18) << addr << endl 52 | // << "Physical Address: " << setw(18) << (pte.PFN() + offset) << endl << endl; 53 | // 54 | // Out(ss.str().c_str()); 55 | //} 56 | 57 | void dump_page_info(size_t addr) 58 | { 59 | size_t pxe_index = (addr >> 39) & 0x1FF; 60 | size_t ppe_index = (addr >> 30) & 0x1FF; 61 | size_t pde_index = (addr >> 21) & 0x1FF; 62 | size_t pte_index = (addr >> 12) & 0x1FF; 63 | size_t offset = addr & 0xFFF; 64 | 65 | stringstream ss; 66 | 67 | size_t cr3 = get_cr3() & 0xFFFFFFFFFFFFFFF0; 68 | 69 | PTE64 pxe(EXT_F_READX(cr3 + pxe_index * 8)); 70 | PTE64 ppe(pxe.valid() ? EXT_F_READX(pxe.PFN() + ppe_index * 8) : 0); 71 | PTE64 pde(ppe.valid() ? EXT_F_READX(ppe.PFN() + pde_index * 8) : 0); 72 | PTE64 pte(pde.valid() ? EXT_F_READX(pde.PFN() + pte_index * 8) : 0); 73 | 74 | size_t paddr = pte.PFN(); 75 | 76 | ss << hex << showbase 77 | << "PXE: Valid=" << (pxe.valid() ? "Y" : "n") << ", Index=" << setw(6) << pxe_index << ", PFN=" << setw(18) << pxe.PFN() / 0x1000 << ", Flags=" << pxe.str() << endl 78 | << "PPE: Valid=" << (ppe.valid() ? "Y" : "n") << ", Index=" << setw(6) << ppe_index << ", PFN=" << setw(18) << ppe.PFN() / 0x1000 << ", Flags=" << ppe.str() << endl 79 | << "PDE: Valid=" << (pde.valid() ? "Y" : "n") << ", Index=" << setw(6) << pde_index << ", PFN=" << setw(18) << pde.PFN() / 0x1000 << ", Flags=" << pde.str() << endl 80 | << "PTE: Valid=" << (pte.valid() ? "Y" : "n") << ", Index=" << setw(6) << pte_index << ", PFN=" << setw(18) << pte.PFN() / 0x1000 << ", Flags=" << pte.str() << endl 81 | << "Virtual Address: " << setw(18) << addr << endl 82 | << "Physical Address: " << setw(18) << (pte.PFN() + offset) << endl << endl; 83 | 84 | EXT_F_OUT(ss.str().c_str()); 85 | } 86 | 87 | void dump_pages_around(size_t addr) 88 | { 89 | size_t pxe_index = (addr >> 39) & 0x1FF; 90 | size_t ppe_index = (addr >> 30) & 0x1FF; 91 | size_t pde_index = (addr >> 21) & 0x1FF; 92 | size_t pte_index = (addr >> 12) & 0x1FF; 93 | size_t offset = addr & 0xFFF; 94 | 95 | stringstream ss; 96 | 97 | size_t cr3 = get_cr3() & 0xFFFFFFFFFFFFFFF0; 98 | 99 | PTE64 pxe(EXT_F_READX(cr3 + pxe_index * 8)); 100 | PTE64 ppe(pxe.valid() ? EXT_F_READX(pxe.PFN() + ppe_index * 8) : 0); 101 | PTE64 pde(ppe.valid() ? EXT_F_READX(ppe.PFN() + pde_index * 8) : 0); 102 | 103 | size_t* pde_entries = new size_t[0x200]; 104 | memset(pde_entries, 0, 0x1000); 105 | 106 | if (pxe.valid() && ppe.valid() && pde.valid()) 107 | { 108 | auto status = EXT_D_IDebugDataSpaces->ReadPhysical(pde.PFN(), pde_entries, 0x1000, NULL); 109 | if (S_OK != status) 110 | EXT_F_THROW(E_ACCESSDENIED, "Fail to read memory"); 111 | } 112 | 113 | for (size_t i = 0; i < 0x200; i++) 114 | { 115 | PTE64 pte(pde_entries[i]); 116 | 117 | ss << hex << showbase 118 | << setw(18) << ((addr & 0xFFFFFFFFFFE00000) + i * 0x1000) << " : "; 119 | 120 | if (pte.valid()) 121 | ss << setw(18) << pte.PFN(); 122 | 123 | if (i == pte_index) 124 | ss << "\t\t<---------------- [" << addr << " ]"; 125 | 126 | ss << endl; 127 | } 128 | 129 | delete[] pde_entries; 130 | 131 | EXT_F_DML(" Previous \n", addr - 0x200000); 132 | EXT_F_OUT(ss.str().c_str()); 133 | EXT_F_DML(" Next \n", addr + 0x200000); 134 | } 135 | 136 | void dump_hole(size_t addr) 137 | { 138 | try 139 | { 140 | //if (valid_addr(addr)) 141 | bool bHoleFound = false; 142 | while (!bHoleFound) 143 | { 144 | bool current = false; 145 | 146 | size_t start_page_addr = (addr & 0xFFFFFFFFFFFFF000 - 0x1000 * 0x80) & 0xFFFFFFFFFFF00000; 147 | 148 | stringstream ss; 149 | ss << "\n++++++++++++++++++++++++++++++++++++++++++++++\n"; 150 | for (size_t i = 0; i < 0x200; i++) 151 | { 152 | if (i % 0x10 == 0) 153 | { 154 | if (current) 155 | { 156 | current = false; 157 | ss << "\t\t <-----[" << hex << showbase << setw(16) << setfill('0') << "]" << addr; 158 | } 159 | ss << "\n" << hex << showbase << setw(16) << setfill('0') << start_page_addr + i * 0x1000 << ": "; 160 | } 161 | 162 | if (addr >= start_page_addr + i * 0x1000 && addr <= start_page_addr + (i + 1) * 0x1000) 163 | current = true; 164 | 165 | if (EXT_F_ValidAddr(start_page_addr + i * 0x1000)) 166 | ss << "!"; 167 | else 168 | { 169 | ss << "."; 170 | bHoleFound = true; 171 | } 172 | } 173 | 174 | ss << "\n++++++++++++++++++++++++++++++++++++++++++++++\n"; 175 | 176 | EXT_F_OUT(ss.str().c_str()); 177 | 178 | addr += 0x200000; 179 | } 180 | } 181 | FC; 182 | } -------------------------------------------------------------------------------- /page.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CmdInterface.h" 4 | 5 | #include 6 | 7 | DECLARE_CMD(page) 8 | DECLARE_CMD(pages) 9 | DECLARE_CMD(hole) 10 | 11 | #pragma pack(push, 1) 12 | struct PTE64 13 | { 14 | size_t Valid : 1; 15 | size_t Write : 1; 16 | size_t Owner : 1; 17 | size_t WriteThrough : 1; 18 | size_t CacheDisabled : 1; 19 | size_t Accessed : 1; 20 | size_t Dirty : 1; 21 | size_t LargePage : 1; 22 | size_t Global : 1; 23 | size_t SoftCopyOnWrite : 1; 24 | size_t SoftPrototype : 1; 25 | size_t SoftWrite : 1; 26 | size_t PageFrameNumber : 28; 27 | size_t Reserved : 12; 28 | size_t SoftWorkingSetIndex : 11; 29 | size_t NoExecute : 1; 30 | 31 | PTE64(size_t source) 32 | { 33 | memcpy(this, &source, 8); 34 | } 35 | 36 | size_t PFN() 37 | { 38 | return (size_t)PageFrameNumber << 12; 39 | } 40 | 41 | bool valid() { return Valid != 0; } 42 | bool write() { return Write != 0; } 43 | bool owner() { return Owner != 0; } 44 | bool writeThrough() { return WriteThrough != 0; } 45 | bool cache() { return CacheDisabled == 0; } 46 | bool accessed() { return Accessed != 0; } 47 | bool dirty() { return Dirty != 0; } 48 | bool large() { return LargePage != 0; } 49 | bool global() { return Global != 0; } 50 | bool softCow() { return SoftCopyOnWrite != 0; } 51 | bool softProto() { return SoftPrototype != 0; } 52 | bool softWrite() { return SoftWrite != 0; } 53 | bool nx() { return NoExecute != 0; } 54 | size_t workingsetIndex() { return SoftWorkingSetIndex; } 55 | 56 | string str() 57 | { 58 | stringstream ss; 59 | ss << (valid() ? "Valid" : "invalid") << " " 60 | << (write() ? "Write" : "readonly") << " " 61 | << (owner() ? "Usermode" : "kernelmode") << " " 62 | << (accessed() ? "Accessed" : "noaccess") << " " 63 | << (dirty() ? "Dirty" : "no-dirty") << " " 64 | << (large() ? "Large" : "no-large") << " " 65 | << (global() ? "Global" : "no-global") << " " 66 | << (softCow() ? "CopyOnWrite" : "no-copyonwrite") << " " 67 | << (softWrite() ? "SoftWrite" : "no-softwrite") << " " 68 | << (nx() ? "NX" : "no-NX") << " "; 69 | ; 70 | 71 | return ss.str(); 72 | } 73 | }; 74 | #pragma pack(pop) 75 | 76 | void dump_page_info(size_t addr); 77 | void dump_pages_around(size_t addr); 78 | void dump_hole(size_t addr); 79 | -------------------------------------------------------------------------------- /pe.cpp: -------------------------------------------------------------------------------- 1 | #include "pe.h" 2 | #include "CmdExt.h" 3 | #include "CmdList.h" 4 | 5 | DEFINE_CMD(peguid) 6 | { 7 | size_t addr = EXT_F_IntArg(args, 1, 0); 8 | dump_pe_guid(addr); 9 | } 10 | 11 | void dump_pe_guid(size_t addr) 12 | { 13 | try 14 | { 15 | size_t dos_magic = EXT_F_READ(addr); 16 | 17 | if (dos_magic != 0x0000000300905a4d) 18 | return; 19 | 20 | uint32_t e_lfanew = EXT_F_READ(addr + 0x3C); 21 | 22 | uint32_t nt_magic = EXT_F_READ(addr + e_lfanew); 23 | if (nt_magic != 0x00004550) 24 | return; 25 | 26 | uint32_t timestamp = EXT_F_READ(addr + e_lfanew + 0x08); 27 | uint32_t sizeof_image = EXT_F_READ(addr + e_lfanew + 0x50); 28 | 29 | EXT_F_OUT(R"(guid : http://msdl.microsoft.com/download/symbols/[xxx]/%08X%08X/[xxx]\n)", timestamp, sizeof_image); 30 | } 31 | FC; 32 | } -------------------------------------------------------------------------------- /pe.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CmdInterface.h" 4 | 5 | DECLARE_CMD(peguid) 6 | 7 | void dump_pe_guid(size_t addr); -------------------------------------------------------------------------------- /pool.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CmdInterface.h" 4 | 5 | #include 6 | 7 | DECLARE_CMD(free_pool) 8 | DECLARE_CMD(bigpool); 9 | DECLARE_CMD(poolrange); 10 | DECLARE_CMD(pooltrack); 11 | DECLARE_CMD(poolmetrics); 12 | DECLARE_CMD(tpool); 13 | DECLARE_CMD(poolhdr); 14 | 15 | class CPoolHeader 16 | { 17 | public: 18 | CPoolHeader(size_t data) 19 | { 20 | memcpy(this, &data, 8); 21 | } 22 | 23 | uint32_t prev_size : 8; 24 | uint32_t pool_index : 8; 25 | uint32_t block_size : 8; 26 | uint32_t pool_type : 8; 27 | char tag[4]; 28 | }; 29 | 30 | //kd> dt _POOL_TRACKER_BIG_PAGES 31 | //nt!_POOL_TRACKER_BIG_PAGES 32 | //+ 0x000 Va : Uint8B 33 | //+ 0x008 Key : Uint4B 34 | //+ 0x00c Pattern : Pos 0, 8 Bits 35 | //+ 0x00c PoolType : Pos 8, 12 Bits 36 | //+ 0x00c SlushSize : Pos 20, 12 Bits 37 | //+ 0x010 NumberOfBytes : Uint8B 38 | 39 | class CBigPoolHeader 40 | { 41 | public: 42 | CBigPoolHeader(uint8_t* data) 43 | { 44 | memcpy(this, data, 0x18); 45 | } 46 | 47 | size_t va; 48 | char tag[4]; 49 | uint32_t pattern : 8; 50 | uint32_t pool_type : 12; 51 | uint32_t slush_size : 12; 52 | size_t size; 53 | }; 54 | 55 | /**************************************************** 56 | * 8 5 2 1 0 57 | * | | | | | 58 | * V V V V V 59 | * ___________________________________________________ 60 | * | | | | | | | | | 61 | * |____________________________|_|________|_|_|_|_|_| 62 | * ^ ^ ^ ^ ^ 63 | * | | | | | 64 | * | | | | 0: Non-Paged Pool 65 | * | | | | 1: Paged Pool 66 | * | | | | 67 | * | | | 1: Must Succeed (0x02) 68 | * | | | 69 | * | | | 70 | * | | 1: Cache Aligned (0x04) 71 | * | | 72 | * | | 73 | * | 1: Session Pool (0x20) 74 | * | 75 | * | 76 | * 1: NX, No Execute (0x200) 77 | * 78 | *****************************************************/ 79 | 80 | #define NonPagedPool 0x0000 81 | #define NonPagedPoolExecute 0x0000 82 | #define NonPagedPoolBase 0x0000 83 | 84 | #define PagedPool 0x0001 85 | 86 | #define NonPagedPoolMustSucceed 0x0002 87 | #define NonPagedPoolBaseMustSucceed 0x0002 88 | 89 | #define DontUseThisType 0x0003 90 | 91 | #define NonPagedPoolCacheAligned 0x0004 92 | #define NonPagedPoolBaseCacheAligned 0x0004 93 | 94 | #define PagedPoolCacheAligned 0x0005 95 | 96 | #define NonPagedPoolCacheAlignedMustS 0x0006 97 | #define NonPagedPoolBaseCacheAlignedMustS 0x0006 98 | 99 | #define MaxPoolType 0x0007 100 | 101 | #define NonPagedPoolSession 0x0020 102 | #define PagedPoolSession 0x0021 103 | #define NonPagedPoolMustSucceedSession 0x0022 104 | #define DontUseThisTypeSession 0x0023 105 | #define NonPagedPoolCacheAlignedSession 0x0024 106 | #define PagedPoolCacheAlignedSession 0x0025 107 | #define NonPagedPoolCacheAlignedMustSSession 0x0026 108 | 109 | #define NonPagedPoolNx 0x0200 110 | #define NonPagedPoolNxCacheAligned 0x0204 111 | 112 | #define NonPagedPoolSessionNx 0x0220 113 | 114 | class POOL_METRICS 115 | { 116 | public: 117 | size_t _pool_addr; 118 | size_t _pool_index; 119 | size_t _pool_type; 120 | size_t _pool_start; 121 | size_t _pool_end; 122 | size_t _total_pages; 123 | size_t _total_bytes; 124 | size_t _total_big_pages; 125 | string _comment; 126 | vector _pending_frees; 127 | map> _free_lists; 128 | }; 129 | 130 | void dump_free_pool(size_t size); 131 | void dump_big_pool(); 132 | void dump_pool_track(); 133 | void dump_pool_range(); 134 | void dump_pool_metrics(); 135 | void tpool(size_t addr); 136 | void poolhdr(size_t addr); -------------------------------------------------------------------------------- /process.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CmdInterface.h" 4 | 5 | DECLARE_CMD(pses) 6 | DECLARE_CMD(ps_flags); 7 | DECLARE_CMD(kill); 8 | DECLARE_CMD(process); 9 | 10 | void dump_process(size_t process_addr); 11 | void dump_ps_flags(size_t addr); 12 | size_t get_process_silo(size_t process_addr); 13 | size_t get_job_silo(size_t job_addr); 14 | string getProtectionText(uint8_t protection); 15 | string getTokenIL(size_t token_addr); 16 | 17 | size_t get_cr3(); 18 | 19 | size_t curr_proc(); 20 | size_t curr_thread(); 21 | size_t curr_tid(); 22 | size_t curr_token(); 23 | 24 | void kill_process(size_t proc_addr); -------------------------------------------------------------------------------- /session.cpp: -------------------------------------------------------------------------------- 1 | #include "session.h" 2 | #include "CmdExt.h" 3 | #include "CmdList.h" 4 | #include "object.h" 5 | #include "token.h" 6 | #include "process.h" 7 | #include 8 | 9 | DEFINE_CMD(sessions) 10 | { 11 | dump_logon_sessions(); 12 | } 13 | 14 | DEFINE_CMD(sessionpool) 15 | { 16 | dump_session_pool(); 17 | } 18 | 19 | void dump_logon_sessions() 20 | { 21 | try 22 | { 23 | size_t logon_sessions_addr = EXT_F_Sym2Addr("nt!SepLogonSessions"); 24 | if (logon_sessions_addr == 0) 25 | return; 26 | 27 | size_t logon_sessions_table_addr = EXT_F_READ(logon_sessions_addr); 28 | if (logon_sessions_table_addr == 0) 29 | return; 30 | 31 | for (size_t i = 0; i < 0x10; i++) 32 | { 33 | size_t logon_session_addr = EXT_F_READ(logon_sessions_table_addr + i * 8); 34 | if (logon_session_addr == 0) 35 | continue; 36 | 37 | EXT_F_OUT("#%x:\n", i); 38 | dump_session(logon_session_addr); 39 | } 40 | } 41 | FC; 42 | } 43 | 44 | void dump_session(size_t session_addr) 45 | { 46 | if (session_addr == 0) 47 | return; 48 | 49 | try 50 | { 51 | ExtRemoteTyped session("(nt!_SEP_LOGON_SESSION_REFERENCES*)@$extin", session_addr); 52 | EXT_F_OUT("Session: 0x%I64x\n", session_addr); 53 | EXT_F_OUT("%16s: %s\n", "LogonId", dump_luid(session_addr + session.GetFieldOffset("LogonId")).c_str()); 54 | EXT_F_OUT("%16s: %s\n", "BuddyLogonId", dump_luid(session_addr + session.GetFieldOffset("BuddyLogonId")).c_str()); 55 | EXT_F_OUT("%16s: 0x%I64x\n", "ReferenceCount", session.Field("ReferenceCount").GetUlong64()); 56 | EXT_F_OUT(L"%16s: %s\n", L"AccountName", EXT_F_READ_USTR(session_addr + session.GetFieldOffset("AccountName")).c_str()); 57 | EXT_F_OUT(L"%16s: %s\n", L"AuthorityName", EXT_F_READ_USTR(session_addr + session.GetFieldOffset("AuthorityName")).c_str()); 58 | 59 | EXT_F_OUT("%16s: 0x%I64x\n", "Token", session.Field("Token").GetUlongPtr()); 60 | } 61 | FC 62 | } 63 | 64 | void dump_session_pool() 65 | { 66 | try 67 | { 68 | size_t proc_addr = curr_proc(); 69 | size_t session_addr = EXT_F_READ(proc_addr + 0x400); 70 | 71 | size_t this_session_addr = session_addr; 72 | dump_session_space(this_session_addr); 73 | session_addr = EXT_F_READ(session_addr + 0x98) - 0x90; 74 | while (session_addr != this_session_addr) 75 | { 76 | if ((session_addr & 0x00000FFF) == 0x000) 77 | dump_session_space(session_addr); 78 | 79 | session_addr = EXT_F_READ(session_addr + 0x98) - 0x90; 80 | } 81 | } 82 | FC; 83 | } 84 | 85 | 86 | void dump_session_space(size_t addr) 87 | { 88 | uint32_t session_id = EXT_F_READ(addr + 0x08); 89 | 90 | EXT_F_OUT("Session : %d\n", session_id); 91 | 92 | stringstream ss; 93 | ss.str(""); 94 | ss << "dt nt!_POOL_DESCRIPTOR " 95 | << hex << showbase << addr + 0xcc0 96 | << ""; 97 | 98 | EXT_F_EXEC(ss.str()); 99 | } -------------------------------------------------------------------------------- /session.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CmdInterface.h" 4 | 5 | DECLARE_CMD(sessions) 6 | DECLARE_CMD(sessionpool) 7 | 8 | void dump_logon_sessions(); 9 | void dump_session(size_t session_addr); 10 | void dump_session_pool(); 11 | void dump_session_space(size_t addr); -------------------------------------------------------------------------------- /stack.cpp: -------------------------------------------------------------------------------- 1 | #include "stack.h" 2 | #include "CmdExt.h" 3 | #include "CmdList.h" 4 | #include "process.h" 5 | 6 | DEFINE_CMD(kall) 7 | { 8 | dump_threads_stack(curr_proc()); 9 | } 10 | 11 | DEFINE_CMD(pkall) 12 | { 13 | dump_all_threads_stack(); 14 | } 15 | 16 | void dump_threads_stack(size_t process_addr) 17 | { 18 | try 19 | { 20 | //size_t process_addr = curr_proc(); 21 | ExtRemoteTyped proc("(nt!_EPROCESS*)@$extin", process_addr); 22 | size_t thread_list_head_addr = process_addr + proc.GetFieldOffset("ThreadListHead"); 23 | 24 | ExtRemoteTypedList threads_list(thread_list_head_addr, "nt!_ETHREAD", "ThreadListEntry"); 25 | for (threads_list.StartHead(); threads_list.HasNode(); threads_list.Next()) 26 | { 27 | size_t thread_addr = threads_list.GetNodeOffset(); 28 | 29 | EXT_F_OUT("-------------------------------\n"); 30 | 31 | size_t trap_frame_addr = threads_list.GetTypedNode().Field("Tcb.TrapFrame").GetUlongPtr(); 32 | 33 | stringstream cmd; 34 | cmd << ".thread " << hex << showbase << thread_addr << ";"; 35 | 36 | if (S_OK == EXT_F_EXEC(cmd.str()) && (trap_frame_addr == 0 || EXT_F_ValidAddr(trap_frame_addr))) 37 | EXT_F_EXEC("kf"); 38 | } 39 | } 40 | FC; 41 | } 42 | 43 | void dump_all_threads_stack() 44 | { 45 | try 46 | { 47 | ExtRemoteTypedList pses_list = ExtNtOsInformation::GetKernelProcessList(); 48 | 49 | for (pses_list.StartHead(); pses_list.HasNode(); pses_list.Next()) 50 | { 51 | size_t proc_addr = pses_list.GetNodeOffset(); 52 | EXT_F_OUT("-----------[0x%I64x]-----------\n", proc_addr); 53 | dump_threads_stack(proc_addr); 54 | } 55 | }FC; 56 | } 57 | -------------------------------------------------------------------------------- /stack.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CmdInterface.h" 4 | 5 | DECLARE_CMD(kall) 6 | DECLARE_CMD(pkall) 7 | 8 | void dump_threads_stack(size_t process_addr); 9 | void dump_all_threads_stack(); -------------------------------------------------------------------------------- /svg/Coordinates.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | class CoordinatesManager 8 | { 9 | public: 10 | CoordinatesManager(uint64_t grid_width, uint64_t grid_height, uint64_t addr_width) 11 | :m_grid_width(grid_width) 12 | , m_grid_height(grid_height) 13 | , m_addr_width(addr_width) 14 | ,m_addr_height(grid_height) 15 | { 16 | m_canvas_width = 3000; 17 | m_canvas_height = m_grid_height * 512 + 200; 18 | } 19 | 20 | tuple GetCanvasSize() 21 | { 22 | return make_tuple(m_canvas_width, m_canvas_height); 23 | } 24 | 25 | tuple GetLAddrPivot(uint64_t i) 26 | { 27 | return make_tuple(100, 100 + m_grid_height * i); 28 | } 29 | 30 | tuple GetLGridPivot(uint64_t i, uint64_t j) 31 | { 32 | return make_tuple(100 + m_addr_width + i * m_grid_width, 100 + m_grid_height * j); 33 | } 34 | 35 | tuple GetLAddrParameters() 36 | { 37 | return make_tuple(m_addr_width, m_addr_height, m_l_addr_columns, m_l_addr_rows); 38 | } 39 | 40 | tuple GetLGridParameters() 41 | { 42 | return make_tuple(m_grid_width, m_grid_height, m_l_grid_columns, m_l_grid_rows); 43 | } 44 | 45 | uint64_t GetLRowHeight(uint64_t i) 46 | { 47 | return 100 + i * m_grid_height; 48 | } 49 | 50 | tuple GetMRowPivot(uint64_t i) 51 | { 52 | return make_tuple(1000, 100 + m_addr_height * i); 53 | } 54 | 55 | tuple GetRRowPivot(uint64_t i) 56 | { 57 | return make_tuple(2000, 100 + m_addr_height * i); 58 | } 59 | 60 | private: 61 | uint64_t m_grid_width{ 0 }; 62 | uint64_t m_grid_height{ 0 }; 63 | 64 | uint64_t m_addr_width{ 0 }; 65 | uint64_t m_addr_height{ 0 }; 66 | 67 | uint64_t m_canvas_width{ 0 }; 68 | uint64_t m_canvas_height{ 0 }; 69 | 70 | uint64_t m_l_addr_rows{ 512 }; 71 | uint64_t m_l_addr_columns{ 1 }; 72 | 73 | uint64_t m_l_grid_rows{ 512 }; 74 | uint64_t m_l_grid_columns{ 8 }; 75 | }; 76 | -------------------------------------------------------------------------------- /thread.cpp: -------------------------------------------------------------------------------- 1 | #include "thread.h" 2 | #include "CmdExt.h" 3 | #include "CmdList.h" 4 | 5 | #include 6 | 7 | DEFINE_CMD(threads) 8 | { 9 | size_t proc_addr = EXT_F_IntArg(args, 1, 0); 10 | 11 | if (proc_addr == 0) 12 | { 13 | EXT_F_ERR("Usage: !dk threads \n"); 14 | EXT_F_ERR("proc_addr can't be 0 or empty\n"); 15 | return; 16 | } 17 | 18 | dump_process_threads(proc_addr); 19 | } 20 | 21 | void dump_process_threads(size_t process_addr) 22 | { 23 | try 24 | { 25 | ExtRemoteTyped proc("(nt!_EPROCESS*)@$extin", process_addr); 26 | size_t thread_list_head_addr = process_addr + proc.GetFieldOffset("ThreadListHead"); 27 | 28 | ExtRemoteTypedList threads_list(thread_list_head_addr, "nt!_ETHREAD", "ThreadListEntry"); 29 | stringstream ss; 30 | for (threads_list.StartHead(); threads_list.HasNode(); threads_list.Next()) 31 | { 32 | auto thread = threads_list.GetTypedNode(); 33 | size_t thread_addr = threads_list.GetNodeOffset(); 34 | 35 | size_t unique_process = thread.Field("Cid.UniqueProcess").GetUlongPtr(); 36 | size_t unique_thread = thread.Field("Cid.UniqueThread").GetUlongPtr(); 37 | 38 | size_t teb_addr = thread.Field("Tcb.Teb").GetUlongPtr(); 39 | 40 | auto thread_token_info = get_thread_token(thread_addr); 41 | 42 | size_t thread_token_addr = get<0>(thread_token_info); 43 | 44 | size_t thread_silo = thread.Field("Silo").GetUlongPtr(); 45 | 46 | size_t start_addr = thread.Field("Win32StartAddress").GetUlongPtr(); 47 | 48 | string start_func_name = get<0>(EXT_F_Addr2Sym(start_addr)); 49 | 50 | 51 | ss << "\tThread: " << thread_addr << " " 52 | << "dt " 53 | << "detail " 54 | << "switch " 55 | << "Cid: " << setw(6) << unique_process << "." << left << setw(6) << unique_thread << right << " Thread Func: "; 56 | 57 | 58 | if (start_func_name.empty()) 59 | ss << "" << start_addr << ""; 60 | else 61 | ss << start_func_name; 62 | 63 | 64 | if (thread_token_addr != 0) 65 | { 66 | ss << "\t\tImpersonation Token: " << thread_token_addr << " " 67 | << "detail " 68 | << "dt " 69 | << getImpersonationLevel(get<1>(thread_token_info)) << "(" << get<1>(thread_token_info) << ") "; 70 | } 71 | 72 | if (thread_silo != 0xfffffffffffffffd) 73 | { 74 | ss << " silo: " << thread_silo; 75 | } 76 | else 77 | { 78 | ss << " silo: Inherited"; 79 | } 80 | 81 | ss << endl; 82 | } 83 | 84 | EXT_F_DML(ss.str().c_str()); 85 | } 86 | FC; 87 | } 88 | 89 | tuple get_thread_token(size_t thread_addr) 90 | { 91 | size_t token = 0; 92 | size_t level = 0; 93 | try 94 | { 95 | ExtRemoteTyped thread("(nt!_ETHREAD*)@$extin", thread_addr); 96 | bool impersonating = (thread.Field("CrossThreadFlags").GetUlong() & 8) != 0; 97 | if (impersonating) 98 | { 99 | token = thread.Field("ClientSecurity.ImpersonationToken").GetUlongPtr() & 0xFFFFFFFFFFFFFFF8; 100 | level = thread.Field("ClientSecurity.ImpersonationLevel").GetUlong64(); 101 | } 102 | } 103 | FC; 104 | return make_tuple(token, level); 105 | } 106 | 107 | string 108 | getImpersonationLevel( 109 | __in const size_t level 110 | ) 111 | { 112 | static map s_impersonation_level_map{ { 113 | { SecurityAnonymous, "SecurityAnonymous" }, 114 | { SecurityIdentification, "SecurityIdentification" }, 115 | { SecurityImpersonation, "SecurityImpersonation" }, 116 | { SecurityDelegation, "SecurityDelegation" }, 117 | } }; 118 | 119 | auto it = s_impersonation_level_map.find(level); 120 | 121 | if (it != s_impersonation_level_map.end()) 122 | return it->second; 123 | 124 | return ""; 125 | } -------------------------------------------------------------------------------- /thread.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CmdInterface.h" 4 | 5 | #include 6 | 7 | DECLARE_CMD(threads) 8 | 9 | void dump_process_threads(size_t process_addr); 10 | 11 | tuple get_thread_token(size_t thread_addr); 12 | 13 | string getImpersonationLevel(const size_t level); -------------------------------------------------------------------------------- /token.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CmdInterface.h" 4 | 5 | DECLARE_CMD(sid) 6 | DECLARE_CMD(token) 7 | DECLARE_CMD(add_privilege) 8 | 9 | tuple dump_sid(size_t sid_addr); 10 | size_t get_sid_attr_hash_item(size_t addr, size_t index); 11 | size_t get_sid_attr_array_item(size_t sid_addr, size_t count, size_t index); 12 | string getWellKnownAccount(const string& sidText); 13 | 14 | void dump_token(size_t token_addr); 15 | 16 | string dump_luid(size_t addr); 17 | string dump_acl(size_t acl_addr, string type_name = "File"); 18 | string dump_privilege(size_t addr); 19 | string dump_privileges_by_bitmap(size_t bitmap); 20 | string privilege_bit_to_text(size_t bit_offset); 21 | string dump_sid_attr_hash(size_t addr); 22 | string dump_sid_attr_array(size_t sid_addr, size_t count); 23 | 24 | void dump_sdr(size_t sd_addr, string type_name); 25 | 26 | void token_privilege_add(size_t token_addr, size_t bitmap); 27 | 28 | string 29 | getAceMaskStr( 30 | __in const size_t ace_mask, 31 | __in string type_name = "File", 32 | __in bool pureText = false 33 | ); -------------------------------------------------------------------------------- /ttd_cmd.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CmdInterface.h" 4 | 5 | #include "ttd/TTD.hpp" 6 | 7 | #include "svg/Coordinates.h" 8 | #include "svg/SvgElements.h" 9 | 10 | #include 11 | #include 12 | 13 | DECLARE_CMD(ldttd) 14 | DECLARE_CMD(dump_ttd_events) 15 | 16 | typedef struct _ttd_position 17 | { 18 | uint64_t sequence_id; 19 | uint64_t step_id; 20 | } ttd_position; 21 | 22 | typedef struct _ttd_event 23 | { 24 | enum { 25 | TTD_NONE_EVENT = 0, 26 | TTD_CALLRET_EVENT = 1, 27 | TTD_INDIRECT_JUMP_EVENT = 2, 28 | TTD_MEM_WATCHPOINT_EVENT = 3, 29 | TTD_MAX_EVENT, 30 | } event_type; 31 | 32 | union { 33 | struct { 34 | uint64_t insn_addr; 35 | uint64_t next_addr; 36 | } callret_event; 37 | struct { 38 | uint64_t target_addr; 39 | } indirect_jump_event; 40 | struct { 41 | uint64_t address; 42 | uint64_t size; 43 | uint64_t access_type; 44 | } mem_watchpoint_event; 45 | }u_data; 46 | 47 | uint64_t tid; 48 | ttd_position position; 49 | ttd_position prev_position; 50 | uint64_t pc; 51 | uint64_t stack_pointer; 52 | uint64_t frame_pointer; 53 | }ttd_event; 54 | 55 | typedef struct _ttd_callnode 56 | { 57 | string func_name; 58 | 59 | string caller_name; 60 | uint64_t caller_offset; 61 | 62 | uint64_t call_event_index; 63 | uint64_t return_event_index; 64 | 65 | shared_ptr parent; 66 | vector> children; 67 | 68 | uint64_t seqs_count{ 0 }; 69 | ttd_position start_pos{ 0,0 }; 70 | ttd_position end_pos{ 0,0 }; 71 | 72 | string callstack; 73 | }ttd_callnode; 74 | 75 | using DK_TTD_CALLNODE = shared_ptr; 76 | 77 | class CTTDInsight; 78 | 79 | class CTTDModelCallstackBuilder 80 | { 81 | public: 82 | CTTDModelCallstackBuilder() 83 | { 84 | } 85 | 86 | void build_ttd_callstack_model(); 87 | uint64_t min_index_ttd_callnode(DK_TTD_CALLNODE callnode); 88 | uint64_t max_index_ttd_callnode(DK_TTD_CALLNODE callnode); 89 | DK_TTD_CALLNODE is_func_in_chain(tuple func, DK_TTD_CALLNODE chain); 90 | 91 | tuple addr2sym(uint64_t addr); 92 | DK_TTD_CALLNODE fix_missing_chain(DK_TTD_CALLNODE root_chain, ttd_position pos, tuple orphan_event_node); 93 | 94 | void dump_root_chain(DK_TTD_CALLNODE root_chain); 95 | 96 | tuple build_new_root_chain(ttd_position pos); 97 | 98 | void build_callstack_svg(string filename, DK_TTD_CALLNODE root); 99 | 100 | void append_callstack_svg_node(DK_TTD_CALLNODE node, CSvgPoint pivot); 101 | 102 | void calc_seqs_count(DK_TTD_CALLNODE node); 103 | 104 | map m_ttd_lastnodes; 105 | map> m_ttd_call_forest; 106 | 107 | vector m_root_chain; 108 | 109 | shared_ptr m_rect_g; 110 | shared_ptr m_text_g; 111 | shared_ptr m_tag_g; 112 | 113 | uint64_t m_canvas_width{ 0 }; 114 | uint64_t m_canvas_height{ 0 }; 115 | 116 | uint64_t m_canvas_lines{ 1 }; 117 | }; 118 | 119 | class CTTDInsight 120 | { 121 | friend class CTTDModelCallstackBuilder; 122 | public: 123 | static CTTDInsight* Instance() 124 | { 125 | static CTTDInsight s_instance; 126 | return &s_instance; 127 | } 128 | 129 | void ttd_call_ret_callback( 130 | uintptr_t context, 131 | TTD::GuestAddress guestInstructionAddress, 132 | TTD::GuestAddress guestFallThroughInstructionAddress, 133 | TTD::TTD_Replay_IThreadView* threadView); 134 | 135 | void load_ttd(); 136 | 137 | void dump_ttd_model_events(string out_filename); 138 | 139 | string dump_ttd_callnode(DK_TTD_CALLNODE callnode, size_t level = 0); 140 | 141 | protected: 142 | vector m_ttd_events; 143 | 144 | vector m_ttd_call_forest; 145 | }; 146 | 147 | -------------------------------------------------------------------------------- /type.cpp: -------------------------------------------------------------------------------- 1 | #include "type.h" 2 | #include "CmdList.h" 3 | #include "CmdExt.h" 4 | #include "object.h" 5 | #include "token.h" 6 | 7 | #pragma warning( disable : 4244) 8 | 9 | DEFINE_CMD(types) 10 | { 11 | dump_types(); 12 | } 13 | 14 | void dump_types() 15 | { 16 | try 17 | { 18 | size_t types_table = EXT_F_Sym2Addr("nt!ObpObjectTypes"); 19 | 20 | for (size_t i = 0; i < 0xFF; i++) 21 | { 22 | size_t type_addr = EXT_F_READ(types_table + i * sizeof(size_t)); 23 | 24 | if (type_addr == 0) 25 | break; 26 | 27 | ExtRemoteTyped type("(nt!_OBJECT_TYPE*)@$extin", type_addr); 28 | wstring name = EXT_F_READ_USTR(type_addr + type.GetFieldOffset("Name")); 29 | //wstring name = readUnicodeString(type.Field("Name").GetPtr()); 30 | uint32_t num_objects = type.Field("TotalNumberOfObjects").GetUlong(); 31 | uint32_t num_handles = type.Field("TotalNumberOfHandles").GetUlong(); 32 | uint32_t valid_access_mask = type.Field("TypeInfo.ValidAccessMask").GetUlong(); 33 | static const char* routines[]{ 34 | "DumpProcedure", 35 | "OpenProcedure", 36 | "CloseProcedure", 37 | "DeleteProcedure", 38 | "ParseProcedure", 39 | "SecurityProcedure", 40 | "QueryNameProcedure", 41 | "OkayToCloseProcedure" 42 | }; 43 | 44 | EXT_F_OUT("---------------------------------------------------------\n"); 45 | EXT_F_OUT(L"%02X objs: 0x%08x, handles: 0x%08x 0x%08x %s\n", i, num_objects, num_handles, valid_access_mask, name.c_str()); 46 | EXT_F_OUT("[ Routines: ]\n"); 47 | for (auto& routine : routines) 48 | { 49 | string field = "TypeInfo."; 50 | field += routine; 51 | size_t routine_addr = type.Field(field.c_str()).GetUlongPtr(); 52 | string routine_name = get<0>(EXT_F_Addr2Sym(routine_addr)); 53 | EXT_F_OUT("\t%20s : 0x%I64x %s\n", routine, routine_addr, routine_name.c_str()); 54 | } 55 | 56 | string strname(name.begin(), name.end()); 57 | 58 | uint32_t gR_access = type.Field("TypeInfo.GenericMapping.GenericRead").GetUlong(); 59 | uint32_t gW_access = type.Field("TypeInfo.GenericMapping.GenericWrite").GetUlong(); 60 | uint32_t gE_access = type.Field("TypeInfo.GenericMapping.GenericExecute").GetUlong(); 61 | uint32_t gA_access = type.Field("TypeInfo.GenericMapping.GenericAll").GetUlong(); 62 | 63 | EXT_F_OUT("[ Generic Mapping: ]\n\t%20s : 0x%08x %s\n\t%20s : 0x%08x %s\n\t%20s : 0x%08x %s\n\t%20s : 0x%08x %s\n", 64 | "GenericRead", gR_access, getAceMaskStr(gR_access, strname).c_str(), 65 | "GenericWrite", gW_access, getAceMaskStr(gW_access, strname).c_str(), 66 | "GenericExecute", gE_access, getAceMaskStr(gE_access, strname).c_str(), 67 | "GenericAll", gA_access, getAceMaskStr(gA_access, strname).c_str()); 68 | } 69 | } 70 | FC; 71 | } -------------------------------------------------------------------------------- /type.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CmdInterface.h" 4 | 5 | DECLARE_CMD(types) 6 | 7 | void dump_types(); 8 | -------------------------------------------------------------------------------- /usermode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CmdInterface.h" 4 | 5 | #include 6 | 7 | DECLARE_CMD(usearch_astr) 8 | DECLARE_CMD(usearch_ustr) 9 | DECLARE_CMD(usearch_bytes) 10 | DECLARE_CMD(usearch_addr) 11 | DECLARE_CMD(uaddr_ref_disp) 12 | DECLARE_CMD(uaddr_ref_by) 13 | DECLARE_CMD(uaddr_ref_tree) 14 | DECLARE_CMD(uaddr_analyze) 15 | DECLARE_CMD(uaddr_analyze_svg) 16 | DECLARE_CMD(uaddr_analyze2) 17 | DECLARE_CMD(ustacks) 18 | DECLARE_CMD(uregs) 19 | 20 | 21 | 22 | void usermode_search_astr(string pattern, size_t level); 23 | void usermode_search_ustr(string pattern, size_t level); 24 | void usermode_search_bytes(string bytes, size_t level); 25 | void usermode_search_addr(size_t addr, size_t level); 26 | void usermode_addr_ref_disp(size_t start, size_t len, size_t ref_start, size_t ref_len, size_t ref_disp); 27 | void usermode_addr_ref_by(size_t start); 28 | void usermode_addr_ref_tree(size_t start, size_t level); 29 | void usermode_addr_analyze(size_t start, size_t len, size_t offset); 30 | void usermode_addr_analyze_svg(size_t start, size_t len, string svg_filename, size_t offset); 31 | void usermode_addr_analyze2(size_t start, size_t len, size_t offset); 32 | 33 | void usermode_stacks(); 34 | void usermode_regs(); 35 | 36 | class CUsermodeStack 37 | { 38 | public: 39 | CUsermodeStack(size_t start, size_t end, size_t size, size_t t_index, size_t tid, size_t pid, string usage); 40 | 41 | ~CUsermodeStack(); 42 | 43 | void Analyze(); 44 | 45 | bool in_range(size_t addr) 46 | { 47 | return addr >= m_start && addr < m_end; 48 | } 49 | 50 | string desc(size_t addr); 51 | 52 | tuple dump(); 53 | private: 54 | size_t m_start{ 0 }; 55 | size_t m_end{ 0 }; 56 | size_t m_size{ 0 }; 57 | size_t m_t_index{ 0 }; 58 | size_t m_tid{ 0 }; 59 | size_t m_pid{ 0 }; 60 | 61 | string m_usage_str; 62 | }; 63 | 64 | class CUsermodeModule 65 | { 66 | public: 67 | CUsermodeModule(size_t start, size_t end, size_t size, string name, string path, string usage); 68 | ~CUsermodeModule(); 69 | 70 | void Analyze(); 71 | 72 | bool in_range(size_t addr) 73 | { 74 | return addr >= m_start && addr < m_end; 75 | } 76 | 77 | bool is_code() 78 | { 79 | return m_usage_str.find("PAGE_EXECUTE_READ") != string::npos; 80 | } 81 | 82 | bool is_readonly() 83 | { 84 | return m_usage_str.find("PAGE_READONLY") != string::npos; 85 | } 86 | 87 | bool is_global() 88 | { 89 | return m_usage_str.find("PAGE_READWRITE") != string::npos || 90 | m_usage_str.find("PAGE_WRITECOPY") != string::npos; 91 | } 92 | 93 | string code_desc(size_t addr); 94 | 95 | string data_desc(size_t addr); 96 | 97 | 98 | private: 99 | size_t m_start{ 0 }; 100 | size_t m_end{ 0 }; 101 | size_t m_size{ 0 }; 102 | string m_name{ 0 }; 103 | string m_path{ 0 }; 104 | 105 | string m_usage_str; 106 | }; 107 | 108 | class CUsermodeHeapAllocation 109 | { 110 | public: 111 | CUsermodeHeapAllocation(size_t start, size_t end); 112 | ~CUsermodeHeapAllocation(); 113 | 114 | bool in_range(size_t addr) 115 | { 116 | return addr >= m_start && addr < m_end; 117 | } 118 | 119 | bool equal(shared_ptr other) 120 | { 121 | return other && m_start == other->start() && m_end == other->end(); 122 | } 123 | 124 | void add_ref(shared_ptr ref) 125 | { 126 | for (auto& it_ref : m_references) 127 | { 128 | if (it_ref->equal(ref)) 129 | return; 130 | } 131 | 132 | m_references.push_back(ref); 133 | } 134 | 135 | void add_ptr(shared_ptr ptr) 136 | { 137 | for (auto& it_ptr : m_pointers) 138 | { 139 | if (it_ptr->equal(ptr)) 140 | return; 141 | } 142 | 143 | m_pointers.push_back(ptr); 144 | } 145 | 146 | size_t start() 147 | { 148 | return m_start; 149 | } 150 | 151 | size_t end() 152 | { 153 | return m_end; 154 | } 155 | 156 | size_t size() 157 | { 158 | return m_size; 159 | } 160 | 161 | void set_desc(string desc) 162 | { 163 | m_desc = desc; 164 | } 165 | 166 | string desc() 167 | { 168 | return m_desc; 169 | } 170 | 171 | private: 172 | size_t m_start; 173 | size_t m_end; 174 | size_t m_size; 175 | 176 | string m_desc; 177 | 178 | vector> m_pointers; 179 | vector> m_references; 180 | }; 181 | 182 | class CUsermodeHeap 183 | { 184 | public: 185 | CUsermodeHeap(size_t start, size_t end, size_t size, size_t id, size_t handle, string type, string usage); 186 | ~CUsermodeHeap(); 187 | 188 | void Analyze(); 189 | 190 | bool in_range(size_t addr) 191 | { 192 | return addr >= m_start && addr < m_end; 193 | } 194 | 195 | string desc(size_t addr); 196 | 197 | string ref_by_desc(size_t addr); 198 | 199 | tuple>, set> ref_by(size_t addr); 200 | 201 | shared_ptr get_allocation(size_t start, size_t end) 202 | { 203 | for (auto& alloc : m_allocations) 204 | { 205 | if (alloc->start() == start && alloc->end() == end) 206 | return alloc; 207 | } 208 | 209 | return nullptr; 210 | } 211 | 212 | void add_allocation(shared_ptr alloc) 213 | { 214 | m_allocations.push_back(alloc); 215 | } 216 | 217 | shared_ptr get_alloc_for_addr(size_t addr) 218 | { 219 | for (auto& alloc : m_allocations) 220 | { 221 | if (alloc->start() <= addr && alloc->end() > addr) 222 | return alloc; 223 | } 224 | 225 | return nullptr; 226 | } 227 | 228 | private: 229 | size_t m_start{ 0 }; 230 | size_t m_end{ 0 }; 231 | size_t m_size{ 0 }; 232 | size_t m_id{ 0 }; 233 | size_t m_handle{ 0 }; 234 | string m_type{ 0 }; 235 | 236 | string m_usage_str; 237 | 238 | vector> m_allocations; 239 | 240 | }; 241 | 242 | class CUsermodeMemory 243 | { 244 | public: 245 | static CUsermodeMemory* GetInstance() 246 | { 247 | static CUsermodeMemory s_instance; 248 | 249 | return &s_instance; 250 | } 251 | 252 | CUsermodeMemory(); 253 | ~CUsermodeMemory(); 254 | 255 | void Analyze(); 256 | 257 | bool is_stack(size_t addr) 258 | { 259 | for (auto& stack : m_stacks) 260 | { 261 | if (stack->in_range(addr)) 262 | return true; 263 | } 264 | 265 | return false; 266 | } 267 | 268 | bool is_heap(size_t addr) 269 | { 270 | for (auto& heap : m_heaps) 271 | { 272 | if (heap->in_range(addr)) 273 | return true; 274 | } 275 | 276 | return false; 277 | } 278 | 279 | bool is_code(size_t addr) 280 | { 281 | for (auto& module : m_images) 282 | { 283 | if (module->in_range(addr) && module->is_code()) 284 | return true; 285 | } 286 | 287 | return false; 288 | } 289 | 290 | bool is_readonly(size_t addr) 291 | { 292 | for (auto& module : m_images) 293 | { 294 | if (module->in_range(addr) && module->is_readonly()) 295 | return true; 296 | } 297 | 298 | return false; 299 | } 300 | 301 | bool is_global(size_t addr) 302 | { 303 | for (auto& module : m_images) 304 | { 305 | if (module->in_range(addr) && module->is_global()) 306 | return true; 307 | } 308 | 309 | return false; 310 | } 311 | 312 | bool is_module_data(size_t addr) 313 | { 314 | for (auto& module : m_images) 315 | { 316 | if (module->in_range(addr) && !module->is_code()) 317 | return true; 318 | } 319 | 320 | return false; 321 | } 322 | 323 | string heap_desc(size_t addr); 324 | 325 | string code_desc(size_t addr); 326 | 327 | string module_data_desc(size_t addr); 328 | 329 | string stack_desc(size_t addr); 330 | 331 | string heap_ref_by_desc(size_t addr); 332 | 333 | tuple>, set> heap_ref_by(size_t addr); 334 | 335 | shared_ptr get_allocation(size_t start, size_t end); 336 | 337 | shared_ptr get_alloc_for_addr(size_t addr); 338 | 339 | void analyze_mem(size_t addr, size_t len, size_t offset, bool b_recurse = false); 340 | 341 | void analyze_mem_svg(size_t addr, size_t len, size_t offset, string svg_filename, bool b_recurse = false); 342 | 343 | void analyze_qword(size_t qword); 344 | 345 | void analyze_mem_around(size_t addr); 346 | 347 | void analyze_ref_by(size_t addr); 348 | 349 | void analyze_ref_tree(size_t addr, size_t level = 0); 350 | 351 | void dump_all_stacks(); 352 | 353 | void dummy() 354 | { 355 | } 356 | 357 | string qword_2_buffer(size_t qw) 358 | { 359 | string str(8, '0'); 360 | memcpy(str.data(), &qw, 8); 361 | return str; 362 | } 363 | 364 | void set_ref_by_tree_levels(size_t level) 365 | { 366 | m_max_ref_by_tree_levels = level; 367 | } 368 | 369 | private: 370 | vector> m_stacks; 371 | vector> m_heaps; 372 | vector> m_images; 373 | 374 | size_t m_max_ref_by_tree_levels{ 10 }; 375 | }; 376 | --------------------------------------------------------------------------------