1. Instalação e execução
	
		
		
		O meu IMsniff também parava constantemente, então pesquisando encontrei uma solução: substituir algumas linhas nos arquivos msn_conntrack.cpp e util.cpp. Como não lembro qual parte deve ser substituída, aí vão os arquivos: (Vale lembrar que o programa deve ser recompilado)
msn_conntrack.cpp
/* THE CODE HERE TAKES CARE OF KEEPING TRACKING OF THE INFORMATION WE
   COLLECT ABOUT ONGOING TCP CONNECTIONS */
#include "imsniff.h"
   
struct msn_connection *msn_conns_first = NULL;
struct msn_connection *msn_conns_last = NULL;
void add_user_to_sb (struct msn_connection *conn, u_char *user)
{
	if (conn!=NULL && conn->users!=NULL)
	{
		int i=0;
		while (i<conn->num_users)
		{
			if (strcmp ((char *) conn->users[i], (char *) user)==0)
				return; // Don't duplicate
			i++;
		}
	}
	log_debug (5, "Adding user [%s] to SB",user);
	if (!conn) 
		{
			conn = (struct msn_connection *) malloc (sizeof (struct msn_connection));
	if (!conn)
		return;
	if (msn_conns_first==NULL)
		msn_conns_first=conn;
	memset (conn,0,sizeof (struct msn_connection)); // All zeros is fine
	if (msn_conns_last != NULL)
	{
		msn_conns_last->next=conn;
		conn->previous=msn_conns_last;
	}
	msn_conns_last=conn;
	conn->users=NULL;
	conn->num_users=0;
	conn->log_full_path=NULL;
	}
	conn->users=(u_char **) realloc (conn->users, sizeof (u_char *) * (conn->num_users+1));
	log_debug (5, "Done realloc");
	if (conn->users!=NULL)
	{
		conn->users[conn->num_users]=(u_char *) malloc (strlen ((char *) user) +1 );
		log_debug (5, "Done malloc");	
		strcpy ((char *) conn->users[conn->num_users],(char *) user);
		log_debug (5, "Done strcpy");		
		conn->num_users++;
	}
	log_debug (5, "Done, number of users now = %d",conn->num_users);
}
void clear_msn_connection (struct msn_connection *conn)
{
	log_debug (3, "Clearing connection %d.%d.%d.%d:%d -> %d.%d.%d.%d:%d",
		conn->IP_A.byte1,conn->IP_A.byte2,conn->IP_A.byte3,conn->IP_A.byte4,
			conn->port_A, conn->IP_B.byte1,
			conn->IP_B.byte2,conn->IP_B.byte3,conn->IP_B.byte4,conn->port_B);	
	if (conn->owner!=NULL)
	{
		free (conn->owner);
		conn->owner=NULL;
	}
	conn->conn_type=type_unknown;
	if (conn->users!=NULL)
	{
		int i=0;
		while (i<conn->num_users)
		{
			free (conn->users[i]);
			i++;
		}
		free (conn->users);
		conn->num_users=0;
	}
	if (conn->pending_A!=NULL)
		free (conn->pending_A);
	if (conn->pending_B!=NULL)
		free (conn->pending_B);
	if (conn->log_full_path!=NULL)
		free (conn->log_full_path);
	conn->pending_A_length=0;
	conn->pending_B_length=0;
	conn->pending_A=NULL;
	conn->pending_B=NULL;		
	conn->log_full_path=NULL;
	conn->whowserver=unknown;
	
}
void set_owner (struct msn_connection *conn, u_char *owner)
{
	if (conn==NULL || owner==NULL)
	{
		log_debug (0, "Entry in set_owner() with NULL parameter(s)");
		return;
	}
	log_debug (5, "Setting owner [%s] to connection %d.%d.%d.%d:%d -> %d.%d.%d.%d:%d",
		owner, conn->IP_A.byte1,conn->IP_A.byte2,conn->IP_A.byte3,conn->IP_A.byte4,
			conn->port_A, conn->IP_B.byte1,
			conn->IP_B.byte2,conn->IP_B.byte3,conn->IP_B.byte4,conn->port_B);
	
	if (conn->owner != NULL)
	{
		if (strcmp ((char *) conn->owner, (char *) owner))
		{
			log_debug (0, "Warning: Owner change in MSN connection, this looks like a bug");
		}
		else
		{
			log_debug (5, "set_owner(): Owner match, all OK");
		}
	}
	else
	{
		log_debug (5, "(no previous owner)");
	}
	strcpymalloc (&conn->owner, owner);
}
int is_from_A (struct msn_connection *conn, ip_address *ip, int port)
{
	if (conn==NULL)
		return -1;
	if (conn->IP_A.byte1 == ip->byte1 &&
		conn->IP_A.byte2 == ip->byte2 &&
		conn->IP_A.byte3 == ip->byte3 &&
		conn->IP_A.byte4 == ip->byte4 &&
		conn->port_A == port)
	{
			return 1;
	}
	if (conn->IP_B.byte1 == ip->byte1 &&
		conn->IP_B.byte2 == ip->byte2 &&
		conn->IP_B.byte3 == ip->byte3 &&
		conn->IP_B.byte4 == ip->byte4 &&
		conn->port_B == port)
	{
			return 0;
	}
	return -1; // Not from any of them */
	
}
int is_from_server (struct msn_connection *conn, ip_address *ip, int port)
{
	if (conn==NULL)
		return -1;
	if (conn->IP_A.byte1 == ip->byte1 &&
		conn->IP_A.byte2 == ip->byte2 &&
		conn->IP_A.byte3 == ip->byte3 &&
		conn->IP_A.byte4 == ip->byte4 &&
		conn->port_A == port)
	{
		if (conn->whowserver==endpointA)
			return 1;
		else 
			return 0;
	}
	if (conn->IP_B.byte1 == ip->byte1 &&
		conn->IP_B.byte2 == ip->byte2 &&
		conn->IP_B.byte3 == ip->byte3 &&
		conn->IP_B.byte4 == ip->byte4 &&
		conn->port_B == port)
	{
		if (conn->whowserver==endpointB)
			return 1;
		else 
			return 0;
	}
	return -1; // Not server and not user?		
}
void set_as_server (struct msn_connection *conn, ip_address *ip, int port)
{
	if (conn==NULL)
		return;
		
	if (conn->IP_A.byte1 == ip->byte1 &&
		conn->IP_A.byte2 == ip->byte2 &&
		conn->IP_A.byte3 == ip->byte3 &&
		conn->IP_A.byte4 == ip->byte4 &&
		conn->port_A == port)
	{
		if (conn->whowserver==endpointB)
		{
			log_debug (0, "Warning: In this connection, the server was previously misidentified");
		}
		conn->whowserver=endpointA;
	}	
	else
	{
		if (conn->whowserver==endpointA)
		{
			log_debug (0, "Warning: In this connection, the server was previously misidentified");
		}
		conn->whowserver=endpointB;
	}
}
int remove_msn_connection (struct msn_connection *conn)
{
	if (conn)
	{
		log_debug (5, "Removing connection from linked list");
		clear_msn_connection (conn);
		if (conn->previous!=NULL)
			conn->previous->next=conn->next;
		if (conn->next!=NULL)
			conn->next->previous=conn->previous;
		if (msn_conns_first == conn)
			msn_conns_first = conn->next;
		if (msn_conns_last == conn)
			msn_conns_last = conn->previous;
		free (conn);
	}
	return 0;
}
struct msn_connection *get_or_create_msn_connection (ip_address *source_ip, int source_port, 
	ip_address *target_ip, int target_port,
	enum e_msn_conn_create create)
{
	struct msn_connection * ipa = msn_conns_first;
	log_debug (5,"get_or_create_msn_connection: %d.%d.%d.%d:%d -> %d.%d.%d.%d:%d",
			source_ip->byte1,source_ip->byte2,source_ip->byte3,source_ip->byte4,source_port,
			target_ip->byte1,target_ip->byte2,target_ip->byte3,target_ip->byte4,target_port);	
	
