CVE:CVE-2009-2694
CNNVD:CNNVD-200908-297
Pidgin是一款跨平台的实时通信客户端，它支持多个常用的实时通信协议，用户可用同一个软件登录不同的实时通信服务。 
Pidgin和其他一些即时消息客户端所使用的Libpurple库中存在内存破坏漏洞，远程攻击者可以通过向聊天客户端发送特制的MSNSLP报文触发这个漏洞，导致执行任意代码。
攻击需要发送两个连续的MSNSLP消息，第一个用于对slpmsg存储会话id，第二个用于触发漏洞，最终目标是到达msn_slplink_process_msg()中的memcpy()调用。需要创建偏移为非0的MSNSLP消息，因为这个值是memcpy()的目标。
因为偏移非0，所以在调用msn_slplink_message_find()返回NULL时会出现第一个问题：
/-----------
if (offset == 0)
{
 .. construct a new slpmsg ..
}
else
{
 slpmsg = msn_slplink_message_find(slplink，
msg->msnslp_header.session_id， msg->msnslp_header.id);
}
if (slpmsg == NULL)
{
 /* Probably the transfer was canceled */
 purple_debug_error("msn"， "Couldn't find slpmsg\n");
 return;
}
- -----------/
因此，slpmsg必须为非空，这就是为什么需要发送两次消息才能进行攻击。发送的第一个MSNSLP消息偏移为0，用于创建slpmsg对象，Libpurple会存储这个对象；第二个MSNSLP消息的偏移非0，但由于Libpurple已经存储了第一个MSNSLP消息，因此调用msn_slplink_message_find()会有效的返回之前的对象而不是NULL：
/-----------
if (slpmsg->fp)
{
 /* fseek(slpmsg->fp， offset， SEEK_SET); */
 len = fwrite(data， 1， len， slpmsg->fp);
}
else if (slpmsg->size)
{
 if (G_MAXSIZE - len < offset || (offset='' + len='') > slpmsg->size)
 {
  purple_debug_error("msn"，
   "Oversized slpmsg - msgsize=%lld offset=%" G_GSIZE_FORMAT "
len=%" G_GSIZE_FORMAT "\n"，
   slpmsg->size， offset， len);
  g_return_if_reached();
 }
 else
  memcpy(slpmsg->buffer + offset， data， len);
 }
- -----------/
例如，如果创建的第一个MSNSLP消息大小为0x01ffffff，第二个消息的偏移为小于0x01ffffff - len的任意值，就满足了任意写入的条件。
最后，以小于0x01ffffff - len的任意偏移值到达了memcpy()，缓冲区指向0。这意味着可以向低于0x01ffffff - len的任意位置写入数据内容。
solution:Upgrade adium adium to a higher version than 1.3.5,1.2.7,1.3,1.3.1,1.3.2,1.3.3,1.3.4,and avoid the version (,1.3.5],1.2.7,1.3,1.3.1,1.3.2,1.3.3,1.3.4; Upgrade pidgin pidgin to a higher version than 2.5.8,2.0.0,2.0.1,2.0.2,2.1.0,2.1.1,2.2.0,2.2.1,2.2.2,2.3.0,2.3.1,2.4.0,2.4.1,2.4.2,2.4.3,2.5.0,2.5.1,2.5.2,2.5.3,2.5.4,2.5.6,2.5.7,and avoid the version (,2.5.8],2.0.0,2.0.1,2.0.2,2.1.0,2.1.1,2.2.0,2.2.1,2.2.2,2.3.0,2.3.1,2.4.0,2.4.1,2.4.2,2.4.3,2.5.0,2.5.1,2.5.2,2.5.3,2.5.4,2.5.6,2.5.7