diff --git a/vnr/ithsys/ithsys.cc b/vnr/ithsys/ithsys.cc index 96a0af4..e9e530f 100644 --- a/vnr/ithsys/ithsys.cc +++ b/vnr/ithsys/ithsys.cc @@ -34,73 +34,25 @@ BYTE LeadByteTable[0x100] = { // - API functions - extern "C" { -DWORD SearchPattern(DWORD base, DWORD base_length, LPCVOID search, DWORD search_length) // KMP +/** +* Return the address of the first matched pattern. +* Artikash 7/14/2018: changed implementation, hopefully it behaves the same +* Return 0 if failed. The return result is ambiguous if the pattern address is 0. +* +* @param startAddress search start address +* @param range search range +* @param pattern array of bytes to match +* @param patternSize size of the pattern array +* @return relative offset from the startAddress +*/ +DWORD SearchPattern(DWORD base, DWORD base_length, LPCVOID search, DWORD search_length) { - __asm - { - mov eax,search_length -alloc: - push 0 - sub eax,1 - jnz alloc + // Artikash 7/14/2018: not sure, but I think this could throw read access violation if I dont subtract search_length + for (int i = 0; i < base_length - search_length; ++i) + if (memcmp((void*)(base + i), search, search_length) == 0) + return i; - mov edi,search - mov edx,search_length - mov ecx,1 - xor esi,esi -build_table: - mov al,byte ptr [edi+esi] - cmp al,byte ptr [edi+ecx] - sete al - test esi,esi - jz pre - test al,al - jnz pre - mov esi,[esp+esi*4-4] - jmp build_table -pre: - test al,al - jz write_table - inc esi -write_table: - mov [esp+ecx*4],esi - - inc ecx - cmp ecx,edx - jb build_table - - mov esi,base - xor edx,edx - mov ecx,edx -matcher: - mov al,byte ptr [edi+ecx] - cmp al,byte ptr [esi+edx] - sete al - test ecx,ecx - jz match - test al,al - jnz match - mov ecx, [esp+ecx*4-4] - jmp matcher -match: - test al,al - jz pre2 - inc ecx - cmp ecx,search_length - je finish -pre2: - inc edx - cmp edx,base_length // search_length - jb matcher - mov edx,search_length - dec edx -finish: - mov ecx,search_length - sub edx,ecx - lea eax,[edx+1] - lea ecx,[ecx*4] - add esp,ecx - } + return 0; } DWORD IthGetMemoryRange(LPCVOID mem, DWORD *base, DWORD *size) diff --git a/vnr/memdbg/memsearch.cc b/vnr/memdbg/memsearch.cc index a589baf..3bfc12a 100644 --- a/vnr/memdbg/memsearch.cc +++ b/vnr/memdbg/memsearch.cc @@ -1,6 +1,7 @@ // memsearch.cc // 4/20/2014 jichi #include "memdbg/memsearch.h" +#include "ithsys/ithsys.h" #include // Helpers @@ -31,173 +32,6 @@ _mask: } } -/** - * Return the address of the first matched pattern. - * The same as ITH SearchPattern(). KMP is used. - * Return 0 if failed. The return result is ambiguous if the pattern address is 0. - * - * @param startAddress search start address - * @param range search range - * @param pattern array of bytes to match - * @param patternSize size of the pattern array - * @return relative offset from the startAddress - */ -DWORD searchPattern(DWORD base, DWORD base_length, LPCVOID search, DWORD search_length) // KMP -{ - __asm - { - mov eax,search_length -alloc: - push 0 - sub eax,1 - jnz alloc - - mov edi,search - mov edx,search_length - mov ecx,1 - xor esi,esi -build_table: - mov al,byte ptr [edi+esi] - cmp al,byte ptr [edi+ecx] - sete al - test esi,esi - jz pre - test al,al - jnz pre - mov esi,[esp+esi*4-4] - jmp build_table -pre: - test al,al - jz write_table - inc esi -write_table: - mov [esp+ecx*4],esi - - inc ecx - cmp ecx,edx - jb build_table - - mov esi,base - xor edx,edx - mov ecx,edx -matcher: - mov al,byte ptr [edi+ecx] - cmp al,byte ptr [esi+edx] - sete al - test ecx,ecx - jz match - test al,al - jnz match - mov ecx, [esp+ecx*4-4] - jmp matcher -match: - test al,al - jz pre2 - inc ecx - cmp ecx,search_length - je finish -pre2: - inc edx - cmp edx,base_length // search_length - jb matcher - mov edx,search_length - dec edx -finish: - mov ecx,search_length - sub edx,ecx - lea eax,[edx+1] - lea ecx,[ecx*4] - add esp,ecx - } -} - -/** - * jichi 2/5/2014: The same as SearchPattern except it uses 0xff to match everything - * According to @Andys, 0xff seldom appears in the source code: http://sakuradite.com/topic/124 - */ -DWORD searchPatternEx(DWORD base, DWORD base_length, LPCVOID search, DWORD search_length, BYTE wildcard) // KMP -{ - __asm - { - // jichi 2/5/2014 BEGIN - mov bl,wildcard - // jichi 2/5/2014 END - mov eax,search_length -alloc: - push 0 - sub eax,1 - jnz alloc // jichi 2/5/2014: this will also set %eax to zero - - mov edi,search - mov edx,search_length - mov ecx,1 - xor esi,esi -build_table: - mov al,byte ptr [edi+esi] - cmp al,byte ptr [edi+ecx] - sete al - test esi,esi - jz pre - test al,al - jnz pre - mov esi,[esp+esi*4-4] - jmp build_table -pre: - test al,al - jz write_table - inc esi -write_table: - mov [esp+ecx*4],esi - - inc ecx - cmp ecx,edx - jb build_table - - mov esi,base - xor edx,edx - mov ecx,edx -matcher: - mov al,byte ptr [edi+ecx] // search - // jichi 2/5/2014 BEGIN - mov bh,al // save loaded byte to reduce cache access. %ah is not used and always zero - cmp al,bl // %bl is the wildcard byte - sete al - test al,al - jnz wildcard_matched - mov al,bh // restore the loaded byte - // jichi 2/5/2014 END - cmp al,byte ptr [esi+edx] // base - sete al - // jichi 2/5/2014 BEGIN -wildcard_matched: - // jichi 2/5/2014 END - test ecx,ecx - jz match - test al,al - jnz match - mov ecx, [esp+ecx*4-4] - jmp matcher -match: - test al,al - jz pre2 - inc ecx - cmp ecx,search_length - je finish -pre2: - inc edx - cmp edx,base_length // search_length - jb matcher - mov edx,search_length - dec edx -finish: - mov ecx,search_length - sub edx,ecx - lea eax,[edx+1] - lea ecx,[ecx*4] - add esp,ecx - } -} - #if 0 /** * Search from stopAddress back to startAddress - range @@ -494,7 +328,7 @@ bool iterFindBytes(const address_fun_t &fun, const void *pattern, DWORD patternS bool iterMatchBytes(const address_fun_t &fun, const void *pattern, DWORD patternSize, DWORD lowerBound, DWORD upperBound) { for (DWORD addr = lowerBound; addr < upperBound - patternSize; addr += patternSize) { ; - addr = matchBytes(pattern, patternSize, addr, upperBound); + addr = findBytes(pattern, patternSize, addr, upperBound); if (!addr || !fun(addr)) return false; } @@ -780,13 +614,7 @@ DWORD findEnclosingFunctionAfterNop(DWORD start, DWORD back_range, DWORD step) DWORD findBytes(const void *pattern, DWORD patternSize, DWORD lowerBound, DWORD upperBound) { - DWORD reladdr = searchPattern(lowerBound, upperBound - lowerBound, pattern, patternSize); - return reladdr ? lowerBound + reladdr : 0; -} - -DWORD matchBytes(const void *pattern, DWORD patternSize, DWORD lowerBound, DWORD upperBound, BYTE wildcard) -{ - DWORD reladdr = searchPatternEx(lowerBound, upperBound - lowerBound, pattern, patternSize, wildcard); + DWORD reladdr = SearchPattern(lowerBound, upperBound - lowerBound, pattern, patternSize); return reladdr ? lowerBound + reladdr : 0; } @@ -809,7 +637,7 @@ DWORD findBytesInPages(const void *pattern, DWORD patternSize, DWORD lowerBound, //upperBound = 0x14000000; //SIZE_T ok = ::VirtualQuery((LPCVOID)lowerBound, &mbi, sizeof(mbi)); //ITH_GROWL_DWORD7(1, start, stop, mbi.RegionSize, mbi.Protect, mbi.Type, mbi.State); - //return matchBytes(pattern, patternSize, lowerBound, upperBound, wildcard); + //return findBytes(pattern, patternSize, lowerBound, upperBound, wildcard); while (stop < upperBound) { SIZE_T ok = ::VirtualQuery((LPCVOID)start, &mbi, sizeof(mbi)); if (!mbi.RegionSize) @@ -843,7 +671,7 @@ DWORD matchBytesInPages(const void *pattern, DWORD patternSize, DWORD lowerBound //upperBound = 0x14000000; //SIZE_T ok = ::VirtualQuery((LPCVOID)lowerBound, &mbi, sizeof(mbi)); //ITH_GROWL_DWORD7(1, start, stop, mbi.RegionSize, mbi.Protect, mbi.Type, mbi.State); - //return matchBytes(pattern, patternSize, lowerBound, upperBound, wildcard); + //return findBytes(pattern, patternSize, lowerBound, upperBound, wildcard); while (stop < upperBound) { SIZE_T ok = ::VirtualQuery((LPCVOID)start, &mbi, sizeof(mbi)); if (!mbi.RegionSize) @@ -851,7 +679,7 @@ DWORD matchBytesInPages(const void *pattern, DWORD patternSize, DWORD lowerBound // Only visit readable and committed region // Protect could be zero if not allowed to query if (!ok || !mbi.Protect || mbi.Protect&PAGE_NOACCESS) { - if (stop > start && (ret = matchBytes(pattern, patternSize, lowerBound, upperBound, wildcard))) + if (stop > start && (ret = findBytes(pattern, patternSize, lowerBound, upperBound, wildcard))) return ret; if (search != SearchAll) return 0; @@ -861,7 +689,7 @@ DWORD matchBytesInPages(const void *pattern, DWORD patternSize, DWORD lowerBound stop += mbi.RegionSize; } if (stop > start) - ret = matchBytes(pattern, patternSize, start, min(upperBound, stop), wildcard); + ret = findBytes(pattern, patternSize, start, min(upperBound, stop), wildcard); return ret; } diff --git a/vnr/memdbg/memsearch.h b/vnr/memdbg/memsearch.h index 5bd3132..2f3ef36 100644 --- a/vnr/memdbg/memsearch.h +++ b/vnr/memdbg/memsearch.h @@ -165,25 +165,6 @@ dword_t findEnclosingFunctionAfterNop(dword_t addr, dword_t searchSize = Maximum * @exception illegal memory access */ dword_t findBytes(const void *pattern, dword_t patternSize, dword_t lowerBound, dword_t upperBound); -//dword_t reverseFindBytes(const void *pattern, dword_t patternSize, dword_t lowerBound, dword_t upperBound); - -/** - * jichi 2/5/2014: The same as findBytes except it uses widecard to match everything. - * The widecard should use the byte seldom appears in the pattern. - * See: http://sakuradite.com/topic/124 - * - * @param pattern array of bytes to match - * @param patternSize size of the pattern array - * @param lowerBound search start address - * @param upperBound search stop address - * @param* widecard the character to match everything - * @return absolute address - * @exception illegal memory access - */ -enum : byte_t { WidecardByte = 0x11 }; // jichi 7/17/2014: 0x11 seldom appear in PSP code pattern -//enum : WORD { WidecardWord = 0xffff }; -dword_t matchBytes(const void *pattern, dword_t patternSize, dword_t lowerBound, dword_t upperBound, - byte_t wildcard = WidecardByte); // User space: 0 - 2G (0 - 0x7ffeffff) // Kernel space: 2G - 4G (0x80000000 - 0xffffffff) diff --git a/vnr/profile/misc.cpp b/vnr/profile/misc.cpp index efeaf4c..effb5cf 100644 --- a/vnr/profile/misc.cpp +++ b/vnr/profile/misc.cpp @@ -117,7 +117,7 @@ bool Parse(const std::wstring& cmd, HookParam& hp) // ":GDI.dll" -> MODULE_OFFSET && module != NULL // ":GDI.dll:strlen" -> MODULE_OFFSET | FUNCTION_OFFSET && module != NULL && function != NULL // ":GDI.dll:#123" -> MODULE_OFFSET | FUNCTION_OFFSET && module != NULL && function != NULL - std::wstring module(L"([^:[:space:]]+)"), name(L"[^:[:space:]]+"), ordinal(L"\\d+"); + std::wstring module(L"([^:]+)"), name(L"[^:[:space:]]+"), ordinal(L"\\d+"); rx = wregex(L"^:(" + module + L"(:" + name + L"|#" + ordinal + L")?)?$", wregex::icase); result = regex_search(start, end, m, rx); if (result) // :[module[:{name|#ordinal}]] diff --git a/vnr/texthook/host/textthread.cc b/vnr/texthook/host/textthread.cc index a925deb..1992a62 100644 --- a/vnr/texthook/host/textthread.cc +++ b/vnr/texthook/host/textthread.cc @@ -87,7 +87,7 @@ void TextThread::AddText(const BYTE *con, int len) void TextThread::GetEntryString(LPSTR buffer, DWORD max) { - int len = sprintf(buffer, "%.4X:%.4d:0x%08X:0x%08X:0x%08X:", + int len = sprintf(buffer, "%.5d:%.4d:0x%08X:0x%08X:0x%08X:", thread_number, tp. pid, tp.hook, tp.retn, tp.spl); GetHookName(buffer + len, tp.pid, tp.hook, max - len); }