minor fixes

This commit is contained in:
Akash Mozumdar 2018-07-14 23:18:08 -04:00
parent 7802195193
commit c87729814a
5 changed files with 26 additions and 265 deletions

View File

@ -34,73 +34,25 @@ BYTE LeadByteTable[0x100] = {
// - API functions - // - API functions -
extern "C" { 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 // 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)
mov eax,search_length if (memcmp((void*)(base + i), search, search_length) == 0)
alloc: return i;
push 0
sub eax,1
jnz alloc
mov edi,search return 0;
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
}
} }
DWORD IthGetMemoryRange(LPCVOID mem, DWORD *base, DWORD *size) DWORD IthGetMemoryRange(LPCVOID mem, DWORD *base, DWORD *size)

View File

@ -1,6 +1,7 @@
// memsearch.cc // memsearch.cc
// 4/20/2014 jichi // 4/20/2014 jichi
#include "memdbg/memsearch.h" #include "memdbg/memsearch.h"
#include "ithsys/ithsys.h"
#include <windows.h> #include <windows.h>
// Helpers // 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 #if 0
/** /**
* Search from stopAddress back to startAddress - range * 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) 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) { ; 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)) if (!addr || !fun(addr))
return false; 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 findBytes(const void *pattern, DWORD patternSize, DWORD lowerBound, DWORD upperBound)
{ {
DWORD reladdr = searchPattern(lowerBound, upperBound - lowerBound, pattern, patternSize); 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);
return reladdr ? lowerBound + reladdr : 0; return reladdr ? lowerBound + reladdr : 0;
} }
@ -809,7 +637,7 @@ DWORD findBytesInPages(const void *pattern, DWORD patternSize, DWORD lowerBound,
//upperBound = 0x14000000; //upperBound = 0x14000000;
//SIZE_T ok = ::VirtualQuery((LPCVOID)lowerBound, &mbi, sizeof(mbi)); //SIZE_T ok = ::VirtualQuery((LPCVOID)lowerBound, &mbi, sizeof(mbi));
//ITH_GROWL_DWORD7(1, start, stop, mbi.RegionSize, mbi.Protect, mbi.Type, mbi.State); //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) { while (stop < upperBound) {
SIZE_T ok = ::VirtualQuery((LPCVOID)start, &mbi, sizeof(mbi)); SIZE_T ok = ::VirtualQuery((LPCVOID)start, &mbi, sizeof(mbi));
if (!mbi.RegionSize) if (!mbi.RegionSize)
@ -843,7 +671,7 @@ DWORD matchBytesInPages(const void *pattern, DWORD patternSize, DWORD lowerBound
//upperBound = 0x14000000; //upperBound = 0x14000000;
//SIZE_T ok = ::VirtualQuery((LPCVOID)lowerBound, &mbi, sizeof(mbi)); //SIZE_T ok = ::VirtualQuery((LPCVOID)lowerBound, &mbi, sizeof(mbi));
//ITH_GROWL_DWORD7(1, start, stop, mbi.RegionSize, mbi.Protect, mbi.Type, mbi.State); //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) { while (stop < upperBound) {
SIZE_T ok = ::VirtualQuery((LPCVOID)start, &mbi, sizeof(mbi)); SIZE_T ok = ::VirtualQuery((LPCVOID)start, &mbi, sizeof(mbi));
if (!mbi.RegionSize) if (!mbi.RegionSize)
@ -851,7 +679,7 @@ DWORD matchBytesInPages(const void *pattern, DWORD patternSize, DWORD lowerBound
// Only visit readable and committed region // Only visit readable and committed region
// Protect could be zero if not allowed to query // Protect could be zero if not allowed to query
if (!ok || !mbi.Protect || mbi.Protect&PAGE_NOACCESS) { 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; return ret;
if (search != SearchAll) if (search != SearchAll)
return 0; return 0;
@ -861,7 +689,7 @@ DWORD matchBytesInPages(const void *pattern, DWORD patternSize, DWORD lowerBound
stop += mbi.RegionSize; stop += mbi.RegionSize;
} }
if (stop > start) if (stop > start)
ret = matchBytes(pattern, patternSize, start, min(upperBound, stop), wildcard); ret = findBytes(pattern, patternSize, start, min(upperBound, stop), wildcard);
return ret; return ret;
} }

View File

@ -165,25 +165,6 @@ dword_t findEnclosingFunctionAfterNop(dword_t addr, dword_t searchSize = Maximum
* @exception illegal memory access * @exception illegal memory access
*/ */
dword_t findBytes(const void *pattern, dword_t patternSize, dword_t lowerBound, dword_t upperBound); 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) // User space: 0 - 2G (0 - 0x7ffeffff)
// Kernel space: 2G - 4G (0x80000000 - 0xffffffff) // Kernel space: 2G - 4G (0x80000000 - 0xffffffff)

View File

@ -117,7 +117,7 @@ bool Parse(const std::wstring& cmd, HookParam& hp)
// ":GDI.dll" -> MODULE_OFFSET && module != NULL // ":GDI.dll" -> MODULE_OFFSET && module != NULL
// ":GDI.dll:strlen" -> MODULE_OFFSET | FUNCTION_OFFSET && module != NULL && function != NULL // ":GDI.dll:strlen" -> MODULE_OFFSET | FUNCTION_OFFSET && module != NULL && function != NULL
// ":GDI.dll:#123" -> 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); rx = wregex(L"^:(" + module + L"(:" + name + L"|#" + ordinal + L")?)?$", wregex::icase);
result = regex_search(start, end, m, rx); result = regex_search(start, end, m, rx);
if (result) // :[module[:{name|#ordinal}]] if (result) // :[module[:{name|#ordinal}]]

View File

@ -87,7 +87,7 @@ void TextThread::AddText(const BYTE *con, int len)
void TextThread::GetEntryString(LPSTR buffer, DWORD max) 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); thread_number, tp. pid, tp.hook, tp.retn, tp.spl);
GetHookName(buffer + len, tp.pid, tp.hook, max - len); GetHookName(buffer + len, tp.pid, tp.hook, max - len);
} }