Files
sigmaker-ida/idasdk75/dbg/win32/winbase_debmod.h
2021-06-05 21:10:25 +03:00

180 lines
5.5 KiB
C++

#ifndef __WINBASE_HPP__
#define __WINBASE_HPP__
// Base class for win32 and windbg modules
#include <algorithm>
#include <map>
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<uint32> 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<highdll_range_t>
{
private:
size_t num_ntdlls; // count of actual ntdll*.dll modules in the list
public:
typedef qvector<highdll_range_t> 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; // use check_wow64_process()
protected:
HANDLE process_handle;
dep_policy_t dep_policy;
highdll_vec_t highdlls;
// 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;
public:
virtual void idaapi dbg_term(void) override;
static win_tool_help_t *get_tool_help();
static win_version_t winver;
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