WarCraft 3: Часть 2: Функция Preloader

Preload Exploit: работа с файлами

Preloader

В этой главе я расскажу, как запускать код из файла и как читать информацию из файла.. Но не из любого, а только из того, который мы создали при помощи функции PreloadGenEnd. Далее будем называть этот файл Выходным файлом.
Вернёмся к файлу save\PreExp.txt.
function PreloadFiles takes nothing returns nothing

	call Preload( "hi" )
	call Preload( "65757" )
	call Preload( "jjj" )
	call Preload( "testtesttesr" )
	call Preload( "5gfhgf" )
	call Preload( "asefsdf" )
	call Preload( "lolololo" )
	call Preload( "hi" )
	call PreloadEnd( 37.9 )

endfunction
Чтобы выполнить этот код, необходимо вызвать функцию:
call Preloader("save\\PreExp.txt")
Эта функция берёт параметр - путь к файлу. Preloader открывает этот файл и выполняет функцию PreloadFiles из его кода. Если функции PreloadFiles нет или если есть синтаксические ошибки, то ничего не выполняется.
Как мы видим, в файле вызывается функция Preload - т.е. заполняется буфер.
Но, увы, способа читать информацию из буфера я не знаю, и его, похоже, нет.
Так что применим хитрость...

Химичим со строками

Нам необходимо добавить какой-то код в выходной файл при помощи функции Preload.
Если разобраться, то запись в выходной файл происходит так: вводится Preload( ", затем строка из буфера, затем " ) и перевод строки. То есть строка из буфера помещается как параметр функции Preload.
Чтобы добавить свой код, добавим в буфер такую строку, чтобы в выходном файле она:
  1. Закрыла функцию Preload("
  2. Ввела нужный нам код
  3. Избавилась от остатка - ")
Это делается так:
call Preload("\")\n <some code> \n //")
<some code> - это тот код, который мы хотим вставить.
Итак, разбор строки \")\n <some code> \n //
\"\n - это кавычки и перевод строки. Перед кавычками необходим слеш, так как иначе они воспринимаются варом как конец строки. \n, как известно, переводит строку.
<some code> \n - это наш код и перевод строки.
// - это комментарий, чтобы избавиться от хвостика - ")
Вводимый код может быть многострочным - для этого строки нужно разделять при помощи \n.
В итоге в выходном файле получим следующее:
call Preload( "")
<some code>
//" )
Таким образом можно вставлять свой код в выходной файл.
Это может практически любой код. Сейчас я покажу, какой код нужен, чтобы можно было читать информацию из файла.

Про код в выходном файле

Нужно заметить, что в функции PreloadFiles из выходного файла:
  • Недоступны переменные из карты
  • Невозможно вызывать функции из кода карты при помощи call function()
  • Насколько я понял, можно вызывать native-функции. Если я ошибаюсь, поправьте меня.
  • ВАЖНО: Можно применять call ExecuteFunc(function) для вызова функций из кода карты.
Последний пункт очень важен.
Для начала попробуем это проверить.
Откройте ту карту, где мы в прошлой главе делали систему записи чата в файл.
Зайдите в нестандартный код карты и введите туда следующую функцию:
function Test takes nothing returns nothing
    call DisplayTextToForce(GetPlayersAll(),"All OK!")
endfunction
Теперь откройте файл save\PreExp.txt и вставьте в него следующее:
function PreloadFiles takes nothing returns nothing
	call ExecuteFunc("Test")
endfunction
Таким образом, при выполнении кода этого файла запустится функция Test и на экране появится сообщение All OK!.
Откроем в карте триггер, срабатывающий при вводе строки, и немного изменим его код:
if (GetEventPlayerChatString()=="-save") then
    call PreloadGenEnd("save\\PreExp.txt")
elseif (GetEventPlayerChatString()=="-load") then
    call Preloader("save\\PreExp.txt")
else 
    call Preload(GetEventPlayerChatString())
endif
Теперь при вводе -load на экране появится сообщение All OK!.
Запускайте карту и пишите в чат -load. Как мы видим, на экране появляется сообщение All OK!
Не пишите -save, иначе выходной файл испортится. :)

Как получить информацию из файла?

