101

Re: AHK: Карта памяти

YMP пишет:

А фиг его знает. Как я опять же уже писал, надо определить, где именно происходят потери времени, на каких операциях.

  Погонял усечённый код из сообщений выше.
Только сами по себе
Ret := DllCall("ReadProcessMemory" и If(!Ret) требуют 300 секунд.

102 (изменено: serzh82saratov, 2014-01-03 21:52:16)

Re: AHK: Карта памяти

использовать машинный код

Ну это для совсем посвящённых...
На нём кто-же писать умеет. В наше время и про ассемблер не каждый хакер слышал

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v20H2, AutoHotkey_L v1.1.34.01 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

103

Re: AHK: Карта памяти

Слышать-то слышал, хоть и не хакер, и про машинный код тоже. И даже когда-то пытался изучить. Вот только больших успехов не достиг.  (

104

Re: AHK: Карта памяти

Off:
Да, и я про то что слышали-то многие, а кто же сейчас умеет-то такое. Да чтобы ещё и быстрее было, а то можно и медленнее легко наваять.
Только совсем "бородатые", кто с самых Windows 1.0 (1985) начинал...
Один только YMP и остался наверное. А правильных вопросов задать, да научится, некому.
Канет в Лету ремесло, а актуальность останется.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v20H2, AutoHotkey_L v1.1.34.01 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

105

Re: AHK: Карта памяти

Вы про что это тут? Никто не предлагает писать на машинном коде. Он копируется из отладчика или из вывода дизассемблера. А исходник может быть на С, например. Да и в ассемблере ничего страшного нет. Инструкции там простые, число туда, число сюда.

Только сами по себе
Ret := DllCall("ReadProcessMemory" и If(!Ret) требуют 300 секунд.

А какой у вас конкретно код, можно увидеть?

106

Re: AHK: Карта памяти

Он копируется из отладчика или из вывода дизассемблера.

Не про этот, он не адаптирован. Ассемблер, он же "простой" алгоритм, в нём много излишнего.
Я про чистый машинный код написанный от руки.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v20H2, AutoHotkey_L v1.1.34.01 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

107

Re: AHK: Карта памяти

serzh82saratov, отрезал нашу беседу в отдельную тему: OFF: Про ассемблер.

108 (изменено: Next, 2014-01-04 03:29:53)

Re: AHK: Карта памяти

YMP пишет:

Вы про что это тут? Никто не предлагает писать на машинном коде. Он копируется из отладчика или из А какой у вас конкретно код, можно увидеть?

   Вот надёргал кое-что из этой темы и других, слепил как сумел.

SetBatchLines, -1
SetFormat, Integer, H

ProcessName := "Notepad.exe"
start := 0x00000000
end :=   0x80000000
ReadSize := 4


VarSetCapacity(Buf, ReadSize,0)  ; Буфер, куда считывать.
PROCESS_VM_READ = 0x10            ; Права на процесс.
Process, Exist, %ProcessName%     ; Поиск процесса.
If(!ErrorLevel)
    {
    MsgBox, Процесс не найден.
    ExitApp                   
    }
PID := ErrorLevel                 ; Идентификатор процесса будет в ErrorLevel.
hProcess := DllCall("OpenProcess", UInt, PROCESS_VM_READ
                                , Int, False
                                , UInt, PID)

If(!hProcess)
    {
    MsgBox, Не удалось открыть процесс.
    ExitApp                            
    }


index := -1 
time := A_now
Loop, %end%
    {    
    index := index + 1
    ReadAdres := start + index    
    Ret := DllCall("ReadProcessMemory", UInt, hProcess
                                    , UInt, ReadAdres
                                    , UInt, &Buf
                                    , UInt, ReadSize
                                    , UInt, 0)
    if (index > end)
        Break
    
    If(!Ret)
        {
        index := index + 0x100 ;jump
        continue
        }
    }

time := A_now - time
MsgBox, time %time%

jump - раз не определены границы регионов, используется для максимальной скорости прохода нечитаемых зон.
     Для теста, ИМХО, вполне достаточно.

  Для разных приложений от 300 до 1500 секунд получается.

109

Re: AHK: Карта памяти

YMP пишет:

Вы про что это тут? Никто не предлагает писать на машинном коде. Он копируется из отладчика или из вывода дизассемблера.

  Что именно нужно дизассемблировать?  ArtMoney?

110

Re: AHK: Карта памяти

Next пишет:

  Что именно нужно дизассемблировать?  ArtMoney?

Нет, конечно. Я имел в виду, что реализуется некий алгоритм, например поиска числа в буфере, на том же ассемблере или С, а потом машинный код этой функции внедряется в скрипт АНК и оттуда вызывается. Суть в том, что тут уже функции самого АНК оказываются незадействованными, т.е. убирается вся их обвязка. Например, переменные в АНК хранятся в виде строк. Т.е. читая число из памяти, АНК должен преобразовать его в строку. Зачем это нужно при поиске числа в буфере? Низачем. Но на это тратится время. Считать число из памяти в регистр — это одна инструкция процессора, а преобразовать в строку и записать в переменную — ещё несколько инструкций. А для чего это делать в данном случае? Чистая потеря времени.

111

Re: AHK: Карта памяти

ReadSize := 4

Зачем читать по 4 байта, если можно по 4 килобайта? Я же выше писал, что память выделяется страницами.

index := index + 0x100 ;jump

Почему именно на 0x100? В общем, вы действуете наугад, поэтому хреноватый результат неудивителен.

112 (изменено: YMP, 2014-01-04 09:47:43)

Re: AHK: Карта памяти

Вот моя попытка оценить время чисто на чтение из процесса. Мой результат для Explorer.exe:

Прочитано 51608 страниц за 3 сек.


SetBatchLines, -1
ProcessName = explorer.exe
Start := 0, End := 0x80000000, Page := 0x1000
Pages := Ceil((End - Start) / Page)
Rights := 0x10  ; PROCESS_VM_READ
VarSetCapacity(Buf, Page)

Process, Exist, %ProcessName%
If !(PID := ErrorLevel) {
    MsgBox, Процесс не найден.
    ExitApp
}
hProcess := DllCall("OpenProcess", UInt, Rights
                                 , Int, False
                                 , UInt, PID, "Ptr")

If(!hProcess) {
    MsgBox, Не удалось открыть процесс.
    ExitApp                            
}

StartTime := A_TickCount, PagesRead := 0, CurAddr := Start - Page

Loop, %Pages%
{
    CurAddr += Page
    If ! DllCall("ReadProcessMemory", Ptr, hProcess
                                    , Ptr, CurAddr
                                    , Ptr, &Buf
                                    , Ptr, Page
                                    , Ptr, 0)
        Continue
    ++PagesRead
}
Time := (A_TickCount - StartTime) // 1000
MsgBox, Прочитано %PagesRead% страниц за %Time% сек.

113

Re: AHK: Карта памяти

Быстро получается, но я что-то совсем перестал понимать смысл происходящего.
  Как теперь читать Buf размером 4К? Разве её можно парсить прямо в двоичном виде? Так может тогда можно обойтись и без Num(),  не переводить всё в Hex , а как-то заранее преобразовать нужные значения, которые ищутся, в двоичный вид  и сравнивать в таком виде при парсинге Buf?

114

Re: AHK: Карта памяти

Разумеется, в Хекс или любой другой строковый формат переводить ни к чему. Это нужно только для представления данных человеку. Двоичный поиск как раз и логично поручить машинному коду.

115

Re: AHK: Карта памяти

Дело за малым, изучить применение машинных кодов, написать программу, и суметь уговорить AHK иметь с ней дело. Реально человеку за месяц с этим управится? Или даже пытаться не стоит?

116

Re: AHK: Карта памяти

Нет, имеется в виду программа (скрипт) на АНК. Машинный код будет в одной из функций в виде хекс-строки. В Коллекции есть тема "Ускорение скриптов машинным кодом", там видна вся технология. При первом вызове функции хекс-строка пишется в буфер уже в виде двоичного кода, а потом код будет вызываться через DllCall, по его адресу.

117

Re: AHK: Карта памяти

Посмотрел эту тему. Сразу тоже не особо разберёшься, но убуду пытаться, спасибо.   Вторая часть кода приведена ведь только для пояснения?  Там ничего не устарело с 2009г? А то у меня выдаёт в Msg нули в результатах.

118

Re: AHK: Карта памяти

Если в АНК64 запускаете, то результат предсказуем. Машинный код различается для х86 и х64.
Функцию поиска в буфере я вам могу написать. Думаю, даже если поиск будет в лоб, без хитрых алгоритмов, всё равно будет выигрыш в скорости. Что именно вы хотите искать в памяти процесса?

Если какое-то изменяемое программой значение, то опять же прихожу к мысли об использовании VirtualQueryEx, чтобы с её помощью сразу отбрасывать участки с атрибутом исполнения или только для чтения.

119

Re: AHK: Карта памяти

YMP пишет:

Если в АНК64 запускаете, то результат предсказуем. Машинный код различается для х86 и х64.
Функцию поиска в буфере я вам могу написать.

   Годный и для х86 и х64? Огромное спасибо!

Что именно вы хотите искать в памяти процесса?

    Конкретные значения размером в 4 и 8 байт. Можно и только по 4, если это сократит время работы над кодом.  Думаю, что их можно задавать в AHK в Hex, а он преобразует их в двоичные и передаст в функцию с машинным кодом.

Если какое-то изменяемое программой значение, то опять же прихожу к мысли об использовании VirtualQueryEx, чтобы с её помощью сразу отбрасывать участки с атрибутом исполнения или только для чтения.

    Эти значения действительно могут меняться, но при пролистывании нечитаемых регионов по 0x1000, никаких дополнительных проверок не нужно, временные затраты на это совершенно незначительны и не стоят того чтобы отдельно заморачиваться.

120

Re: AHK: Карта памяти

Next пишет:

    Эти значения действительно могут меняться, но при пролистывании нечитаемых регионов по 0x1000, никаких дополнительных проверок не нужно, временные затраты на это совершенно незначительны и не стоят того чтобы отдельно заморачиваться.

Так дело не в затратах, а в том, что какой вам прок от числа, если это часть кода программы, например? Это же явно не то, что вы ищете, вам нужны числа из области данных.

121

Re: AHK: Карта памяти

На ваше усмотрение.

122

Re: AHK: Карта памяти

А вы учитываете, что этих чисел может быть не одно, а много и даже очень много? Что ожидается от функции в этом случае?

123

Re: AHK: Карта памяти

Получиться обычно от одного до ста.  Дальше я могу с помощью уже приведенного тут кода, проверить соседние адреса на совпадение с нужным значением. Проверить 400-500 значений  - это довольно быстро.

124

Re: AHK: Карта памяти

Что значит "обычно"? Это число вообще где угодно может встретиться и вовсе не являться тем самым числом, которое вы ищете.

Т.е. задача функции найти одно такое число, и всё? И вернуть его адрес в памяти того процесса? Или что?

125

Re: AHK: Карта памяти

Под "обычно" имелось ввиду то, что я уже раз 200 сканировал память этого приложения и те значения, которые я ищу встречались не настолько часто чтобы это было проблемой.  Понятно, что если бы это было 0xFFFFFFFF, или 0x000000FF, то картина была бы совсем другая, но к счастью это не так.
  Уверяю Вас не стоит уделять внимания дополнительной идентификации найденных адресов, я с этим легко справлюсь.  Список найденных адресов с заранее заданным значением - это всё что мне нужно.  Если Вы затрудняетесь с выбором типа хранения этих данных, то можете смело рассчитывать что более 100 значений там не будет.

Всё что мне нужно - я задаю значение и получаю список адресов с ним, или подтверждение отсутствия таких адресов. Ничего более не нужно. 

   Единственный вопрос в том, что не всегда эти адреса будут кратны четырём байтам.  Адрес может быть как и 0x01DFE000, и 0x7FA12345. Надеюсь, что излишних затруднений в написании кода этот факт у Вас не вызовет.

126

Re: AHK: Карта памяти

Next пишет:

Список найденных адресов с заранее заданным значением - это всё что мне нужно.

Вот, это я и хотел узнать.

Если Вы затрудняетесь с выбором типа хранения этих данных, то можете смело рассчитывать что более 100 значений там не будет.

Про число понял, про тип не понял. В каком виде должен быть возвращён этот список, решать вам. Вы же будете его дальше использовать.

Единственный вопрос в том, что не всегда эти адреса будут кратны четырём байтам.  Адрес может быть как и 0x01DFE000, и 0x7FA12345. Надеюсь, что излишних затруднений в написании кода этот факт у Вас не вызовет.

Нет, это проблема небольшая. Но что уточнили — это правильно.

127 (изменено: Next, 2014-01-04 20:45:44)

Re: AHK: Карта памяти

Надо как-то их нумеровать чтобы к ним обращаться. Массив с количеством элементов до 100? Или просто переменная с номером типа var%number%? Подойдёт  и то, и то. Будут это строки, или числа неважно, ведь дальше всё в AHK.

128

Re: AHK: Карта памяти

Трудно даётся?

129

Re: AHK: Карта памяти

На другие дела пришлось отвлекаться. Функция написана, сейчас надо проверять, и, разумеется, косяки полезут, надо будет исправлять.

130 (изменено: YMP, 2014-01-13 17:57:08)

Re: AHK: Карта памяти

На 100% не уверен, что всё чики-пуки, но вроде работает. В начале идёт пример вызова и проверочный код, сама функция ниже. Ищется, собственно, последовательность байт заданной длины, поэтому число сперва пишется в буфер, а функции передаётся указатель на буфер и длина искомого. Строки, по идее, можно передавать непосредственно, если они передадутся в нужной кодировке, а если нет, то так же писать в буфер функцией StrPut с перекодировкой. Но строки я пока не пробовал искать.

Если вы ищете, скажем, число 0x44444444, а в памяти есть последовательность из 6 байт 44 44 44 44 44 44, то найдено будет 3 адреса: для 44 44 44 44 хх хх,  для хх 44 44 44 44 хх и для хх хх 44 44 44 44.  Т.к. не известно, с какого именно байта начинается ваше число.

Мой результат при запуске кода ниже:


0.438000 сек. Найдено 15269

Число 0x44444444 оказалось очень популярным в памяти Проводника.


SetBatchLines, -1

ProcessName := "explorer.exe"
Start := 0, End := 0x80000000
Number := 0x44444444    ; Число для поиска.
cbTarget := 4   ; Длина искомого в байтах. По умолчанию 4.
VarSetCapacity(Target, cbTarget)
NumPut(Number, Target, 0, "uint")
cAddrs := 100000    ; Сколько адресов искать. По умолчанию 100.

; Поиск. Функция вернёт массив адресов либо 0, если ничего не найдено.
StartTime := A_TickCount
Found := SearchProcess(ProcessName, Start, End, &Target, cbTarget, cAddrs)
Time := (A_TickCount - StartTime) / 1000
If (Found = 0) {
    MsgBox, %Time% сек. Ничего не найдено
    ExitApp
}
Else {
    MsgBox, % Time " сек. Найдено " Found.MaxIndex()
}

; Проверка. Читаются числа по найденным адресам и сравниваются с заданным.
Process, Exist, %ProcessName%
If !(PID := ErrorLevel) {
    MsgBox, Процесс не найден.
    ExitApp
}
hProcess := DllCall("OpenProcess", "uint", 0x10, "int", False, "uint", PID, "ptr")
If (!hProcess) {
    MsgBox, Не удалось открыть процесс.
    ExitApp
}
VarSetCapacity(TestBuf, cbTarget, 0)
Matches = 0
Loop, % Found.MaxIndex()
{
    Ret := DllCall("ReadProcessMemory", "ptr", hProcess, "ptr", Found[A_Index]
                                             , "ptr", &TestBuf, "ptr", cbTarget
                                             , "ptr *", BytesRead, "int")
    If (!Ret) {
        MsgBox, Не удалось прочитать.
        Break
    }
    Number2 := NumGet(TestBuf, 0, "uint")
    If (Number2 = Number) {
        ++Matches
    }
}
DllCall("CloseHandle", "ptr", hProcess)
MsgBox, Совпадений %Matches%


; ============================== Функция =======================================

SearchProcess(NameOrPID, StartAddr, EndAddr, pTarget, cbTarget = 4, cAddrs = 100)
{
    static Code := 0, MFunc, Len, Page := 0x1000, mbi, mbiSize
    static stateOffset, protOffset, regSizeOffset
    static Rights := 0x410  ; PROCESS_VM_READ | PROCESS_QUERY_INFORMATION
    static MEM_COMMIT := 0x1000, PAGE_READWRITE := 4, PAGE_READONLY := 2
    static PAGE_WRITECOPY := 0x08
    static BufSize := 0x100000  ; 1 MB. Размер буфера для чтения из процесса.
    If (Code != 0)  ; Если не первый вызов, то машинный код уже готов.
        GoTo Process
    If (A_PtrSize = 8) {    ; x64
        mbiSize := 48, stateOffset := 32, protOffset := 36, regSizeOffset := 24
        Code = 
        ( Join LTrim
        48894C240848895424104C894424184C894C2420555357564889E54883EC08488B
        7D288B4D308B5540488B5D48C745F800000000FFCA29D1783B488B7538ACF2AE75
        325189D1F3A60F94C04829D14801CF5984C0741B488D47FF482B45284803455848
        89034883C308FF45F8FF4D50740485C975C58B45F8488D65005E5F5B5DC3
        )
    }
    Else {      ; x86
        mbiSize := 28, stateOffset := 16, protOffset := 20, regSizeOffset := 12
        Code = 
        ( Join LTrim
        5553575689E583EC048B7D148B4D188B55208B5D24C745FC000000004A29D17833
        8B751CACF2AE752B5189D1F3A60F94C029D101CF5984C074168D47FF2B45140345
        2C890383C304FF45FCFF4D28740485C975CD8B45FC89EC5E5F5B5DC21C00
        )
    }
    Len := StrLen(Code) // 2
    ; Память под машинный код.
    MFunc := DllCall("VirtualAlloc", "ptr", 0, "ptr", Len
                                   , "uint", 0x3000, "uint", 0x40, "ptr")
    Loop, % Len
        NumPut("0x" . SubStr(Code, A_Index * 2 - 1, 2), MFunc + 0
                                     , A_Index - 1, "uchar")
    VarSetCapacity(mbi, mbiSize) ; Структура MEMORY_BASIC_INFORMATION
Process:
    Process, Exist, %NameOrPID%
    If !(PID := ErrorLevel) {
        MsgBox, Процесс не найден
        Return 0
    }
    hProcess := DllCall("OpenProcess", "uint", Rights, "int", False, "uint", PID, "ptr")
    If(!hProcess) {
        MsgBox, Не удалось открыть процесс.
        Return 0                           
    }
    VarSetCapacity(AddrBuf, A_PtrSize * cAddrs, 0) ; Буфер для найденных адресов.
    VarSetCapacity(Buf, BufSize) ; Буфер для считанной из процесса памяти.
    CurAddr := (StartAddr // Page) * Page ; Текущий адрес. Округлить до начала страницы.
    pAddrBuf := &AddrBuf ; Указатель на свободное место в буфере адресов.
    FoundAll := 0 ; Всего найдено.

    While(CurAddr < EndAddr) {
        BytesRet := DllCall("VirtualQueryEx", "ptr", hProcess, "ptr", CurAddr
                                            , "ptr", &mbi, "uint", mbiSize, "ptr")
        If (BytesRet = 0) {
            CurAddr += Page
            Continue
        }
        RegionSize := NumGet(mbi, regSizeOffset, "uptr")
        ; Если память не выделена (адреса свободны или только зарезервированы),
        ; пропускаем весь этот регион.
        If (NumGet(mbi, stateOffset, "uint") != MEM_COMMIT) {
            CurAddr += RegionSize
            If (A_PtrSize = 4 && CurAddr > 0xFFFFFFFF)
                GoTo Done
            Continue
        }
        Protect := NumGet(mbi, protOffset, "uint")
        ; Проверять только память для записи и чтения (данные).
        If !(Protect = PAGE_READWRITE || Protect = PAGE_WRITECOPY
                                      || Protect = PAGE_READONLY) {
            CurAddr += RegionSize
            If (A_PtrSize = 4 && CurAddr > 0xFFFFFFFF)
                GoTo Done
            Continue
        }
        While(RegionSize) { ; Считывание в буфер и поиск в нём.
            ReadSize := BufSize < RegionSize ? BufSize : RegionSize
            RegionSize -= ReadSize
            Ret := DllCall("ReadProcessMemory", "ptr", hProcess, "ptr", CurAddr
                                              , "ptr", &Buf, "ptr", ReadSize
                                              , "ptr *", BytesRead, "int")
            If (!Ret) { ; Если ошибка чтения, идём дальше.
                CurAddr += ReadSize
                Continue
            }
            ; Вызов машинной функции для поиска.
            Found := DllCall(MFunc, "ptr", &Buf, "ptr", BytesRead
                                  , "ptr", pTarget, "uint", cbTarget
                                  , "ptr", pAddrBuf, "uint", cAddrs - FoundAll
                                  , "ptr", CurAddr, "uint")
            CurAddr += ReadSize
            If (Found = 0) {
                Continue
            }
            If ((FoundAll += Found) < cAddrs) {
                pAddrBuf += Found * A_PtrSize
                Continue
            }
            Goto Done
        }
    }
Done:
    DllCall("CloseHandle", "ptr", hProcess)
    If (FoundAll = 0)
        Return 0
    Array := []
    Loop, %FoundAll%
        Array.Insert(NumGet(&AddrBuf+(A_PtrSize * (A_Index - 1)), 0, "uptr"))
    Return Array    
}

131

Re: AHK: Карта памяти

Кстати, разделение памяти на 2 нижних пользовательских ГБ и два верхних системных актуально для 32-битных процессов. В 64 битах как-то по-другому, насколько я понимаю, но не знаю подробностей. Так что с определением зоны поиска не всё так просто может быть.

132

Re: AHK: Карта памяти

Даже чисто визуально, приличный объём работы. Огромное спасибо! Буду разбираться.

133

Re: AHK: Карта памяти

Бегло просмотрел, позапускал. Отвечает действительно почти мгновенно. Но я пока не нашёл в чём хранится результат - собственно сам список найденных адресов.

134

Re: AHK: Карта памяти

В массиве, который возвращает функция. Доступ по индексу: Found[1], Found[2] и т.д. Количество: Found.MaxIndex(). Если ничего не найдено, возвращается просто число 0.

135

Re: AHK: Карта памяти

Проверил пока только  на x64. Пока всего пару тестов, но работает ВЕЛИКОЛЕПНО!
  Спасибо!

136

Re: AHK: Карта памяти

Немного исправил, чтобы вызовы OpenProcess возвращали тип "ptr".

Я проверял поиск из 32-битного скрипта в 64-битном процессе. Вроде проблем нет, и время то же. Но, конечно, на 64-битной ОС надёжнее будет запускать в АНК 64. И, само собой, если поиск пойдёт выше адреса 0xFFFFFFFF, то и выбора нет.

137

Re: AHK: Карта памяти

YMP, если вызывать по горячей клавише, через пару вызовов всё перестаёт работать. Очевидно какая-то переменная не обновляется.
  Остановка происходит на линии

BytesRet := DllCall("VirtualQueryEx", "ptr", hProcess, "ptr", CurAddr

Посмотрите, пожалуйста, что с этим можно сделать.

138

Re: AHK: Карта памяти

Наоборот, не сохранялись три переменные. Забыл их объявить статическими.
Код выше я исправил, сейчас должно работать.

139

Re: AHK: Карта памяти

Ещё пара вопросов по оптимизации.
  Я обращаюсь к этом поиску  каждые 5-10 секунд. И ещё на основании полученных данных,  каждые 2-3 секунды читаю "обычным способом"  по 200-300 ячеек памяти.  Получается что все проверки процесса, открытия, закрытия производятся

VarSetCapacity
...
hProcess := DllCall("OpenProcess", 
...
DllCall("CloseHandle", 

по несколько тысяч раз за 5-10 секунд.

  Как правильно организовать процесс, чтобы этого избежать?  Возможно стоит один раз при запуске программы задать объём переменных, найти процесс, открыть его и закрывать только при закрытии программы или при постановке на паузу?  Или лучше это делать перед каждой "порцией" чтения?

140

Re: AHK: Карта памяти

При чтении 200-300 для каждой ячейки открываете и закрываете процесс? Если да, то, конечно, лучше делать это один раз для всей группы.

141

Re: AHK: Карта памяти

А что мешает сделать один раз при запуске программы и держать всё в таком виде 7-8 часов? В чём суть этих открытий/закрытий?  Это как-то нагружает память или ещё чем-то может проявится?

142

Re: AHK: Карта памяти

Да ничто не мешает, сделайте один раз.

143 (изменено: Next, 2014-12-28 20:08:30)

Re: AHK: Карта памяти

Привет!

Какая-то странная проблема у меня появилась с

Ret := DllCall("ReadProcessMemory", UInt, hProcess
                                    , UInt, ReadAdres
                                    , UInt, &Buf
                                    , UInt, ReadSize
                                    , UInt, 0)

Несколько минут программа работает нормально и вдруг при чтении того же самого адреса в очередной, иногда тысячный раз, вдруг ret становится нулевым.  Поставил до 20 повторов чтения того же адреса с задержкой в 100мс. Выдаёт то же самое. А потом через паузу опять 1000 раз может прочитать адрес нормально, а потом снова такой сбой.

Чем это может быть вызвано?

Проверял этот участок памяти с помощью "Cheat Engine". Ничего в нём особого не происходит. Значение по адресу, как и обычно меняется время от времени, и всё.

144

Re: AHK: Карта памяти

А битности процессов какие? Того, что читает, и того, откуда читаете.

145

Re: AHK: Карта памяти

ahk - x64
исследуемый - x32

146

Re: AHK: Карта памяти

Попробуйте в вызове ReadProcessMemory все UInt заменить на Ptr.

147

Re: AHK: Карта памяти

Не помогло. Конвертация в x32 exe тоже не помогла.

148 (изменено: YMP, 2014-12-29 16:07:25)

Re: AHK: Карта памяти

Тогда не знаю. Остаётся погуглить на тему проблем с ReadProcessMemory.

Да, ещё можно посмотреть код ошибки в переменной A_LastError.

149

Re: AHK: Карта памяти

Код ошибки всё время "6".

150

Re: AHK: Карта памяти

И ещё вопрос к ситуации. Если я при обнаружении ошибки отправляю в цикл с задержкой и возвратом на чтение адреса, то в течение 3-5 секунд непрерывно идёт ошибка. А если просто пропустить выполнение функций зависящих от результата чтения, и через 3 секунды прочитать тот же адрес, то обычно читается нормально. Мне кажется в этой особенности работы что-то кроется, а что понять не могу.

151

Re: AHK: Карта памяти

6 — это, видимо, ERROR_INVALID_HANDLE. Вы через эти самые 3 секунды, hProcess заново получаете или тот же самый используете, у которого непрерывная ошибка была? Вообще, hProcess проверяете?

152

Re: AHK: Карта памяти

hProcess проверяется при запуске и потом непрерывно раз в 50-70 мс. При зацикливании он не проверяется, поскольку у подпрограммы откуда читаются адреса статус "Critical". А при нормальном ходе процедуры он скорее всего успевает проверяться. Тут ещё и CloseHandle не всё ясно. Когда его правильно применять? У меня он стоит в конце одной из подпрограмм. Наверное возможны ситуации когда я читаю адрес уже после CloseHandle. Из-за этого возможен такой эффект?

  Да, проблема где-то здесь. Написал отдельную программу, которая только и делает, что читает известный заранее адрес в том же самом процессе. За 10 минут - ни одной ошибки.

153

Re: AHK: Карта памяти

Проверку я имел в виду при получении hProcess. Если, скажем, хэндл закрывается, потом опять процесс открывается, чтобы хэндл по-новой получить.
Если хэндл закрыть, то он станет недействительным, так что вполне логична такая ошибка.

154

Re: AHK: Карта памяти

Да, была путаница в открытиях/закрытиях. Спасибо за помощь!

155

Re: AHK: Карта памяти

Интересная тема. А можно всё-таки создать файл именно с картой памяти? Не обязательно сразу всё писать в файл, допустим стартовать по нажатию клавиши быстро считать память, а потом уже записывать всё в файл в виде карты, чтобы были видны не только значения, а и адреса.
А как запишется, можно и следующее нажатие производить. Реально так сделать?

156

Re: AHK: Карта памяти

Этот вариант смотрел?

Win 7 x64
AHK v1.1.33.02
                       Справка тебе в помощь.

157

Re: AHK: Карта памяти

Этот намного быстрее. Всего чуть-чуть не хватает. Ещё бы разика в полтора ускорить.

158

Re: AHK: Карта памяти

Не посмотрел, что изначально стоит намного меньший объём чтения памяти, чем в первом коде. На самом деле чрезвычайно читается медленно.

159

Re: AHK: Карта памяти

А конечная ваша цель какова? Для чего эта карта памяти? Может, можно решить задачу не в лоб, с меньшими затратами ресурсов.

160 (изменено: Kurskador, 2016-03-29 22:37:24)

Re: AHK: Карта памяти

Я хочу поймать данные, которые появляются на короткое время и потом удаляются. А также отследить механизм их формирования. Сделать это в реальном времени затруднительно. Поэтому хотелось бы читать за 3-5 секунд всю память, записывать в файл, а потом спокойно ковырять без спешки полученное, и сравнивать снимки памяти в разные моменты времени.
  Первоочередная задача - получить снимок памяти размером 100-200 мб за 3-5 секунд, пока там не произошли значительные изменения.

161

Re: AHK: Карта памяти

Нет шансов?

162

Re: AHK: Карта памяти

А делать заморозку процесса перед дампом памяти - не вариант?

163

Re: AHK: Карта памяти

Не в курсе как это делается. И боюсь, что это сильно нарушит всё, что будет происходить потом, а это важно. Хотелось бы иметь инструмент не мешающий работе программы.

164

Re: AHK: Карта памяти

Kurskador пишет:

Нет шансов?

Есть несколько вопросов. Как должна выглядеть нужная вам для этого функция? Т.е. какие аргументы вы хотите ей передавать при вызове и что она должна возвращать. Во-вторых, как должен выглядеть снимок памяти? Можно сохранить его в бинарный файл или надо преобразовать в хекс-строку и как-то отформатировать для удобства чтения.

Всю память сохранять явно не нужно, т.к. вам требуются только данные, причём не все, а только те, которые можно изменять.

165 (изменено: Kurskador, 2016-03-30 19:51:30)

Re: AHK: Карта памяти

Я представляю себе код, в который можно нужное вписать имя процесса. Старт чтения должен начинаться по нажатию горячих клавиш. Время чтения, чем меньше тем лучше, но желательно не более 3-5 секунд. В конечном результате хотелось бы иметь то же самое, что дают уже имеющие здесь скрипты: текстовый файл с разбивкой по рядам адресов и их значений. Можно как-то явно отделять одни части памяти от других, делать маленькие отступы в местах нечитаемой памяти. Как это будет конкретно осуществлено мне не принципиально. Наверное сначала быстрее читать в бинарном виде, как-то сохранять, а потом уже преобразовывать в описанный выше вид. Длина паузы в работе программы на преобразование и запись в удобном виде, если она не превысит 30-50 секунд,  значения не имеет.

Наверное не стоит разбивать файлы на части, чтобы было удобнее искать что нужно. Есть программы, которые читают большие текстовый файлы без проблем.

Это моё представление о том как было бы здорово. Если Вы сможете осуществить это хотя бы в каком-то приближении, то я буду очень благодарен.

166

Re: AHK: Карта памяти

YMP, я правильно понимаю, что Вы пытаетесь как-то реализовать обсуждаемое? Или я напрасно жду и надеюсь?

167

Re: AHK: Карта памяти

Пока что не было возможности заняться. Кроме того хотел уточнить: вас устроит только бесплатная помощь? Если да, то не уверен, что мне хватит мотивации. "Нет уже того энтузиазма". (с) К сожалению.

168

Re: AHK: Карта памяти

Жаль. Спасибо, что ответили, а то я почему-то подумал, что раз расспросили, то пытаетесь реализовать, и уже губу раскатал и в таком виде ждал.

169

Re: AHK: Карта памяти

А идея вообще-то интересная. Не знаю может ли мой, ранее осуществленный взнос в поддержку форума, считаться некоторым вкладом в мотивацию? Если может, то мне было бы очень интересно владеть таким инструментом, который может получиться на основе изложенных идей.

170

Re: AHK: Карта памяти

Мог бы, если бы я был владельцем форума.

171

Re: AHK: Карта памяти

YMP, если есть предложения, то Вы можете мне написать личным сообщением.

172

Re: AHK: Карта памяти

Имеете в виду какие-нибудь предложения по форуму? Нет, речь не об этом. Тут был вопрос, может ли взнос в поддержку форума быть для меня мотивацией к написанию кода. Я и говорю, что если бы форум был мой, тогда да, но он же не мой.

173

Re: AHK: Карта памяти

В такой постановке вопроса он вообще получается ничей, полная сумма взносов идёт только на хостинг, и ни копейки в карман владельца, а по сути человека который это всё организовал и поддерживает безвозмездно.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v20H2, AutoHotkey_L v1.1.34.01 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

174

Re: AHK: Карта памяти

OFF:
Вообще-то человек, который организовал, уже не поддерживает. Форум общий, взносы общие, поддержкой занимаемся безвозмездно. Одним словом, коммунизм.

175

Re: AHK: Карта памяти

Kurskador пишет:

Я всё ещё жду ответа.

Если вы про личное сообщение, то я на него ответил ещё 13 числа. Ответ должен был прийти к вам на почту, которую вы указали, когда здесь регистрировались.

176 (изменено: YMP, 2016-04-19 18:34:35)

Re: AHK: Карта памяти

Kurskador
Вынужден опять в теме писать, т.к. на почту вам ответить не получается.

Это письмо создано автоматически сервером Mail.Ru, отвечать на него не нужно.

К сожалению, Ваше письмо не может быть доставлено одному или нескольким получателям:

Другого какого-то ящика нет у вас?

177

Re: AHK: Карта памяти

+ открыть спойлер
Alectric пишет:

Спасибо.
Сейчас попробую.



Later:
Объем: 0x500000            ; 5 mB
Время работы: 2979     ; 3 sec       1,6 mB/sec

Только почему-то считало 4 mB вместо 5-и. (судя по адресу)
А-а, понял, просто у блокнота пусто после 4-х mB.

+ открыть спойлер
#SingleInstance,Force
#NoEnv
SetFormat, Integer, H
onexit,exit
SetBatchLines,-1

starttime:=a_tickcount

ProcessName = notepad.exe         ; Имя процесса.
StartAdres:=ReadAddress:= 0x0             ; Адрес, откуда читать.
ReadSizeL = 1280             ; Сколько байт читать.
ReadSize = 4096
EndAdres:=ReadAddress+ReadSizeL*ReadSize
new:=1
savefile=map_%ProcessName%_%new%.txt

    tooltip,Начальный адрес: %StartAdres%`nТекущий адрес: "%ReadAddress%"`nКонечный адрес: %EndAdres%`nEsc - для отмены.
;file := FileOpen(savefile, "w")
;if !IsObject(file)
;{
;    MsgBox Can't open "%FileName%" for writing.
;    return
;}


map=__________ | 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F`n______________________________________________________`n%ReadAddress% |

VarSetCapacity(Buf, ReadSize, 0)  ; Буфер, куда считывать.

PROCESS_VM_READ = 0x10            ; Права на процесс.

Process, Exist, %ProcessName%     ; Поиск процесса.

If(!ErrorLevel) {
  MsgBox, Процесс не найден.
  ExitApp
}

PID := ErrorLevel                 ; Идентификатор процесса будет в ErrorLevel.

hProcess := DllCall("OpenProcess", UInt, PROCESS_VM_READ
                                 , Int, False
                                 , UInt, PID)
If(!hProcess)
{
  MsgBox, Не удалось открыть процесс.
  ExitApp
}

loop,%ReadSizeL%  ; \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
{
  c++
  if c>5000
  {
    c=
    tooltip,Начальный адрес: %StartAdres%`nТекущий адрес: "%ReadAddress%"`nКонечный адрес: %EndAdres%`nEsc - для отмены.
  }

  Ret := DllCall("ReadProcessMemory", UInt, hProcess
                                    , UInt, ReadAddress
                                    , UInt, &Buf
                                    , UInt, ReadSize
                                    , UInt, 0)

  If(Ret)
  {
    loop,%ReadSize%
    {
      char:=  NumGet(Buf, a_index-1, "UChar")
;tooltip, % char "`n" a_index  ; Считывание из буфера в переменную.
      stringtrimleft,char,char,2
      StringLen,len,char
      if len<2
        char:=" 0"char
      else
        char:=" "char

      r++
      if r<17
        map.=char
      else
      {
        r=1
        map.="`n" ReadAddress+a_index-1 " | " char
      }
    }
    fileappend,%map%,%savefile%
    map=
  }

ReadAddress+=ReadSize
}
map.="`n`n"
fileappend,%map%,%savefile%
gosub,exit

~esc::
exitapp
return

exit:
DllCall("CloseHandle", UInt, hProcess) ; Освобождение хэндла процесса.
SetFormat, Integer, D
end:=a_tickcount-starttime
Msgbox,Время работы: %end%
exitapp

Спасибо ТС-у за эту тему, давно хотел с памятью поработать.

  А можно добавить ещё и запись в файл в  изначальном виде? Насколько я понимаю осуществлять поиск каких-то слов, значений в нём, посредством того же "Cheat engine" будет намного проще, чем в текстовом файле, где всё разбито на строки. А потом уже можно будет сопоставить с конкретными адресами.
Это же не должно сильно замедлить весь процесс?