2014-06-26 14:52:25 -07:00
|
|
|
#include <ida.hpp>
|
|
|
|
#include <idp.hpp>
|
|
|
|
#include <loader.hpp>
|
2014-07-06 12:36:57 +09:00
|
|
|
#include <bytes.hpp>
|
2014-06-26 14:52:25 -07:00
|
|
|
|
2014-07-18 20:01:39 -07:00
|
|
|
//#define DEBUG
|
2014-06-26 14:52:25 -07:00
|
|
|
|
|
|
|
// ***************** WEBSOCKETS *******************
|
|
|
|
#include <libwebsockets.h>
|
|
|
|
|
|
|
|
static int callback_http(struct libwebsocket_context* context,
|
|
|
|
struct libwebsocket* wsi,
|
|
|
|
enum libwebsocket_callback_reasons reason, void* user,
|
|
|
|
void* in, size_t len) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void thread_safe_jump_to(ea_t a) {
|
|
|
|
struct uireq_jumpto_t: public ui_request_t {
|
|
|
|
uireq_jumpto_t(ea_t a) {
|
|
|
|
la = a;
|
|
|
|
}
|
|
|
|
virtual bool idaapi run() {
|
|
|
|
jumpto(la);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
ea_t la;
|
|
|
|
};
|
|
|
|
execute_ui_requests(new uireq_jumpto_t(a), NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct libwebsocket* gwsi = NULL;
|
|
|
|
|
|
|
|
static int callback_qira(struct libwebsocket_context* context,
|
|
|
|
struct libwebsocket* wsi,
|
|
|
|
enum libwebsocket_callback_reasons reason, void* user,
|
|
|
|
void* in, size_t len) {
|
|
|
|
//msg("QIRA CALLBACK: %d\n", reason);
|
|
|
|
switch(reason) {
|
|
|
|
case LWS_CALLBACK_ESTABLISHED:
|
|
|
|
// we only support one client
|
|
|
|
gwsi = wsi;
|
2014-07-02 11:31:15 -07:00
|
|
|
msg("QIRA web connected\n");
|
2014-06-26 14:52:25 -07:00
|
|
|
break;
|
|
|
|
case LWS_CALLBACK_RECEIVE:
|
|
|
|
#ifdef DEBUG
|
2014-07-06 11:46:39 +09:00
|
|
|
msg("QIRARX:%s\n", (char *)in);
|
2014-06-26 14:52:25 -07:00
|
|
|
#endif
|
2014-07-06 11:46:39 +09:00
|
|
|
if (memcmp(in, "setaddress ", sizeof("setaddress ")-1) == 0) {
|
|
|
|
ea_t addr = atoi((char*)in+sizeof("setaddress ")-1);
|
2014-06-26 14:52:25 -07:00
|
|
|
thread_safe_jump_to(addr);
|
|
|
|
}
|
|
|
|
break;
|
2014-07-06 11:46:39 +09:00
|
|
|
default:
|
|
|
|
break;
|
2014-06-26 14:52:25 -07:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ws_send(char *str) {
|
|
|
|
#ifdef DEBUG
|
|
|
|
msg("QIRATX:%s\n", str);
|
|
|
|
#endif
|
|
|
|
int len = strlen(str);
|
|
|
|
unsigned char *buf = (unsigned char*)
|
|
|
|
malloc(LWS_SEND_BUFFER_PRE_PADDING + len + LWS_SEND_BUFFER_POST_PADDING);
|
|
|
|
memcpy(&buf[LWS_SEND_BUFFER_PRE_PADDING], str, len);
|
|
|
|
if (gwsi != NULL) {
|
|
|
|
libwebsocket_write(gwsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], len, LWS_WRITE_TEXT);
|
|
|
|
}
|
|
|
|
free(buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ***************** IDAPLUGIN *******************
|
|
|
|
|
2014-07-06 12:36:57 +09:00
|
|
|
static void update_address(const char *type, ea_t addr) {
|
2014-06-26 14:52:25 -07:00
|
|
|
//msg("addr 0x%x\n", addr);
|
|
|
|
char tmp[100];
|
2014-07-18 16:02:51 -07:00
|
|
|
#ifdef __EA64__
|
|
|
|
qsnprintf(tmp, 100-1, "set%s %llu", type, addr);
|
|
|
|
#else
|
|
|
|
qsnprintf(tmp, 100-1, "set%s %u", type, addr);
|
|
|
|
#endif
|
2014-06-26 14:52:25 -07:00
|
|
|
ws_send(tmp);
|
|
|
|
}
|
|
|
|
|
2014-07-21 03:20:28 -07:00
|
|
|
static int idaapi hook(void *user_data, int event_id, va_list va) {
|
2014-06-26 14:52:25 -07:00
|
|
|
static ea_t old_addr = 0;
|
|
|
|
ea_t addr;
|
2014-07-06 12:36:57 +09:00
|
|
|
if (event_id == view_curpos) {
|
2014-06-26 14:52:25 -07:00
|
|
|
addr = get_screen_ea();
|
|
|
|
if (old_addr != addr) {
|
2014-07-06 12:36:57 +09:00
|
|
|
if (isCode(getFlags(addr))) {
|
|
|
|
update_address("iaddr", addr);
|
|
|
|
} else {
|
|
|
|
update_address("daddr", addr);
|
|
|
|
}
|
2014-06-26 14:52:25 -07:00
|
|
|
}
|
|
|
|
old_addr = addr;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ***************** WEBSOCKETS BOILERPLATE *******************
|
|
|
|
|
|
|
|
static struct libwebsocket_protocols protocols[] = {
|
|
|
|
{ "http-only", callback_http, 0 },
|
|
|
|
{ "qira", callback_qira, 0 },
|
|
|
|
{ NULL, NULL, 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
qthread_t websockets_thread;
|
|
|
|
int websockets_running;
|
|
|
|
|
2014-07-21 03:20:28 -07:00
|
|
|
int idaapi websocket_thread(void *) {
|
2014-06-26 14:52:25 -07:00
|
|
|
struct libwebsocket_context* context;
|
|
|
|
|
|
|
|
struct lws_context_creation_info info;
|
|
|
|
memset(&info, 0, sizeof info);
|
|
|
|
info.port = 3003;
|
|
|
|
info.iface = NULL;
|
|
|
|
info.protocols = protocols;
|
|
|
|
info.extensions = libwebsocket_get_internal_extensions();
|
|
|
|
info.gid = -1;
|
|
|
|
info.uid = -1;
|
|
|
|
info.options = 0;
|
|
|
|
|
|
|
|
context = libwebsocket_create_context(&info);
|
|
|
|
msg("yay websockets\n");
|
|
|
|
|
|
|
|
while (websockets_running) {
|
|
|
|
libwebsocket_service(context, 50);
|
|
|
|
}
|
|
|
|
libwebsocket_context_destroy(context);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void start_websocket_thread() {
|
|
|
|
websockets_running = 1;
|
|
|
|
websockets_thread = qthread_create(websocket_thread, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void exit_websocket_thread() {
|
|
|
|
websockets_running = 0;
|
|
|
|
qthread_join(websockets_thread);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ***************** IDAPLUGIN BOILERPLATE *******************
|
|
|
|
|
2014-07-21 03:20:28 -07:00
|
|
|
int idaapi IDAP_init(void) {
|
2014-07-06 11:46:39 +09:00
|
|
|
hook_to_notification_point(HT_VIEW, hook, NULL);
|
2014-06-26 14:52:25 -07:00
|
|
|
start_websocket_thread();
|
|
|
|
return PLUGIN_KEEP;
|
|
|
|
}
|
|
|
|
|
2014-07-21 03:20:28 -07:00
|
|
|
void idaapi IDAP_term(void) {
|
2014-07-06 11:46:39 +09:00
|
|
|
unhook_from_notification_point(HT_VIEW, hook);
|
2014-07-01 16:53:55 -07:00
|
|
|
exit_websocket_thread();
|
2014-06-26 14:52:25 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-07-21 03:20:28 -07:00
|
|
|
void idaapi IDAP_run(int arg) {
|
2014-06-26 14:52:25 -07:00
|
|
|
msg("installing book\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
char IDAP_comment[] = "This is my test plug-in";
|
|
|
|
char IDAP_help[] = "My plugin";
|
|
|
|
char IDAP_name[] = "QIRA server";
|
|
|
|
char IDAP_hotkey[] = "Alt-X";
|
|
|
|
|
|
|
|
plugin_t PLUGIN = {
|
|
|
|
IDP_INTERFACE_VERSION, // IDA version plug-in is written for
|
|
|
|
0, // Flags (see below)
|
|
|
|
IDAP_init, // Initialisation function
|
|
|
|
IDAP_term, // Clean-up function
|
|
|
|
IDAP_run, // Main plug-in body
|
|
|
|
IDAP_comment, // Comment
|
|
|
|
IDAP_help, // As above
|
|
|
|
IDAP_name, // Plug-in name shown in
|
|
|
|
IDAP_hotkey // Hot key to run the plug-in
|
|
|
|
};
|
|
|
|
|