1

Тема: AHK: Запись строки в память

Здравствуйте! Просьба. Необходимо записать строку текста в память процесса. Уверен, сделать это просто, т.к. в том же CheatEngine это дело пары кликов.
Суть: Есть процесс (primer.dll или primer.exe, не принципиально), адрес памяти (конкретный) - например, 07831A6E. Тип данных в нем - текст. Самому мучаться - устал уже.
Буду благодарен, если напишите готовую функцию. Я пытался сделать такого типа: WriteText(text, address) и ReadText(text, address) << ничего не получается. Числовые значения без проблем, а текст никак.

ууу

2

Re: AHK: Запись строки в память

Drygok пишет:

primer.dll или primer.exe, не принципиально

Тут у вас путаница, имя процесса всегда *.exe, вроде бы, или я чего-то не знаю?

Drygok пишет:

Числовые значения без проблем, а текст никак.

Покажите, как числовые значения записываете. Там со строками большой разницы нет. Нужно лишь строку сначала в локальный буфер записать (StrPut(), учесть кодировку), затем через WriteProcessMemory записать по нужному адресу в чужой процесс, указав размер.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

3

Re: AHK: Запись строки в память

teadrinker пишет:

имя процесса всегда *.exe, вроде бы, или я чего-то не знаю?

Не только exe, а любые исполняемые файлы, например *.com.

4

Re: AHK: Запись строки в память

Значит я не в теме. dll — тоже исполняемый файл. Пример из диспетчера задач?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

5

Re: AHK: Запись строки в память

Я разве dll исполняемый файл?

6 (изменено: teadrinker, 2017-08-01 03:03:57)

Re: AHK: Запись строки в память

Ну, в определённом смысле. А разве .com — исполняемый файл?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

7

Re: AHK: Запись строки в память

Com - да.

A COM file is a type of simple executable file.

https://en.wikipedia.org/wiki/COM_file
А так как dll сам себя не может запустить, то поэтому не пишут, что он executable file.
https://en.wikipedia.org/wiki/Dynamic-link_library

8

Re: AHK: Запись строки в память

Оказалось, действительно, процесс *.com может существовать, проверил.

Malcev пишет:

Не только exe, а любые исполняемые файлы

Не любые.
Во всяком случае, процесса с именем *.dll быть не может, если только его имя не подменено.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

9 (изменено: belyankin12, 2017-08-01 09:25:42)

Re: AHK: Запись строки в память

в том же CheatEngine это дело пары кликов.

Это дело пары кликов благодаря стараниям разработчиков. Банально: сделайте какой-нибудь себе gui интерфейс на скрипт с кнопочками. У вас тоже все операции будут выполняться кликами, но вы то знаете, сколько процессов выполняет скрипт и сколько сил ушло на то, чтобы написать это.

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

10

Re: AHK: Запись строки в память

teadrinker пишет:

Тут у вас путаница, имя процесса всегда *.exe, вроде бы, или я чего-то не знаю?

teadrinker пишет:

Значит я не в теме. dll — тоже исполняемый файл. Пример из диспетчера задач?

http://i.imgur.com/o1q8Z3M.png

ууу

11

Re: AHK: Запись строки в память

teadrinker пишет:

Покажите, как числовые значения записываете.

WriteProcessMemory(title,addresse,wert,size)  
{ 
VarSetCapacity(idvar,32,0) 
VarSetCapacity(processhandle,32,0) 
VarSetCapacity(value, 32, 0) 
NumPut(wert,value,0,Uint) 
address=%addresse% 
WinGet ,idvar,PID,%title% 
processhandle:=DllCall("OpenProcess","Uint",0x38,"int",0,"int",idvar) 
Bvar:=DllCall("WriteProcessMemory","Uint",processhandle,"Uint",address+0,"Uint",&value,"Uint",size,"Uint",0) 
}
ууу

12 (изменено: teadrinker, 2017-08-01 14:49:14)

Re: AHK: Запись строки в память

Ну, это не код, это танец с бубном.
Для числа и для строки, как я уже писал выше, способ одинаковый:

WriteProcessMemory(PID, pAddress, pLocalBuff, size)  {
   static PROCESS_VM_OPERATION := 0x8, PROCESS_VM_WRITE := 0x20
   
   if !hProc := DllCall("OpenProcess", UInt, PROCESS_VM_OPERATION|PROCESS_VM_WRITE, Int, 0, UInt, PID, Ptr)  {
      MsgBox, Не удалось открыть процесс! Ошибка %A_LastError%
      return
   }
   if !DllCall("WriteProcessMemory", Ptr, hProc, Ptr, pAddress, Ptr, pLocalBuff, Ptr, size, PtrP, writtenBytes)
      MsgBox, Не удалось записать данные! Ошибка %A_LastError%
   DllCall("CloseHandle", Ptr, hProc)
   Return writtenBytes
}

Использование для числа:

process := "MyProcess.exe"  ; указать имя процесса
address := 0x1234567        ; указать адрес, куда писать данные
number := 12345             ; число, которое нужно записать

res := WriteNumToProcessMemory(number, process, address)
MsgBox, Записано %res% байт

WriteNumToProcessMemory(number, sProcessName, pAddress)  {
   size := VarSetCapacity(buff, 4, 0)
   NumPut(number, buff)
   Process, Exist, % sProcessName
   Return WriteProcessMemory(ErrorLevel, pAddress, &buff, size)
}

Использование для строки:

process := "MyProcess.exe"  ; указать имя процесса
address := 0x1234567        ; указать адрес, куда писать данные
cp := "cp1200"              ; указать кодировку, в которой строка должна быть записана в процесс
str := "Моя строка"

res := WriteStringToProcessMemory(str, cp, process, address)
MsgBox, Записано %res% байт

WriteStringToProcessMemory(string, cp, sProcessName, pAddress)  {
   size := VarSetCapacity(buff, StrPut(string, cp) * ( (cp = "utf-16" || cp = "cp1200") ? 2 : 1 ), 0)
   StrPut(string, &buff, cp)
   Process, Exist, % sProcessName
   Return WriteProcessMemory(ErrorLevel, pAddress, &buff, size)
}
Drygok пишет:

http://i.imgur.com/o1q8Z3M.png

Наверно, тут какие-то фокусы с подменой имени процесса, фиг знает.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

13

Re: AHK: Запись строки в память

teadrinker пишет:
Malcev пишет:

Не только exe, а любые исполняемые файлы

Не любые.
Во всяком случае, процесса с именем *.dll быть не может, если только его имя не подменено.

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

14

Re: AHK: Запись строки в память

Спасибо за помощь, решено.

ууу

15

Re: AHK: Запись строки в память

Malcev пишет:

Почему не любые?

Например, vbs — тоже считается исполняемым файлом.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

16

Re: AHK: Запись строки в память

Я не вижу, чтобы здесь было написано, что vbs - исполняемый файл.
https://en.wikipedia.org/wiki/VBScript
А написано, что:

A Windows Script File (WSF) is styled after XML. A WSF file can include multiple VBS files. As a result, WSF files provide a means for code reuse: a library of classes or functions can be stored in one or more .vbs files, which can be included in .wsf files, so the functionality can be reused in a modular way. The files have extension .wsf and can be executed using wscript.exe or cscript.exe, just as a .vbs file can.

То есть могут быть исполнены с помощью стороннего файла.

17

Re: AHK: Запись строки в память

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

Win7x64, AutoHotkey 1.1.30.00

18

Re: AHK: Запись строки в память

in some contexts a file containing bytecode or scripting language instructions may also be considered executable.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

19

Re: AHK: Запись строки в память

Запускаются напрямую (помимо exe): com, bat, cmd, scr, msi, pif.

20

Re: AHK: Запись строки в память

ypppu, bat, cmd  - это пакетные файлы.
Msi запускается msiexec.

21

Re: AHK: Запись строки в память

Переименовать exe в cmd или bat - запустится. Msi сам не запустится, точно.

22

