Для поиска произвольной строки в блоке памяти с использованием бинарной маски я написал следующую процедуру:
; ---------------------------------------------
; Процедура поиска строки в блоке памяти
; (C) ManHunter / PCL
; ---------------------------------------------
; SRCdata - блок памяти в котором выполняется поиск
; SRCsize - размер блока в котором выполняется поиск
; PTRdata - строка для поиска
; PTRsize - длина строки для поиска
; MSKdata - бинарная маска для поиска или 0 если не используется
;
; Возврат: EAX = offset найденной строки
; EAX = -1 если ничего не найдено
; ---------------------------------------------
proc scanmem SRCdata:dword, SRCsize:dword, PTRdata:dword,\
PTRsize:dword, MSKdata:dword
push esi edi ebx ecx edx
; Длина паттерна больше длины данных?
mov eax,[PTRsize]
cmp eax,[SRCsize]
; Да, возврат -1
ja .scanmem_not_found
mov esi,[SRCdata]
mov edi,[PTRdata]
mov edx,[MSKdata]
mov ebx,esi
add ebx,[SRCsize]
sub ebx,[PTRsize]
.scanmem_loop:
xor ecx,ecx
.scanmem_test_char:
or edx,edx
jz .scanmem_no_mask
cmp byte [edx+ecx],0
jz .scanmem_char_equal
.scanmem_no_mask:
mov al,[esi+ecx]
cmp al,[edi+ecx]
jne .scanmem_next_pattern
.scanmem_char_equal:
inc ecx
cmp ecx,[PTRsize]
jb .scanmem_test_char
jmp .scanmem_found
.scanmem_next_pattern:
inc esi
cmp esi,ebx
jbe .scanmem_loop
.scanmem_not_found:
; Строка не найдена
mov eax,-1
jmp .scanmem_ret
.scanmem_found:
; Строка найдена
mov eax,esi
.scanmem_ret:
pop edx ecx ebx edi esi
ret
endp
Пример использования процедуры:
; Сегмент данных
section '.data' data readable writeable
str1 db 'This game has no name',0
slen1 = $-str1
str2 db 'name'
slen2 = $-str2
str3 db 'lame'
slen3 = $-str3
mask db 0,1,1,1 ; 0 - совпадение не обязательно, 1 - совпадение обязательно
; Сегмент кода
section '.code' code readable executable
...
; Поиск с использованием маски
; строка поиска = '?ame'
stdcall scanmem, str1, slen1, str3, slen3, mask
; eax => 'game has no name'
; Поиск без использования маски и такой строки нет
; строка поиска = 'lame'
stdcall scanmem, str1, slen1, str3, slen3, NULL
; eax = -1, ничего не найдено
; Поиск без использования маски (точное совпадение)
; строка поиска = 'name'
stdcall scanmem, str1, slen1, str2, slen2, NULL
; eax => 'name'
Длина строки поиска должна быть меньше или равна длине блока памяти, в котором выполняется поиск. Если используется бинарная маска, то ее длина должна в точности совпадать с длиной строки поиска. Значения позиций в маске: 0 - на этой позиции может быть любой символ, 1 - точное совпадение байта в памяти и в строке поиска.