Написал для перезаписи кода функции: Все нормально кроме WriteProcessMemory, после его вызова вылазит ошибка: "Privileged instruction" и есно память код не переписан . Код (Text): var msFile: TMemoryStream; p, p1, p2: pointer; dp: integer; h: THandle; p_buf: pointer; t: Cardinal; begin p1 := @MainF; // адрес начала функции p2 := @EndF; // Конец dp := integer(p2) - integer(p1) - 1; h := OpenProcess(PROCESS_VM_WRITE, false, GetCurrentProcessId); if h = NULL then begin Memo1.lines.Add('Не могу открыть свой процесс.'); exit; end; p_buf := nil; p_buf := VirtualAlloc(nil,dp,MEM_COMMIT,PAGE_EXECUTE_READWRITE); if p_buf = nil then Memo1.lines.Add('Не могу выделить память.'); // Загрузка данных в выдленную память // Можно не обращать внимания msFile := TMemoryStream.Create; msFile.LoadFromFile('code.dat'); msFile.Position := 0; msFile.Read(p_buf, dp); msFile.Free; if ( not WriteProcessMemory(h, p1, p_buf, dp, t)) then Memo1.lines.Add('Не могу записать в память процесса.') else Memo1.lines.Add('Память записана.'); VirtualFree(p_buf, dp, 0); end;
Это все Ms Rem виноват, с его подачи теперь считается нормальным тоном постить на wasm листинги на дельфи
Asterix В чем же я виноват? Случайно не в том, что заставил некоторых оставить старинные предрассудки? Или может быть кто-то здесь суеверен? SnugForce Код довольно хренов. Во-первых: зачем открывать свой процесс? Хэедл своего процесса ВСЕГДА равен INVALID_HANDLE_VALUE. Во-вторых: VirtualAlloc для маленьких участков памяти лучше не использовать. В Delphi RTL есть функция GetMem, которая работает в разы быстрее, если же пишеться код без RTL, то лучше использовать HeapAlloc. В-третьих: зачем записывать с помощью WriteProcessMemory в свой процесс? Лучше с помощью VirtualProtect изменить атрибуты нужной области памяти и использовать CopyMemory В-Четвертых (хотя это уже придирка): ООП не рулит, долой TMemoryStream и TMemo. В-пятых: зачем перед VirtualAlloc делать p_buf := nil? Короче, перепиши код по нормальному и тогда он заработает.
SnugForce С подобным кодом тебе дорога в "Королевство Делфи", в лучшем случае на рсдн в соответствующий форум. Asterix Не надо делать кого-то виноватым в ламерстве третьих лиц. Ms Rem Значит, — это постить на форум Win32 сайта, посвящённого низкоуровневому программированию, откровенно ламерские листинги Делфи с использованием VCL?
Вообще то Asterix высказался не против кода в этом листинге, а против языка на котором он написан. А про хреновость этого кода я и сам сказал. А оставить предрассудки означает лишь принятие любого языка пригодного для решения низкоуровневых задач. Если бы был приведен листинг даже на Visual Basic (а на нем тоже ухитряются системные вещи писать), то я был бы не против этого. К VCL конечно отношение особое, этому действительно место в "Королевстве Delphi", но сам вопрос вроде не был связан с VCL.
Только не понимаю, почему все взъелись на SnugForce. Какая разница на чём написан код, у человека проблема, кто может помочь решить помогите.Не можете помочь проигнорируйте. Если модераторы сочтут нужным, объяснят человеку всё "по понятиям про WASM и DELPHI".
SnugForce > "Просто для меня еще туго все на API писать..." 1) Пиши на чем хочешь, но вопросы формулируй по сути и без излишеств. И IceStudent прав - откровенно ламерские листинги Делфи с использованием VCL тут ни к месту, и Ms Rem прав - дело не в языке, а в сути вопроса. А посему совет: не приводи длинные листинги с ненужными подробностями (особенно на "чуждом" языке - заменяй несущественные детали многоточиями типа if not WriteProcessMemory then ... else ..., можно с пояснениями типа "читаем из файла" и т.п. 2) По сути вопроса по Win32: в любом случае для записи в секцию кода (хоть своего процесса, хоть чужого) нужно получить разрешение на запись в соответствующую область памяти. Для своего процесса это делается с помощью VirtualProtect(p1,dp,PAGE_EXECUTE_READWRITE,OldProtect) и соответсвенно никаких OpenProcess и WriteProcessMemory делать не нужно. Затем код просто копируется из p_buf в p1 (апишнной CopyMemory или дельфийской Move). PS: А TMemoryStream ты тут юзаешь по ламерски, т.к. при LoadFromFile он сам выделяет нужное количесво памяти и грузит туда данные из файла. Если уж он тебе так нравится, то не нужно выделять никакой доп памяти под p_buf, а просто использовать p_buf:=msFile.Memory. Но это уже вопрос из сферы Королевства кривых зеркал
Вот переписал код . Но он не правильно код сохраняет... только первые байты, остальные нулями заполняются... Код (Text): var OldProtect: DWORD; iFile: Cardinal; wb: Cardinal; begin p_begin := @ForCopy; p_end := @End_ForCopy; dp := integer(p_end) - integer(p_begin); VirtualProtect(p_begin, dp, PAGE_EXECUTE_READWRITE, OldProtect); iFile := CreateFile('code.dat',GENERIC_WRITE, 0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,0); WriteFile(iFile, p_begin, dp, wb, 0); CloseHandle(iFile); end;
Строчка-то правильная. По кол-ву байт все нормально, но вот содержимое файла и буфера отличаются. Я уж и стандартные функции перепробовал и API. Записывает только первые байты, остальные не хочет. Может надо по блочно записывать? Например, по байту...
SnugForce Это скорее всего дельфийские прибамбасы с импортом - они часто в апишных функциях заменяют аргументы lpvoid на нетипированные var. Поэтому скорее всего у тебя пишется сам адрес p_begin, а не то что лежит по этому адресу. Проверь по подсказке или залезь в windows.pas - скорее всего нужно передавать p_begin^
Вот рабочий код: Код (Text): program Project2; uses windows; procedure ForCopy(); asm nop add eax, 1 add eax, 2 xchg edx, esp pop eax nop nop end; procedure End_ForCopy(); asm end; var iFile: Cardinal; p_begin, p_end: pointer; dp, wb: dword; begin p_begin := @ForCopy; p_end := @End_ForCopy; dp := integer(p_end) - integer(p_begin); iFile := CreateFile('c:\code.dat',GENERIC_WRITE, 0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,0); WriteFile(iFile, p_begin^, dp, wb, nil); CloseHandle(iFile); end. VirtualProtect я выкинул, потому что он там нафиг не нужен.
Чем гадать, не проще ли заглянуть в отладчик? Остатки Делфи я снёс пару месяцев назад, а то бы и сам проверил, чего она там накуролесила. -- пока писал, Ms-Rem привёл код..
Ms Rem, SnugForce И не лень вам приведение типов в integer(p_begin)-integer(p_end) делать Не проще ли в подобных случаях объявлять указатели как pChar Ах, извините, это уже из сферы Королевства ))