Поиск и замена строки в памяти

Тема в разделе "WASM.A&O", создана пользователем Flasher, 8 янв 2009.

  1. Flasher

    Flasher Member

    Публикаций:
    0
    Регистрация:
    31 янв 2004
    Сообщения:
    640
    Помогите реализовать максимально быстрый поиск заданной строки в памяти процесса.
    Набросал код поблочного чтения, могет можно как-то оптимизировать по скорости этот код, или предложите свой вариант...

    Код (Text):
    1. .686p
    2. .mmx
    3. .model flat,stdcall
    4. option casemap:none
    5.  
    6. include \masm32\include\ntdll.inc
    7. includelib \masm32\lib\ntdll.lib
    8. include \masm32\include\kernel32.inc
    9. includelib \masm32\lib\kernel32.lib
    10. include \masm32\include\user32.inc
    11. includelib \masm32\lib\user32.lib
    12.  
    13. .data
    14. szString      db "строка которую нужно изменить",0
    15. szNewString   db "новая строка с той  же длиной",0
    16.  
    17. .code
    18. FindWriteMemory proc uses esi edi ebx ProcessHandle:dword,lpString:dword,lpNewString:dword,lpStringsLen:dword
    19.      local ReturnLength:dword
    20.      local SystemInformation:SYSTEM_BASIC_INFORMATION
    21.      local AllocationBase:dword
    22.      local AllocationSize:dword
    23.      local MemoryInformation:MEMORY_BASIC_INFORMATION
    24.      local RegionLenght:dword
    25.  
    26.        invoke ZwQuerySystemInformation,SystemBasicInformation,addr SystemInformation,sizeof SYSTEM_BASIC_INFORMATION,addr ReturnLength
    27.         .if eax == 0
    28.            mov AllocationSize,1024*2024
    29.            mov AllocationBase,0
    30.            invoke ZwAllocateVirtualMemory,-1,addr AllocationBase,0,addr AllocationSize,MEM_COMMIT,PAGE_READWRITE
    31.             .if eax == 0
    32.                mov edi,AllocationBase
    33. NextRegionMemory:
    34.                invoke ZwQueryVirtualMemory,ProcessHandle,SystemInformation.LowestUserAddress,MemoryBasicInformation,addr MemoryInformation,sizeof MEMORY_BASIC_INFORMATION,addr ReturnLength
    35.                 .if eax == 0
    36.                    cmp MemoryInformation.State,MEM_COMMIT or MEM_RESERVE
    37.                    jz NextRegionMemory
    38. NextFragmentMemory:
    39.                    .if MemoryInformation.RegionSize <= 1024*2024
    40.                       mov eax,MemoryInformation.RegionSize
    41.                     .else
    42.                       mov eax,1024*2024
    43.                    .endif
    44.                    mov RegionLenght,eax
    45.                    invoke ZwReadVirtualMemory,ProcessHandle,MemoryInformation.BaseAddress,edi,RegionLenght,0
    46.                     .if eax == 0
    47.                        mov esi,RegionLenght
    48.                        mov ebx,esi
    49.                     @@:
    50.                        invoke memcmp,edi,lpString,lpStringsLen
    51.                         .if eax == 0
    52.                            mov eax,MemoryInformation.BaseAddress
    53.                            sub eax,RegionLenght
    54.                            add eax,ebx ;определяем адрес
    55.                            invoke ZwWriteVirtualMemory,ProcessHandle,eax,lpNewString,lpStringsLen,0
    56.                         .endif
    57.                        inc edi
    58.                        inc ebx
    59.                        dec esi
    60.                        jnz @B
    61.                     .endif
    62.  
    63.                    .if MemoryInformation.RegionSize <= 1024*2024
    64.                       mov eax,MemoryInformation.BaseAddress
    65.                       add eax,MemoryInformation.RegionSize
    66.                       mov SystemInformation.LowestUserAddress,eax
    67.                       cmp eax,SystemInformation.HighestUserAddress
    68.                       jc NextRegionMemory
    69.                     .else
    70.                       mov eax,1024*2024
    71.                       sub MemoryInformation.RegionSize,eax
    72.                       add MemoryInformation.BaseAddress,eax
    73.                       jmp NextFragmentMemory
    74.                    .endif
    75.  
    76.                 .endif
    77.                invoke ZwFreeVirtualMemory,-1,addr AllocationBase,addr AllocationSize,MEM_RELEASE
    78.             .endif
    79.         .endif        
    80.        ret
    81. FindWriteMemory endp
    82. start proc
    83.      local Buffer[1024]:byte
    84.        invoke lstrcpy,addr Buffer,offset szString
    85.        invoke FindWriteMemory,-1,offset szString,offset szNewString,sizeof szString
    86.        invoke MessageBox,0,offset szString,addr Buffer,0
    87.        invoke ExitProcess,0
    88. start endp
    89. end start
     
  2. Forever

    Forever Виталий

    Публикаций:
    0
    Регистрация:
    12 апр 2008
    Сообщения:
    244
    Нужен алгоритм поиска побыстрее. Используй алгоритм Кнута-Морриса-Пратта. Только не влоб. Нужно организовать поблочное чтение памяти, а внутри блока искать КМП. Когда блок заканчивается, подгрузить новый и продолжить поиск.
     
  3. Flasher

    Flasher Member

    Публикаций:
    0
    Регистрация:
    31 янв 2004
    Сообщения:
    640
    Неукого нет более лучщей схемы ? :)
     
  4. Forever

    Forever Виталий

    Публикаций:
    0
    Регистрация:
    12 апр 2008
    Сообщения:
    244
    Сомневаюсь, что она возможна, эта лучшая схема. Единственный возможный способ искать быстрее, это использовать более быстрый алгоритм поиска. И здесь уже ты можешь извращаться как хочешь.
    Например memcmp требует очень много времени за счет того, что ты по много раз будешь проверять один и тот же байт. Алгоритм КМП будет проверять каждый байт только один раз. Лучше быть уже не может. Улучшения могут быть лишь в упрощении реализации. Ты можешь выбрать любой из быстрых алгоритмов поиска подстроки.
    Если хочешь чего-нибудь попроще, то используй хеширование (Если использовать нужный хеш, то ты можешь пересчитывать за константу, при сдвиге на один байт вперед) Сверяешь хеш куска памяти нужного размера, с хешем того, что ты ищешь. Если совпадают, то проверяй memcmp, если нет - то идешь дальше. При хорошем подборе алгоритма хеширования, ты будешь вызывать memcmp крайне редко.