Re: AHK: Запись строки в память

Интересно, почему так происходит?

23

Re: AHK: Запись строки в память

Ответ.
Здесь:

HKEY_CLASSES_ROOT\batfile\shell\open\command

«Пакетный» файл отправляется на исполнение, где происходит разбор содержимого его заголовка, и он исполняется, как любой другой PE-файл.

24 (изменено: stealzy, 2017-08-06 20:17:22)

Re: AHK: Запись строки в память

Malcev пишет:

«Пакетный» файл отправляется на исполнение, где

интерпретатор видит, что файл нифига ни текстовый, и пытается понять, что ему подсунули из мета-данных.
Если вас это удивляет, можете еще переименовать jpg → gif, mp3 → wav, zip → rar, rtf → doc, etc. Главное, чтобы интерпретатор был общим или из той же сферы применения.

Кстати, в диспетчере отображается под именем файла, подозреваю, что в скриншоте Drygok с .dll ситуация аналогична.

Win7x64, AutoHotkey 1.1.30.00

25

Re: AHK: Запись строки в память

stealzy пишет:

подозреваю, что в скриншоте Drygok с .dll ситуация аналогична

А подробнее?
Если мы запускаем переименованный exe в bat, то в диспетчере видим bat.
Как эта ситуация может быть аналогична dll?

26 (изменено: wisgest, 2020-05-11 03:00:37)

Re: AHK: Запись строки в память

Формально расширение исполняемого файла может быть любым:

FileCopy %windir%\notepad.exe, *.txt
ComObjCreate("WScript.Shell").Exec("notepad.txt")
FileCopy %windir%\notepad.exe, *.unknown_extension
Run notepad.unknown_extension

Второй случай будет работать и из командной строки.


