К списку форумов К списку вопросов
Вопрос к профессионалам.
Крокодил Гена
21.07.2004 - 02:16
Нужно написать маленькую прогу на дельфи. Задача такая:
чтоб при нажатии на кнопку прога меняла значение по адресу в памяти по адресу 004С3160. Надо поменять значение которое храниться по этому адресу с
250 на 120. Однако этот адрес памяти используется другим приложением.
Подскажите что надо вставить в это место:
procedure TForm1.Button1Click(Sender: TObject);
begin
end;
Я в программировании разбираюсь плохо, но надо очень 8(
Огромная просьба помочь. Писал даже на www.delphikingdom.ru.
Никто не помог, все молчат. Прога должна работать по принципу O'Matic(а),
но адрес известен и при каждом новом запуске он одинаковый.
Delphist
1 - 21.07.2004 - 10:45
Уважаемый Крокодил!
Я сильно Вас разочарую, но! Дело в том, что КАЖДАЯ запущенная программа работает в СВОЕМ адресном пространстве, и соответственно имеет свой собственный адрес 004С3160. Это как в комедии "С легким паром" - улица Строителей есть в каждом городе, но живут на ней разные люди.
Поэтому написав
procedure TForm1.Button1Click(Sender: TObject);
var p: PBYTE;
begin
  p = Ptr($004C3160);
  p^ = 120;
end;
Вы ничего не добьетесь - это изменит память ЭТОЙ программы, а не другой.
Тут нужно применять cross-process subclassing с внедрением DLL, но эта тема - не для начинающего.
archimag
2 - 21.07.2004 - 11:03
Адрес то физический или виртуальный? Какая операционная система?
   
Если это адресс из чужого виртуального адресого пространства, то делаем следущее: загружаем в адресное пространство чужого процесса свой dll-моудуль и создаём там свой поток, который сразу переводим в режим ожидания с помощью какого-нибудь объекта синхронизации (например, мьютекса). В обработчике Button1Click переводим, используемый объект синхронизации в незатяное состояние, наш поток просыпается, изменяет 250 на 120 и, если необходимо, снова ждёт.
Алгоритм примерно такой. Более подробную информацию смотри у Рихтера ("Windows для профессионалов") или ищи в нете инфу о внедрении dll.
    
В принципе, есть ещё вариант работы в режиме ядра с обращением к диспетчеру страниц - но это значительно сложнее.
    
Обрати внимание, что Windwos (особенно семейство NT)- специально разработано так, чтобы исключить ситуацию, когда один процесс пишет по адресам другого :-)
tvv
3 - 21.07.2004 - 11:55
Есть такой утиль ArtMoney это типа для взлома игрушек, так он так и работает: выбираешь процесс, находишь в нем нужные адреса (для этого там много способов), и меняешь значения по ним. Так вот для твоей цели сгодится.
Смотри здесь http://www.artmoney.ru/rus.htm
тебе подойдет и бесплатная версия.
Хотя решение не сосвсем стандартное.
Delphist
4 - 21.07.2004 - 18:27
Вспомнил, на Королевстве Дельфи пример есть - Memory Inspector
Старый Добрый UE
5 - 22.07.2004 - 14:57
WriteProcessMemory() ?
Sabrian
6 - 23.07.2004 - 14:56
var
    hproc:hhandle;
    buffer,writen:integer;
begin
    //получить handle нужного процесса
    hproc:=OpenProcess(PROCESS_ALL_ACCESS,True,handle);
    buffer:=120;
    WriteProcessMemory(hproc,$004С3160,buffer,4,writen);
end;
Sabrian
7 - 23.07.2004 - 15:07
Верхний код не совсем верен (он по MSDN писан). Прототип Windows.WriteMemory отличается от того каким я его полагал. Верно будет вот-так:
var
    process,hproc:cardinal;
    buffer,writen:cardinal;
begin
    hproc:=OpenProcess(PROCESS_ALL_ACCESS,true,process);
    buffer:=120;
    WriteProcessMemory(hproc,ptr($004C3160),@buffer,4,writen);
end;
Я не знаю будет ли это работать в NT семействе.
archimag
8 - 23.07.2004 - 15:29
7: не будет :-)
archimag
9 - 23.07.2004 - 16:26
Беру свои слова обратно. WriteProcessMemory можно писать что угодно и куда угодно, за исключением закрытого 64КБ раздела в 2000(и страше) - который начинается с 0х7FFF000. Техника с внедрением dll обычно нужна для определения куда писать, ну а если уже узвестно куда писать - без проблем...
Sabrian
10 - 26.07.2004 - 11:24
Вообще говоря, применяя dll можно читать и писать пямать на порядок быстрее
(не нужны вызовы, копирование памяти и.т.д)
Крокодил Гена
11 - 01.08.2004 - 15:32
Всем спасибо, особенно Sabrianu. Менять значение по определенному адресу получается, но возникла другая проблемма: чтоб его менять необходимо указывать ид процесса, я его выуживаю с помощью армини там есть "информация о процессе", где отражается его ид, но он при каждом новом запуске другой. Подскажите как с этим бороться. Вот используемый мною листинг:
var
  hproc:cardinal;
  buffer,writen:cardinal;
const
  PatchAddr: pointer = Pointer($004С3160);
  process: cardinal; = cardinal($FFF98467); //ид процесса
begin
  hproc:=OpenProcess(PROCESS_VM_WRITE,false,process);
  buffer:=120;
  WriteProcessMemory(hproc,PatchAddr,@buffer,4,writen);
end
Крокодил Гена
12 - 01.08.2004 - 15:37
Имя другого приложения в памяти которого необходимо менять значение - известно.
Крокодил Гена
13 - 01.08.2004 - 15:39
Как задать ид используя имя файла?
Старый Добрый UE
14 - 02.08.2004 - 00:43
Посмотри в сторону ToolHelp Api: CreateToolhelp32Snapshot и т.д.
Ты получаешь список процессов, и находишь нужный, сравнивая имя модуля каждого процесса с нужным тебе.
Sabrian
15 - 03.08.2004 - 18:45
var
    h:integer;
    p:tagProcessEntry32;
    b:boolean;
begin
    h:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
    b:=process32First(h,p);
    while b do
    begin
        //сдесь смотри p
        b:=Process32Next(h,p);
    end;
end;
Не забудь добавить в Uses модуль tlhelp32
У структуры tagProcessEntry32 есть поля szExeName и th32ProcessID.
И скажи спасибо UE, иначе я бы не знал бы где мне искать информацию, и наверное тогда я и не стал бы.

К списку вопросов на форуме Программирование

>>