3838#include < cstdio>
3939#include < iostream>
4040#include < memory>
41+ #include < algorithm>
4142#include < stdexcept>
4243#include < string>
4344#include < array>
@@ -78,6 +79,7 @@ void integrity_check();
7879void integrity_watchdog ();
7980std::string extract_host (const std::string& url);
8081bool hosts_override_present (const std::string& host);
82+ bool module_paths_ok ();
8183std::string seed;
8284void cleanUpSeedData (const std::string& seed);
8385std::string signature;
@@ -88,6 +90,7 @@ bool KeyAuth::api::debug = false;
8890std::atomic<bool > LoggedIn (false );
8991std::atomic<long long > last_integrity_check{ 0 };
9092std::atomic<int > integrity_fail_streak{ 0 };
93+ std::atomic<long long > last_module_check{ 0 };
9194
9295void KeyAuth::api::init ()
9396{
@@ -1628,10 +1631,11 @@ int VerifyPayload(std::string signature, std::string timestamp, std::string body
16281631 long long current_unix_time = std::chrono::duration_cast<std::chrono::seconds>(
16291632 current_time.time_since_epoch ()).count ();
16301633
1631- if (current_unix_time - unix_timestamp > 20 ) {
1632- std::cerr << " [ERROR] Timestamp too old (diff = "
1633- << (current_unix_time - unix_timestamp) << " s)\n " ;
1634- MessageBoxA (0 , " Signature verification failed (timestamp too old)" , " KeyAuth" , MB_ICONERROR);
1634+ const long long diff = std::llabs (current_unix_time - unix_timestamp);
1635+ if (diff > 120 ) {
1636+ std::cerr << " [ERROR] Timestamp too skewed (diff = "
1637+ << diff << " s)\n " ;
1638+ MessageBoxA (0 , " Signature verification failed (timestamp skew)" , " KeyAuth" , MB_ICONERROR);
16351639 exit (3 );
16361640 }
16371641
@@ -1762,6 +1766,35 @@ bool hosts_override_present(const std::string& host)
17621766 return false ;
17631767}
17641768
1769+ static std::wstring to_lower_ws (std::wstring value)
1770+ {
1771+ std::transform (value.begin (), value.end (), value.begin (),
1772+ [](wchar_t c) { return static_cast <wchar_t >(towlower (c)); });
1773+ return value;
1774+ }
1775+
1776+ bool module_paths_ok ()
1777+ {
1778+ const wchar_t * kModules [] = { L" ntdll.dll" , L" kernel32.dll" , L" kernelbase.dll" , L" user32.dll" };
1779+ const wchar_t * sysroot_env = _wgetenv (L" SystemRoot" );
1780+ std::wstring sysroot = sysroot_env ? sysroot_env : L" C:\\ Windows" ;
1781+ std::wstring sys32 = to_lower_ws (sysroot + L" \\ System32\\ " );
1782+ std::wstring syswow = to_lower_ws (sysroot + L" \\ SysWOW64\\ " );
1783+
1784+ for (const auto * name : kModules ) {
1785+ HMODULE mod = GetModuleHandleW (name);
1786+ if (!mod)
1787+ continue ;
1788+ wchar_t path[MAX_PATH] = {};
1789+ if (!GetModuleFileNameW (mod, path, MAX_PATH))
1790+ return false ;
1791+ std::wstring p = to_lower_ws (path);
1792+ if (p.rfind (sys32, 0 ) != 0 && p.rfind (syswow, 0 ) != 0 )
1793+ return false ;
1794+ }
1795+ return true ;
1796+ }
1797+
17651798void KeyAuth::api::setDebug (bool value) {
17661799 KeyAuth::api::debug = value;
17671800}
@@ -2143,6 +2176,15 @@ void checkInit() {
21432176 if (!initialized) {
21442177 error (XorStr (" You need to run the KeyAuthApp.init(); function before any other KeyAuth functions" ));
21452178 }
2179+ const auto now = std::chrono::duration_cast<std::chrono::seconds>(
2180+ std::chrono::system_clock::now ().time_since_epoch ()).count ();
2181+ const auto last_mod = last_module_check.load ();
2182+ if (now - last_mod > 60 ) {
2183+ last_module_check.store (now);
2184+ if (!module_paths_ok ()) {
2185+ error (XorStr (" module path check failed, possible side-load detected." ));
2186+ }
2187+ }
21462188 integrity_check ();
21472189}
21482190
@@ -2166,6 +2208,15 @@ void integrity_watchdog() {
21662208 Sleep (static_cast <DWORD>(sleep_seconds (gen) * 1000 ));
21672209 if (!initialized || !LoggedIn.load ())
21682210 continue ;
2211+ const auto now = std::chrono::duration_cast<std::chrono::seconds>(
2212+ std::chrono::system_clock::now ().time_since_epoch ()).count ();
2213+ const auto last_mod = last_module_check.load ();
2214+ if (now - last_mod > 120 ) {
2215+ last_module_check.store (now);
2216+ if (!module_paths_ok ()) {
2217+ error (XorStr (" module path check failed, possible side-load detected." ));
2218+ }
2219+ }
21692220 if (check_section_integrity (XorStr (" .text" ).c_str (), false )) {
21702221 const int streak = integrity_fail_streak.fetch_add (1 ) + 1 ;
21712222 if (streak >= 2 ) {
0 commit comments