	int i=0;
	while (ipa)
	{		
		log_debug (6,"%d - IPA: %d.%d.%d.%d:%d -> %d.%d.%d.%d:%d",i,
			ipa->IP_A.byte1,ipa->IP_A.byte2,ipa->IP_A.byte3,ipa->IP_A.byte4,ipa->port_A,
			ipa->IP_B.byte1,ipa->IP_B.byte2,ipa->IP_B.byte3,ipa->IP_B.byte4,ipa->port_B);
		if ((ipa->IP_A.byte1 == source_ip->byte1 &&
			ipa->IP_A.byte2 == source_ip->byte2 &&
			ipa->IP_A.byte3 == source_ip->byte3 &&
			ipa->IP_A.byte4 == source_ip->byte4 &&
			ipa->port_A == source_port &&
			ipa->IP_B.byte1 == target_ip->byte1 &&
			ipa->IP_B.byte2 == target_ip->byte2 &&
			ipa->IP_B.byte3 == target_ip->byte3 &&
			ipa->IP_B.byte4 == target_ip->byte4 &&
			ipa->port_B == target_port) ||
			(ipa->IP_A.byte1 == target_ip->byte1 &&
			ipa->IP_A.byte2 == target_ip->byte2 &&
			ipa->IP_A.byte3 == target_ip->byte3 &&
			ipa->IP_A.byte4 == target_ip->byte4 &&
			ipa->port_A == target_port &&
			ipa->IP_B.byte1 == source_ip->byte1 &&
			ipa->IP_B.byte2 == source_ip->byte2 &&
			ipa->IP_B.byte3 == source_ip->byte3 &&
			ipa->IP_B.byte4 == source_ip->byte4 &&
			ipa->port_B == source_port))
		{
			log_debug (6, "Match");
			if (create==create_replace)
				clear_msn_connection(ipa);
			log_debug (5, "Connection requested found");
			return ipa;
		}
		else
		{
			log_debug (5, "No match");
		}
		i++;
		ipa=ipa->next;
	}
	if (create==create_yes)
	{
		struct msn_connection * ipa = (struct msn_connection *) malloc (sizeof (struct msn_connection));
		log_debug (5, "Creating new connection, %d", i);
		if (ipa!=NULL)
		{
			if (msn_conns_first==NULL)
				msn_conns_first=ipa;
		
			memset (ipa,0,sizeof (struct msn_connection)); // All zeros is fine
			if (msn_conns_last != NULL)
			{
				msn_conns_last->next=ipa;
				ipa->previous=msn_conns_last;
			}
			msn_conns_last=ipa;
			memcpy (&ipa->IP_A,source_ip,sizeof (struct ip_address));
			ipa->port_A=source_port;
			memcpy (&ipa->IP_B,target_ip,sizeof (struct ip_address));
			ipa->port_B=target_port;				
			ipa->whowserver=unknown;
			ipa->num_users=0;
			ipa->users=NULL;
			ipa->log_full_path=NULL;
			return ipa;			
		}
		
	}
	return NULL;
}
util.cpp
#include "imsniff.h"
#include <stdarg.h>
#include <time.h>
#include <ctype.h>
int debug_level = 2;
char *gettimestring4log (char *store)
{
	time_t now=time (NULL);
#ifdef WIN32
	struct tm *stm;
	stm = localtime (&now);
	strncpy (store, asctime(stm), 24);
#else	
	struct tm stm;
	localtime_r (&now, &stm);
	asctime_r (&stm, store);
#endif
	store[24]=0;
	return store;
}
int createdir4nick (u_char *nick)
{
	if (nick && nick[0])
	{
		char dir[1024];
		strcpy (dir, chatlogdir);
		if (dir[strlen (dir)-1]!='/')
			strcat (dir,"/");
		strcat (dir,(char *) nick);
#ifdef WIN32
		mkdir (dir);
#else
		mkdir (dir,0755);
#endif
	}
	return 0;
}
int log_switchboard_end (struct msn_connection *conn)
{
	if (conn!=NULL && conn->log_full_path!=NULL)
	{
		FILE *o=fopen (conn->log_full_path, "a+t");
		if (o!=NULL)
		{
			fprintf (o, "*********************  CHAT END  *************************\n");
			fclose (o);
		}
	}
	return 0;
}
int log_switchboard_event (struct msn_connection *conn, const char *fmt, ...)
{
	char strtme[27];
	char *result;
	int firsttime = 0;
	if (conn == NULL || conn->owner == NULL)
	{
		log_debug (0, "No switchboard or unknown owner, can't log");
		return -1;
	}
	if (conn->log_full_path==NULL && chatlogdir[0]!=0) 
	{
		if (conn->users==NULL || conn->users[0]==NULL)
		{
			log_debug (0, "No known partipants in SB owned by %s, can't log", conn->owner);
			return -1;
		}
		size_t l=strlen (chatlogdir)+1+strlen ((char *) conn->owner)+1+
			strlen ((char *) conn->users[0])+5;
		conn->log_full_path=(char *) malloc (l);
		if (conn->log_full_path==NULL)
			return -1;
		sprintf (conn->log_full_path,"%s/%s/%s.txt",chatlogdir,conn->owner,conn->users[0]);
		log_debug (0, "Set SB log name to: %s",conn->log_full_path);
		firsttime = 1;
	}
	gettimestring4log (strtme);
	va_list ap;	
#ifdef WIN32
	result=(char *) malloc (MAX_VPRINTF);
	if (result)
	{
		 va_start(ap, fmt);
		 vsnprintf (result, MAX_VPRINTF, fmt, ap);
		 va_end (ap);
	}
#else
	va_start (ap, fmt);
	vasprintf (&result,fmt,ap);
	va_end (ap);
#endif	
	if (conn->log_full_path!=NULL)
	{
		FILE *o=fopen (conn->log_full_path, "a+t");
		if (o!=NULL)
		{
			if (firsttime)
				fprintf (o, "********************* CHAT START *************************\n");
			fprintf (o, "%s | %s\n", strtme, result);
			fclose (o);
		}
		else
		{
			log_debug (0, "Failed to create/append SB event file at [%s]", conn->log_full_path);
		}
	}
	else
	{
		log_debug (0, "SB event: %s", result);
	}
	free (result);
	
	return 0;
}
int delete_profile (u_char *nick)
{			
	if (nick && nick[0]!=0 && chatlogdir[0]!=0)
	{
		log_debug (3, "Deleting profile [%s]", nick);
		char fn[1024];
		sprintf (fn, "%s/%s/profile.txt", chatlogdir, nick);
		unlink (fn);
	}
	return 0;
}
int delete_contact_list (u_char *nick)
{			
	if (nick && nick[0]!=0 && chatlogdir[0]!=0)
	{
		log_debug (3, "Deleting contact list for [%s]", nick);
		char fn[1024];
		sprintf (fn, "%s/%s/contact_list.txt", chatlogdir, nick);
		unlink (fn);
	}
	return 0;
}
int log_profile (u_char *nick, u_char *payload, int length)
{
	char strtme[27];
	gettimestring4log (strtme);
	log_debug (5, "Entry in log_profile");
	if (nick && nick[0]==0)
		log_debug (3, "Profile for an unknown user, not logged");
	else	
	{
		u_char *prof = (u_char *) malloc (length + 1);
		if (prof == NULL)
			return OUT_OF_MEMORY;
			
		memcpy (prof, payload, length);
		prof[length]=0;
		
		if (chatlogdir[0]==0)
		{
			log_debug (1, "%s | %s | %s", strtme, nick, prof);
		}
		else
		{
			createdir4nick (nick);
			char fn[1024];
			sprintf (fn, "%s/%s/profile.txt", chatlogdir, nick);
			FILE *o=fopen (fn, "w");
			// printf ("%s\n",fn);
			if (o!=NULL)
			{
				fwrite (prof, 1, length, o);
				fclose (o);
			}
			else
			{
				log_debug (0, "Failed to create profile file [%s]", fn);
			}
		}
		free (prof);	
	}
	return 0;
}
int log_contact (u_char *nick, u_char *contact)
{
	char strtme[27];
	gettimestring4log (strtme);
	log_debug (5, "Entry in log_contact");
	if (nick && nick[0]==0)
		log_debug (3, "Contact [%s] for an unknown user, not logged", contact);
	else	
	{
		if (chatlogdir[0]==0)
		{
			log_debug (1, "%s | %s | Contact: %s", strtme, nick, contact);
		}
		else
		{
			createdir4nick (nick);
			char fn[1024];
			sprintf (fn, "%s/%s/contact_list.txt", chatlogdir, nick);
			FILE *o=fopen (fn, "a+t");
			// printf ("%s\n",fn);
			if (o!=NULL)
			{
				fprintf (o, "%s | %s\n", strtme, contact);
				fclose (o);
			}
			else
			{
				log_debug (0, "Failed to create contact file [%s]", fn);
			}
		}		
	}
	return 0;
}
int log_debug (int level, const char *fmt, ...)
{
	char *result;
	char strtme[27];
	if (level<=debug_level)
	{
		gettimestring4log (strtme);
		va_list ap;
#ifdef WIN32
	result=(char *) malloc (MAX_VPRINTF);
	if (result)
	{
		 va_start(ap, fmt);
		 vsnprintf (result, MAX_VPRINTF, fmt, ap);
		 va_end (ap);
	}
#else
		va_start (ap, fmt);
		vasprintf (&result,fmt,ap);
		va_end (ap);
#endif
		if (debuglogdir[0]==0)
		{
			if (!daemonize)
				printf ("%s | %d | %s\n", strtme, level, result);
		}
		else
		{
			char fn[1024];
			time_t now=time (NULL);
#ifdef WIN32
			struct tm *stm;
			stm= localtime (&now);
			sprintf (fn, "%s/imsniff_%04d-%02d-%02d.txt", debuglogdir, stm->tm_year, stm->tm_mon, stm->tm_mday);
#else
			struct tm stm;
			localtime_r (&now, &stm);
			sprintf (fn, "%s/imsniff_%04d-%02d-%02d.txt", debuglogdir, stm.tm_year, stm.tm_mon, stm.tm_mday);
#endif
			FILE *o=fopen (fn, "a+t");
			if (o!=NULL)
			{
				fprintf (o, "%s | %d | %s\n", strtme, level, result);
				fclose (o);
			}
		}
		free (result);
	}
	return 0;
}
int log_event (u_char *nick, const char *fmt, ...)
{
	char *result;
	va_list ap;
	char strtme[27];
#ifdef WIN32
	result=(char *) malloc (MAX_VPRINTF);
	if (result)
	{
		 va_start(ap, fmt);
		 vsnprintf (result, MAX_VPRINTF, fmt, ap);
		 va_end (ap);
	}
#else
	va_start (ap, fmt);
	vasprintf (&result,fmt,ap);
	va_end (ap);
#endif
	gettimestring4log (strtme);
	if (nick==NULL || nick[0]==0)
		log_debug (1, "Event for an unknown nick: %s", result);
	else
	{
		if (chatlogdir[0]==0)
		{
			log_debug (1, "Nick [%s] Event: [%s]", nick, result);
		}
		else
		{
			createdir4nick (nick);
			char fn[1024];
			sprintf (fn, "%s/%s/events.txt", chatlogdir, nick);
			FILE *o=fopen (fn, "a+t");
			// printf ("%s\n",fn);
			if (o!=NULL)
			{
				fprintf (o, "%s | %s\n", strtme, result);
				fclose (o);
			}
		
		}
	}
	
	free (result);
	return 0;
}
int get_new_line_malloc (u_char **target, u_char *source, int length)
{
		int must_free=0;		
		if (length<2) // No room for \r\n
		{
			log_debug (5, "get_new_line_malloc: line too short.");
			return LINE_INCOMPLETE;
		}		
		if (target!=NULL) 
		{
			if (*target != NULL)
				free (*target);
			*target = (u_char *) malloc (length + 1);
			if (*target == NULL)
				return OUT_OF_MEMORY;
			memset (*target, 0, length+1);
			
		}
	
		u_char *now = source; // Where we are copying from 
		u_char *work = (target==NULL)?NULL:*target; // Where, if anywhere, we are copying to 
		int skipped=0;
		while (skipped<length-2 && *now!='\n' && *now!='\r')
		{		
			if (work!=NULL && *now>=' ')
			{
				*work=*now;
				*work++;
			}
			skipped++;
			*now++;
		}			
		if ( *(now)!='\r' || *(now+1)!='\n') // No \r\n? Not MSN or incomplete
		{
			log_debug (5, "get_new_line_malloc: Incomplete\n");
			log_debug (5, "get_new_line_malloc: Source was: %s\n",source); // TODO: Fix not null-terminated! 
			return -1;
		}
		return skipped+2; // Skip \r\n too
}
/* Note: *line must be zero-terminated (as returned by get_new_line_malloc) */
void dump_tokens (u_char **tokens)
{
	if (tokens==NULL)
		return;
	int i=0;
	while (tokens[i]!=NULL)
	{
		log_debug (0, "Token %d: %s",i, tokens[i]);
		i++;
	}
}
u_char *strcpymalloc (u_char **target, u_char * src)
{
	if (target==NULL)
		return NULL;
	if (*target!=NULL)
		free (*target);
	*target=(u_char *) malloc (strlen ((char *) src)+1);
	if (*target!=NULL)
	{
		strcpy ((char *) *target,(char *) src);
	}
	return *target;
}
void free_array (u_char ***tokens)
{
	if (*tokens!=NULL)
	{
		int i=0;
		while ((*tokens)[i]!=NULL)
		{
			free ((*tokens)[i]);
			i++;
		}
		/* ...free the array itself */
		free (*tokens);
	}
}
int get_tokens (u_char *line, u_char ***tokens, int max_tokens)
{
	log_debug (5, "entry in get_tokens");
	int capacity = (max_tokens==0)?50:max_tokens; 
	/* First, delete the tokens if there are any ... */
	free_array(tokens);
	*tokens=(u_char **) malloc (sizeof (u_char *) * (capacity +1)); // Final one is NULL
	if (*tokens==NULL)
		return OUT_OF_MEMORY;
	int num=0; /* Number of tokens added so far */	
	u_char *now = line;
	u_char *newtoken; 
	for (;;)
	{
		size_t i;
		/* Skip spaces and control stuff */
		while (*now<=' ' && *now!=0)
		{
			now++;
		}
					
		if (*now==0) /* End of line */
			break; 
			
		i=0;
		if (max_tokens==num+1 && max_tokens!=0) 
			i=strlen ((char *) now);
		else
		{
			while (now[i]>' ') /* Look ahead, how long is the next token? */
				i++;
		}
		newtoken=(u_char *) malloc (i+1);
		memcpy (newtoken, now, i);
		now = now + i;
		newtoken[i]=0;
		if (num==capacity)
		{
			capacity += 10;
			*tokens = (u_char **) realloc (*tokens, sizeof (u_char *) * (capacity +1));
			if (*tokens==NULL) /* A bit unstable now I'm afraid */
				return OUT_OF_MEMORY;
		}
		(*tokens)[num]=newtoken;
		if (num==7)
		{
			break;
		}
		num++;
	}
	(*tokens)[num]=NULL;
	return num;
}
int get_value_from_hex (char c)
{
	c=toupper (c);
	if (c>='0' && c<='9')
		return c-'0';
	if (c>='A' && c<='F')
		return c-'A';
	return -1;
}
u_char *urldecode (u_char *src)
{
	u_char *tmp = (u_char *) malloc (strlen ((char *) src) + 1);
	u_char *c = src;
	if (tmp==NULL)
		return src;
	memset (tmp, 0, strlen ((char *) src) +1);
	u_char *now = tmp;	
	while (*c)
	{
		if (*c!='%')
		{
			*now = *c;
			now++;
			c++;
		}
		else
		{
			if (*(c+1)==0 || *(c+2)==0) // ?? Doesn't look good.
			{
				free (tmp);
				return src;
			}
			int v1 = get_value_from_hex (* (c+1));
			int v2 = get_value_from_hex (* (c+2));
			if (v1==-1 || v2==-1)
			{
				free (tmp);
				return src;
			}
			*now = (v1*16+v2);
			now++;
			c+=3;
		}
	}
	strcpy ((char *) src, (char *) tmp);
	free (tmp);
	return src;
}