![]() |
|
| Правила Форума редакция от 22.06.2020 |
|
|||||||
|
|
Окажите посильную поддержку, мы очень надеемся на вас. Реквизиты для переводов ниже. |
|
![]() |
|
|
Опции темы | Опции просмотра |
Language
|
|
|
#1
|
|
ViP
![]() Пол:
Регистрация: 17.09.2006
Сообщений: 1,182
Репутация: 1592
|
Предмет повествования состоит в изучении принципов сканирования виртуальной памяти процессов (этим занимаются такие программы как ArtMoney и др.), создании и реализации алгоритма целочисленного "универсального обманщика игр".
Задача: Найти адрес переменной в адресном пространстве целевого процесса. Ограничения: Для простоты рассматриваются целочисленные переменные размером dword, поиск проводится по младшему байту. 2. Идея: Организация поиска в страницах памяти, доступных для чтения и записи, целевого процесса начиная с адреса 010000h по 7FFF0000h [1]. Для получения информации о страницах памяти внешнего процесса естественно использовать VirtualQueryEx. Для чтения памяти - ReadProcessMemory. Поиск адресов происходит многопроходным образом, причем начальный этап отличается от остальных: сначала необходимо сохранить адреса всех байтов, имеющих заданное значение, далее сужать поиск по сохраненным адресам при изменении значения искомой переменной. Алгоритм верхнего уровня детализации для первого прохода выглядит так: 1. Получить описание страницы памяти чужого процесса; 2. ЕСЛИ страница принадлежит диапазону поиска то п. 3 ИНАЧЕ выход; 3. ЕСЛИ страница не доступна для чтения и записи ТО п. 5; 4. сохранить в список все адреса переменных, значения которых равны заданному; 5. Перейти к следующей странице и п. 1; Алгоритм последующих проходов: 1. Прочитать значение переменной по адресу из списка (в памяти исследуемого процесса); 2. ЕСЛИ значение равно заданному ТО п. 4; 3. Удалить адрес из списка; 4. ЕСЛИ список не закончился ТО Перейти к адресу следующей переменной и п. 1; 3. Алгоритм Общий алгоритм программы состоит из нескольких частей: Организация списка адресов. Так как заранее неизвестно количество найденных переменных при первом проходе (в дальнейшем оно будет уменьшаться), логично зарезервировать некоторый объем памяти, скажем 4*VARMAX, где VARMAX - это наибольшее возможное количество найденных переменных. Это число, на практике, небесконечно и определяется, с одной стороны, временем максимально долгого возможного поиска, а с другой, - достаточностью объема для проведения поиска. В среднем хватает 10*1024*1024 переменных. Причем, следует отметить, что при начальном поиске переменных со значением 0, велика вероятность нехватки указанного объема, по нескольким причинам, в том числе и из-за чтения зарезервированных областей (еще не используемых процессом), которые возвращают 0. Множитель 4 введен исходя из размера хранимого адреса переменной равного dword. Легко видеть что нет необходимости передавать всю зарезервированную память адресов сразу (это можно сделать при первом обращении к ней), т.о. можно считать подготовку списка адресов переменных завершенной: ;резервирование с передачей физической памяти при обращении. invoke VirtualAlloc,0,BSIZE,MEM_RESERVE+MEM_COMMIT,PAGE_R EADWRITE ;ЕСЛИ не удалось выделить память, ТО выход ;(далее для краткости обработка ошибок опускается) test eax,eax jz NotEnoughMem ;ИНАЧЕ сохранение адреса начала блока памяти. mov [addrbuffer],eax Примечание: здесь и далее программный код приводится в соответствии с синтаксисом flat assembler (fasm)[2]. Получение Handle процесса для чтения, записи. Предлагается следующий путь: Сначала получим Handle окна необходимого процесса, затем получим идентификатор процесса создавшего окно, затем "откроем" процесс для проведения операций с памятью. ;ebx содержит адрес названия необходимого окна. invoke FindWindow,0,ebx ;создать в стеке переменную, и передать ее адрес из esp в параметры push eax ;для получения идентификатора процесса invoke GetWindowThreadProcessId,eax,esp pop eax ;вынуть из стека результат. ;получить Handle процесса для операций с памятью invoke OpenProcess,PROCESS_QUERY_INFORMATION+PROCESS_VM_O PERATION+PROCESS_VM_READ+PROCESS_VM_WRITE,0,eax mov [hProcess],eax ;сохранить Handle открытого процесса. Организация считывания целевых (RW) страниц. Итак, по порядку: получаем адрес начала и размер текушей страницы памяти, проверяем права доступа на чтение и запись. Создаем блок памяти требуемого размера в текущем адресном пространстве (для копирования), читаем блок из исследуемого процесса в созданный блок. После отработки поиска байтов освобождаем уже не нужный блок. ;Сначала [fmbi.BaseAddress] = начальному адресу 10000h, ;а [fmbi.RegionSize] = 0, BaseAddress+RegionSize = адресу первого блока getblock: ;в дальнейшем BaseAddress+RegionSize = адресу следующего блока mov eax,[fmbi.BaseAddress] add eax,[fmbi.RegionSize] mov [address],eax ;прочитать состояние блока invoke VirtualQueryEx,[hProcess],[address],fmbi,MBIsz cmp [fmbi.Protect],PAGE_READWRITE ;проверить доступ jne getblock ;ЕСЛИ нет возможности чтения и записи, ТО перейти к новому блоку ;создать блок нужного размера блока invoke VirtualAlloc,0,[fmbi.RegionSize],MEM_COMMIT,PAGE_READWRITE mov [buffer],eax ;скопировать в него память исследуемого процесса invoke ReadProcessMemory,[hProcess],[fmbi.BaseAddress],eax,[fmbi.RegionSize],BytesRead ;... осушествить поиск и сохранение адресов ;освободить блок invoke VirtualFree,[buffer],0,MEM_RELEASE Сохранение адресов искомых переменных. Запустить сканирование до совпадения байта или конца строки, получить адрес совпадающего байта в пространстве искомого процесса (учитывая то, что поиск ведется в созданном блоке текущего процесса), сохранить адрес в списке. ;вход: ; ecx = edx = количеству прочитанных байт ; esi содержит адрес блока (в текущем адресном пространстве) ; edi - адрес списка ; ebx - адрес начала блока в адресном пространстве исследумого процесса lfind: xchg edi,esi repne scasb ;поиск до совпадения al с байтом из строки edi xchg edi,esi jne getblock;ЕСЛИ ничего не найдено ТО к следующему блоку ;Адрес = Адрес начала блока в исследуемом процессе + смещение в текущем ;Смещение в текущем = количество прочитанных байт edx - оставшиеся байты ecx neg ecx ;изменить знак lea eax,[edx+ecx] ;получить смещение dec eax ;учесть что считаем с 0, а не с 1 add eax,ebx ;добавить [fmbi.BaseAddress] stosd ;сохранить адрес в список адресов neg ecx ;проверить последний ли это байт jz getblock ;ЕСЛИ да ТО перейти к следующему блоку jmp lfind ;ИНАЧЕ проболжать поиск в текущем блоке Примечание: В [3] использование префиксов описано с ошибками. Определение действительных адресов искомых переменных (дальнейший поиск). Получить адрес из списка, прочитать память процесса, сравнить прочитанное значение с заданым, если 1= то удалить адрес. Последний раз редактировалось Deementor; 24.05.2007 в 10:51.. |
|
|
|
| Эти 4 пользователя(ей) сказали cпасибо за это полезное сообщение: |
| Реклама: | эустома букеты | барнхаус планировки размеры | Мебельный магазин: стол разделочный кухонный с ящиками - Переходи на сайт! | галтовочная установка для окрашивания деревянных деталей | Мебельный магазин: стол фаворит - Переходи на сайт! |
|
|
#2
|
|
echo, если не трудно выложите пожалуйста готовый исходник на FASM, заранее спасибо.
__________________
Проблема есть следствие ее решения... Чем больше я узнаю, тем больше чувствую себя дураком. |
|
|
|
|
![]() |
Похожие темы
|
||||
| Тема | Автор | Раздел | Ответов | Последнее сообщение |
| Сканер Mustek A3 EP | serg5255 | Компьютерные проблемы | 6 | 12.04.2017 23:35 |
| LPT-сканер + MB без LPT | Skirr | Компьютерные проблемы | 9 | 30.01.2010 12:57 |
| Можно ли на Z530i увеличить размер памяти СМС за счет карты памяти? | pcdos | Sony Ericsson | 0 | 24.02.2008 14:15 |
| Сканер! | masterdoc | Архив | 3 | 04.04.2006 00:38 |
|
|