Разработчики любят усложнять жизнь игрокам. Вместо грамотного противодействия спаму, они убрали возможность копировать и вставлять текст. Ход их мысли сочетает в себе гениальность и простоту, и еще пофигизм.
К сожалению, справиться с пороком лени и сделать по человечески они не могут. Я предлагаю поправить их косяк самостоятельно.
Смышленые игроки, и тем более спамеры, нашли способы вставлять
текст в игру с помощью макросов и стороннего ПО. Но так не интересно.
Я продемонстрирую свой способ решения проблемы.
1. Подготовка
Разрабы убрали возможность вставлять текст на уровне функций. Чтобы вернуть такую возможность, необходимо поправить и дописать код в некоторых местах. В этом деле лучший помощник - hiew32
Для хранения временных данных используйте блокнот.
1.1 Функции буфера обмена
Для работы с буфером обмена необходимы как минимум три функции:
1. - OpenClipboard
2. - GetClipboardData
3. - CloseClipboard
Эти функции игра не импортирует. Необходимо это исправить.
Делать это будем по ординалам, потому что так удобнее.
Скопируйте и откройте файл user32.dll в hiew32.
(Если у вас 64х разрядная ОС, ищите в SysWOW64, иначе в System32)
Переключитесь в HEX или Decode, для этого нажмите Enter.
Откройте список экспорта, для этого нажмите F8 затем F9.
Найдите их в списке и выпишите соответствующие им ординалы (крайний левый ряд чисел). Конвертируйте эти числа в HEX с помощью калькулятора в режиме программиста и запишите их в блокнот. Это необходимо потому что у разных версий user32.dll смещены ординалы одних и тех же API функций.
Дополнительно убедитесь, что функция SendMessageW находится в пределах блока 65кб от начала, для этого отсортируйте список по смещениям (F3).
1.2 Место для хранения данных
Место для адресов импортированных функций и не только, можно взять в самом начале секции данных. Там находится пафосный, но бесполезный текст, ссылки на который я не обнаружил.
Откройте файл warspear.exe в hiew32.
Переключитесь в HEX, для этого нажмите Enter.
Откройте начало секции данных.
Для этого, нажмите F8 затем F6, выберите пункт .data и нажмите Enter.
Первое двойное слово используются приложением.
По смещению +8 находится тот самый текст.
Выпишите адрес [красная рамка], прибавьте к нему 8 и сохраните в блокнот.
1.3 Дополнительные функции
Далее необходимо взять указатели адресов двух функций в таблице импорта:
SendMessageW и GetProcAddress.
Нажмите F8 затем F7.
Найдите функцию SendMessageW в списке импорта.
(Начните набирать ее имя и она появится)
Нажмите Enter и ждите.
Сохраните в блокнот последние 4 байта инструкции задом наперед.
Пример: FF15|60A4AE00| -> 00AEA460
Это самый простой способ получить указатель адреса в таблице импорта.
Проделайте то же самое с функцией GetProcAddress.
1.4 Точка входа
Нажмите F8, затем F5.
Запишите в блокнот адрес на который указывает вызов на точке входа в программу [пурпурный цвет].
1.5 Процедура выделения памяти
Наконец, нужно записать адрес процедуры выделения памяти:
Нажмите F7 и в поле HEX введите сигнатуру: 6A 11 FF D6 0F B7 D8 C1
Нажмите Enter.
(Затем нажмите Ctrl + F7, т.к. в расширенной версии таких участков два.
Необходим последний.)
Запишите в блокнот адрес на который указывает второй call [красная рамка].
Так же, запишите адрес самой инструкции вызова [желтая рамка].
2. Импорт функций
Я предлагаю совместить приятное с полезным, и параллельно оптимизировать одну процедуру. В качестве благодарности, пропишемся в ее квартире.
2.1 Оптимизация
Нажмите Ctrl + Home, чтобы перейти в начало файла.
Нажмите F7 и в поле HEX введите сигнатуру: 66 89 50 FE 3B F7
Не смешно. Между прочим, это критический участок кода,
через который ежесекундно проходит туча данных.
Установите курсор в начало этого "шедевра" компилятора [красная рамка].
Нажмите F3 затем Enter.
Запишите следующие инструкции, после каждой нажимайте Enter:
push edi
mov edi,[ecx]
push ecx
mov ecx,[ecx+8]
xor eax,eax
rep stosw
pop ecx
mov [ecx+8],eax
mov eax,ecx
pop edi
retn
Оптимизация завершена.
Нажмите ESC и F9.
Запишите в блокнот адрес текущей инструкции!
С этого момента будет располагаться наша процедура импорта.
2.2 Процедура импорта
Снова нажмите F3, затем Enter.
Запишите туда следующие инструкции, после каждой нажимайте Enter.
Если HEX число, адрес или указатель начинается с буквы, записывайте его с нулем в начале! Исключением является непосредственно машинный код.
На место SendMessageW и GetProcAddress, запишите их указатели (см. 1.3).
На место DATA запишите адрес (без точки) полученный в параграфе 1.2.
На место ord1, ord2, ord3, запишите соответствующие ординалы HEX (см. 1.1).
pushad
mov ebp,[SendMessageW]
and ebp,0FFFF0000h
mov esi,GetProcAddress
mov edi,DATA
push ord3
push ord2
push ord1
push ebp
call d,[esi]
stosd
Здесь нажмите ESC и впишите вручную опкод перехода: EBB1
(Поскольку переход короткий, мне удобнее вам представить его в таком виде)
Нажмите F9 чтобы сохранить изменения.
Теперь поднимаемся выше к блоку межпроцедурной области.
Она заполнена байтами CC (инструкция int3) [красная рамка].
(Используем недостаток компиляторов как преимущество).
Установите курсор в начало верхней межпроцедурной области.
Сюда указывает наш короткий прыжок.
Нажмите, F3 затем Enter.
Запишите следующие инструкции, после каждой нажимайте Enter:
На место ENTRY запишите адрес (с точкой в начале) полученный
в параграфе 1.4
push ebp
call d,[esi]
stosd
push ebp
call d,[esi]
stosd
popad
jmp ENTRY
Нажмите F9 чтобы сохранить изменения.
Процедура импорта готова, остался последний штрих.
Необходимо подменить оригинальную точку входа вызовом нашей процедуры.
Перейдите к точки входа приложения, для этого нажмите F8 затем F5.
Нажмите F3, затем Enter.
Запишите сюда следующую инструкцию:
Заместо IMPROC запишите адрес (с точкой в начале) нашей процедуры, см. конец параграфа 2.1
call IMPROC
Нажмите F9 чтобы сохранить изменения.
Для навигации по адресам в hiew32 используйте F5, и указывайте виртуальный адрес с точкой в начале.
3. Обработчик сочетания клавиш
Процедура обработки не уживется с другими, в силу своего лишнего веса.
Поэтому, прийдется ей жить в подвале в конце секции кода.
Нажмите F8, затем F6.
Обратите внимание на значения PhysSize и Offset секции раздела .text
Выпишите значение PhysSize и прибавьте к нему значение Offset.
Выйдите из окна просмотра разделов двойным нажатием ESC.
Нажмите F5 и введите получившийся адрес (без точки).
Нажмите Enter.
Это конец раздела кода. Здесь достаточно места из за выравнивания секции.
Перейдите вверх, в начало нулевых байтов. Установите курсор на самом первом.
Запишите в блокнот адрес этого места! [красная рамка]
Здесь будет располагаться обработчик сочетания клавиш.
Нажмите F3.
Запишите в ручном режиме опкод:
81 7C E4 08 00 01 00 00 75 4D 83 FF 56 75 48 84 DB 74 44
Теперь нажмите Enter.
Запишите следующие инструкции, после каждой нажимайте Enter:
На место DATA запишите адрес полученный в параграфе 1.2.
pushad
mov esi,DATA
push 0dh
push 0
call d,[esi]
call d,[esi+4]
cmp w,[eax],0
Здесь нажмите ESC и в ручном режиме запишите опкод перехода: 742E
Теперь нажмите Enter и допишите оставшуюся часть кода:
На место SendMessageW запишите ее указатель полученный в параграфе 1.3.
На место MEM, запишите адрес (с точкой в начале), процедуры выделения памяти (см. 1.5) [красная рамка].
mov d,[esi+0ch],eax
mov edi,eax
mov ecx,0FFFFh
xor eax,eax
repnz scasw
neg cx
dec ecx
dec ecx
mov d,[esi+10h],ecx
push 1
push 30h
push 102h
mov eax,[esp+48h]
push ss:[eax+8]
call d,[SendMessageW]
popad
jmp MEMP
Нажмите F9 чтобы сохранить изменения.
Обработчик сочетания Ctrl + V готов.
Осталось подменить им вызов процедуры выделения памяти.
Нажмите F5 и введите адрес вызова (c точкой в начале), полученный в параграфе 1.5 [желтая рамка]. Нажмите Enter.
Теперь нажмите F3, затем Enter.
Запишите следующую инструкцию:
На место CTRLV запишите адрес (с точкой в начале) нашего обработчика сочетаний клавиш (см. выше).
call CTRLV
Нажмите F9 чтобы сохранить изменения.
Непосредственно процедура выделения памяти не нужна.
Тем не менее, она очень удачно располагается, сразу после вызова GetAsyncKeyState клавиши Ctrl, результат которой обработчик будет проверять если нажата клавиша "V" [Код: 56h]. Затем будет получен и сохранен указатель на блок буфера обмена в формате UNICODE. Его длина будет вычислена и так же записана в заготовленное ранее место "DATA".
4. Внедрение в систему ввода сообщений
Система ввода сообщений устроена не самым лучшим образом.
Текстовая ее чать состоит из двух блоков: сокращенного и расширенного.
В них помещается текст который будет отправлен сообщением (за исключением ссылки предметов).
[голубая рамка]: Сокращенный текстовый блок сообщения;
[красная рамка] 0: Адрес расширенного текстового блока сообщения;
[желтая рамка] +4: Размер расширенного текстового блока сообщения;
[зеленая рамка] +8: Текущий размер текста сообщения (UNICODE);
Фиксированный размер сокращенного блока - 19 символов (UNICODE).
При достижении лимита, весь текст копируется в расширенный текстовый блок с последующим его использованием. В отличие от сокращенного, размер расширенного блока увеличивается по мере необходимости. Каждый раз при введении сообщения выделяются новые блоки, старые освобождаются.
Сказать что это тупо - ничего не сказать.
4.1 Модификация процедуры заполнения
За манипуляции с блоками и текстом сообщений отвечают соответствующие процедуры. Определенную из них необходимо модифицировать.
Нажмите Ctrl + Home, чтобы перейти в начало файла.
Нажмите F7 и в поле HEX введите сигнатуру: 8B 16 85 DB 74 1E 8B 45
Нажмите F3, затем Enter.
Запишите следующие инструкции, после каждой нажимайте Enter:
push edi
mov edi,[esi]
mov [esi+8],ebx
push esi
lea esi,[ebp+0ch]
push ecx
Здесь нажмите ESC и в ручном режиме запишите опкод:
89 D9 83 F9 01 72 19 74 0E
Теперь нажмите Enter и допишите оставшуюся часть кода:
На место DATA запишите адрес полученный в параграфе 1.2.
mov eax,DATA+0ch
mov esi,[eax]
mov d,[eax+4],1
rep movsw
call d,[DATA+8]
pop ecx
pop eax
pop edi
pop esi
pop ebx
pop ebp
nop
Нажмите F9 чтобы сохранить изменения.
Модификация процедуры заполнения завершена.
4.2 Трансляция размера
Последнее что необходимо сделать - настроить передачу длины
текста буфера обмена системе ввода сообщений.
Для этого потребуется изменить определенный участок кода.
Нажмите Ctrl + Home, чтобы перейти в начало файла.
Нажмите F7 и в поле HEX введите сигнатуру: 08 00 FF 75 0C 8B CE 50
Установите курсор в начало инструкции push сразу после retn [красная рамка].
Нажмите F3 и запишите опкод перехода: EB 0B 90
Установите курсор в начало первой инструкции pop, сразу за call [желтая рамка].
Нажмите F3 и запишите опкод перехода: EB EA
Теперь нажмите Enter и запишите следующую инструкцию:
На место DATA запишите адрес полученный в параграфе 1.2.
push d,[DATA+10h]
Здесь нажмите ESC и в ручном режиме запишите опкод перехода: EB EE
Нажмите F9 чтобы сохранить изменения.
Заключение
Сохранив все изменения вы сможете использовать сочетание клавиш Ctrl + V для вставки текста в сообщения.
Не используйте сообщения с переносом на новую строку.
Удачной игры!