//--------------------------------------------------------------------------
ssize_t idaapi rpc_debmod_t::dbg_read_file(int fn, uint32 off, void *buf, size_t size)
{
  bytevec_t req = prepare_rpc_packet(RPC_READ_FILE);
  append_dd(req, fn);
  append_dd(req, off);
  append_dd(req, (uint32)size);

  rpc_packet_t *rp = process_request(req);
  if ( rp == NULL )
    return -1;

  const uchar *answer = (uchar *)(rp+1);
  const uchar *end = answer + rp->length;

  int32 rsize = extract_long(&answer, end);
  if ( size != rsize )
    qerrcode(extract_long(&answer, end));

  if ( rsize > 0 )
  {
    if ( rsize > size )
      error("rpc_read_file: protocol error");
    extract_memory(&answer, end, buf, rsize);
  }
  qfree(rp);
  return rsize;
}
//--------------------------------------------------------------------------
int idaapi rpc_debmod_t::dbg_attach_process(pid_t _pid, int event_id)
{
  bytevec_t req = prepare_rpc_packet(RPC_ATTACH_PROCESS);
  append_dd(req, _pid);
  append_dd(req, event_id);
  return process_start_or_attach(req);
}
//--------------------------------------------------------------------------
int idaapi rpc_debmod_t::dbg_write_register(thid_t tid, int reg_idx, const regval_t *value)
{
  bytevec_t req = prepare_rpc_packet(RPC_WRITE_REG);
  append_dd(req, tid);
  append_dd(req, reg_idx);
  append_regvals(req, value, 1, NULL);

  return process_long(req);
}
//--------------------------------------------------------------------------
int idaapi rpc_debmod_t::dbg_is_ok_bpt(bpttype_t type, ea_t ea, int len)
{
  bytevec_t req = prepare_rpc_packet(RPC_ISOK_BPT);
  append_dd(req, type);
  append_ea64(req, ea);
  append_dd(req, len+1);

  return process_long(req);
}
//--------------------------------------------------------------------------
int idaapi rpc_debmod_t::dbg_init(bool _debug_debugger)
{
  has_pending_event = false;
  poll_debug_events = false;

  bytevec_t req = prepare_rpc_packet(RPC_INIT);
  append_dd(req, debugger.flags);
  append_dd(req, _debug_debugger);

  return process_long(req);
}
//--------------------------------------------------------------------------
int rpc_debmod_t::getint2(uchar code, int x)
{
  bytevec_t req = prepare_rpc_packet(code);
  append_dd(req, x);

  return process_long(req);
}
//--------------------------------------------------------------------------
void idaapi rpc_debmod_t::dbg_close_file(int fn)
{
  bytevec_t req = prepare_rpc_packet(RPC_CLOSE_FILE);
  append_dd(req, fn);

  qfree(process_request(req));
}
//--------------------------------------------------------------------------
int idaapi rpc_debmod_t::dbg_open_file(const char *file, uint32 *fsize, bool readonly)
{
  bytevec_t req = prepare_rpc_packet(RPC_OPEN_FILE);
  append_str(req, file);
  append_dd(req, readonly);

  rpc_packet_t *rp = process_request(req);
  if ( rp == NULL )
    return -1;

  const uchar *answer = (uchar *)(rp+1);
  const uchar *end = answer + rp->length;

  int fn = extract_long(&answer, end);
  if ( fn != -1 )
  {
    if ( fsize != NULL && readonly )
      *fsize = extract_long(&answer, end);
  }
  else
  {
    qerrcode(extract_long(&answer, end));
  }
  qfree(rp);
  return fn;
}
//--------------------------------------------------------------------------
int idaapi rpc_debmod_t::dbg_eval_lowcnd(thid_t tid, ea_t ea)
{
  bytevec_t req = prepare_rpc_packet(RPC_EVAL_LOWCND);
  append_dd(req, tid);
  append_ea64(req, ea);
  return process_long(req);
}
//--------------------------------------------------------------------------
void idaapi rpc_debmod_t::dbg_set_exception_info(const exception_info_t *table, int qty)
{
  bytevec_t req = prepare_rpc_packet(RPC_SET_EXCEPTION_INFO);
  append_dd(req, qty);
  append_exception_info(req, table, qty);

  qfree(process_request(req));
}
//--------------------------------------------------------------------------
ssize_t idaapi rpc_debmod_t::dbg_write_memory(ea_t ea, const void *buffer, size_t size)
{
  bytevec_t req = prepare_rpc_packet(RPC_WRITE_MEMORY);
  append_ea64(req, ea);
  append_dd(req, (uint32)size);
  append_memory(req, buffer, size);

  return process_long(req);
}
//--------------------------------------------------------------------------
int idaapi rpc_debmod_t::dbg_start_process(
        const char *path,
        const char *args,
        const char *startdir,
        int flags,
        const char *input_path,
        uint32 input_file_crc32)
{
  bytevec_t req = prepare_rpc_packet(RPC_START_PROCESS);
  append_str(req, path);
  append_str(req, args);
  append_str(req, startdir);
  append_dd(req, flags);
  append_str(req, input_path);
  append_dd(req, input_file_crc32);

  return process_start_or_attach(req);
}
//--------------------------------------------------------------------------
ea_t idaapi rpc_debmod_t::dbg_appcall(
        ea_t func_ea,
        thid_t tid,
        int stkarg_nbytes,
        const struct regobjs_t *regargs,
        struct relobj_t *stkargs,
        struct regobjs_t *retregs,
        qstring *errbuf,
        debug_event_t *event,
        int flags)
{
  bytevec_t req = prepare_rpc_packet(RPC_APPCALL);
  append_ea64(req, func_ea);
  append_dd(req, tid);
  append_dd(req, stkarg_nbytes);
  append_dd(req, flags);
  regobjs_t *rr = (flags & APPCALL_MANUAL) == 0 ? retregs : NULL;
  append_appcall(req, *regargs, *stkargs, rr);

  rpc_packet_t *rp = process_request(req);
  if ( rp == NULL )
    return BADADDR;

  const uchar *answer = (uchar *)(rp+1);
  const uchar *end = answer + rp->length;

  ea_t sp = extract_ea64(&answer, end);
  if ( sp == BADADDR )
  {
    if ( (flags & APPCALL_DEBEV) != 0 )
      extract_debug_event(&answer, end, event);
    if ( errbuf != NULL )
      *errbuf = extract_str(&answer, end);
  }
  else if ( (flags & APPCALL_MANUAL) == 0 )
  {
    if ( retregs != NULL )
      extract_regobjs(&answer, end, retregs, true);
  }
  qfree(rp);
  return sp;
}
Beispiel #14
0
bool save_class(class_t * clas)
{	
	bytevec_t buffer;
	append_ea(buffer, clas->virt_table_ea);
	append_dd(buffer, clas->flags);
	append_eavec(buffer, 0, clas->functions_ea);
	append_eavec(buffer, 0, clas->parents_tid);
	netnode n = netnode(clas->tid);
	n.setblob(&buffer.front(), buffer.size(), 0, 'm');
	return true;
}
//--------------------------------------------------------------------------
int idaapi rpc_debmod_t::dbg_thread_get_sreg_base(thid_t tid, int sreg_value, ea_t *ea)
{
  bytevec_t req = prepare_rpc_packet(RPC_GET_SREG_BASE);
  append_dd(req, tid);
  append_dd(req, sreg_value);

  rpc_packet_t *rp = process_request(req);
  if ( rp == NULL )
    return -1;

  const uchar *answer = (uchar *)(rp+1);
  const uchar *end = answer + rp->length;

  bool result = extract_long(&answer, end) != 0;

  if ( result )
    *ea = extract_ea64(&answer, end);

  qfree(rp);
  return result;
}
//--------------------------------------------------------------------------
ssize_t idaapi rpc_debmod_t::dbg_write_file(int fn, uint32 off, const void *buf, size_t size)
{
  bytevec_t req = prepare_rpc_packet(RPC_WRITE_FILE);
  append_dd(req, fn);
  append_dd(req, off);
  append_dd(req, (uint32)size);
  append_memory(req, buf, size);

  rpc_packet_t *rp = process_request(req);
  if ( rp == NULL )
    return -1;

  const uchar *answer = (uchar *)(rp+1);
  const uchar *end = answer + rp->length;

  int32 rsize = extract_long(&answer, end);
  if ( size != rsize )
    qerrcode(extract_long(&answer, end));

  qfree(rp);
  return rsize;
}
//--------------------------------------------------------------------------
gdecode_t idaapi rpc_debmod_t::dbg_get_debug_event(debug_event_t *event, int timeout_ms)
{
  if ( has_pending_event )
  {
    verbev(("get_debug_event => has pending event, returning it\n"));
    *event = pending_event;
    has_pending_event = false;
    poll_debug_events = false;
    return GDE_ONE_EVENT;
  }

  gdecode_t result = GDE_NO_EVENT;
  if ( poll_debug_events )
  {
    // do we have something waiting?
    if ( irs_ready(irs, timeout_ms) != 0 )
    {
      verbev(("get_debug_event => remote has an event for us\n"));
      // get the packet - it should be RPC_EVENT (nothing else can be)
      bytevec_t empty;
      rpc_packet_t *rp = process_request(empty);
      verbev(("get_debug_event => processed remote event, has=%d\n", has_pending_event));
      if ( rp != NULL || !has_pending_event )
      {
        warning("rpc: event protocol error (rp=%p has_event=%d)", rp, has_pending_event);
        return GDE_ERROR;
      }
    }
  }
  else
  {
    verbev(("get_debug_event => first time, send GET_DEBUG_EVENT\n"));
    bytevec_t req = prepare_rpc_packet(RPC_GET_DEBUG_EVENT);
    append_dd(req, timeout_ms);

    rpc_packet_t *rp = process_request(req);
    if ( rp == NULL )
      return GDE_ERROR;
    const uchar *answer = (uchar *)(rp+1);
    const uchar *end = answer + rp->length;

    result = gdecode_t(extract_long(&answer, end));
    if ( result >= GDE_ONE_EVENT )
      extract_debug_event(&answer, end, event);
    else
      poll_debug_events = true;
    verbev(("get_debug_event => remote said %d, poll=%d now\n", result, poll_debug_events));
    qfree(rp);
  }
  return result;
}
//--------------------------------------------------------------------------
int idaapi rpc_debmod_t::dbg_read_registers(thid_t tid, int clsmask, regval_t *values)
{
  bytevec_t req = prepare_rpc_packet(RPC_READ_REGS);
  append_dd(req, tid);
  append_dd(req, clsmask);
  // append additional information about the class structure
  bytevec_t regmap;
  int n_regs = calc_regmap(&regmap, clsmask);
  append_dd(req, n_regs);
  append_memory(req, regmap.begin(), regmap.size());

  rpc_packet_t *rp = process_request(req);
  if ( rp == NULL )
    return -1;

  const uchar *answer = (uchar *)(rp+1);
  const uchar *end = answer + rp->length;

  int result = extract_long(&answer, end);
  if ( result )
    extract_regvals(&answer, end, values, n_regs, regmap.begin());
  qfree(rp);
  return result;
}
//--------------------------------------------------------------------------
int idaapi rpc_debmod_t::dbg_update_lowcnds(const lowcnd_t *lowcnds, int nlowcnds)
{
  ea_t ea = 0;
  bytevec_t req = prepare_rpc_packet(RPC_UPDATE_LOWCNDS);
  append_dd(req, nlowcnds);
  const lowcnd_t *lc = lowcnds;
  for ( int i=0; i < nlowcnds; i++, lc++ )
  {
    append_ea64(req, lc->ea-ea); ea = lc->ea;
    append_str(req, lc->cndbody);
    if ( !lc->cndbody.empty() )
    {
      append_dd(req, lc->type);
      if ( lc->type != BPT_SOFT )
        append_dd(req, lc->size);
      append_db(req, lc->orgbytes.size());
      append_memory(req, lc->orgbytes.begin(), lc->orgbytes.size());
      append_ea64(req, lc->cmd.ea);
      if ( lc->cmd.ea != BADADDR )
        append_memory(req, &lc->cmd, sizeof(lc->cmd));
    }
  }
  return process_long(req);
}
//--------------------------------------------------------------------------
bool idaapi rpc_debmod_t::dbg_update_call_stack(thid_t tid, call_stack_t *trace)
{
  bytevec_t req = prepare_rpc_packet(RPC_UPDATE_CALL_STACK);
  append_dd(req, tid);

  rpc_packet_t *rp = process_request(req);
  if ( rp == NULL )
    return false;

  const uchar *answer = (uchar *)(rp+1);
  const uchar *end = answer + rp->length;

  bool result = extract_long(&answer, end) != 0;
  if ( result )
    extract_call_stack(&answer, end, trace);
  qfree(rp);
  return result;
}
//--------------------------------------------------------------------------
ssize_t idaapi rpc_debmod_t::dbg_read_memory(ea_t ea, void *buffer, size_t size)
{
  bytevec_t req = prepare_rpc_packet(RPC_READ_MEMORY);
  append_ea64(req, ea);
  append_dd(req, (uint32)size);

  rpc_packet_t *rp = process_request(req);
  if ( rp == NULL )
    return -1;

  const uchar *answer = (uchar *)(rp+1);
  const uchar *end = answer + rp->length;

  int result = extract_long(&answer, end);
  if ( result > 0 )
    extract_memory(&answer, end, buffer, result);
  qfree(rp);
  return result;
}
//--------------------------------------------------------------------------
// input is valid only if n==0
int idaapi rpc_debmod_t::dbg_process_get_info(int n, const char *input, process_info_t *procinf)
{
  bytevec_t req = prepare_rpc_packet(RPC_GET_PROCESS_INFO);
  append_dd(req, n);
  if ( n == 0 )
    append_str(req, input);

  rpc_packet_t *rp = process_request(req);
  if ( rp == NULL )
    return -1;
  const uchar *answer = (uchar *)(rp+1);
  const uchar *end = answer + rp->length;

  bool result = extract_long(&answer, end) != 0;
  if ( result )
    extract_process_info(&answer, end, procinf);

  qfree(rp);
  return result;
}
Beispiel #23
0
//---------------------------------------------------------- main thread ---
void win32_debmod_t::handle_pdb_request()
{
  if ( pdbthread.req_kind == 1 )
  {
    // read input file
    bytevec_t cmd;
    append_dq(cmd, pdbthread.off_ea);
    append_dd(cmd, pdbthread.count);
    void *outbuf = NULL;
    ssize_t outsize = 0;
    // send request to IDA
    int rc = send_ioctl(WIN32_IOCTL_READFILE, &cmd[0], cmd.size(), &outbuf, &outsize);
    if ( rc == 1 && outbuf != NULL )
    {
      // OK
      size_t copylen = qmin(pdbthread.count, outsize);
      memcpy(pdbthread.buffer, outbuf, copylen);
      pdbthread.count = copylen;
      pdbthread.req_result = true;
    }
    else
    {
      pdbthread.req_result = false;
    }
    if ( outbuf != NULL )
      qfree(outbuf);
  }
  else if ( pdbthread.req_kind == 2 )
  {
    // read memory
    ssize_t rc = _read_memory(ea_t(pdbthread.off_ea), pdbthread.buffer, pdbthread.count);
    if ( rc >= 0 )
      pdbthread.count = rc;
    pdbthread.req_result = rc >= 0;
  }
  else
  {
    // unknown request
    pdbthread.req_result = false;
  }
}
Beispiel #24
0
//--------------------------------------------------------------------------
static void handle_single_session(rpc_server_t *server)
{
  static int s_sess_id = 1;
  int sid = s_sess_id++;

  char peername[MAXSTR];
  if ( !irs_peername(server->irs, peername, sizeof(peername), false) )
    qstrncpy(peername, "(unknown)", sizeof(peername));
  lprintf("=========================================================\n"
          "[%d] Accepting connection from %s...\n", sid, peername);

  bytevec_t req = prepare_rpc_packet(RPC_OPEN);
  append_dd(req, IDD_INTERFACE_VERSION);
  append_dd(req, DEBUGGER_ID);
  append_dd(req, sizeof(ea_t));

  rpc_packet_t *rp = server->process_request(req, true);

  bool handle_request = true;
  bool send_response  = true;
  bool ok;
  if ( rp == NULL )
  {
    lprintf("[%d] Could not establish the connection\n", sid);
    handle_request = false;
    send_response  = false;
  }

  if ( handle_request )
  {
    // Answer is beyond the rpc_packet_t buffer
    const uchar *answer = (uchar *)(rp+1);
    const uchar *end = answer + rp->length;

    ok = extract_long(&answer, end) != 0;
    if ( !ok )
    {
      lprintf("[%d] Incompatible IDA version\n", sid);
      send_response = false;
    }
    else if ( server_password != NULL )
    {
      char *pass = extract_str(&answer, end);
      if ( strcmp(pass, server_password) != '\0' )
      {
        lprintf("[%d] Bad password\n", sid);
        ok = false;
      }
    }

    qfree(rp);
  }

  if ( send_response )
  {
    req = prepare_rpc_packet(RPC_OK);
    append_dd(req, ok);
    server->send_request(req);

    if ( ok )
    {
      // the main loop: handle client requests until it drops the connection
      // or sends us RPC_OK (see rpc_debmod_t::close_remote)
      bytevec_t empty;
      rpc_packet_t *packet = server->process_request(empty);
      if ( packet != NULL )
        qfree(packet);
    }
  }
  server->network_error_code = 0;
  lprintf("[%d] Closing connection from %s...\n", sid, peername);

  bool preserve_server = keep_broken_connections && server->get_broken_connection();
  if ( !preserve_server )
  { // Terminate dedicated debugger instance.
    server->get_debugger_instance()->dbg_term();
    server->term_irs();
  }
  else
  {
    server->term_irs();
    lprintf("[%d] Debugged session entered into sleeping mode\n", sid);
    server->prepare_broken_connection();
  }

  if ( !preserve_server )
  {
    // Remove the session from the list
    srv_lock_begin();
    for (rpc_server_list_t::iterator it = clients_list.begin(); it != clients_list.end();++it)
    {
      if ( it->first != server )
        continue;

#ifndef __SINGLE_THREADED_SERVER__
      // free the thread resources
      qthread_free(it->second);
#endif

      // remove client from the list
      clients_list.erase(it);
      break;
    }
    srv_lock_end();

    // Free the debug session
    delete server;
  }
}
//--------------------------------------------------------------------------
int idaapi rpc_debmod_t::dbg_update_bpts(update_bpt_info_t *ubpts, int nadd, int ndel)
{
  int skipped = 0;
  update_bpt_info_t *b;
  update_bpt_info_t *bend = ubpts + nadd;
  for ( b=ubpts; b != bend; b++ )
    if ( b->code != BPT_OK )
      skipped++;
  if ( skipped == nadd && ndel == 0 )
    return 0; // no bpts to update

  bytevec_t req = prepare_rpc_packet(RPC_UPDATE_BPTS);
  append_dd(req, nadd-skipped);
  append_dd(req, ndel);
  ea_t ea = 0;
  for ( b=ubpts; b != bend; b++ )
  {
    if ( b->code == BPT_OK )
    {
      append_ea64(req, b->ea-ea); ea = b->ea;
      append_dd(req, b->size);
      append_dd(req, b->type);
    }
  }

  ea = 0;
  bend += ndel;
  for ( ; b != bend; b++ )
  {
    append_ea64(req, b->ea-ea); ea = b->ea;
    append_db(req, b->orgbytes.size());
    append_memory(req, b->orgbytes.begin(), b->orgbytes.size());
    append_dd(req, b->type);
  }

  rpc_packet_t *rp = process_request(req);
  if ( rp == NULL )
    return -1;

  const uchar *ptr = (uchar *)(rp+1);
  const uchar *end = ptr + rp->length;

  int ret = extract_long(&ptr, end);
  bend = ubpts + nadd;
  for ( b=ubpts; b != bend; b++ )
  {
    if ( b->code == BPT_OK )
    {
      b->code = extract_byte(&ptr, end);
      if ( b->code == BPT_OK && b->type == BPT_SOFT )
      {
        uchar len = extract_byte(&ptr, end);
        b->orgbytes.resize(len);
        extract_memory(&ptr, end, b->orgbytes.begin(), len);
      }
    }
  }

  bend += ndel;
  for ( ; b != bend; b++ )
    b->code = extract_byte(&ptr, end);

  return ret;
}
//-------------------------------------------------------------------------
bool varser_t::serialize(bytevec_t &out, const VARIANT &var)
{
  append_dw(out, var.vt);
  if ( (var.vt & VT_BYREF) == VT_BYREF
    || (var.vt & VT_ARRAY) == VT_ARRAY )
  {
    return false;
  }

  const size_t sz_before = out.size();
  switch ( var.vt )
  {
    case VT_EMPTY: // = 0x0000,
    case VT_NULL: // = 0x0001,
      break;
    case VT_I2: // = 0x0002,
    case VT_UI2: // = 0x0012,
      append_dw(out, var.uiVal);
      break;
    case VT_I4: // = 0x0003,
    case VT_UI4: // = 0x0013,
      append_dd(out, var.ulVal);
      break;
    case VT_R4: // = 0x0004,
      append_dd(out, *(uint32*)&var.fltVal);
      break;
    case VT_R8: // = 0x0005,
      append_dq(out, *(uint64*)&var.dblVal);
      break;
    case VT_CY: // = 0x0006,
    case VT_DATE: // = 0x0007,
      break;
    case VT_BSTR: // = 0x0008,
      {
        uint8 *ptr = (uint8*) var.bstrVal;
        ptr -= 4;
        uint32 bcnt = * (uint32*) ptr;
        append_dd(out, bcnt);
        append_memory(out, ptr + 4, bcnt);
      }
      break;
    case VT_DISPATCH: // = 0x0009,
    case VT_ERROR: // = 0x000A,
    case VT_BOOL: // = 0x000B,
    case VT_VARIANT: // = 0x000C,
    case VT_UNKNOWN: // = 0x000D,
    case VT_DECIMAL: // = 0x000E,
    case VT_I1: // = 0x0010,
    case VT_UI1: // = 0x0011,
      append_db(out, var.bVal);
      break;
    case VT_I8: // = 0x0014,
    case VT_UI8: // = 0x0015,
      append_dq(out, var.ullVal);
      break;
    case VT_INT: // = 0x0016,
    case VT_UINT: // = 0x0017,
    case VT_HRESULT: // = 0x0019,
      append_dd(out, var.uintVal);
      break;
    case VT_VOID: // = 0x0018,
    case VT_PTR: // = 0x001A,
    case VT_SAFEARRAY: // = 0x001B,
    case VT_CARRAY: // = 0x001C,
    case VT_USERDEFINED: // = 0x001D,
    case VT_LPSTR: // = 0x001E,
    case VT_LPWSTR: // = 0x001F,
    case VT_RECORD: // = 0x0024,
    case VT_INT_PTR: // = 0x0025,
    case VT_UINT_PTR: // = 0x0026,
      break;
    default: break;
  }
  return out.size() > sz_before;
}
//--------------------------------------------------------------------------
int idaapi rpc_debmod_t::dbg_cleanup_appcall(thid_t tid)
{
  bytevec_t req = prepare_rpc_packet(RPC_CLEANUP_APPCALL);
  append_dd(req, tid);
  return process_long(req);
}
//--------------------------------------------------------------------------
bool rpc_debmod_t::open_remote(
    const char *hostname,
    int port_number,
    const char *password)
{
  rpc_packet_t *rp = NULL;
  network_error_code = 0;
  irs = init_client_irs(hostname, port_number);
  if ( irs == NULL )
  {
FAILURE:
    if ( rp != NULL )
      qfree(rp);
    term_irs();
    return false;
  }

  rp = recv_request();
  if ( rp == NULL || rp->code != RPC_OPEN )  // is this an ida debugger server?
  {
    rpc_client_t::dwarning("ICON ERROR\nAUTOHIDE NONE\n"
                           "Bogus or irresponsive remote server");
    goto FAILURE;
  }

  const uchar *answer = (uchar *)(rp+1);
  const uchar *end = answer + rp->length;
  int version = extract_long(&answer, end);
  int remote_debugger_id = extract_long(&answer, end);
  int easize = extract_long(&answer, end);
  qstring errstr;
  if ( version != IDD_INTERFACE_VERSION )
    errstr.sprnt("protocol version is %d, expected %d", version, IDD_INTERFACE_VERSION);
  else if ( remote_debugger_id != debugger.id )
    errstr.sprnt("debugger id is %d, expected %d (%s)", remote_debugger_id, debugger.id, debugger.name);
  else if ( easize != get_expected_addrsize() )
    errstr.sprnt("address size is %d bytes, expected %d", easize, inf.is_64bit() ? 8 : 4);
  if ( !errstr.empty() )
  {
    bytevec_t req = prepare_rpc_packet(RPC_OK);
    append_dd(req, false);
    send_request(req);
    warning("ICON ERROR\nAUTOHIDE NONE\n"
            "Incompatible debugging server:\n"
            "%s\n", errstr.c_str());
    goto FAILURE;
  }
  qfree(rp);

  bytevec_t req = prepare_rpc_packet(RPC_OK);
  append_dd(req, true);
  append_str(req, password);
  send_request(req);

  rp = recv_request();
  if ( rp == NULL || rp->code != RPC_OK )
    goto FAILURE;

  answer = (uchar *)(rp+1);
  end = answer + rp->length;
  bool password_ok = extract_long(&answer, end) != 0;
  if ( !password_ok )  // is this an ida debugger server?
  {
    warning("ICON ERROR\nAUTOHIDE NONE\n"
            "Bad password");
    goto FAILURE;
  }

  qfree(rp);
  return true;
}