#include #include #include "stringutils.h" #include "debug.h" #include "cenk.h" // pregutl -s hklm\init :Launch09='loadhook.exe' :Depend10=hex:09,00 // on sm2003 loading from init somehow does not work. // class BaseError { protected: std::Wstring msg_; va_list ap_; public: BaseError(WCHAR *fmt, va_list ap) { int desired_length= 1024; msg_.resize(desired_length); int printedlength= _vsnwprintf(&msg_[0], msg_.size(), fmt, ap); va_end(ap); if (printedlength!=-1) msg_.resize(printedlength); } const WCHAR* c_str() const { return msg_.c_str(); } }; class SystemError : public BaseError { private: DWORD dwErrorCode; std::Wstring err_; public: SystemError(WCHAR *fmt, ...) : BaseError(fmt, (va_start(ap_, fmt), ap_)) , dwErrorCode(GetLastError()) { WCHAR* msgbuf; int rc= FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwErrorCode, 0, (WCHAR*) &msgbuf, 0, NULL); if (rc) { err_= msg_ + L": " + msgbuf; LocalFree(msgbuf); } else { err_= msg_ + L": " + ToWString(stringformat("%08lx", dwErrorCode)); } } const WCHAR* c_str() const { return err_.c_str(); } }; class win32api { public: static HMODULE GetModuleHandle(const std::Wstring& modulename) { HMODULE hMod= ::GetModuleHandle(modulename.c_str()); if (hMod==NULL || hMod==INVALID_HANDLE_VALUE) throw SystemError(L"GetModuleHandle(%ls)", modulename.c_str()); return hMod; } static HMODULE LoadLibrary(const std::Wstring& modulename) { HMODULE hMod= ::LoadLibrary(modulename.c_str()); if (hMod==NULL || hMod==INVALID_HANDLE_VALUE) throw SystemError(L"LoadLibrary(%ls)", modulename.c_str()); return hMod; } static LPVOID GetProcAddress(HMODULE hMod, const std::Wstring& procname) { LPVOID pfn= ::GetProcAddress(hMod, procname.c_str()); if (pfn==NULL) throw SystemError(L"GetProcAddress(%08lx, %ls)", hMod, procname.c_str()); return pfn; } }; DWORD RemoteLoadLibrary(HANDLE hProcess, const std::Wstring& dllname) { CALLBACKINFO cbi; cbi.hProc= hProcess; HMODULE hCoredll= win32api::GetModuleHandle(L"coredll.dll"); LPVOID pfnLoadLib= win32api::GetProcAddress(hCoredll, L"LoadLibraryW"); cbi.pfn= (FARPROC)MapPtrToProcess(pfnLoadLib, cbi.hProc); cbi.pvArg0= MapPtrToProcess((void*)dllname.c_str(), GetCurrentProcess()); debug("loadhook: coredll=%08lx pfnloadlib=%08lx->%08lx\n", hCoredll, pfnLoadLib, cbi.pfn); return PerformCallBack4(&cbi, 0, 0, 0); } DWORD RemoteFreeLibrary(HANDLE hProcess, DWORD hModule) { CALLBACKINFO cbi; cbi.hProc= hProcess; HMODULE hCoredll= win32api::GetModuleHandle(L"coredll.dll"); LPVOID pfnFreeLib= win32api::GetProcAddress(hCoredll, L"FreeLibrary"); cbi.pfn= (FARPROC)MapPtrToProcess(pfnFreeLib, cbi.hProc); cbi.pvArg0= (LPVOID)hModule; debug("loadhook: coredll=%08lx pfnloadlib=%08lx->%08lx\n", hCoredll, pfnFreeLib, cbi.pfn); return PerformCallBack4(&cbi, 0, 0, 0); } DWORD RemoteCallHookApi(HANDLE hProcess, const std::Wstring& apiname, DWORD p0, DWORD p1, DWORD p2, DWORD p3) { CALLBACKINFO cbi; cbi.hProc= hProcess; static HMODULE hLocalHookMod; if (hLocalHookMod==NULL) { hLocalHookMod= win32api::LoadLibrary(L"apihook.dll"); debug("loadhook: local=%08lx\n", hLocalHookMod); } LPVOID pfn= win32api::GetProcAddress(hLocalHookMod, apiname); cbi.pfn= (FARPROC)MapPtrToProcess(pfn, cbi.hProc); cbi.pvArg0= (void*)p0; debug("loadhook: pfn=%08lx -> %08lx\n", pfn, cbi.pfn); return PerformCallBack4(&cbi, p1, p2, p3); } void loadhook(HANDLE hProc) { try { DWORD hRemoteHookMod= RemoteLoadLibrary(hProc, L"apihook.dll"); debug("loadhook: remote=%08lx\n", hRemoteHookMod); DWORD res= RemoteCallHookApi(hProc, L"starthook", 0,0,0,0); debug("loadhook: starthook: %08lx\n", res); Sleep(1000); DWORD count= RemoteCallHookApi(hProc, L"callcount", 0,0,0,0); debug("loadhook: count: %08lx\n", count); } catch (SystemError e) { debug("loadhook: ERROR: %ls\n", e.c_str()); } } void unloadhook(HANDLE hProc) { try { DWORD count= RemoteCallHookApi(hProc, L"callcount", 0,0,0,0); debug("unloadhook: count: %08lx\n", count); DWORD res= RemoteCallHookApi(hProc, L"endhook", 0,0,0,0); debug("unloadhook: endhook: %08lx\n", res); HMODULE hApiHookModule= win32api::GetModuleHandle(L"apihook.dll"); debug("hh= %08lx\n", hApiHookModule); res= RemoteFreeLibrary(hProc, (DWORD)hApiHookModule); debug("unloadhook: freeremote=%08lx\n", res); } catch (SystemError e) { debug("unloadhook: ERROR: %ls\n", e.c_str()); } } // PUserKData c:/local/wince420/PUBLIC/COMMON/SDK/INC/kfuncs.h // KDataStruct c:/local/wince420/PRIVATE/WINCEOS/COREOS/NK/INC/nkarm.h // KINX_APISETS c:/local/wince420/PUBLIC/COMMON/OAK/INC/pkfuncs.h // SH_FILESYS_APIS c:/local/wince420/PUBLIC/COMMON/SDK/INC/kfuncs.h // CINFO c:/local/wince420/PRIVATE/WINCEOS/COREOS/NK/INC/kernel.h // PROCESS c:/local/wince420/PRIVATE/WINCEOS/COREOS/NK/INC/kernel.h // HT_FILE c:/local/wince420/PUBLIC/COMMON/OAK/INC/psyscall.h int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { DebugSetLogfile("hook.log"); // setkmode+setprocperms is only nescesary under wm2005 // for ppc2003 loadhook works fine without. BOOL bMode = SetKMode(TRUE); DWORD dwPerm = SetProcPermissions(0xFFFFFFFF); debug("%08lx:%08lx loadhook started hProc=%08lx hThread=%08lx: %ls\n", hCurProc, hCurThread, hCurProc, hCurThread, lpCmdLine); CINFO **apisets= (CINFO **)KData.aInfo[KINX_APISETS]; debug("loadhook: apisets=%08lx\n", apisets); CINFO *w32a= apisets[SH_FILESYS_APIS]; debug("loadhook: api[%d]: %08lx %d methods, svr: %08lx ( h%08lx )\n", SH_FILESYS_APIS, w32a, w32a->cMethods, w32a->pServer, w32a->pServer->hProc); if (ToWString(lpCmdLine)==L"-unload") unloadhook(w32a->pServer->hProc); else { loadhook(w32a->pServer->hProc); // calling SignalStarted to be able to run loadhook from HKLM\Init DWORD dwInitValue= _wtol(lpCmdLine); if (dwInitValue) SignalStarted(dwInitValue); } SetProcPermissions(dwPerm); SetKMode(bMode); debug("loadhook ended\n"); return 0; }