К сожалению, ExecuteFunc не позволяет передать функции параметры.
Поэтому их нужно передать другим способом. Глобальные переменные, как я говорил, не работают, зато можно вызывать нативки. Можно изменить какое либо игровое значение и затем прочитать его. В DataManager'е, например, используется имя 16-го игрока. Сделаем то же самое.
Откроем в карте триггер, срабатывающий при вводе строки, и вместо следующей строки:
call Preload(GetEventPlayerChatString())
напишем следующую:
call Preload("\")\ncall SetPlayerName(Player(15),\""+GetEventPlayerChatString()+"\")\ncall ExecuteFunc(\"Test\")\n//")
Выглядит ужасно, но это то, что нужно. Оно сделает в выходном файле следующее:
call Preload( "")
call SetPlayerName(Player(15),"<введённая строка>")
call ExecuteFunc("Test")
//" )
Это то, что нам нужно.
Теперь откроем нестандартный код карты и вместо
call DisplayTextToForce(GetPlayersAll(),"All OK!")
введём
call DisplayTextToForce(GetPlayersAll(),GetPlayerName(Player(15)))
Таким образом, выводиться будет не All OK!, а имя 16-го игрока, что нам и нужно.
Кроме того, давайте избавимся от непонятного call PreloadEnd.
Для этого перед функцией
call PreloadGenEnd("save\\PreExp.txt")
введём
call Preload("\")\nendfunction\nfunction Other takes nothing returns nothing\n//")
Таким образом, сразу перед call PreloadEnd функция PreloadFiles закончится, и call PreloadEnd будет вынесено в отдельную функцию.
Теперь у нас получилось следующее:
if (GetEventPlayerChatString()=="-save") then
    call Preload("\")\nendfunction\nfunction Other takes nothing returns nothing\n//")
    call PreloadGenEnd("save\\PreExp.txt")
elseif (GetEventPlayerChatString()=="-load") then
    call Preloader("save\\PreExp.txt")
else 
    call Preload("\")\ncall SetPlayerName(Player(15),\""+GetEventPlayerChatString()+"\")\ncall ExecuteFunc(\"Test\")\n//")
endif
Эту карту можно скачать во вложении.
Запустите карту. Введите сообщения в чат. Затем -save, затем -load. На экран будут выведены наши сообщения.
Скорее всего, этии сообщения будут перекрыты чатом, так что чтобы их увидеть, откройте журнал.
После того, как ввести -save, можно закрыть вар и перезагрузить компьютер - данные останутся, так как записаны в файле.
Давайте откроем файл save\PreExp.txt:
» Содержимое выходного файла
function PreloadFiles takes nothing returns nothing

	call Preload( "")
call SetPlayerName(Player(15),"1")
call ExecuteFunc("Test")
//" )
	call Preload( "")
call SetPlayerName(Player(15),"lol")
call ExecuteFunc("Test")
//" )
	call Preload( "")
call SetPlayerName(Player(15),"hello")
call ExecuteFunc("Test")
//" )
	call Preload( "")
call SetPlayerName(Player(15),"...1")
call ExecuteFunc("Test")
//" )
	call Preload( "")
endfunction
function Other takes nothing returns nothing
//" )
	call PreloadEnd( 12621.8 )

endfunction


Действительно, всё как и нужно было нам.
Таким образом можно читать информацию из файла. Конечно, совсем необязательно выводить текст на экран - можно записать его в переменную и вообще делать с ним всё, что угодно.

Заключение

Мы познакомились с функцией Preloader, которая запускает функцию PreloadFiles из файла и научились передавать информацию в карту.
В следующей главе я расскажу про некоторые мелочи, не описанных в этих двух главах.

Просмотров: 3 557

Doc #1 - 6 лет назад 0
ВАЖНО: Можно применять call ExecuteFunc(function) для вызова функций из кода карты.
вот это жара =)
и главный минус прелоада.
Артас Менетил #2 - 6 лет назад 0
Т.е. ExecuteFunc - зло?
Не, ну можно вместо этого крутить переодический триггер 50 раз в секунду и смотреть на имя 16-го игрока...
Doc #3 - 6 лет назад 0
Нет, просто хак карты еще более возможен с экзекатом.
Nikir #4 - 5 лет назад 0
Не могу понять, что я могу ввести вместо "call DisplayTextToForce(GetPlayersAll(),GetPlayerName(Player(15)))" К примеру я хочу записать файлы из PreExp.txt в переменную.
Все, разобрался, вставил "set udg_MyVar = GetPlayerName(Player(15))
SiT3D #5 - 5 лет назад 0
Чтото экзекут фанк не работает... ( вроде всё сделал как в примере, скопировал куда надо. И ничего.
Zonnery #6 - 5 лет назад 0
SiT3D:
Чтото экзекут фанк не работает... ( вроде всё сделал как в примере, скопировал куда надо. И ничего.
Локальные файлы не включены, без них прелоад из внешнего файла невозможен.
Zkay #7 - 4 года назад (отредактировано ) 0
call Preload("\")\nendfunction\nfunction Other takes nothing returns nothing\n//") ---> Не работает.
прикреплены файлы
nvc123 #8 - 4 года назад 1
после \n пробел надо
и используй ворд для просмотра(в блокноте отступы плохо работают)
Zkay #9 - 4 года назад 0
nvc123, Благодарю.
Хорошо было бы, если автор примеры и тему бы подправил.