При работе с символьными объектами (управляющими последовательностями, &-сущностями, экранирующими последовательностями, мнемониками и т.д.) в моём случае Escape-последовательностями типа "\xnn", возникла необходимость их динамического формирования. Такая задача может возникнуть, например, при разборе вредоносного кода атакованного сайта.
Собственно проблема — не работает следующий код:
При разборе выяснил, что такой код работает:
И совсем не работает код в одинарных кавычках, т.к. последовательность вообще не интерпретируется:
Теперь задачу можно сформулировать так: необходима правильная интерпритация строки, содержащей динамически сформированную последовательность типа "\xnn", символы которой составлены из фрагментов.
В данном случае выполняются две операции — конкатенация и интерпритация символьных объектов. И выполняется они в строгой последовательности. Сначала выполняется интерпритация символьных объектов, затем конкатенация, но не наоборот.
Таким образом, в первом примере один из зашифрованных символов последовательности разбивается на фрагменты.
"\x51" преобразуется в символ «Q», а для строки "\х" php ищет последующие 2 символа, не находит их и при совмещении частей выводит в строку 4-мя символами. Такая строка уже не является для php-интерпритатора командой к преобразованию.
Во втором примере php заменяет содержимое двойных кавычек на символы и «склеивает» их в единую строку.
Поскольку заставить php сначала склеивать символы, а затем их интерпретировать не удалось, попробуем получить строку как есть и заменить неинтерпретирующиеся последовательности на готовые символы.
Мои поиски встроенной или готовой функции преобразования последовательности типа "\xnn" в символы к внятному результату не привели. «Говорят, что плохо искал» (В.Цой). В итоге данная задача была решена использованием функция strtr(). Здесь заменяются неинтерпритируемые последовательности '\х50' на преобразуемые"\x50". Разница только в кавычках.
Вот готовая функция для символьных объектов типа "\xnn" и вызов:
Теперь всё хорошо:
Пользователь Habra-Mikhail предложил вариант без использования собственной функции
Поиск причины и решения заняло некоторое количество времени, думаю пройденный мной путь поможет быстрее разобраться всем, кто столкнётся с подобной задачей в дальнейшем.
Собственно проблема — не работает следующий код:
$inx = '50';
$str = "\x".$inx;
$str .= "\x51";
var_dump($str);
// выведет \x50Q
При разборе выяснил, что такой код работает:
$str = "\x50";
$str .= "\x51";
var_dump($str);
// выведет PQ
И совсем не работает код в одинарных кавычках, т.к. последовательность вообще не интерпретируется:
$str = '\x50';
$str .= ‘\x51’;
var_dump($str);
// выведет \x50\x51
Постановка задачи
Теперь задачу можно сформулировать так: необходима правильная интерпритация строки, содержащей динамически сформированную последовательность типа "\xnn", символы которой составлены из фрагментов.
В данном случае выполняются две операции — конкатенация и интерпритация символьных объектов. И выполняется они в строгой последовательности. Сначала выполняется интерпритация символьных объектов, затем конкатенация, но не наоборот.
Таким образом, в первом примере один из зашифрованных символов последовательности разбивается на фрагменты.
"\x51" преобразуется в символ «Q», а для строки "\х" php ищет последующие 2 символа, не находит их и при совмещении частей выводит в строку 4-мя символами. Такая строка уже не является для php-интерпритатора командой к преобразованию.
Во втором примере php заменяет содержимое двойных кавычек на символы и «склеивает» их в единую строку.
Решение
Поскольку заставить php сначала склеивать символы, а затем их интерпретировать не удалось, попробуем получить строку как есть и заменить неинтерпретирующиеся последовательности на готовые символы.
Мои поиски встроенной или готовой функции преобразования последовательности типа "\xnn" в символы к внятному результату не привели. «Говорят, что плохо искал» (В.Цой). В итоге данная задача была решена использованием функция strtr(). Здесь заменяются неинтерпритируемые последовательности '\х50' на преобразуемые"\x50". Разница только в кавычках.
Вот готовая функция для символьных объектов типа "\xnn" и вызов:
function str2escape($string) {
$sym_tbl = array(
'\x00' => "\x00", '\x01' => "\x01", '\x02' => "\x02", '\x03' => "\x03", '\x04' => "\x04", '\x05' => "\x05",
'\x06' => "\x06", '\x07' => "\x07", '\x08' => "\x08", '\x09' => "\x09", '\x0a' => "\x0a",
'\x0b' => "\x0b", '\x0c' => "\x0c", '\x0d' => "\x0d", '\x0e' => "\x0e", '\x0f' => "\x0f",
'\x11' => "\x11", '\x12' => "\x12", '\x13' => "\x13", '\x14' => "\x14", '\x15' => "\x15",
'\x16' => "\x16", '\x17' => "\x17", '\x18' => "\x18", '\x19' => "\x19", '\x1a' => "\x1a",
'\x1b' => "\x1b", '\x1c' => "\x1c", '\x1d' => "\x1d", '\x1e' => "\x1e", '\x1f' => "\x1f",
'\x21' => "\x21", '\x22' => "\x22", '\x23' => "\x23", '\x24' => "\x24", '\x25' => "\x25",
'\x26' => "\x26", '\x27' => "\x27", '\x28' => "\x28", '\x29' => "\x29", '\x2a' => "\x2a",
'\x2b' => "\x2b", '\x2c' => "\x2c", '\x2d' => "\x2d", '\x2e' => "\x2e", '\x2f' => "\x2f",
'\x31' => "\x31", '\x32' => "\x32", '\x33' => "\x33", '\x34' => "\x34", '\x35' => "\x35",
'\x36' => "\x36", '\x37' => "\x37", '\x38' => "\x38", '\x39' => "\x39", '\x3a' => "\x3a",
'\x3b' => "\x3b", '\x3c' => "\x3c", '\x3d' => "\x3d", '\x3e' => "\x3e", '\x3f' => "\x3f",
'\x41' => "\x41", '\x42' => "\x42", '\x43' => "\x43", '\x44' => "\x44", '\x45' => "\x45",
'\x46' => "\x46", '\x47' => "\x47", '\x48' => "\x48", '\x49' => "\x49", '\x4a' => "\x4a",
'\x4b' => "\x4b", '\x4c' => "\x4c", '\x4d' => "\x4d", '\x4e' => "\x4e", '\x4f' => "\x4f",
'\x51' => "\x51", '\x52' => "\x52", '\x53' => "\x53", '\x54' => "\x54", '\x55' => "\x55",
'\x56' => "\x56", '\x57' => "\x57", '\x58' => "\x58", '\x59' => "\x59", '\x5a' => "\x5a",
'\x5b' => "\x5b", '\x5c' => "\x5c", '\x5d' => "\x5d", '\x5e' => "\x5e", '\x5f' => "\x5f",
'\x61' => "\x61", '\x62' => "\x62", '\x63' => "\x63", '\x64' => "\x64", '\x65' => "\x65",
'\x66' => "\x66", '\x67' => "\x67", '\x68' => "\x68", '\x69' => "\x69", '\x6a' => "\x6a",
'\x6b' => "\x6b", '\x6c' => "\x6c", '\x6d' => "\x6d", '\x6e' => "\x6e", '\x6f' => "\x6f",
'\x71' => "\x71", '\x72' => "\x72", '\x73' => "\x73", '\x74' => "\x74", '\x75' => "\x75",
'\x76' => "\x76", '\x77' => "\x77", '\x78' => "\x78", '\x79' => "\x79", '\x7a' => "\x7a",
'\x7b' => "\x7b", '\x7c' => "\x7c", '\x7d' => "\x7d", '\x7e' => "\x7e", '\x7f' => "\x7f",
'\x81' => "\x81", '\x82' => "\x82", '\x83' => "\x83", '\x84' => "\x84", '\x85' => "\x85",
'\x86' => "\x86", '\x87' => "\x87", '\x88' => "\x88", '\x89' => "\x89", '\x8a' => "\x8a",
'\x8b' => "\x8b", '\x8c' => "\x8c", '\x8d' => "\x8d", '\x8e' => "\x8e", '\x8f' => "\x8f",
'\x91' => "\x91", '\x92' => "\x92", '\x93' => "\x93", '\x94' => "\x94", '\x95' => "\x95",
'\x96' => "\x96", '\x97' => "\x97", '\x98' => "\x98", '\x99' => "\x99", '\x9a' => "\x9a",
'\x9b' => "\x9b", '\x9c' => "\x9c", '\x9d' => "\x9d", '\x9e' => "\x9e", '\x9f' => "\x9f",
'\xa1' => "\xa1", '\xa2' => "\xa2", '\xa3' => "\xa3", '\xa4' => "\xa4", '\xa5' => "\xa5",
'\xa6' => "\xa6", '\xa7' => "\xa7", '\xa8' => "\xa8", '\xa9' => "\xa9", '\xaa' => "\xaa",
'\xab' => "\xab", '\xac' => "\xac", '\xad' => "\xad", '\xae' => "\xae", '\xaf' => "\xaf",
'\xb1' => "\xb1", '\xb2' => "\xb2", '\xb3' => "\xb3", '\xb4' => "\xb4", '\xb5' => "\xb5",
'\xb6' => "\xb6", '\xb7' => "\xb7", '\xb8' => "\xb8", '\xb9' => "\xb9", '\xba' => "\xba",
'\xbb' => "\xbb", '\xbc' => "\xbc", '\xbd' => "\xbd", '\xbe' => "\xbe", '\xbf' => "\xbf",
'\xc1' => "\xc1", '\xc2' => "\xc2", '\xc3' => "\xc3", '\xc4' => "\xc4", '\xc5' => "\xc5",
'\xc6' => "\xc6", '\xc7' => "\xc7", '\xc8' => "\xc8", '\xc9' => "\xc9", '\xca' => "\xca",
'\xcb' => "\xcb", '\xcc' => "\xcc", '\xcd' => "\xcd", '\xce' => "\xce", '\xcf' => "\xcf",
'\xd1' => "\xd1", '\xd2' => "\xd2", '\xd3' => "\xd3", '\xd4' => "\xd4", '\xd5' => "\xd5",
'\xd6' => "\xd6", '\xd7' => "\xd7", '\xd8' => "\xd8", '\xd9' => "\xd9", '\xda' => "\xda",
'\xdb' => "\xdb", '\xdc' => "\xdc", '\xdd' => "\xdd", '\xde' => "\xde", '\xdf' => "\xdf",
'\xe1' => "\xe1", '\xe2' => "\xe2", '\xe3' => "\xe3", '\xe4' => "\xe4", '\xe5' => "\xe5",
'\xe6' => "\xe6", '\xe7' => "\xe7", '\xe8' => "\xe8", '\xe9' => "\xe9", '\xea' => "\xea",
'\xeb' => "\xeb", '\xec' => "\xec", '\xed' => "\xed", '\xee' => "\xee", '\xef' => "\xef",
'\xf1' => "\xf1", '\xf2' => "\xf2", '\xf3' => "\xf3", '\xf4' => "\xf4", '\xf5' => "\xf5",
'\xf6' => "\xf6", '\xf7' => "\xf7", '\xf8' => "\xf8", '\xf9' => "\xf9", '\xfa' => "\xfa",
'\xfb' => "\xfb", '\xfc' => "\xfc", '\xfd' => "\xfd", '\xfe' => "\xfe", '\xff' => "\xff",
);
return strtr($string, $sym_tbl);
}
// вызов:
$str = str2escape($str);
Теперь всё хорошо:
$inx = '50';
$str = "\x".$inx;
$str .= "\x51";
var_dump(str2escape($str));
// выведет PQ
Пользователь Habra-Mikhail предложил вариант без использования собственной функции
$inx = '50';
$str = chr(hexdec($inx));
$str .= "\x51";
var_dump($str);
// выведет PQ
Поиск причины и решения заняло некоторое количество времени, думаю пройденный мной путь поможет быстрее разобраться всем, кто столкнётся с подобной задачей в дальнейшем.
Поделиться с друзьями
Комментарии (5)
drtropin
28.06.2017 15:21Вирус прописывал смешанную последовательность
@include "\x2fus\x72/l\x6fca\x6c/w\x77w/
Одна из задач была расшифровать и сохранить в читабельном виде в файл.
$inx = '50'; var_dump(chr(hexdec($inx)));
Да, так работаетmichael_vostrikov
30.06.2017 17:42Одна из задач была расшифровать и сохранить в читабельном виде в файл.
echo "\x2fus\x72/l\x6fca\x6c/w\x77w/"; // /usr/local/www/
Habra-Mikhail
28.06.2017 15:21+3Также таблица символов будет работать неправильно если будет использован двойной обратный слэш(\\), который уберёт экранирование спец символа.
И последняя ошибка: В последовательности \xnn — nn — это 16-ричное число, следовательно в коде будет пропущена половина символов.
drtropin
29.06.2017 09:37Да, совершенно верно, спасибо!
Но если будет использован двойной слэш это уже не будет последовательность типа \xnn.
Habra-Mikhail
А зачем потребовалось интерпретировать строку?
Возможно, было бы правильнее в данном случае воспользоваться встроенной функцией chr:
php.net manual — chr
Т.к в программе известны коды символов