Декодирование T-SQL CAST в C#/VB.NET
Вопрос
Недавно наш сайт заполонили сообщения о возрождении Ботнет Аспрокс SQL-инъекция атака.Не вдаваясь в подробности, атака пытается выполнить код SQL, закодировав Т-SQL команды в двоичной строке в кодировке ASCII.Это выглядит примерно так:
DECLARE%20@S%20NVARCHAR(4000);SET%20@S=CAST(0x44004500...06F007200%20AS%20NVARCHAR(4000));EXEC(@S);--
Мне удалось расшифровать это с помощью SQL, но я немного опасался этого делать, так как не знал точно, что происходило в тот момент.
Я попытался написать простой инструмент декодирования, чтобы я мог декодировать этот тип текста, даже не прикасаясь к нему. SQL сервер.Основная часть, которую мне нужно расшифровать:
CAST(0x44004500...06F007200 AS
NVARCHAR(4000))
Я безуспешно пробовал все следующие команды:
txtDecodedText.Text =
System.Web.HttpUtility.UrlDecode(txtURLText.Text);
txtDecodedText.Text =
Encoding.ASCII.GetString(Encoding.ASCII.GetBytes(txtURLText.Text));
txtDecodedText.Text =
Encoding.Unicode.GetString(Encoding.Unicode.GetBytes(txtURLText.Text));
txtDecodedText.Text =
Encoding.ASCII.GetString(Encoding.Unicode.GetBytes(txtURLText.Text));
txtDecodedText.Text =
Encoding.Unicode.GetString(Convert.FromBase64String(txtURLText.Text));
Как правильно перевести эту кодировку без использования SQL Server?Является ли это возможным?Я возьму код VB.NET, так как я тоже с ним знаком.
Хорошо, я уверен, что что-то упускаю, так что вот где я нахожусь.
Поскольку мои входные данные представляют собой базовую строку, я начал с фрагмента закодированной части — 4445434C41 (что переводится в DECLA) — и первой попыткой было сделать это...
txtDecodedText.Text = Encoding.UTF8.GetString(Encoding.UTF8.GetBytes(txtURL.Text));
... и все, что он сделал, это вернул то же самое, что и я, поскольку он преобразовал каждый символ в байт.
Я понял, что мне нужно вручную разбирать каждые два символа на байт, поскольку я пока не знаю методов, которые могли бы это сделать, поэтому теперь мой маленький декодер выглядит примерно так:
while (!boolIsDone)
{
bytURLChar = byte.Parse(txtURLText.Text.Substring(intParseIndex, 2));
bytURL[intURLIndex] = bytURLChar;
intParseIndex += 2;
intURLIndex++;
if (txtURLText.Text.Length - intParseIndex < 2)
{
boolIsDone = true;
}
}
txtDecodedText.Text = Encoding.UTF8.GetString(bytURL);
Для первых пар пар всё выглядит хорошо, но затем цикл отказывается, когда доходит до пары «4C», и сообщает, что строка имеет неверный формат.
Интересно, что когда я прохожу через отладчик и обращаюсь к методу GetString для массива байтов, который мне удалось проанализировать до этого момента, я получаю в качестве результата «,-+».
Как мне выяснить, чего мне не хватает - нужно ли мне выполнять «прямое приведение» для каждого байта вместо того, чтобы пытаться его проанализировать?
Решение
Я вернулся к сообщению Майкла, еще немного покопался и понял, что мне действительно нужно выполнить двойное преобразование, и в итоге нашел этот маленький самородок:
Convert.ToString(Convert.ToChar(Int32.Parse(EncodedString.Substring(intParseIndex, 2), System.Globalization.NumberStyles.HexNumber)));
После этого я просто сделал цикл, чтобы пройти по всем символам 2 на 2, «шестнадцатерично» их преобразовать, а затем преобразовать в строку.
Для Ника и всех, кто заинтересован, я пошел дальше и разместил свое маленькое приложение в КодПлекс.Не стесняйтесь использовать/изменять по мере необходимости.
Другие советы
Попробуйте удалить 0x
сначала а потом позвони Encoding.UTF8.GetString
.Я думаю, это может сработать.
По сути:0x44004500
Уберите 0x, и тогда два байта всегда будут одним символом:
44 00 = D
45 00 = E
6F 00 = o
72 00 = r
Так что это определенно формат Unicode/UTF с двумя байтами/символами.