Расшифровка T-SQL CAST в C# / VB.NET

Недавно наш сайт захлестнула волна атак с использованием SQL-инъекций ботнета Asprox . Не вдаваясь в подробности, атака пытается выполнить код SQL, кодируя команды T-SQL в строку BINARY в кодировке ASCII. Это выглядит примерно так:

DECLARE%[email protected]%20NVARCHAR(4000);SET%[email protected]=CAST(0x44004500...06F007200%20AS%20NVARCHAR(4000));EXEC(@S);--

Мне удалось расшифровать это в SQL, но я немного опасался этого, поскольку не знал точно, что происходило в то время.

Я попытался написать простой инструмент декодирования, чтобы я мог декодировать этот тип текста, даже не касаясь SQL Server . Основная часть, которую мне нужно декодировать, это:

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 в массиве байтов, который я смог проанализировать до этого момента, в результате я получаю «, - +».

Как понять, что мне не хватает - нужно ли выполнять «прямое приведение» для каждого байта вместо того, чтобы пытаться его проанализировать?

Ответов (2)

Решение

Я вернулся к сообщению Майкла, немного потыкал и понял, что мне действительно нужно сделать двойное преобразование, и в конце концов разработал этот маленький самородок:

Convert.ToString(Convert.ToChar(Int32.Parse(EncodedString.Substring(intParseIndex, 2), System.Globalization.NumberStyles.HexNumber)));

Оттуда я просто сделал цикл, чтобы перебрать все символы 2 на 2 и получить их "шестнадцатеричное", а затем преобразовать в строку.

Для Ника и всех, кого это интересует, я отправил свое небольшое приложение в CodePlex . Не стесняйтесь использовать / изменять по своему усмотрению.

Попробуйте 0x сначала удалить, а потом позвоните Encoding.UTF8.GetString . Я думаю, это может сработать.

По сути: 0x44004500

Удалите 0x, и тогда всегда два байта будут одним символом:

44 00 = D

45 00 = E

6F 00 = o

72 00 = r

Так что это определенно формат Unicode / UTF с двумя байтами на символ.