mirror of
https://github.com/Artikash/Textractor.git
synced 2024-12-24 01:14:12 +08:00
minor fixes
This commit is contained in:
parent
7802195193
commit
c87729814a
@ -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)
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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}]]
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user