一秒钟让windows pc端微信开启自杀模式,理论支持windows的全平台以及所有版本
操作方法:
打开wechat.exe,甚至不需要登陆
只需要将鼠标放置于右下角,右键点击调整时间
手动将时间2038年以后
即可触发pc端wechat.exe进程超高cpu占比
如下通过任务管理器可查看到其cpu占比
我们对其原因进行分析:
研究了下,对GetSystemTimeAsFileTime进行下断,发现在获取时间的时候、
对于溢出的情况下,将结构体中的第一个变量赋值为0了
导致boost得到的时间有关逻辑错误
线程的wait失效
进一步通过mars库进行分析分析:
发现在实现条件变量condition的相关代码中
其wait的实现逻辑采用了boost::get_system_time()等函数去获取时间
在create_time[marsboostdate_time microsec_time_clock.hpp]去获取有关本机时间的时候
static time_type create_time(time_converter converter)
{
#ifdef BOOST_HAS_GETTIMEOFDAY
timeval tv;
gettimeofday(&tv, 0); //gettimeofday does not support TZ adjust on Linux.
std::time_t t = tv.tv_sec;
boost::uint32_t sub_sec = tv.tv_usec;
#elif defined(BOOST_HAS_FTIME)
winapi::file_time ft;
winapi::get_system_time_as_file_time(ft);
uint64_t micros = winapi::file_time_to_microseconds(ft); // it will not wrap, since ft is the current time
// and cannot be before 1970-Jan-01
std::time_t t = static_cast<std::time_t>(micros / 1000000UL); // seconds since epoch
// microseconds -- static casts suppress warnings
mars_boost::uint32_t sub_sec = static_cast<mars_boost::uint32_t>(micros % 1000000UL);
#else
#error Internal Boost.DateTime error: BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK is defined, however neither gettimeofday nor FILETIME support is detected.
#endif
std::tm curr;
std::tm* curr_ptr = converter(&t, &curr);
date_type d(static_cast< typename date_type::year_type::value_type >(curr_ptr->tm_year + 1900),
static_cast< typename date_type::month_type::value_type >(curr_ptr->tm_mon + 1),
static_cast< typename date_type::day_type::value_type >(curr_ptr->tm_mday));
//The following line will adjust the fractional second tick in terms
//of the current time system. For example, if the time system
//doesn't support fractional seconds then res_adjust returns 0
//and all the fractional seconds return 0.
int adjust = static_cast< int >(resolution_traits_type::res_adjust() / 1000000);
time_duration_type td(static_cast< typename time_duration_type::hour_type >(curr_ptr->tm_hour),
static_cast< typename time_duration_type::min_type >(curr_ptr->tm_min),
static_cast< typename time_duration_type::sec_type >(curr_ptr->tm_sec),
sub_sec * adjust);
return time_type(d,td);
}
走到了BOOST_HAS_GETTIMEOFDAY的代码逻辑里面
原因是未注意其boost库在windows端的有关配置
以及日志库appender.cc为了跨平台操作,采用了结构体timeval + gettimeofday自实现[marscommwindowssystime.c]的方法使其编译可正常通过
int gettimeofday(struct timeval *tv, struct timezone *tz)
{
FILETIME ft;
unsigned __int64 tmpres = 0;
static int tzflag;
if (NULL != tv)
{
GetSystemTimeAsFileTime(&ft);
tmpres |= ft.dwHighDateTime;
tmpres <<= 32;
tmpres |= ft.dwLowDateTime;
/*converting file time to unix epoch*/
tmpres /= 10; /*convert into microseconds*/
tmpres -= DELTA_EPOCH_IN_MICROSECS;
tv->tv_sec = ((long)(tmpres / 1000000UL)<0 ? 0 : (long)(tmpres / 1000000UL)); // 注意这里
tv->tv_usec = (long)(tmpres % 1000000UL);
}
if (NULL != tz)
{
if (!tzflag)
{
tzset();
tzflag++;
}
tz->tz_minuteswest = _timezone / 60;
tz->tz_dsttime = _daylight;
}
return 0;
}
但如果我们将windows 本机时间变成2038年以后
由于微软所提供的头文件struct timeval里面的tv_sec为4字节,使得tv->tvsec=0
从而导致线程中cond.wait相关功能失效,相当于没有sleep,从而导致cpu高
以及日志库不正常
需要修改
#ifndef WIN32
#define BOOST_HAS_GETTIMEOFDAY
#endif
[mars\boost\config\user.php]
并更新boost库(过于老,而且也存在2038相关逻辑错误)以及建议日志库不使用 timeval 因为这种情况下会导致日志名始终为MM_19700101.xlog以及日志库里时间不正常