Автор Тема: Реверс плагина на примере увеличения лимита img-архивов  (Прочитано 7028 раз)

Оффлайн xanser

  • Главный Модератор
  • Постоялец
  • *****
  • Сообщений: 598
  • Репутация: +92/-0
  • Есть такая профессия - на работе сидеть
    • Просмотр профиля
Бывают случаи, когда авторы создают полезные плагины, но не делятся исходным кодом. Мне например не хочется использовать чужие плагины в своем моде, спрашивать разрешение авторов включать их в свою сборку, поэтому стараюсь все писать сам. Но как раздобыть необходимый адрес, если код закрыт. Если с CLEO-скриптами все просто, их можно открыть и посмотреть, вытащить оттуда все полезное, то с ASI-плагинами поможет только IDA PRO.

Многие знают плагин Img Limit Adjuster, но как он работает.
Сначала пойдем честным путем (я так и сделал). Подключение img-архива происходит в default.dat или gta_vc.dat командой CDIMAGE, отсюда легко это найти в IDA



На рисунке видно, что лимит img-архивов задается не ограничением количества CDIMAGE_COUNT, а размером памяти, выделенной под их названия CDIMAGE_NAMES и соответственно под сам массив указателей CDIMAGES. Получаем максимум 8 архивов, кроме gta3.img, больше просто некуда записать.

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

Код: C++
  1. void *CDIMAGE_NAMES; CDIMAGE_NAMES = VirtualAlloc(NULL,0x4000,MEM_COMMIT,PAGE_READWRITE);
  2. void *CDIMAGES;      CDIMAGES      = VirtualAlloc(NULL,0x1000,MEM_COMMIT,PAGE_READWRITE);

Осталось перенаправить все первоначальные ссылки (их легко увидеть, нажав X в IDA), которые были на 0x6F7488 CDIMAGE_NAMES и 0x6F76D0 CDIMAGES на новые области

Код: C++
  1. WriteDWORD((DWORD*)0x4081D2,(DWORD)CDIMAGE_NAMES);
  2. WriteDWORD((DWORD*)0x40823A,(DWORD)CDIMAGE_NAMES);
  3. WriteDWORD((DWORD*)0x408801,(DWORD)CDIMAGE_NAMES);
  4. WriteDWORD((DWORD*)0x40818B,(DWORD)CDIMAGES);
  5. WriteDWORD((DWORD*)0x408199,(DWORD)CDIMAGES);
  6. WriteDWORD((DWORD*)0x4081C7,(DWORD)CDIMAGES);
  7. WriteDWORD((DWORD*)0x408215,(DWORD)CDIMAGES);
  8. WriteDWORD((DWORD*)0x408221,(DWORD)CDIMAGES);
  9. WriteDWORD((DWORD*)0x40851B,(DWORD)CDIMAGES);
  10. WriteDWORD((DWORD*)0x4086E1,(DWORD)CDIMAGES);
  11. WriteDWORD((DWORD*)0x4087E2,(DWORD)CDIMAGES);
  12. WriteDWORD((DWORD*)0x4087EE,(DWORD)CDIMAGES);
  13. WriteDWORD((DWORD*)0x40885B,(DWORD)CDIMAGES);
  14. WriteDWORD((DWORD*)0x408869,(DWORD)CDIMAGES);

На всякий случай моя процедура WriteDWORD, которая просто пишет в адрес 4 байта

Код: C++
  1. void WriteDWORD(DWORD *Address, DWORD Value)
  2. {
  3.     DWORD OldProtect;   VirtualProtect(Address,sizeof(DWORD),PAGE_READWRITE,&OldProtect);
  4.     *Address = Value;   VirtualProtect(Address,sizeof(DWORD),OldProtect,&OldProtect);
  5. }

Теперь лимит img-архивов ограничивается только выделенной под них областью памяти.

Теперь о реверсе существующего плагина IMG Limit Adjuster. Я использовал это, только чтобы проверить свои описанные выше догадки, но те кто не догадаются, смогут с чего-то начать. Можно открыть плагин в IDA, сразу появится основная функция и действительно в ней видно, что автор руководствовался точно такой же логикой, два раза выделяется память VirtualAlloc и дальше перебрасываются на нее все ссылки через VirtualProtect. Это и означает, что адрес, переданный в качестве параметра в VirtualProtect будет меняться, их и смотрим.



Кстати, достаточно выделить память один раз и правильно распределить, по 64 байта под названия, по 4 под указатели.
P.S. А еще лучше обойтись динамическими массивами.
« Последнее редактирование: Июль 01, 2014, 12:00:06 pm от xanser »

Оффлайн Sektor

  • Администратор
  • Постоялец
  • *****
  • Сообщений: 521
  • Репутация: +34/-0
    • Просмотр профиля
Замечательная статья, думаю многим будет полезна...

Оффлайн xanser

  • Главный Модератор
  • Постоялец
  • *****
  • Сообщений: 598
  • Репутация: +92/-0
  • Есть такая профессия - на работе сидеть
    • Просмотр профиля
Единственный момент, который я заметил, что плагин оставляет gta3.img еще и по старому адресу, не знаю зачем, если туда больше нет ссылок. Список изменяемый адресов в точности как у меня. И еще меня смущает функция, вызываемая первой, не знаю что это. Плохо что всякие offset дизассемблируются не всегда правильно, приходится переключать их на более подходящие по смыслу варианты. Но в моем варианте игра запустилась нормально, лимит увеличен, просто смущает какой-то еще штрих.

P.S. Все понял, плагин грузится позднее и не успевает сразу все поменять. Тогда я сделал один в один.
« Последнее редактирование: Апрель 06, 2014, 07:47:58 am от xanser »