Добавлено: Для работоспособности может дополнительно потребоваться скопировать и переименовать файлы *.mui (http://forum.script-coding.com/viewtopi … 32#p139432).

27

Re: AHK: Запись строки в память

wisgest пишет:
FileCopy %windir%\notepad.exe, *.txt

Так не работает, особенно учитывая, что встроенной переменной windir в AHK не существует. Но даже если переименовать notepad.exe в notepad.txt, на Windows 10 ни первый способ, ни второй не работает.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

28

Re: AHK: Запись строки в память

На Win7 работает.

29

Re: AHK: Запись строки в память

wisgest пишет:

Но ведь и

#NoEnv

не указана.

А, точно, просто запускал не сохраняя в файл через Shell.Exec. Ну всё равно, на 10 не работает даже, если просто notepad.exe переместить в другую папку.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

30

Re: AHK: Запись строки в память

А вот скомпилированный AHK-файл с изменённым расширением запустился и первым, и вторым способом, с соответствующим названием процесса в диспетчере задач.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

31

Re: AHK: Запись строки в память

teadrinker Для записи числа в память я использовал Ваш код. Он прекрасно работает для конкретного адреса, но после перезапуска процесса адрес меняется. Его можно узнать средствами AHK не используя CheatEngine, зная указатели?

32

Re: AHK: Запись строки в память

Не совсем понял вопрос. Какие указатели Вы имеете в виду?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

33

Re: AHK: Запись строки в память

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

34

Re: AHK: Запись строки в память

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

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

35

Re: AHK: Запись строки в память

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

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

36

Re: AHK: Запись строки в память

Не, всё равно не понимаю, что именно нужно искать, и по каким признакам.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

37

Re: AHK: Запись строки в память

KusochekDobra пишет:

наверное в этом и есть суть вопроса - зная смещения, найти базовый адрес.

Зная расстояние между домами, определить их адрес? Как это возможно?

38

Re: AHK: Запись строки в память

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

39

Re: AHK: Запись строки в память

Ну, если известны значения членов структуры, тогда можно найти, конечно.

40 (изменено: Vicoriyan, 2018-01-24 14:03:58)

Re: AHK: Запись строки в память

teadrinker Нужно найти конечный адрес зная смещение. Согласен, не сильно понятно написал.
По простому и как я это понимаю выглядит так. Конечный адрес всегда имеет базовый адрес. Базовый адрес меняется, но смещения никогда, они уникальны. Базовый адрес например 100, у нас 4 смещения.
Это например смещение 1 = 3; 2 = 7; 3 = 25; 4 = 8. Конечный адрес у нас получается 143. Это 100+3+7+25+8=143. С перезагрузкой процесса у нас базовый адрес меняется например на 120, то конечный адрес у нас получится уже не 143, а 163. Так вот, поменять значение нельзя с базового адреса, а только с конечного. Вот мне и нужно узнать конечный адрес, зная смещения. В CheatEngine это называется указателями. Как бы CheatEngine зная эти смещения, он находит базовый адрес. Вот и хочу узнать, можно ли средствами AHK такое проделывать.

41

Re: AHK: Запись строки в память

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

Если к этому относиться серьёзно, то хорошо бы почитать полезной литературы, или на крайний случай, статьи на Хабре, спросив у Гугля что-то вроде - как устроено адресное пространство приложения, а ещё лучше, полистать форумы, которые целенаправленно освящают функционал программ, вроде "CheatEngine"("CE") и их сферу применения. В общих же чертах, картина рисуется так:

У каждого, загруженного в оперативную память процесса, адресное пространство локально изнутри и начинается с 0x00000000(x32), но глобально, оно подразумевается как базовый адрес приложения, являющийся смещением в адресном пространстве оперативной памяти операционной системы(среды). Поэтому, когда производятся манипуляции в том же "CE", все литеральные представления адресов начинаются с "TargetProgrammName.exe". Иными словами и очень грубо говоря, понимаемый под базовым адресом программы "TargetProgrammName.exe" - это указатель на всю структуру приложения в оперативной памяти среды. Его значение может меняться.

Указатели же, которые интересны в нашем случае - константны в локальном пространстве адресов процесса. Они не меняются при перезагрузке самой программы и среды. Эти указатели нужны самой программе, чтобы "знать", как она была распределена в памяти и содержат адреса, в которых начинаются её структуры(логика, данные, ... ). Меняются они только в случае изменения кода, происходящего, например, в результате апдейтов.

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

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

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

Неправильно описал это в 36 посте.

Поправьте пожалуйста, если я где-то опять не корректен.

42

Re: AHK: Запись строки в память

Vicoriyan пишет:

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

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

43

Re: AHK: Запись строки в память

teadrinker пишет:

Но даже если переименовать notepad.exe в notepad.txt, на Windows 10 ни первый способ, ни второй не работает.

teadrinker пишет:

Ну всё равно, на 10 не работает даже, если просто notepad.exe переместить в другую папку.

Потому что не хватает файла *.mui. У меня работает, если дополнительно рядом с копией notepad.exe создать каталог ru-RU, в него скопировать файл %windir%\ru-RU\notepad.exe.mui под тем же именем, что и копию исполняемого файла, но с дополнительным расширением mui (notepad.txt.mui, notepad.unknown_extension.mui…)

Но возникает дополнительный вопрос: как в общем случае программно узнать, какой код языка на месте ru-RU использовать (к тому же, как я понимаю, их может быть установлено несколько), хотя бы, например, пройдясь по всем соседним каталогам и определив, являются ли их имена допустимыми обозначениями языков (локалей)?

44

Re: AHK: Запись строки в память

Если, как я понял, нужен(ы) язык(и) интерфейса, то так:

pCallBack := RegisterCallback("UILANGUAGE_ENUMPROC", "F", 2)
Langs := []
pLangs := Object(Langs)
DllCall("EnumUILanguages", "Ptr", pCallBack, "UInt", MUI_LANGUAGE_NAME := 0x8, "Ptr", pLangs)
ObjRelease(pLangs)
res := ""
for k, v in Langs
   res .= (res = "" ? "" : "`n") . v
MsgBox, % res

UILANGUAGE_ENUMPROC(pStr, pLangs) {
   Langs := Object(pLangs)
   Langs.Push( StrGet(pStr) )
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg