Trim (). Split вызывает проблему в Contains () - PullRequest
0 голосов
/ 14 января 2019

Я получаю строку и сначала обрезаю ее, затем разделяю и присваиваю ей string[]. Затем я использую каждый элемент в массиве для string.Contains() или string.StartsWith() метода. Интересно, что даже если строка содержит элемент, Contains() не работает должным образом. И ситуация такая же для StartsWith() тоже. Кто-нибудь имеет представление о проблеме?

P.S .: Я обрезал строки после разделения и проблема была решена.

string inputTxt = "tasklist";
string commands = "net, netsh, tasklist";

string[] maliciousConsoleCommands = commands.Trim(' ').Split(',');

for (int i = 0; i < maliciousConsoleCommands.Length; i++) {
    if (inputTxt.StartsWith(maliciousConsoleCommands[i])) {
        return false;
    }
} 

// этот код работает, но не знаю, почему предыдущий код не работал.

string[] maliciousConsoleCommands = commands.Split(',');

for (int i = 0; i < maliciousConsoleCommands.Length; i++) {
    if (inputTxt.StartsWith(maliciousConsoleCommands[i].Trim(' '))) {
        return false;
    }
}

Я ожидал, что будет работать должным образом, но это решается путем обрезки после разделения.

Ответы [ 4 ]

0 голосов
/ 14 января 2019

Еще один способ разделения, если у команд нет пробелов, - это использовать ' ' в качестве разделителя и отбрасывать пустые записи:

var  maliciousConsoleCommands =  commands.Split(new[]{',',' '},StringSplitOptions.RemoveEmptyEntries)
                                         .ToArray();

Это позволяет избежать временных строк, генерируемых каждой командой обработки строк.

Чтобы ваш код работал, вы должны использовать Contains для каждой команды вместо StartWith:

var isSuspicious = maliciousCommands.Any(cmd=>input.Contains(cmd));

Или даже:

var isSuspicious = maliciousCommands.Any(input.Contains);

Это может быть довольно медленным, если у вас несколько команд или если введенный текст большой

Альтернативное регулярное выражение

Гораздо более быстрый способ - использовать регулярное выражение. Это выполняет лот быстрее, чем поиск по отдельным ключевым словам:

var regex=new Regex("net|netsh|tasklist");
var isSuspicious=regex.IsMatch(inputTxt);

Регулярные выражения являются поточно-ориентированными, что означает, что они могут быть созданы один раз и повторно использованы различными потоками / запросами.

Используя Match/Matches вместо IsMatch, регулярное выражение может возвращать фактические обнаруженные ключевые слова:

var detection=regex.Match(inputTxt);
if (detection.Success)
{
    var detectedKeyword=detection.Value;
    ....
}

Преобразование исходного списка, разделенного запятыми, в регулярное выражение можно выполнить с помощью одного String.Replace(", ") или другого регулярного выражения, которое может обрабатывать любой символ пробела:

string commands = "net , netsh, \ttasklist";
var pattern=Regex.Replace(commands,@"\s*,\s*","|").Dump();
var regex=new Regex(pattern);

Обнаружение только целых слов

И Contains, и исходное регулярное выражение будет соответствовать tasklist1, а также tasklist. Можно сопоставлять только целые слова, если шаблон окружен разделителем слов, \b:

@"\b(" + pattern + @")\b"

Это будет соответствовать tasklist и net, но отклонить tasklist1

0 голосов
/ 14 января 2019

Ваш разделитель - это не запятая, это запятая, за которой следует пробел, поэтому вместо разделения на ',', просто деление на ", ":

string[] maliciousConsoleCommands = commands.Split(new string[] {", "});

Это вернет элементы без пробела, поэтому обрезка будет избыточной.

0 голосов
/ 14 января 2019

Первый код, который вы представили, не будет работать, потому что вы хотите обрезать начальную строку, поэтому "net, netsh, tasklist" останется неизменным после обрезки (без пробелов в начале и в конце), а затем разделение его запятыми приведет к появлению записей, которые имеют пробел в начале. Таким образом, вы получите неожиданные результаты. Вы должны обрезать после разбиения строки.

Второй код также не будет работать, потому что вы используете Trim после StartsWith, который возвращает значение bool. Вы не можете применить Trim к bool, этот код даже не должен компилироваться.

0 голосов
/ 14 января 2019

Кажется, вам следует Trim каждый предмет:

// ["net", "netsh, "tasklist"]
string[] maliciousConsoleCommands = commands
  .Split(',')                   // "net" " netsh", " tasklist" - note leading spaces
  .Select(item => item.Trim())  // removing leading spaces from each item
  .ToArray();

Наконец, если вы хотите проверить, является ли inputTxt вредоносным:

if (commands
      .Split(',')
      .Select(item => item.Trim()) // You can combine Select and Any            
      .Any(item => inputTxt.StartsWith(item))
  return false;
...