Сейчас на форуме: 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 системе. Прошу мне помочь.



Ранг: 315.1 (мудрец), 631thx
Активность: 0.30.33
Статус: Модератор
CrackLab

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

wladimir55 пишет:
Прошу мне помочь.

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



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

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

Что значит патч кривой? Я же указал функцию, которая и делает "патч". Адрес и байт соответствует с тем, что я делаю и через CheatEngine. Через CheatEngine всё работает хорошо, через ту функцию - как то не так.



Ранг: 315.1 (мудрец), 631thx
Активность: 0.30.33
Статус: Модератор
CrackLab

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

а что с твоей функции, откуда кто знает что ты в неё передаешь? память в таргете смотрел после ее вызова, патчится то что нужно и ничего больше?




Ранг: 271.2 (наставник), 331thx
Активность: 0.321.49
Статус: Участник

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

Есть вариант VirtualProtectEx убрать на всякий случай, ибо
Code:
  1. 764A4590 WriteProcessMemory         MOV EDI,EDI
  2. 764A4592                  PUSH EBP
  3. 764A4593                  MOV EBP,ESP
  4. 764A4595                  SUB ESP,14
  5. 764A4598                  PUSH EBX
  6. 764A4599                  MOV EBX,DWORD PTR SS:[EBP+0C]
  7. 764A459C                  LEA EAX,[EBP-4]
  8. 764A459F                  PUSH ESI
  9. 764A45A0                  MOV ESI,DWORD PTR SS:[EBP+8]
  10. 764A45A3                  PUSH EDI
  11. 764A45A4                  MOV EDI,DWORD PTR SS:[EBP+14]
  12. 764A45A7                  PUSH EAX                                           ; /Arg5
  13. 764A45A8                  PUSH 40                                            ; |Arg4 = 40
  14. 764A45AA                  LEA EAX,[EBP-8]                                    ; |
  15. 764A45AD                  MOV DWORD PTR SS:[EBP-8],EDI                       ; |
  16. 764A45B0                  PUSH EAX                                           ; |Arg3
  17. 764A45B1                  LEA EAX,[EBP-0C]                                   ; |
  18. 764A45B4                  MOV DWORD PTR SS:[EBP-0C],EBX                      ; |
  19. 764A45B7                  PUSH EAX                                           ; |Arg2
  20. 764A45B8                  PUSH ESI                                           ; |Arg1
  21. 764A45B9                  CALL DWORD PTR DS:[<&ntdll.NtProtectVirtualMemory>]; \ntdll.NtProtectVirtualMemory

Аргумент 4 это NewAccessProtection, и 40 это:
Code:
  1. PAGE_EXECUTE_READWRITE = 040h

И раз с читенжин проблем нет, может быть имеет смысл посмотреть как он это делает.

-----
2 оттенка серого




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

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

Могу написать полностью, как происходит "патч".
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;


В ProcessID находит ID нужного процесса.

Именно такой же адрес и на такой же байт и делается замена в CheatEngine. Повторюсь, там это проходит правильно.



Ранг: 315.1 (мудрец), 631thx
Активность: 0.30.33
Статус: Модератор
CrackLab

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

а где imagebase? или у тебя aslr отключен?



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

Создано: 03 ноября 2019 20:25 · Поправил: wladimir55
· Личное сообщение · #8

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

Code:
  1. <strike>говнокод</strike>

HexBytes - массив байт для поиска.
Адрес находит правильно, тот же самый что находит и CheatEngine.

Добавлено спустя 12 минут
Напишу функции из Windows.pas:
function VirtualProtectEx(hProcess: THandle; lpAddress: Pointer;
dwSize, flNewProtect: DWORD; lpflOldProtect: Pointer): BOOL;
external kernel32 name 'VirtualProtectEx';
function VirtualProtectEx(hProcess: THandle; lpAddress: Pointer;
dwSize, flNewProtect: DWORD; var OldProtect: DWORD): BOOL; stdcall; overload;


function WriteProcessMemory; external kernel32 name 'WriteProcessMemory';
function WriteProcessMemory(hProcess: THandle; const lpBaseAddress: Pointer; lpBuffer: Pointer;
nSize: DWORD; var lpNumberOfBytesWritten: DWORD): BOOL; stdcall;


Быть может в них что-то поменялось? Всё-таки Delphi 7




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

Создано: 03 ноября 2019 20:40 · Поправил: Kindly
· Личное сообщение · #9

а что у тебя в @oldProtect?
там же должно VirtualAlloc вызываться перед VirtualProtect.

на асме помню вставку писал:
Code:
  1.         PUSHAD
  2.         ADD EAX,$0FFFF39E0
  3.         MOV ESI,EAX
  4.         PUSH $040
  5.         PUSH $01000
  6.         PUSH $01000
  7.         PUSH 0
  8.         CALL VirtualAlloc        
  9.         PUSH EAX
  10.         PUSH $040
  11.         MOV EAX,$019FF0
  12.         PUSH EAX
  13.         PUSH ESI
  14.         CALL VirtualProtect       
  15.         POPAD


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




Ранг: 315.1 (мудрец), 631thx
Активность: 0.30.33
Статус: Модератор
CrackLab

Создано: 03 ноября 2019 20:45
· Личное сообщение · #10

Kindly VirtualAlloc там не нужен, там проблема в гавнокоде



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

Создано: 03 ноября 2019 20:49
· Личное сообщение · #11

@oldProtect указатель на переменную для получения предыдущей защиты доступа. Не понимаю для чего там VirtualAlloc.




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

Создано: 03 ноября 2019 21:20 · Поправил: Kindly
· Личное сообщение · #12

