Сейчас на форуме: tyns777, bezumchik (+5 невидимых)

 eXeL@B —› Вопросы новичков —› Вопрос про WriteProcessMemory Delphi7
<< . 1 . 2 . 3 . >>
Посл.ответ Сообщение

Ранг: 2.0 (гость)
Активность: 0.010.04
Статус: Участник

Создано: 03 ноября 2019 19:08
· Личное сообщение · #1

Здравствуйте, уважаемые пользователи. Помогите мне решить невнятную проблему.
Объясню суть, имеется программа, написанная на c#, мне необходимо изменить всего лишь один байт в памяти этой программы при её работе. Для изменения памяти я использую функцию, которую использовал очень часто:

Code:
  1. procedure MemWrite(pHandle:THandle;Address:Pointer; Bytes:pchar; nSize:DWORD);
  2. var
  3.   BytesWrite:Dword;
  4.   oldprotect: DWORD;
  5. begin
  6.   VirtualProtectEx(pHandle,Address, nSize, PAGE_EXECUTE_READWRITE, @oldProtect);
  7.   WriteProcessMemory(pHandle,Address, Bytes, nSize, BytesWrite);
  8.   VirtualProtectEx(pHandle,Address, nSize, oldProtect, @oldProtect);
  9. end;


Всё работает, байт меняется. НО есть одно НО, через время работы программы на ПК возникает ошибка "На компьютере не достаточно памяти", следом идут всяческие ошибки с закрытием этой программы.
Но суть в том, что если эту программу перезапустить и сделать тоже самое, эта ошибка появится уже очень скоро, через минут 5 работы. Складывается такое ощущение, что память забивается непонятно где и не освобождается при закрытии этой программы.
Однако, если не менять этот байт, программа успешно может работать и 48 часов без перебоев.
Также я заметил, что если изменить этот байт через CheatEngine - всё также хорошо работает.
Вопрос, в чем проблема возникает? Проверяется на х64 системе. Прошу мне помочь.



Ранг: 2.0 (гость)
Активность: 0.010.04
Статус: Участник

Создано: 04 ноября 2019 13:31
· Личное сообщение · #2

Вы серьезно? Я повторяю ещё раз, именно КОД поиска адреса не является основой для проблемы. ПОВТОРЮСЬ ещё раз, без этого кода, а только сам MemWrite с указанием адреса, который был найден через CheatEngine, вызывает эту проблему.
Напишу ещё раз, если использовать только

Code:
  1. var
  2. ProcessHandle: THandle;
  3. begin
  4. ProcessHandle := OpenProcess(PROCESS_VM_OPERATION or PROCESS_VM_WRITE or PROCESS_VM_READ, false, ProcessID);
  5. if ProcessHandle <> 0 then
  6. MemWrite(ProcessHandle, Ptr($007CCE18), #$61, 1);
  7. CloseHandle(ProcessHandle);
  8. end;


Проблема остаётся.




Ранг: 275.9 (наставник), 340thx
Активность: 0.22=0.22
Статус: Участник
RBC

Создано: 04 ноября 2019 13:40
· Личное сообщение · #3

Был такой анекдот:
Приходит молодой программист к матерому и говорит:
- Вот моя программа, и она почему то не работает. Можешь найти ошибку?
Матерый программист посмотрел код и сказал:
- Знаешь, где у тебя ошибка?
Молодой спрашивает:
- Где?
Матерый:
- В генетическом коде!

Сорри за оффтоп, но ТС не хочет сначала изучать азы программирования, зато сразу читы писать и банчить ими поскорей бы

-----
Array[Login..Logout] of Life




Ранг: 43.1 (посетитель), 20thx
Активность: 0.160.29
Статус: Участник

Создано: 04 ноября 2019 14:58
· Личное сообщение · #4

wladimir55, приведенный фрагмент кода не содержит каких-либо аномалий, но если смотреть на качество кода в целом, то вашим словам особой веры нет, вы можете делать что-то еще, вроде как незначимое на ваш взгляд, но значимое для операционки (например, в ProcessID передавать какую-то ересь). Не обладая целевой программой, как уже говорилось ранее, угадать в чем конкретно проблема никто не сможет.




Ранг: 324.3 (мудрец), 222thx
Активность: 0.480.37
Статус: Участник

Создано: 04 ноября 2019 15:22
· Личное сообщение · #5

#$61 - тип Char, символ 'a'
WriteProcessMemory() принимает Pointer

Вопрос: Как преобразуется в Delphi Char в Pointer ?

Давно не писал не дельфи, и у меня сейчас 2 варианта ответа:
1) Char -> PChar -> Pointer
2) Char -> Integer -> Pointer (как в си)

Во втором случае WriteProcessMemory() просто вернула бы FALSE.

Претензий к короткому фрагменту нет. Из-за чего могут быть утечки памяти - а тот ли байт, по тому ли адресу патчится? Если байт $61 занести в секцию кода там, где он будет первым байтом инструкции, то это будет инструкция popad. В x86 стек увеличится на 32 байта, в x64 на 64. Кроме того, поскольку, как правило, инструкции из 2х и более байт, 2й байт бывшей инструкции станет 1м новой инструкции. Поведение непредсказуемо...

Добавлено спустя 2 минуты
Совет:
Поставь бряк на WriteProcessMemory() и на останове загляни в asm

-----
IZ.RU





Ранг: 568.2 (!), 465thx
Активность: 0.550.57
Статус: Участник
оптимист

Создано: 04 ноября 2019 15:25 · Поправил: ClockMan
· Личное сообщение · #6

Code:
  1. var _buf : pdword;
  2.      _Adr,_Lp,_hproc:dword;
  3. begin
  4.     _Adr:=$007CCE18 ;
  5.     _buf:=pdword($61);
  6.     WriteProcessMemory(_hproc,pdword(_Adr),@_buf,1,_Lp);
  7. end;


-----
Чтобы правильно задать вопрос, нужно знать большую часть ответа. Р.Шекли.




Ранг: 43.1 (посетитель), 20thx
Активность: 0.160.29
Статус: Участник

Создано: 04 ноября 2019 16:05
· Личное сообщение · #7

DenCoder пишет:
Вопрос: Как преобразуется в Delphi Char в Pointer ?

Там нет преобразований, MemWrite принимает аргумент PChar, т.е. #$61 в данном случае является не символом, а строкой (два символа #$61 и #0).




Ранг: 324.3 (мудрец), 222thx
Активность: 0.480.37
Статус: Участник

Создано: 04 ноября 2019 16:19 · Поправил: DenCoder
· Личное сообщение · #8

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

Складывается ощущение, что в программе одни ошибки добавляют в таргет другие. Реакция на первые - ось требует закрыть программу, на вторые - таргет пожирает память.

Кстати, если программа не зависла на закрытии, память вся должна освободиться нормально. Видимо, я прав - таргет всё сжирает.

-----
IZ.RU




Ранг: 42.8 (посетитель), 16thx
Активность: 0.020.06
Статус: Участник

Создано: 05 ноября 2019 02:09
· Личное сообщение · #9

DenCoder пишет:
В x86 стек увеличится на 32 байта, в x64 на 64

в х64 нет команды popad.




Ранг: 324.3 (мудрец), 222thx
Активность: 0.480.37
Статус: Участник

Создано: 05 ноября 2019 02:50
· Личное сообщение · #10

Ну да, пардон

-----
IZ.RU




Ранг: 145.8 (ветеран), 191thx
Активность: 0.140.36
Статус: Участник

Создано: 05 ноября 2019 09:16
· Личное сообщение · #11

wladimir55 пишет:
Вы серьезно? Я повторяю ещё раз, именно КОД поиска адреса не является основой для проблемы. ПОВТОРЮСЬ ещё раз, без этого кода, а только сам MemWrite с указанием адреса, который был найден через CheatEngine, вызывает эту проблему.
Напишу ещё раз, если использовать только


Code:
  1.  
  2.     var
  3.     ProcessHandle: THandle;
  4.     begin
  5.     ProcessHandle := OpenProcess(PROCESS_VM_OPERATION or PROCESS_VM_WRITE or PROCESS_VM_READ, false, ProcessID);
  6.     if ProcessHandle <> 0 then
  7.     MemWrite(ProcessHandle, Ptr($007CCE18), #$61, 1);
  8.     CloseHandle(ProcessHandle);
  9.     end;
  10.  


Ты даже в этих нескольких строчках умудрился обосраться с невалидным хендлом в конце, потому что проибал begin end, знаешь почему? Потому что не знаешь что он там должен быть. Потому что не знаешь как это работает и кто это такие - какие-то OpenProcess/CloseHandle.

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

Твой код гавно, именно он источник проблемы. Твой поиск по сигнатуре лютое гавно, именно он источник проблемы. Не удивлюсь если там патчится каждый раз рандомное место в целевом АП, перетирая что угодно.

Удачи вам посоны в переписывании этого патчера для этого необучаемого. Может он вас там в кредитс добавит потом когда релизнет свой МЕГАЧИТ с каким-нибудь приклееным хмриг заодно :D



Ранг: 10.8 (новичок), 4thx
Активность: 0.17=0.17
Статус: Участник

Создано: 05 ноября 2019 10:42
· Личное сообщение · #12

wladimir55 пишет:
BytesWrite:Dword;
WriteProcessMemory(pHandle,Address, Bytes, nSize, BytesWrite);

Я в Делфи не разбираюсь, но, наверное, переменная и указатель и в них не одно и то же...




Ранг: 324.3 (мудрец), 222thx
Активность: 0.480.37
Статус: Участник

Создано: 05 ноября 2019 12:03
· Личное сообщение · #13

wladimir55
Тебе мешает уверенность в собственной непогрешимости. Точнее - в непогрешимости поиска. Но что мешает просто выложить программу сюда? Думаешь, она кому-то нужна? Нужна здесь только тем, кто может тебе помочь. Кстати, одной её мало, нужна ещё та, которую ты патчишь.

Добавлено спустя 1 минуту
По тимвью мог бы предоставить доступ, кому не лень

-----
IZ.RU




Ранг: 43.1 (посетитель), 20thx
Активность: 0.160.29
Статус: Участник

Создано: 05 ноября 2019 12:34
· Личное сообщение · #14

AE, в Делфи во многих WinAPI-функциях вместо указателя (в основном на DWORD) используется передача аргумента по ссылке, с точки зрения asm-кода одно и тоже, а вот с точки зрения Делфи-кода получается такая несуразица.

| Сообщение посчитали полезным: Cigan

Ранг: 10.8 (новичок), 4thx
Активность: 0.17=0.17
Статус: Участник

Создано: 05 ноября 2019 14:13
· Личное сообщение · #15

user99, то есть там не будет попытки записать результат по хз какому адресу?
Удивительно...



Ранг: 2.0 (гость)
Активность: 0.010.04
Статус: Участник

Создано: 05 ноября 2019 15:17
· Личное сообщение · #16

Alchemistry пишет:
https://exelab.ru/f/action=vthread&forum=5&topic=26155&page=1#

Почему люди на форуме с высоким рейтингом такие злые или обиженные? Естественно, возможно закрытие пустой хендла с дальнейшим исключением. Однако, я тестирую это, когда ProcessID у нас априори не пустой. И даже если бы вызвалось исключение, разве это было бы ошибкой, которая приводила бы к забиваю памяти винды? Но повторюсь ещё раз - такой ошибки никогда не было. И повторюсь в некоторый раз, я тестировал эту штуку БЕЗ ПОИСКА АДРЕСА, код которого я, кстати, нашёл на этом же форуме от "высокорейтингового" пользователя.
И после самого "патча", я естественно проверяю (CheatEngine), а изменился ли байт - да он поменялся именно там где нужно.
Почему лишь пользователи с маленьким рейтингом пытаются хоть чем-то помочь? А вот пользователи с большим, считая себя гуру во всех делах, пытаются исключительно говорить, что твой код говно.



Ранг: 19.5 (новичок), 8thx
Активность: 0.050.08
Статус: Участник

Создано: 05 ноября 2019 15:29 · Поправил: dezmand07
· Личное сообщение · #17

wladimir55 пишет:
Почему лишь пользователи с маленьким рейтингом пытаются хоть чем-то помочь?

наверно хотят стать пользователями с высоким рейтингом

по сабжу: принципиально использовать delphi?
этим языком мало кто пользуется, имхо синтаксис не удобный.
пиши на плюсах и вопросов станет меньше и помощи получишь больше.




Ранг: 324.3 (мудрец), 222thx
Активность: 0.480.37
Статус: Участник

Создано: 05 ноября 2019 15:32 · Поправил: DenCoder
· Личное сообщение · #18

wladimir55 пишет:
Почему лишь пользователи с маленьким рейтингом пытаются хоть чем-то помочь? А вот пользователи с большим, считая себя гуру во всех делах, пытаются исключительно говорить, что твой код говно.

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

Добавлено спустя 2 минуты
wladimir55
Откуда у тебя утечка памяти-то? Из программы, которой патчишь? Или которую патчишь? Ты это определил?

-----
IZ.RU




Ранг: 2.0 (гость)
Активность: 0.010.04
Статус: Участник

Создано: 05 ноября 2019 15:38
· Личное сообщение · #19

Которую я патчу, по крайней мере, так показывается в событиях винды.




Ранг: 324.3 (мудрец), 222thx
Активность: 0.480.37
Статус: Участник

Создано: 05 ноября 2019 15:48
· Личное сообщение · #20

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

А так, если всё в порядке с kernel32.dll, ntdll.dll, ядро не патчено, поставлен некривой антивирус, антишпион или вообще его или их нет, то WriteProcessMemory() не при чём! Чего я здесь ещё не заметил - никто не упомянул про DEBUG_PRIVILEGE, которую нужно получить в программе, чтобы WriteProcessMemory() делала, что ей предписано. Без этой привилегии, просто функа вернёт FALSE.

-----
IZ.RU




Ранг: 10.8 (новичок), 4thx
Активность: 0.17=0.17
Статус: Участник

Создано: 05 ноября 2019 15:48 · Поправил: AE
· Личное сообщение · #21

wladimir55 пишет:
а изменился ли байт - да он поменялся именно там где нужно

Только он?, а то там наверху спрашивали, видел, ответа не видел...



Ранг: 2.0 (гость)
Активность: 0.010.04
Статус: Участник

Создано: 05 ноября 2019 15:52
· Личное сообщение · #22

dezmand07 пишет:
https://exelab.ru/f/action=vthread&forum=5&topic=26155&page=-1#

Хорошее замечание, переписал это на плюсах и тестирую сейчас... Точнее уже 12 часов программа работает



Ранг: 19.5 (новичок), 8thx
Активность: 0.050.08
Статус: Участник

Создано: 05 ноября 2019 16:02
· Личное сообщение · #23

DenCoder не понял, зачем привилегия отладчика на WriteProcessMemory?
если только патчиться системный процесс (в сессии пользователя конечно же), но ТС вроде не упоминал про сиспроцесс, или я не заметил.



Ранг: 43.1 (посетитель), 20thx
Активность: 0.160.29
Статус: Участник

Создано: 05 ноября 2019 16:29 · Поправил: user99
· Личное сообщение · #24

AE, прототип функции объявлен так:
Code:
  1. function WriteProcessMemory(hProcess: THandle; const lpBaseAddress: Pointer; lpBuffer: Pointer; nSize: SIZE_T; var lpNumberOfBytesWritten: SIZE_T): BOOL; stdcall;

а можно объявить так:
Code:
  1. function WriteProcessMemory(hProcess: THandle; const lpBaseAddress: Pointer; lpBuffer: Pointer; nSize: SIZE_T; lpNumberOfBytesWritten: PSIZE_T): BOOL; stdcall;

по сути это одно и тоже, но с мелким отличием, во втором случае можно в последний аргумент передать nil (NULL), а в первом нет, т.е. параметр из опционального становится обязательным.

wladimir55 пишет:
Но повторюсь ещё раз - такой ошибки никогда не было

Я тоже повторюсь: ничего удивительного в таком отношении нет, сложно на слово верить человеку с таким уровнем кодинга.

wladimir55 пишет:
А вот пользователи с большим, считая себя гуру во всех делах, пытаются исключительно говорить, что твой код говно

Может быть потому что они давно сидят на этом форуме и видели уже сотни подобных творений? И самое печальное, что 99% подобных творений заканчивается ничем, а это грусть-тоска.
Но могу дать добрый совет: лучше не принимать близко к сердцу написанное, а понять почему свой код говно и стараться его улучшить.

dezmand07, если уметь готовить, то Делфи нормальный язык, хотя и не без изъянов

| Сообщение посчитали полезным: SReg


Ранг: 324.3 (мудрец), 222thx
Активность: 0.480.37
Статус: Участник

Создано: 05 ноября 2019 16:30
· Личное сообщение · #25

To open a handle to another local process and obtain full access rights, you must enable the SeDebugPrivilege privilege. А на какие именно права нужна эта привилегия, я уже помню точно. Права на WriteProcessMemory(), по-моему, в их числе. В последнее время при манипуляциях с процессами просто по дефолту вставляю код с получением привилегии.

Добавлено спустя 1 минуту
user99
Второй вариант, кстати, правильный

Добавлено спустя 8 минут
SeDebugPrivilege:
Required to debug and adjust the memory of a process owned by another account.

-----
IZ.RU




Ранг: 10.8 (новичок), 4thx
Активность: 0.17=0.17
Статус: Участник

Создано: 05 ноября 2019 16:42
· Личное сообщение · #26

user99 пишет:
с мелким отличием

вы, я прошу прощения, про мелкое отличие "0" от "4985243"



Ранг: 19.5 (новичок), 8thx
Активность: 0.050.08
Статус: Участник

Создано: 05 ноября 2019 16:51
· Личное сообщение · #27

DenCoder пишет:
В последнее время при манипуляциях с процессами просто по дефолту вставляю код с получением привилегии.

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



Ранг: 10.8 (новичок), 4thx
Активность: 0.17=0.17
Статус: Участник

Создано: 05 ноября 2019 17:18
· Личное сообщение · #28

user99, пардон, въехал....



Ранг: 43.1 (посетитель), 20thx
Активность: 0.160.29
Статус: Участник

Создано: 05 ноября 2019 17:23
· Личное сообщение · #29

DenCoder пишет:
Второй вариант, кстати, правильный

Оба варианта правильные, но второй вариант максимально точный (скажем так "на 100% по стандарту").

AE пишет:
вы, я прошу прощения, про мелкое отличие "0" от "4985243"

Не понял к чему это. Еще раз повторюсь, отличие этих двух прототипов только в одном: в первом варианте аргумент lpNumberOfBytesWritten является обязательным, а во втором - нет. Ну и как следствие, при вызове функции по первому прототипу вы будете в функцию передавать саму DWORD-переменную, а во втором нужно передавать указатель на эту переменную. Оба варианта отработают без ошибок, и Делфи не перепутает самое значение находящее в переменной и адрес этой переменной. И если вы в дизассемблере посмотрите сгенерированный код для этих двух прототипов (где lpNumberOfBytesWritten не NULL), то он будет идентичным.




Ранг: 324.3 (мудрец), 222thx
Активность: 0.480.37
Статус: Участник

Создано: 05 ноября 2019 17:58
· Личное сообщение · #30

dezmand07
Привычка включать SeDebugPrivilege появилась с начала практики инжекта. Тогда использовал CreateRemoteThread(), для неё в любом случае нужна эта привилегия. А так, поскольку прятать мне нечего и не от кого, то в манифесте практически всегда задаю requireAdministrator.

Добавлено спустя 3 минуты
wladimir55 пишет:
Точнее уже 12 часов программа работает

Во как, на си работает, на дельфи не хочет. Дельфи виноват? )

-----
IZ.RU


| Сообщение посчитали полезным: sefkrd


Ранг: 52.0 (постоянный), 146thx
Активность: 0.030.08
Статус: Участник

Создано: 05 ноября 2019 18:29 · Поправил: UniSoft
· Личное сообщение · #31

DenCoder пишет:
Дельфи виноват? )

Так блин Delphi 7 вышел когда...

wladimir55 пишет:
И после самого "патча", я естественно проверяю (CheatEngine), а изменился ли байт - да он поменялся именно там где нужно.

Ну это еще раз говорит о некорректном патче, возможно из-за патча пропустили сборщик мусора, пропустили освобождение какого-либо объекта (а в .NET любая сущность есть объект).
Опять же, тут нужно смотреть сам код, что именно патчите и где, т.е. нужно смотреть цель.
Это что-то секретное?
Раз уж это .NET, почему бы просто не пропатчить сам файл?
Или на нем висит какой-либо протектор?


<< . 1 . 2 . 3 . >>
 eXeL@B —› Вопросы новичков —› Вопрос про WriteProcessMemory Delphi7
Эта тема закрыта. Ответы больше не принимаются.
   Для печати Для печати