#ifndef __WINBASE_HPP__ #define __WINBASE_HPP__ // Base class for win32 and windbg modules using std::for_each; using std::pair; using std::make_pair; //-------------------------------------------------------------------------- #define BASE_DEBUGGER_MODULE pc_debmod_t #include "deb_pc.hpp" #include "pc_debmod.h" #define BPT_CODE_SIZE X86_BPT_SIZE #include "win32_util.hpp" extern const TCHAR kernel32_dll[]; //-------------------------------------------------------------------------- // DEP policies enum dep_policy_t { dp_always_off, dp_always_on, dp_opt_in, dp_opt_out }; //-------------------------------------------------------------------------- enum attach_status_t { as_none, // no attach to process requested as_attaching, // waiting for CREATE_PROCESS_DEBUG_EVENT, indicating the process is attached as_breakpoint, // waiting for first breakpoint, indicating the process was properly initialized and suspended as_attached, // process was successfully attached as_detaching, // waiting for next get_debug_event() request, to return the process as detached as_attach_kernel, // attaching to kernel }; // vector of win32 page protections // we need this type because meminfo_t does not contain the original win32 protections // but we need them to verify page bpts typedef qvector win32_prots_t; //-------------------------------------------------------------------------- // When debugging WOW64 processes with ida32 we have to take into account // ntdll.dll (and wow64*.dll), which are x64 files // that can be loaded into high addresses (above 4GB) // Since ea_t cannot represent such addresses, // we use our own type to remember the DLL boundaries typedef size_t eanat_t; struct highdll_range_t { eanat_t start; eanat_t end; HANDLE handle; highdll_range_t() : start(0), end(0), handle(INVALID_HANDLE_VALUE) {} bool has(eanat_t addr) const { return addr >= start && addr < end; } }; DECLARE_TYPE_AS_MOVABLE(highdll_range_t); struct highdll_vec_t : protected qvector { private: size_t num_ntdlls; // count of actual ntdll*.dll modules in the list public: typedef qvector inherited; highdll_vec_t() : num_ntdlls(0) {} void clear() { inherited::clear(); num_ntdlls = 0; } size_t size() const { return inherited::size(); } size_t count_ntdlls() const { return num_ntdlls; } bool empty() const { return inherited::empty(); } // return false if there is already a dll with such an address bool add(eanat_t addr, size_t size, HANDLE h = INVALID_HANDLE_VALUE); bool add_ntdll(eanat_t addr, size_t size, HANDLE h = INVALID_HANDLE_VALUE) { bool ok = add(addr, size, h); if ( ok ) num_ntdlls++; return ok; }; // it returns true if the dll address doesn't fit in `ea_t` bool add_high_module( eanat_t addr, size_t size, HANDLE h = INVALID_HANDLE_VALUE); // it returns true if the dll address doesn't fit to `ea_t` bool del_high_module(HANDLE *h, eanat_t addr); bool has(eanat_t addr) const; }; //-------------------------------------------------------------------------- class winbase_debmod_t: public BASE_DEBUGGER_MODULE { typedef BASE_DEBUGGER_MODULE inherited; wow64_state_t is_wow64 = WOW64_NONE; // use check_wow64_process() protected: HANDLE process_handle = INVALID_HANDLE_VALUE; dep_policy_t dep_policy = dp_always_off; highdll_vec_t highdlls; bool is64 = false; // local functions bool mask_page_bpts(ea_t startea, ea_t endea, uint32 *protect); void verify_page_protections(meminfo_vec_t *areas, const win32_prots_t &prots); winbase_debmod_t(void); // overridden virtual functions bool idaapi dbg_enable_page_bpt(page_bpts_t::iterator p, bool enable); int idaapi dbg_add_page_bpt(bpttype_t type, ea_t ea, int size); bool check_for_call_large(const debug_event_t *event, HANDLE process_handle); #ifndef __X86__ wow64_state_t check_wow64_process(); #else wow64_state_t check_wow64_process() { return WOW64_NO; } #endif int get_process_addrsize(pid_t pid); bool is_ntdll_name(const char *path); // return number of processes, -1 - not implemented virtual int idaapi get_process_list(procvec_t *proclist, qstring *errbuf) override; // return the file name assciated with pid virtual bool idaapi get_exec_fname(int pid, char *buf, size_t bufsize) newapi; // get process bitness: 32bit - 4, 64bit - 8, 0 - unknown virtual int idaapi get_process_bitness(int pid) newapi; virtual void init_reg_ctx(void) newapi {} virtual void term_reg_ctx(void) newapi {} public: virtual void idaapi dbg_term(void) override; static win_tool_help_t *get_tool_help(); static win_version_t winver; protected: bool handle_process_start(pid_t _pid); void cleanup(void); private: void build_process_ext_name(ext_process_info_t *pinfo); static bool get_process_path( ext_process_info_t *pinfo, char *buf, size_t bufsize); static bool remove_page_protections( DWORD *p_input, bpttype_t bpttype, dep_policy_t dpolicy, HANDLE proc_handle); static win_tool_help_t *win_tool_help; }; bool should_fire_page_bpt(page_bpts_t::iterator p, ea_t ea, DWORD failed_access_type, ea_t pc, dep_policy_t dep_policy); #ifdef _PE_H_ bool read_pe_header(peheader_t *pe); #endif //------------------------------------------------------------------------- inline void tchar_utf8(qstring *buf, TCHAR *tchar) { #ifdef UNICODE utf16_utf8(buf, tchar); #else acp_utf8(buf, tchar); #endif } //------------------------------------------------------------------------- inline void tchar_utf8(char *buf, TCHAR *tchar, size_t bufsize) { qstring utf8; tchar_utf8(&utf8, tchar); qstrncpy(buf, utf8.c_str(), bufsize); } #endif