wladimir55 пишет:
Не понимаю для чего там VirtualAlloc.

в моем инлайне надо было так oldProtect получить для VirtualProtect, но я после записи не устанавливал атрибуты обратно и присваивал им сразу ERW, а у тебя чтоли античит атрибуты проверяет, раз ты обратно после записи пытаешься чето присвоить? oldProtect должен быть PDWORD, как-то так:
PDword(@oldProtect)^
В отладчике уверен что все правильно исполняется?

wladimir55 пишет:
и всё работало отлично, правда это было на Windows 7.
Сейчас же программа другая, не игра даже, и Windows 10...


SReg пишет:
тут же не форум гадалок.


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




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

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

MemWrite как раз таки давно использовался для читов, и всё работало отлично, правда это было на Windows 7.
Сейчас же программа другая, не игра даже, и Windows 10...



Ранг: 315.1 (мудрец), 631thx
Активность: 0.30.33
Статус: Модератор
CrackLab

Создано: 03 ноября 2019 22:31
· Личное сообщение · #14

Kindly
да там как раз таки все правильно

PDword(@oldProtect)^
ребят, вы чего? я еще от этого '$' + IntToHex(Integer(Cardinal(Mbi.BaseAddress) + i) и этого #$61 не отошел

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

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

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

А вы впервые видите Delphi 7? Что Вас смутило в #$61?



Ранг: 315.1 (мудрец), 631thx
Активность: 0.30.33
Статус: Модератор
CrackLab

Создано: 03 ноября 2019 22:56
· Личное сообщение · #16

wladimir55в MemWrite указатели на строку вообще не нужны



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

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

wladimir55
Совершенно очевидно что твой кривой гавнокод не освобождает память которую усиленно выделяет в твоем кривом гавно цикле где ты успешно продемонстрировал непонимание работы try/finally, а заодно отсутствие базовых знаний языка ибо только идиот будет использовать для boolean переменной string.

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

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

Создано: 04 ноября 2019 00:37
· Личное сообщение · #18

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

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




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

Создано: 04 ноября 2019 00:43
· Личное сообщение · #19

wladimir55
GetMem

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




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

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

как тут уже советовали посмотрите что реально записывается вашей прогой - наверняка чтото ещё портится.
ещё как вариант - нужно вначале прочитать dword по этому адресу $007CCE18 затем изменить младший байт и записать 4 байта - не уверен что именно в этом проблема но попробовать стОит.



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

Создано: 04 ноября 2019 06:13 · Поправил: Alchemistry
· Личное сообщение · #21

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




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

Создано: 04 ноября 2019 07:45 · Поправил: UniSoft
· Личное сообщение · #22

wladimir55 пишет:
Что Вас смутило в #$61?

Code:
  1. var
  2.   ...
  3.   C: Char;
  4. begin
  5.   ...
  6.   C := #$61;
  7.   MemWrite(ProcessHandle, Pointer(Cardinal(Mbi.BaseAddress) + i), @C, 1);
  8.   ...




Ранг: 315.1 (мудрец), 631thx
Активность: 0.30.33
Статус: Модератор
CrackLab

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

UniSoft в первом посте же.




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

Создано: 04 ноября 2019 08:37
· Личное сообщение · #24

UniSoft
Да там надо весь код переписывать человек не умеет объявлять переменные и работать с указателями, а ошибка 100% и за GetMem....

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





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

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

ClockMan пишет:
а ошибка 100% и за GetMem....

Сомневаюсь...
Я не спец в Delphi, но если бы столкнулся с проблемой, то просто бы посмотрел в отладчике.

Но в данном коде вот какие косяки я вижу:
FreeAndNil(); для строк, зачем? Delphi сама их удалит корректно. RAD 10.3 вообще падает при вызове FreeAndNil(); со строкой.
FreeMem(Buf); Оператор "exit" не значит просто покинуть функцию, код же обернут в try..finally,
и что получаем, двойной вызов: FreeMem(Buf); FreeAndNil(HexBytes); CloseHandle(ProcessHandle);
Весь код, что лежит в finally будет выполнен, не смотря на Exit



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

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

Что вы докопались до этого #$61? Выглядит убого, но работает, причем работает даже правильно. А вот весь остальной код реально прекрасен, в том числе никто не отметил строчку:
for i := 0 to BytesRead do
которая тоже может вносить свою лепту в общую работу программы.




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

Создано: 04 ноября 2019 10:26 · Поправил: Kindly
· Личное сообщение · #27

у тебя как и сказали:

Code:
  1.         begin
  2.           GetMem(Buf, Mbi.RegionSize);
  3.           try

не высвобождается, потому что если условие не выполняется:
Code:
  1.             if ReadProcessMemory(ProcessHandle, Mbi.BaseAddress, Buf, Mbi.RegionSize, BytesRead) then

то у тебя
Code:
  1.           finally
  2.             FreeMem(Buf);
  3.           end;

которое не выполнится, тебе нужно впихнуть в exception для выгрузки.
у тебя два try, что позволяет использовать костыль exception и finally одновременно.
дело вкуса, но лучше юзать AllocMem, вместо GetMem, которая выделяет память с мусором. возврат делай булевым, либо на крайний случай числовым, если необходимо больше разных типов состояний и далее в case обертуй со своими строками там.
и вообще кодес кривой, ошибки остаются.

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




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

Создано: 04 ноября 2019 11:35
· Личное сообщение · #28

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




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

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

Alchemistry
Тема Вопросы новичков вам не стыдно?)

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




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

Создано: 04 ноября 2019 12:37
· Личное сообщение · #30

ClockMan
Мне нет, а вот ТС должен гореть от ушей до пят от стыда.


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