diff --git a/wufuc/core.c b/wufuc/core.c index 2cb221c..db1f7be 100644 --- a/wufuc/core.c +++ b/wufuc/core.c @@ -5,6 +5,7 @@ #include #include "service.h" #include "util.h" +#include "patternfind.h" #include "core.h" DWORD WINAPI NewThreadProc(LPVOID lpParam) { @@ -46,7 +47,7 @@ DWORD WINAPI NewThreadProc(LPVOID lpParam) { get_svcdll(_T("wuauserv"), lpServiceDll, _countof(lpServiceDll)); HMODULE hwu = GetModuleHandle(lpServiceDll); - if (hwu && PatchWUModule(hwu)) { + if (hwu && PatchWUAgentHMODULE(hwu)) { _tdbgprintf(_T("Patched previously loaded Windows Update module!")); } ResumeAndCloseThreads(lphThreads, cb); @@ -66,35 +67,20 @@ DWORD WINAPI NewThreadProc(LPVOID lpParam) { return 0; } -BOOL PatchWUModule(HMODULE hModule) { +BOOL PatchWUAgentHMODULE(HMODULE hModule) { LPSTR lpszPattern; SIZE_T n1, n2; #ifdef _WIN64 - lpszPattern = - "FFF3" // push rbx - "4883EC??" // sub rsp,?? - "33DB" // xor ebx,ebx - "391D????????" // cmp dword ptr ds:[???????????],ebx - "7508" // jnz $+8 - "8B05????????"; // mov eax,dword ptr ds:[???????????] + lpszPattern = "FFF3 4883EC?? 33DB 391D???????? 7508 8B05????????"; n1 = 10; n2 = 18; #elif defined(_WIN32) if (WindowsVersionCompare(VER_EQUAL, 6, 1, 0, 0, VER_MAJORVERSION | VER_MINORVERSION)) { - lpszPattern = - "833D????????00" // cmp dword ptr ds:[????????],0 - "743E" // je $+3E - "E8????????" // call - "A3????????"; // mov dword ptr ds:[????????],eax + lpszPattern = "833D????????00 743E E8???????? A3????????"; n1 = 2; n2 = 15; } else if (WindowsVersionCompare(VER_EQUAL, 6, 3, 0, 0, VER_MAJORVERSION | VER_MINORVERSION)) { - lpszPattern = - "8BFF" // mov edi,edi - "51" // push ecx - "833D????????00" // cmp dword ptr ds:[????????],0 - "7507" // jnz $+7 - "A1????????"; // mov eax,dword ptr ds:[????????] + lpszPattern = "8BFF 51 833D????????00 7507 A1????????"; n1 = 5; n2 = 13; } @@ -105,20 +91,21 @@ BOOL PatchWUModule(HMODULE hModule) { MODULEINFO modinfo; GetModuleInformation(GetCurrentProcess(), hModule, &modinfo, sizeof(MODULEINFO)); - SIZE_T rva; - if (!FindPattern(modinfo.lpBaseOfDll, modinfo.SizeOfImage, lpszPattern, 0, &rva)) { + SIZE_T rva = patternfind(modinfo.lpBaseOfDll, modinfo.SizeOfImage, 0, lpszPattern); + if (rva == -1) { _tdbgprintf(_T("No pattern match!")); return FALSE; } + SIZE_T fpIsDeviceServiceable = (SIZE_T)modinfo.lpBaseOfDll + rva; _tdbgprintf(_T("Pattern match at offset %p."), fpIsDeviceServiceable); BOOL result = FALSE; + DWORD flOldProtect; + DWORD flNewProtect = PAGE_READWRITE; BOOL *lpbNotRunOnce = (BOOL *)(fpIsDeviceServiceable + n1 + sizeof(DWORD) + *(DWORD *)(fpIsDeviceServiceable + n1)); if (*lpbNotRunOnce) { - DWORD flOldProtect; - DWORD flNewProtect = PAGE_READWRITE; VirtualProtect(lpbNotRunOnce, sizeof(BOOL), flNewProtect, &flOldProtect); *lpbNotRunOnce = FALSE; VirtualProtect(lpbNotRunOnce, sizeof(BOOL), flOldProtect, &flNewProtect); @@ -128,8 +115,6 @@ BOOL PatchWUModule(HMODULE hModule) { BOOL *lpbCachedResult = (BOOL *)(fpIsDeviceServiceable + n2 + sizeof(DWORD) + *(DWORD *)(fpIsDeviceServiceable + n2)); if (!*lpbCachedResult) { - DWORD flOldProtect; - DWORD flNewProtect = PAGE_READWRITE; VirtualProtect(lpbCachedResult, sizeof(BOOL), flNewProtect, &flOldProtect); *lpbCachedResult = TRUE; VirtualProtect(lpbCachedResult, sizeof(BOOL), flOldProtect, &flNewProtect); @@ -145,14 +130,14 @@ HMODULE WINAPI _LoadLibraryExA( _In_ DWORD dwFlags ) { HMODULE result = LoadLibraryExA(lpFileName, hFile, dwFlags); - _dbgprintf("Loaded %s.", lpFileName); if (result) { + _dbgprintf("Loaded %s.", lpFileName); CHAR path[MAX_PATH + 1]; if (!get_svcdllA("wuauserv", path, _countof(path))) { return result; } - if (!_stricmp(lpFileName, path) && PatchWUModule(result)) { + if (!_stricmp(lpFileName, path) && PatchWUAgentHMODULE(result)) { _dbgprintf("Patched Windows Update module!"); } } @@ -165,14 +150,14 @@ HMODULE WINAPI _LoadLibraryExW( _In_ DWORD dwFlags ) { HMODULE result = LoadLibraryExW(lpFileName, hFile, dwFlags); - _wdbgprintf(L"Loaded library: %s.", lpFileName); if (result) { + _wdbgprintf(L"Loaded library: %s.", lpFileName); WCHAR path[MAX_PATH + 1]; if (!get_svcdllW(L"wuauserv", path, _countof(path))) { return result; } - if (!_wcsicmp(lpFileName, path) && PatchWUModule(result)) { + if (!_wcsicmp(lpFileName, path) && PatchWUAgentHMODULE(result)) { _wdbgprintf(L"Patched Windows Update module!"); } } diff --git a/wufuc/core.h b/wufuc/core.h index fbc07f7..41da198 100644 --- a/wufuc/core.h +++ b/wufuc/core.h @@ -2,7 +2,7 @@ DWORD WINAPI NewThreadProc(LPVOID lpParam); -BOOL PatchWUModule(HMODULE hModule); +BOOL PatchWUAgentHMODULE(HMODULE hModule); HMODULE WINAPI _LoadLibraryExA( _In_ LPCSTR lpFileName, diff --git a/wufuc/patternfind.c b/wufuc/patternfind.c new file mode 100644 index 0000000..2f06b0b --- /dev/null +++ b/wufuc/patternfind.c @@ -0,0 +1,118 @@ +#include +#include "patternfind.h" + +/* + Work in progress. Ported to C from x64dbg's patternfind.cpp: + https://github.com/x64dbg/x64dbg/blob/development/src/dbg/patternfind.cpp + x64dbg license (GPL-3.0): + https://github.com/x64dbg/x64dbg/blob/development/LICENSE +*/ + +int hexchtoint(CHAR ch) { + int result = -1; + if (ch >= '0' && ch <= '9') { + result = ch - '0'; + } else if (ch >= 'A' && ch <= 'F') { + result = ch - 'A' + 10; + } else if (ch >= 'a' && ch <= 'f') { + result = ch - 'a' + 10; + } + return result; +} + +SIZE_T formathexpattern(LPCSTR patterntext, LPSTR formattext, SIZE_T formattextsize) { + SIZE_T len = strlen(patterntext); + SIZE_T result = 0; + for (SIZE_T i = 0; i < len && (!formattext || result < formattextsize); i++) { + if (patterntext[i] == '?' || hexchtoint(patterntext[i]) != -1) { + if (formattext) { + formattext[result] = patterntext[i]; + } + result++; + } + } + return result; +} + +BOOL patterntransform(LPCSTR patterntext, LPPATTERNBYTE pattern, SIZE_T *patternsize) { + SIZE_T cb = formathexpattern(patterntext, NULL, 0); + if (!cb || cb > *patternsize) { + return FALSE; + } + LPSTR formattext = calloc(cb, sizeof(CHAR)); + cb = formathexpattern(patterntext, formattext, cb); + + if (cb % 2) { + formattext[++cb] = '?'; + } + formattext[cb] = '\0'; + + for (SIZE_T i = 0, j = 0, k = 0; i < cb; i++, j ^= 1, k = (i - j) / 2) { + if (formattext[i] == '?') { + pattern[k].nibble[j].wildcard = TRUE; + } else { + pattern[k].nibble[j].wildcard = FALSE; + pattern[k].nibble[j].data = hexchtoint(formattext[i]) & 0xf; + } + } + free(formattext); + *patternsize = cb / 2; + return TRUE; +} + +SIZE_T patternfind(LPCBYTE data, SIZE_T datasize, SIZE_T startindex, LPCSTR pattern) { + SIZE_T result = -1; + SIZE_T searchpatternsize = strlen(pattern); + LPPATTERNBYTE searchpattern = calloc(searchpatternsize, sizeof(PATTERNBYTE)); + if (patterntransform(pattern, searchpattern, &searchpatternsize)) { + for (SIZE_T i = startindex, j = 0; i < datasize; i++) //search for the pattern + { + if ((searchpattern[j].nibble[0].wildcard || searchpattern[j].nibble[0].data == ((data[i] >> 4) & 0xf)) + && (searchpattern[j].nibble[1].wildcard || searchpattern[j].nibble[1].data == (data[i] & 0xf))) { //check if our pattern matches the current byte + + if (++j == searchpatternsize) { //everything matched + result = i - searchpatternsize + 1; + break; + } + } else if (j > 0) { //fix by Computer_Angel + i -= j; + j = 0; //reset current pattern position + } + } + } + return result; +} + +//VOID patternwritebyte(LPBYTE byte, LPPATTERNBYTE pbyte) { +// BYTE n1 = (*byte >> 4) & 0xf; +// BYTE n2 = *byte & 0xf; +// if (!pbyte->nibble[0].wildcard) { +// n1 = pbyte->nibble[0].data; +// } +// if (!pbyte->nibble[1].wildcard) { +// n2 = pbyte->nibble[1].data; +// } +// *byte = ((n1 << 4) & 0xf0) | (n2 & 0xf); +//} +// +//VOID patternwrite(LPBYTE data, SIZE_T datasize, LPCSTR pattern) { +// SIZE_T writepatternsize = strlen(pattern); +// if (writepatternsize > datasize) { +// writepatternsize = datasize; +// } +// LPPATTERNBYTE writepattern = calloc(writepatternsize, sizeof(PATTERNBYTE)); +// if (!patterntransform(pattern, writepattern, &writepatternsize)) { +// return; +// } +// for (size_t i = 0; i < writepatternsize; i++) { +// patternwritebyte(&data[i], &writepattern[i]); +// } +//} +// +//SIZE_T patternsnr(LPBYTE data, SIZE_T datasize, SIZE_T startindex, LPCSTR searchpattern, LPCSTR replacepattern) { +// SIZE_T result = patternfind(data, datasize, startindex, searchpattern, NULL, 0); +// if (result == -1) +// return result; +// patternwrite(data + result, datasize - result, replacepattern); +// return result; +//} diff --git a/wufuc/patternfind.h b/wufuc/patternfind.h new file mode 100644 index 0000000..1949d7d --- /dev/null +++ b/wufuc/patternfind.h @@ -0,0 +1,16 @@ +#pragma once + +typedef struct _PATTERNBYTE { + struct _PATTERNNIBBLE { + BYTE data; + BOOL wildcard; + } nibble[2]; +} PATTERNBYTE, *PPATTERNBYTE, *LPPATTERNBYTE; + +int hexchtoint(CHAR ch); +SIZE_T formathexpattern(LPCSTR patterntext, LPSTR formattext, SIZE_T formattextsize); +BOOL patterntransform(LPCSTR patterntext, LPPATTERNBYTE pattern, SIZE_T *patternsize); +SIZE_T patternfind(LPCBYTE data, SIZE_T datasize, SIZE_T startindex, LPCSTR pattern); +//VOID patternwritebyte(LPBYTE byte, LPPATTERNBYTE pbyte); +//VOID patternwrite(LPBYTE data, SIZE_T datasize, LPCSTR pattern) +//SIZE_T patternsnr(LPBYTE data, SIZE_T datasize, SIZE_T startindex, LPCSTR searchpattern, LPCSTR replacepattern); diff --git a/wufuc/util.c b/wufuc/util.c index 2fe02ae..0b576fc 100644 --- a/wufuc/util.c +++ b/wufuc/util.c @@ -38,47 +38,6 @@ LPVOID *FindIAT(HMODULE hModule, LPSTR lpFunctionName) { return NULL; } -BOOL FindPattern(LPCBYTE pvData, SIZE_T nNumberOfBytes, LPSTR lpszPattern, SIZE_T nStart, SIZE_T *lpOffset) { - SIZE_T length = strlen(lpszPattern); - SIZE_T nBytes; - if (length % 2 || (nBytes = length / 2) > nNumberOfBytes) { - return FALSE; - } - - LPBYTE lpBytes = malloc(nBytes * sizeof(BYTE)); - BOOL *lpbwc = malloc(nBytes * sizeof(BOOL)); - - LPSTR p = lpszPattern; - BOOL valid = TRUE; - for (SIZE_T i = 0; i < nBytes; i++) { - if ((lpbwc[i] = strncmp(p, "??", 2)) && sscanf_s(p, "%2hhx", &lpBytes[i]) != 1) { - valid = FALSE; - break; - } - p += 2; - } - BOOL result = FALSE; - if (valid) { - for (SIZE_T i = nStart; i < nNumberOfBytes - nStart - (nBytes - 1); i++) { - BOOL found = TRUE; - for (SIZE_T j = 0; j < nBytes; j++) { - if (lpbwc[j] && pvData[i + j] != lpBytes[j]) { - found = FALSE; - break; - } - } - if (found) { - *lpOffset = i; - result = TRUE; - break; - } - } - } - free(lpBytes); - free(lpbwc); - return result; -} - VOID SuspendProcessThreads(DWORD dwProcessId, DWORD dwThreadId, HANDLE *lphThreads, SIZE_T dwSize, SIZE_T *lpcb) { HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); THREADENTRY32 te; diff --git a/wufuc/util.h b/wufuc/util.h index 26ffeb6..3b556f4 100644 --- a/wufuc/util.h +++ b/wufuc/util.h @@ -14,8 +14,6 @@ VOID DetourIAT(HMODULE hModule, LPSTR lpFuncName, LPVOID *lpOldAddress, LPVOID l LPVOID *FindIAT(HMODULE hModule, LPSTR lpFuncName); -BOOL FindPattern(LPCBYTE lpBytes, SIZE_T nNumberOfBytes, LPSTR lpszPattern, SIZE_T nStart, SIZE_T *lpOffset); - VOID SuspendProcessThreads(DWORD dwProcessId, DWORD dwThreadId, HANDLE *lphThreads, SIZE_T dwSize, SIZE_T *lpcb); VOID ResumeAndCloseThreads(HANDLE *lphThreads, SIZE_T dwSize); diff --git a/wufuc/wufuc.vcxproj b/wufuc/wufuc.vcxproj index 7d9c5a7..beb7726 100644 --- a/wufuc/wufuc.vcxproj +++ b/wufuc/wufuc.vcxproj @@ -177,6 +177,7 @@ + @@ -186,6 +187,7 @@ +