软件下载 https://pc.qq.com/detail/19/detail_25499.html
软件设置保存在注册表 HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\khealtheye
护眼原理 原理是利用 SetDeviceGammaRamp 函数设置色温 关键位置在keyeprotect.dll文件中,关键函数 sub_100A8C10 IDA静态分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 char __usercall sub_100A8C10@<al>(unsigned __int16 per@<ax>, int context@<ecx>, int healthMode@<edi>){ int v3; unsigned __int16 blueStep; unsigned __int16 v5; double multiplier; double v7; unsigned __int16 v8; int redStep; WORD redStepa; WORD greenStep; switch ( healthMode ) { case 0 : v3 = per; redStep = *(_DWORD *)(context + 20 ); blueStep = *(_WORD *)(context + 24 ); v5 = (signed int )((double )per * 1.28 ); goto LABEL_10; case 1 : v3 = per; multiplier = (double )per; v7 = 0.4 * multiplier + 88.0 ; v8 = (signed int )v7; redStepa = (signed int )v7; if ( v8 < 88u ) redStepa = 88 ; greenStep = (signed int )v7; if ( v8 < 88u ) greenStep = 88 ; SetGamma ((_DWORD *)context, redStepa, greenStep, (signed int )(multiplier * 1.28 )); goto LABEL_11; case 2 : v3 = per; v5 = (signed int )((double )per * 1.28 ); break ; case 3 : v3 = per; v5 = (signed int )((double )per * 1.28 ); break ; } LOWORD (redStep) = v5; HIWORD (redStep) = v5; LABEL_10: SetGamma ((_DWORD *)context, redStep, HIWORD (redStep), v5); LABEL_11: sub_100A4AE0 (healthMode); sub_100A4AE0 (v3); return 1 ; }
得出设置公式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 enum class HealthMode { Smart, Office, Movie, Game }; bool SetGamma (double redStep, double greenStep, double blueStep) { auto success = false ; HDC hDevice = ::GetDC (nullptr ); if (hDevice) { WORD ramp[3 ][256 ]; for (auto i = 0 ; i < 256 ; ++i) { const auto r = i * (redStep + 128 ); const auto g = i * (greenStep + 128 ); const auto b = i * (blueStep + 128 ); ramp[0 ][i] = (WORD)(min (0xFFFF , r)); ramp[1 ][i] = (WORD)(min (0xFFFF , g)); ramp[2 ][i] = (WORD)(min (0xFFFF , b)); } success = ::SetDeviceGammaRamp (hDevice, ramp); ::ReleaseDC (nullptr , hDevice); } return success; } bool EyeProtect (double brightness, HealthMode mode) { auto success = false ; const auto multiplier = brightness; double r = 0 ; double g = 0 ; double b = std::round (multiplier * 1.28 ); switch (mode) { case HealthMode::Smart: r = g = 128 ; break ; case HealthMode::Office: r = g = max (88 , 0.4 * multiplier + 88.0 ); break ; case HealthMode::Movie: case HealthMode::Game: r = g = b; break ; } success = SetGamma (r, g, b); return success; }
任何模式下将亮度设置为100都会变为系统默认值,等同于关闭护眼功能。 其中影视模式和游戏模式的公式是同一个,效果相同。
智能模式默认亮度为75% 办公模式默认亮度为30% 影视模式默认亮度为59% 游戏模式默认亮度为78%
配置文件解密 data目录下有部分.dat文件,是xml加密后的数据。 解密方法就是去掉头4字节,就是字符串”.tmp”,然后把余下的数据与0xD8异或,最后从末尾搜索0xFDFDFDFD,找到并删除其之后的数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 #define WIN32_LEAN_AND_MEAN #include <Windows.h> #include <iostream> #include <fstream> #include <string> #include <memory> #include <filesystem> namespace fs = std::filesystem;std::string Decrypt (char * pData, int size) { std::string s; for (auto i = 0 ; i < size; ++i) { pData[i] ^= 0xD8 ; } return s; } int main () { auto dir = fs::current_path (); auto iter = fs::recursive_directory_iterator (dir); auto end = fs::recursive_directory_iterator (); while (iter != end) { if (fs::is_regular_file (*iter)) { auto path = iter->path (); if (path.extension () == ".dat" ) { std::ifstream in (path, std::ios::binary | std::ios::ate) ; if (in.is_open ()) { auto size = in.tellg (); in.seekg (0 , std::ios::beg); auto buf = std::make_unique <char []>(size); auto p = buf.get (); in.read (p, size); if (_strnicmp(p, ".tmp" , 4 ) == 0 ) { p += 4 ; Decrypt (p, (int )size - 4 ); std::ofstream out ("out.xml" , std::ios::binary | std::ios::trunc) ; if (out.is_open ()) { out << p; out.close (); } } in.close (); } } } iter++; } }