XLCd _XlcDynamicLoad(const char *lc_name) { XLCd lcd = (XLCd)NULL; dynamicLoadProc lc_loader = (dynamicLoadProc)NULL; int count; XI18NObjectsList objects_list; char lc_dir[BUFSIZE]; if (lc_name == NULL) return (XLCd)NULL; if (_XlcLocaleDirName(lc_dir, BUFSIZE, (char *)lc_name) == (char*)NULL) return (XLCd)NULL; resolve_object(lc_dir, lc_name); objects_list = xi18n_objects_list; count = lc_count; for (; count-- > 0; objects_list++) { if (objects_list->type != XLC_OBJECT || strcmp(objects_list->locale_name, lc_name)) continue; if (!open_object (objects_list, lc_dir)) continue; lc_loader = (dynamicLoadProc)fetch_symbol (objects_list, objects_list->open); if (!lc_loader) continue; lcd = (*lc_loader)(lc_name); if (lcd != (XLCd)NULL) { break; } close_object (objects_list); } return (XLCd)lcd; }
static void * object_get_from_message_arg(DBusMessage *message, char *type) { char *opath; DBusError error; dbus_error_init(&error); if (!dbus_message_get_args(message, &error, DBUS_TYPE_OBJECT_PATH, &opath, DBUS_TYPE_INVALID)) { dbus_error_free(&error); dbg(0,"wrong arg type\n"); return NULL; } return resolve_object(opath, type); }
static void * object_get_from_message(DBusMessage *message, char *type) { return resolve_object(dbus_message_get_path(message), type); }
static int callback_nyx_websockets(struct libwebsocket_context *context,struct libwebsocket *wsi,enum libwebsocket_callback_reasons reason, void *user,void *in,size_t len) { struct per_session_data_nyx *pss =(struct per_session_data_nyx*)user; int n; node *wsd_state = (node*)libwebsocket_context_user(context); //node *daemon = (node*)libwebsocket_context_user(context); //node *wsd_state = node_GetNode(get_value(daemon)); node *found_prot = NULL; node *state = NULL; node *block = NULL; //node *daemon = NULL; node *daemon_obj = NULL; node *session_uid = NULL; long lsession_uid = 0; node *sessions_num = NULL; node *sessions = NULL; long lsessions_num = 0; if(wsd_state) { state = node_GetItem(wsd_state,0); block = node_GetItem(wsd_state,1); //daemon = node_GetItem(wsd_state,2); node *protocols = node_GetItem(wsd_state,3); session_uid = node_GetItem(wsd_state,4); node *session_uid_value = node_GetItemByKey(session_uid,"value"); lsession_uid = node_GetSint32(session_uid_value); sessions_num = node_GetItem(wsd_state,5); sessions = node_GetItem(wsd_state,6); node *sessions_num_value = node_GetItemByKey(sessions_num,"value"); lsessions_num = node_GetSint32(sessions_num_value); daemon_obj = node_GetItem(wsd_state,9); if(wsi) { node *protocols_items = node_GetItemByKey(protocols,"items"); const struct libwebsocket_protocols *prot = libwebsockets_get_protocol(wsi); if(prot && prot->name) { node_ItemIterationReset(protocols_items); while(node_ItemIterationUnfinished(protocols_items)) { node *proto = node_ItemIterate(protocols_items); if(!strcmp(get_obj_name(proto),prot->name)) { found_prot = proto; } } } } } switch(reason) { //case LWS_CALLBACK_SERVER_NEW_CLIENT_INSTANTIATED: case LWS_CALLBACK_CLIENT_ESTABLISHED: printf("new session created:%d, num:%d\n",lsession_uid,lsessions_num); pss->session = NULL; break; case LWS_CALLBACK_HTTP: if(len < 1) { libwebsockets_return_http_status(context,wsi,HTTP_STATUS_BAD_REQUEST,NULL); return(-1); } if(lws_hdr_total_length(wsi,WSI_TOKEN_POST_URI)) return(0); if(found_prot) { //printf("found prot in http callback : uid:%d,num:%d (sess:%x)\n",lsession_uid+1,lsessions_num,pss->session); if(!pss->session) { lsession_uid++; node *session_uid_value = node_GetItemByKey(session_uid,"value"); node_SetSint32(session_uid_value,lsession_uid); lsessions_num++; node *sessions_num_value = node_GetItemByKey(sessions_num,"value"); node_SetSint32(sessions_num_value,lsessions_num); pss->session = create_session(state,sessions,lsession_uid,get_obj_name(found_prot)); node *session_privates = node_GetItemByKey(pss->session,"privates"); set_obj_int(session_privates,"is_http",1); //printf("created new session :%d actual sessions num:%d\n",lsession_uid,lsessions_num); } node *parameters = create_obj("parameters"); node *base_class = get_base_class(state); node *prot_value = create_class_instance(base_class); set_obj_string(prot_value,"name","protocol"); set_obj_string(prot_value,"value",get_obj_name(found_prot)); node_AddItem(parameters,prot_value); inc_obj_refcount(prot_value); char *url = str_CreateEmpty(); url = str_AddChars(url,in,len); node *url_value = create_class_instance(base_class); set_obj_string(url_value,"name","url"); set_obj_string(url_value,"value",url); node_AddItem(parameters,url_value); inc_obj_refcount(url_value); free(url); node_AddItem(parameters,pss->session); inc_obj_refcount(pss->session); //node_AddItem(parameters,daemon_obj); node_AddItem(parameters,sessions); inc_obj_refcount(sessions); node *tmp_parent = node_GetParent(found_prot); node *bmembers = node_GetItemByKey(block,"members"); node_SetParent(found_prot,bmembers); node *ret_obj = execute_obj(state,found_prot,block,parameters,True,False);//,True);resolve node_SetParent(found_prot,tmp_parent); //dec_obj_refcount(msg_value); dec_obj_refcount(prot_value); //add_garbage(state,msg_value);//TODO check if "just survives" add_garbage(state,prot_value); dec_obj_refcount(url_value); add_garbage(state,url_value); dec_obj_refcount(pss->session); dec_obj_refcount(sessions); node *ret_obj_value = node_GetItemByKey(ret_obj,"value"); if( (node_GetType(ret_obj_value)==NODE_TYPE_STRING && strlen(node_GetString(ret_obj_value))) || (node_GetType(ret_obj_value)==NODE_TYPE_BINARY && node_GetBinaryLength(ret_obj_value)) ) { //printf("returning http message: [%s] :%d\n",node_GetString(ret_obj_value),strlen(node_GetString(ret_obj_value))); //node *ret_obj_copy = node_CopyTree(ret_obj,True,True); node *ret_obj_copy = copy_class(ret_obj); //reset_obj_refcount(ret_obj_copy); set_obj_string(ret_obj_copy,"name","message"); add_member(pss->session,ret_obj_copy); inc_obj_refcount(ret_obj_copy); } libwebsocket_callback_on_writable(context, wsi); } break; case LWS_CALLBACK_HTTP_BODY_COMPLETION: if(found_prot) { printf("found prot in http body complete : %d,num:%d\n",lsession_uid,lsessions_num); if(daemon_obj) { printf("body: found daemon_obj\n"); } } else printf("body closed: prot not found\n"); //lwsl_notice("LWS_CALLBACK_HTTP_BODY_COMPLETION\n"); libwebsockets_return_http_status(context,wsi,HTTP_STATUS_OK,NULL); return(-1); case LWS_CALLBACK_HTTP_FILE_COMPLETION: if(found_prot) { //printf("found prot in http file complete : %d,num:%d\n",lsession_uid,lsessions_num); lsessions_num--; node *sessions_num_value = node_GetItemByKey(sessions_num,"value"); node_SetSint32(sessions_num_value,lsessions_num); delete_session(state,sessions,pss->session); pss->session = NULL; if(daemon_obj) { printf("http: found daemon_obj\n"); } } else printf("file closed: prot not found\n"); return(-1); case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION: if(found_prot) { int n; static const char *token_names[] = { /*[WSI_TOKEN_GET_URI] =*/ "GET URI", /*[WSI_TOKEN_POST_URI] =*/ "POST URI", /*[WSI_TOKEN_OPTIONS] =*/ "Options", /*[WSI_TOKEN_HOST] =*/ "Host", /*[WSI_TOKEN_CONNECTION] =*/ "Connection", /*[WSI_TOKEN_KEY1] =*/ "key 1", /*[WSI_TOKEN_KEY2] =*/ "key 2", /*[WSI_TOKEN_PROTOCOL] =*/ "Protocol", /*[WSI_TOKEN_UPGRADE] =*/ "Upgrade", /*[WSI_TOKEN_ORIGIN] =*/ "Origin", /*[WSI_TOKEN_DRAFT] =*/ "Draft", /*[WSI_TOKEN_CHALLENGE] =*/ "Challenge", /* new for 04 */ /*[WSI_TOKEN_KEY] =*/ "Key", /*[WSI_TOKEN_VERSION] =*/ "Version", /*[WSI_TOKEN_SWORIGIN] =*/ "Sworigin", /* new for 05 */ /*[WSI_TOKEN_EXTENSIONS] =*/ "Extensions", /* client receives these */ /*[WSI_TOKEN_ACCEPT] =*/ "Accept", /*[WSI_TOKEN_NONCE] =*/ "Nonce", /*[WSI_TOKEN_HTTP] =*/ "Http", "Accept:", "Accept_Request_Headers:", "If-None-Match:", "If-Modified-Since:", "Accept-Encoding:", "Accept-Language:", "Pragma:", "Cache-Control:", "Authorization:", "Cookie:", "Content-Length:", "Content-Type:", "Date:", "Range:", "Referer:", "Uri-Args:", /*[WSI_TOKEN_MUXURL] =*/ "MuxURL", }; //printf("found prot in http filter callback : uid:%d,num:%d (sess:%x)\n",lsession_uid+1,lsessions_num,pss->session); if(!pss->session) { lsession_uid++; node *session_uid_value = node_GetItemByKey(session_uid,"value"); node_SetSint32(session_uid_value,lsession_uid); lsessions_num++; node *sessions_num_value = node_GetItemByKey(sessions_num,"value"); node_SetSint32(sessions_num_value,lsessions_num); pss->session = create_session(state,sessions,lsession_uid,get_obj_name(found_prot)); //node *session_privates = node_GetItemByKey(pss->session,"privates"); //set_obj_int(session_privates,"is_http",1); } //printf("filter sess:%x\n",pss->session); for(n=0;n<(int)(sizeof(token_names)/sizeof(token_names[0]));n++) { if (!lws_hdr_total_length(wsi, n)) continue; char *cookies = (char*)malloc(512); memset(cookies,0,512); lws_hdr_copy(wsi,cookies,511,n); //printf("header:%s = [%s]\n",token_names[n],cookies); //fflush(stdout); if(pss->session && !strcmp("Cookie:",token_names[n])) { //printf("cookie found:%s = [%s]\n",token_names[n],cookies); //fflush(stdout); node *base_class = get_base_class(state); node *cookie_value = create_class_instance(base_class); set_obj_string(cookie_value,"name","cookie"); set_obj_string(cookie_value,"value",cookies); add_member(pss->session,cookie_value); inc_obj_refcount(cookie_value); } free(cookies); } } break; case LWS_CALLBACK_HTTP_WRITEABLE: case LWS_CALLBACK_SERVER_WRITEABLE: { //node_PrintTree(pss->session); node *message = get_member(pss->session,"message"); node *session_privates = node_GetItemByKey(pss->session,"privates"); node *http_only = node_GetItemByKey(session_privates,"is_http"); while(message) { //node *session_id = get_member(pss->session,"id"); //node *session_id_value = node_GetItemByKey(session_id,"value"); node *message_value = node_GetItemByKey(message,"value"); unsigned char *me = NULL; unsigned long me_len = 0; if(node_GetType(message_value)==NODE_TYPE_STRING) { me = (unsigned char*)node_GetString(message_value); me_len = strlen((char*)me); } else if(node_GetType(message_value)==NODE_TYPE_BINARY) { me = (unsigned char*)node_GetBinary(message_value); me_len = node_GetBinaryLength(message_value); } //printf("sending message now: [%s] to: %d\n",me,node_GetSint32(session_id_value)); //fflush(stdout); unsigned char *buf = (unsigned char*)malloc(LWS_SEND_BUFFER_PRE_PADDING + me_len + LWS_SEND_BUFFER_POST_PADDING); memcpy(buf+LWS_SEND_BUFFER_PRE_PADDING,me,me_len); if(http_only) //n = libwebsocket_write(wsi, me, me_len, LWS_WRITE_HTTP); n = libwebsocket_write(wsi,buf+LWS_SEND_BUFFER_PRE_PADDING,me_len,LWS_WRITE_HTTP); else //n = libwebsocket_write(wsi, me, me_len, LWS_WRITE_TEXT); n = libwebsocket_write(wsi,buf+LWS_SEND_BUFFER_PRE_PADDING,me_len,LWS_WRITE_TEXT); free(buf); if(n<0) { printf("ERROR %d writing to socket, hanging up\n", n); return(1); } if(n<(long)me_len) { printf("Partial write\n"); return(-1); } //node_FreeTree(pss->message); remove_member(pss->session,message); dec_obj_refcount(message); //printf("removing message from queue:%x (%d)\n",message,get_obj_refcount(message)); add_garbage(state,message); message = get_member(pss->session,"message"); } if(http_only) { //if(lws_http_transaction_completed(wsi)) //{ //printf("removing http session num:%d\n",lsessions_num); lsessions_num--; node *sessions_num_value = node_GetItemByKey(sessions_num,"value"); node_SetSint32(sessions_num_value,lsessions_num); delete_session(state,sessions,pss->session); pss->session = NULL; //printf("removed http\n"); return -1; //return(-1); //} //else // libwebsocket_callback_on_writable(context, wsi); } } break; case LWS_CALLBACK_ESTABLISHED: if(found_prot) { //printf("found prot in establish callback : uid:%d,num:%d (sess:%x)\n",lsession_uid+1,lsessions_num,pss->session); if(!pss->session) { lsession_uid++; node *session_uid_value = node_GetItemByKey(session_uid,"value"); node_SetSint32(session_uid_value,lsession_uid); lsessions_num++; node *sessions_num_value = node_GetItemByKey(sessions_num,"value"); node_SetSint32(sessions_num_value,lsessions_num); pss->session = create_session(state,sessions,lsession_uid,get_obj_name(found_prot)); } if(daemon_obj) { node *connect_handler = get_member(daemon_obj,"connect_handler"); if(connect_handler) { connect_handler = resolve_object(state,connect_handler); node *parameters = create_obj("parameters"); node *base_class = get_base_class(state); node *prot_value = create_class_instance(base_class); set_obj_string(prot_value,"name","protocol"); set_obj_string(prot_value,"value",get_obj_name(found_prot)); node_AddItem(parameters,prot_value); inc_obj_refcount(prot_value); node_AddItem(parameters,pss->session); inc_obj_refcount(pss->session); node_AddItem(parameters,sessions); inc_obj_refcount(sessions); node *tmp_parent = node_GetParent(connect_handler); node *bmembers = node_GetItemByKey(block,"members"); node_SetParent(connect_handler,bmembers); node *ret_obj = execute_obj(state,connect_handler,block,parameters,True,False);//,True);resolve node_SetParent(connect_handler,tmp_parent); dec_obj_refcount(prot_value); add_garbage(state,prot_value); dec_obj_refcount(pss->session); dec_obj_refcount(sessions); node *ret_obj_value = node_GetItemByKey(ret_obj,"value"); if(node_GetType(ret_obj_value)==NODE_TYPE_STRING && strlen(node_GetString(ret_obj_value))) { } } } } break; case LWS_CALLBACK_CLOSED_HTTP: break; case LWS_CALLBACK_CLOSED: case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: if(found_prot) { //printf("found prot in closed callback : uid:%d,num:%d (sess:%x)\n",lsession_uid,lsessions_num,pss->session); if(daemon_obj) { //printf("closed: found daemon_obj\n"); node *disconnect_handler = get_member(daemon_obj,"disconnect_handler"); if(disconnect_handler) { //printf("disc found\n"); disconnect_handler = resolve_object(state,disconnect_handler); node *parameters = create_obj("parameters"); node *base_class = get_base_class(state); node *prot_value = create_class_instance(base_class); set_obj_string(prot_value,"name","protocol"); set_obj_string(prot_value,"value",get_obj_name(found_prot)); node_AddItem(parameters,prot_value); inc_obj_refcount(prot_value); node_AddItem(parameters,pss->session); inc_obj_refcount(pss->session); node_AddItem(parameters,sessions); inc_obj_refcount(sessions); node *tmp_parent = node_GetParent(disconnect_handler); node *bmembers = node_GetItemByKey(block,"members"); node_SetParent(disconnect_handler,bmembers); node *ret_obj = execute_obj(state,disconnect_handler,block,parameters,True,False);//,True);resolve node_SetParent(disconnect_handler,tmp_parent); dec_obj_refcount(prot_value); add_garbage(state,prot_value); dec_obj_refcount(pss->session); dec_obj_refcount(sessions); node *ret_obj_value = node_GetItemByKey(ret_obj,"value"); if(node_GetType(ret_obj_value)==NODE_TYPE_STRING && strlen(node_GetString(ret_obj_value))) { } } } lsessions_num--; node *sessions_num_value = node_GetItemByKey(sessions_num,"value"); node_SetSint32(sessions_num_value,lsessions_num); delete_session(state,sessions,pss->session); pss->session = NULL; //printf("disconnected\n"); } else { printf("closed connection without prot found\n"); if(pss->session) printf("but a session was found\n"); } break; case LWS_CALLBACK_RECEIVE: if(len>1024) { //TODO use some variable lwsl_err("Server received packet bigger than %u, hanging up\n", 1024); return(1); } if(found_prot) { node *parameters = create_obj("parameters"); node *base_class = get_base_class(state); node *prot_value = create_class_instance(base_class); set_obj_string(prot_value,"name","protocol"); set_obj_string(prot_value,"value",get_obj_name(found_prot)); node_AddItem(parameters,prot_value); inc_obj_refcount(prot_value); char *msg = str_CreateEmpty(); msg = str_AddChars(msg,in,len); node *msg_value = create_class_instance(base_class); set_obj_string(msg_value,"name","message"); set_obj_string(msg_value,"value",msg); node_AddItem(parameters,msg_value); inc_obj_refcount(msg_value); free(msg); /*node *session_value = create_class_instance(base_class); reset_obj_refcount(session_value); add_garbage(state,session_value); set_obj_string(session_value,"name","session_id"); set_obj_int(session_value,"value",lsession_uid); set_obj_int(session_value,"item_index",2); node_AddItem(parameters,session_value); */ node_AddItem(parameters,pss->session); inc_obj_refcount(pss->session); //node_AddItem(parameters,daemon_obj); //inc_obj_refcount(daemon_obj); node_AddItem(parameters,sessions); inc_obj_refcount(sessions); //printf("recv callback\n"); //fflush(stdout); node *tmp_parent = node_GetParent(found_prot); node *bmembers = node_GetItemByKey(block,"members"); node_SetParent(found_prot,bmembers); node *ret_obj = execute_obj(state,found_prot,block,parameters,True,False);//,True);resolve node_SetParent(found_prot,tmp_parent); //printf("recv callback finished\n"); //fflush(stdout); dec_obj_refcount(msg_value); dec_obj_refcount(prot_value); add_garbage(state,msg_value);//TODO check if "just survives" add_garbage(state,prot_value); dec_obj_refcount(pss->session); dec_obj_refcount(sessions); //dec_obj_refcount(daemon_obj); //printf("recv gc\n"); //fflush(stdout); //node *ret_obj_value = node_GetItemByKey(ret_obj,"value"); //char *me = node_GetString(ret_obj_value); //printf("returned string:[%s]\n",me); node *ret_obj_value = node_GetItemByKey(ret_obj,"value"); if(node_GetType(ret_obj_value)==NODE_TYPE_STRING && strlen(node_GetString(ret_obj_value))) { //printf("returning message: [%s] :%d\n",node_GetString(ret_obj_value),strlen(node_GetString(ret_obj_value))); //node *ret_obj_copy = node_CopyTree(ret_obj,True,True); node *ret_obj_copy = copy_class(ret_obj); //reset_obj_refcount(ret_obj_copy); set_obj_string(ret_obj_copy,"name","message"); add_member(pss->session,ret_obj_copy); inc_obj_refcount(ret_obj_copy); //set_obj_string(ret_obj,"name","message"); //add_member(pss->session,ret_obj); //inc_obj_refcount(ret_obj); } libwebsocket_callback_on_writable(context, wsi); } break; default: break; } return(0); }
bool VirtualFunctionCallAnalyzer::analyze(CallInformationPtr &call_info) { // Example code: // // A: mov edx, [ecx+4] // B: mod edi, [edx+8] // C: call edi // // Answer: // Virtual, obj_ptr=X, vtable_ptr=Y, object_offet = 4, vtable_offset=8 // 1. Find the abstract access for the vfunc pointer in the call instruction. // 2. Get the instruction that that defined the vfunc pointer. // 3. Find the abstract access that read the vfunc pointer. // 4. Extract the variable and constant portions from the vtable access. // 5. Find the abstract access that read the vtable pointer. // 6. Find the instruction that defined the vtable pointer. // 7. Find the abstract acccess that read the vtable pointer. // 8. Extract the variable and constant portions from the object access. GDEBUG << "Evaluating possible virtual call: " << debug_instruction(call_insn) << LEND; // reset the CallInformationPtr??? call_info.reset(); const DUAnalysis& du = pdg->get_usedef(); // We're looking for the register or address that was read in the call insn const AbstractAccessVector* reads = du.get_reads(call_insn); // If there were no reads in the call, something's really wrong. if (reads == NULL) { GDEBUG << "Non virtual: " << debug_instruction(call_insn) << " - no read of target." << LEND; return false; } // Step 1. Find the abstract access that obtained the virtual function pointer. This is the // read that that was not the stack pointer register. const AbstractAccess* vfunc_aa = NULL; BOOST_FOREACH(const AbstractAccess& aa, *reads) { if (aa.is_mem()) { vfunc_aa = &aa; } else { // ESP should really be obtained from the architecture depdenent layer (e.g. RSP). // EIP and RIP are never in the reads/writes array (because they always are). if (aa.reg_name() == "esp") continue; vfunc_aa = &aa; } } if (vfunc_aa == NULL) { GDEBUG << "Non virtual: " << debug_instruction(call_insn) << " - no read of target." << LEND; return false; } // Step 2. Find the instruction that defined the virtual function call. This is the // instruction that references the virtual function table, including the virtual function // table and the offset into it. A little trick supports calls of the form "call [reg+X]". SgAsmX86Instruction* vtable_insn = NULL; // If the instruction was "call [reg+X]" if (vfunc_aa->is_mem()) { vtable_insn = call_insn; } // If the instruction was "call reg" else { // The vtable instruction will be the latest writer to the register in the call instruction. // If there are no latest writers at all, fail. if (vfunc_aa->latest_writers.size() == 0) { GDEBUG << "Non virtual: " << debug_instruction(call_insn) << " - no latest write for vfunc_aa=" << *vfunc_aa << LEND; return false; } vtable_insn = isSgAsmX86Instruction(*(vfunc_aa->latest_writers.begin())); if (vtable_insn == NULL) { GDEBUG << "Non virtual: " << debug_instruction(call_insn) << " - latest write not an X86 insn vfunc_aa=" << *vfunc_aa << LEND; return false; } } GDEBUG << "Possible vtable instruction: " << debug_instruction(vtable_insn) << LEND; // Step 3. Find the abstract access that read the virtual function pointer from the memory // address in the virtual function table. TreeNodePtr vfunc_ptr = vfunc_aa->value->get_expression(); const AbstractAccess* vtable_aa = find_memory_access(vtable_insn, du, vfunc_ptr); // If we couldn't find where the vtable was written, fail. if (vtable_aa == NULL) { GDEBUG << "Non virtual: " << debug_instruction(call_insn) << " - no vtable abstract access vfunc_ptr=" << *vfunc_ptr << LEND; return false; } // All valid vtable accesses must be memory reads. if (!vtable_aa->is_mem()) { GDEBUG << "Non virtual: " << debug_instruction(call_insn) << " - vtable access was not a memory read" << *vtable_aa << LEND; return false; } // Step 4. Extract the variable and constant portions from the vtable abstract access // providing the vtable pointer and the offset into the vtable. TreeNodePtr vtable_expr = vtable_aa->memory_address->get_expression(); AddConstantExtractor foace = AddConstantExtractor(vtable_expr); // There must be a variable portion for this to be a virtual function call. TreeNodePtr vtable_ptr = foace.variable_portion; if (vtable_ptr == NULL) { GDEBUG << "Non virtual: " << debug_instruction(call_insn) << " - no variable portion in vtable_expr=" << *vtable_expr << LEND; return false; } // Virtual function table offsets are not allowed to be negative, but they can be zero. int64_t vtable_offset = foace.constant_portion; if (vtable_offset < 0) { GDEBUG << "Non virtual: " << debug_instruction(call_insn) << " - negative vtable offset in vtable_expr=" << *vtable_expr << LEND; return false; } // Report the likely virtual function table pointer and offset into the table. GDEBUG << "Possible virtual function table pointer: " << *vtable_ptr << LEND; GDEBUG << "Possible virtual function offset in vtable: " << vtable_offset << LEND; // Step 5. Find the abstract access where the vtable pointer was read. // It's unclear what we should do when vtable_ptr is an ITE expression. Currently, // find_memory_access() uses can_be_equal() which isn't perfect. Cory thought it was // unlikely that such a situation would arise in real virtual calls, but there are some // examples in Lite/poly.exe involving std::basic_char_streambuf. More investigation and // work is required here, probably involving an approach that might result in multiple valid // resolutions of the call. For now, this is good enough, and is close to what we did // previously. const AbstractAccess* vtable_ptr_aa = find_memory_access(vtable_insn, du, vtable_ptr); // If the abstract access was NULL, then there's clearly no latest writer. if (vtable_ptr_aa == NULL) { GDEBUG << "Non virtual: " << debug_instruction(call_insn) << " - no writer for vtable_ptr=" << *vtable_ptr << LEND; return false; } // Step 6. Find the instruction that wrote the value into the vtable pointer. This is the // instruction that references the object pointer and the offset into it. Perhaps we should // be doing something will all of the writers, not just the first one? if (vtable_ptr_aa->latest_writers.size() == 0) { GDEBUG << "Non virtual: " << debug_instruction(call_insn) << " - no latest write for vtable_aa=" << *vtable_ptr_aa << LEND; return false; } SgAsmX86Instruction* object_insn = isSgAsmX86Instruction(*(vtable_ptr_aa->latest_writers.begin())); if (object_insn == NULL) { GDEBUG << "Non virtual: " << debug_instruction(call_insn) << " - no insn for vtable_ptr_aa=" << *vtable_ptr_aa << LEND; return false; } GDEBUG << "Possible object instruction:" << debug_instruction(object_insn) << LEND; // Step 7. Find the abstract access that read the virtual function table pointer from the // memory address in the object. const AbstractAccess* object_aa = find_memory_access(object_insn, du, vtable_ptr); // If we couldn't find where the object was written, fail. if (object_aa == NULL) { GDEBUG << "Non virtual: " << debug_instruction(call_insn) << " - no object abstract access =" << debug_instruction(object_insn) << LEND; return false; } // All reads of the vtable pointer must be from memory (in the object). if (!(object_aa->is_mem())) { GDEBUG << "Non virtual: " << debug_instruction(call_insn) << " - object access not to memory =" << *object_aa << LEND; return false; } // Step 8. We've now got the object pointer expression, but it might be a complicated ITE // expression. To really conmplete step 8, we'll need to invoke the correct logic on each of // the possible values. SymbolicValuePtr object_sv = object_aa->memory_address; GDEBUG << "Possible multi-valued object pointer: " << *object_sv << LEND; // There are probably some major changes that can be made to this logic post-NEWWAY! if (object_sv->contains_ite()) { GDEBUG << "VCall ITE: " << *object_sv << LEND; bool matched = false; BOOST_FOREACH(const TreeNodePtr& tn, object_sv->get_possible_values()) { GDEBUG << "VCall ITE this-ptr: " << *tn << LEND; // The most common non OO condition is the NULL pointer. if (tn->isNumber() && tn->toInt() == 0) { GDEBUG << "Skipping NULL pointer as possible object pointer." << LEND; continue; } if (resolve_object(tn, vtable_ptr, vtable_offset, call_info)) matched = true; } if (matched) return true; }