Проблема с WriteProcessMemory

Тема в разделе "WASM.WIN32", создана пользователем CFA, 14 сен 2010.

  1. CFA

    CFA New Member

    Публикаций:
    0
    Регистрация:
    14 сен 2010
    Сообщения:
    6
    Пытаюсь записать в память процесса данные, VirtualProtectEx и WriteProcessMemory проходят успешно, но данные не изменяются. При попытке записать в данный адрес 1024 байта, записываются только последние ~300 байт, первые же ~700 остаются неизменными. Причем при записи по другим адресам таких проблем нет. Единственное отличие этого адреса, то, что он располагается в сегменте rdata, а те, куда запись проходит успешно text и data.
    Что самое интересное, если считать по этому адресу данные с помощью ReadProcessMemory, то считывается то, что записали, а если я смотрю этот участок памяти с помощью ollydbg, то данные там не изменяются.
    Есть ли какие то ограничения по записи в rdata, и если есть, возможно ли их обойти? Или в чем же может быть дело?

    Возможно, будет полезна дополнительная информация - процесс запускаю сам в состоянии CREATE_SUSPENDED, произвожу необходимые изменения с помощью VirtualProtectEx/WriteProcessMemory после чего делаю ResumeThread.
    Запись происходит так:
    Код (Text):
    1.   if VirtualProtectEx(hProcess, ptr, 1024, PAGE_READWRITE, oldProtect) then
    2.   begin
    3.     //ReadProcessMemory(hProcess, ptr, patch, len, writtenBytes);
    4.     res := WriteProcessMemory(hProcess, ptr, patch, len, writtenBytes);
    5.  
    6.     if not res then
    7.       WriteToLog(lhSystemLog,  Format('WriteProcessMemory fail: %s', [SysErrorMessage(GetLastError)]));
    8.  
    9.     result := res and (len=Integer(writtenBytes));
    10.  
    11.     // восстанавливаем права обратно
    12.     VirtualProtectEx(hProcess, ptr, 1024, oldProtect, oldProtect);
    13.   end
    14.   else
    15.     WriteToLog(lhSystemLog,  Format('VirtualProtectEx fail: %s', [SysErrorMessage(GetLastError)]));
     
  2. fsd

    fsd New Member

    Публикаций:
    0
    Регистрация:
    4 июл 2010
    Сообщения:
    353
  3. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    а вы не думаете, что это проблемы с отладчиком, а не с WriteProcessMemory?
     
  4. CFA

    CFA New Member

    Публикаций:
    0
    Регистрация:
    14 сен 2010
    Сообщения:
    6
    не думаю, тк я подменяю адрес импортируемой функции, а программа продолжает использовать оригинальный адрес функции.
     
  5. spa

    spa Active Member

    Публикаций:
    0
    Регистрация:
    9 мар 2005
    Сообщения:
    2.240
    Тогда возникает вопрос. один ли процесс вы использует для записи/чтения и отладки в оли.
     
  6. CFA

    CFA New Member

    Публикаций:
    0
    Регистрация:
    14 сен 2010
    Сообщения:
    6
    да один, такой процесс в системе, на момент отладки один. и другие изменения в olly отлично видны.

    [​IMG]

    вот картинка до патча и после. выглядит очень странно. данные писались с адреса 4E7000 в количестве 10к байт. В начале картина аналогичная, местами видны тестовые данные AE. А с адреса 4E7384 и до 4E9800 уже идут только тестовые данные, без вкрапления оригинальных.
     
  7. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    1024 байта? всю таблицу импорта подменяете штоль?)
    может сам ваш процесс ее и переписывает)))

    вообще и то и то - отображения файла на виртуальную память... можете посмотреть права и флаги страниц... сделайте VirtualQuery страницам, куда замаппирована .rdata и куда замаппирована .text например (State, Type и AllocationProtect)...
     
  8. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    хехе... на картинке у вас AE попадают в нулевые dword'ы... мистика)))
     
  9. 100gold

    100gold New Member

    Публикаций:
    0
    Регистрация:
    26 фев 2010
    Сообщения:
    165
    Может софтина восстанавливает то что вы меняете из какого-нибудь своего потока. Аппаратный бряк в Olly нужную область памяти можно попробовать и посмотреть, кто и как пишет в память.
     
  10. CFA

    CFA New Member

    Публикаций:
    0
    Регистрация:
    14 сен 2010
    Сообщения:
    6
    1024 в VirtualProtectEx стоит заменить на len, но тк все патчи точечные (менее 16 байт) то 1024 хватает. Что касается 10к байт, то это тестов ради. Реально в таблице импорта надо заменить только 4 байта. Я тоже только сейчас заметил, что заменены нулевые dword'ы, но после адреса 4E7384 заменены уже не только нулевые. И напомню еще раз, что ReadProcessMemory считывает по всем адресам, то что было записано.

    Сегодня уже не посмотрю, какие флаги/права на страницах, но завтра обязательно отпишусь.

    Программа не может ничего восстановить, тк в момент применения патчей процесс в состоянии SUSPENDED
     
  11. gorodon

    gorodon New Member

    Публикаций:
    0
    Регистрация:
    19 окт 2009
    Сообщения:
    301
    CFA
    Вы пытаетесь изменить таблицу импортируемых функций, когда она еще не "инициализирована" (да простят меня Гуру за вольность трактовки) - "инициализация" происходит после запуска вами потока (ResumeThread). И не забывайте, что таблиц - две копии.
    Вы не видите это в оле, т.к. аттач происходит к уже запущенному процессу - при этом "инициализация" таблиц импорта уже произошла.
    Возьмите любой memviewer и посмотрте интересующую память после патча, но ДО запуска потока и сравните ее с тем, что будет ПОСЛЕ запуска потока.
     
  12. CFA

    CFA New Member

    Публикаций:
    0
    Регистрация:
    14 сен 2010
    Сообщения:
    6
    Кое что проясняется. Был бы благодарен, за ссылку про "две копии таблицы импорта".
    И если я правильно понял, то у меня не получится сделать задуманное - подменить в таблице импорта адрес функции и таким образом перехватить ее? И задачу надо как то решать по другому?
     
  13. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    gorodon
    Верно. Импорт настраивается при инициализации процесса в LdrpInitializeProcess() -> LdrpWalkImportDescriptor() после подгрузки Kernel32.dll. Отладчик создаёт потоки в процессе, именно этот поток и выполняет инициализацию.
     
  14. onSide

    onSide New Member

    Публикаций:
    0
    Регистрация:
    18 июн 2008
    Сообщения:
    476
    Да, что за две таблицы импорта??
    Вам легче подгрузить длл-ку, которая поставит хуки.
    Создаете процесс суспендед -> выделяете память->пишите в нее стаб который грузит длл-ку-> вставляете um APC на этот стаб.
    Она вызовется когда все будет проинициализировано и все будет ок.
    Таким образом вам надо написать только 1 стаб, вместо n (кол-во хукаемых ф-ций). Но придется таскать с собой длл-ку :)

    Если подумать, то можно сделать даже без стаба ;)
     
  15. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    onSide
    Используются две IAT(IMAGE_IMPORT_DESCRIPTOR.OriginalFirstThunk и FirstThunk), изменяется одна.
     
  16. CFA

    CFA New Member

    Публикаций:
    0
    Регистрация:
    14 сен 2010
    Сообщения:
    6
    Что же, благодарю за исчерпывающие ответы. Буду делать dll