-1

Помогите понять почему так, есть код:

import re

TEXT = r''' local afp = require "afp" local nmap = require "nmap" local shortport = require "shortport" local stdnse = require "stdnse" local string = require "string" local table = require "table" local unpwdb = require "unpwdb"

-- we don't really need openssl here, but let's attempt to load it as a way -- to simply prevent the script from running, in case we don't have it local openssl = stdnse.silent_require("openssl")

description = [[ Performs password guessing against Apple Filing Protocol (AFP). ]]


-- @usage

-- nmap -p 548 --script afp-brute <host>

-- @output -- PORT STATE SERVICE -- 548/tcp open afp -- | afp-brute: -- |_ admin:KenSentMe => Valid credentials

-- Information on AFP implementations

-- Snow Leopard


-- - Delay 10 seconds for accounts with more than 5 incorrect login attempts (good)

-- - Instant response if password is successful

-- Netatalk


-- - Netatalk responds with a "Parameter error" when the username is invalid

author = "Patrik Karlsson" license = "Same as Nmap--See https://nmap.org/book/man-legal.html" categories = {"intrusive", "brute"}

-- Version 0.3 -- Created 01/15/2010 - v0.1 - created by Patrik Karlsson <patrik@cqure.net> -- Revised 03/09/2010 - v0.2 - changed so that passwords are iterated over users -- - this change makes better sense as guessing is slow -- Revised 09/09/2011 - v0.3 - changed account status text to be more consistent with other *-brute scripts

portrule = shortport.port_or_service(548, "afp")

action = function( host, port )

local result, response, status = {}, nil, nil local valid_accounts, found_users = {}, {} local helper local usernames, passwords

status, usernames = unpwdb.usernames() if not status then return end

status, passwords = unpwdb.passwords() if not status then return end

for password in passwords do for username in usernames do if ( not(found_users[username]) ) then

    helper = afp.Helper:new()
    status, response = helper:OpenSession( host, port )

    if ( not(status) ) then
      stdnse.debug1(&quot;OpenSession failed&quot;)
      return
    end


    stdnse.debug1(&quot;Trying %s/%s ...&quot;, username, password)
    status, response = helper:Login( username, password )

    -- if the response is &quot;Parameter error.&quot; we're dealing with Netatalk
    -- This basically means that the user account does not exist
    -- In this case, why bother continuing? Simply abort and thank Netatalk for the fish
    if response:match(&quot;Parameter error.&quot;) then
      stdnse.debug1(&quot;Netatalk told us the user does not exist! Thanks.&quot;)
      -- mark it as &quot;found&quot; to skip it
      found_users[username] = true
    end

    if status then
      -- Add credentials for other afp scripts to use
      if nmap.registry.afp == nil then
        nmap.registry.afp = {}
      end
      nmap.registry.afp[username]=password
      found_users[username] = true

      table.insert( valid_accounts, string.format(&quot;%s:%s =&gt; Valid credentials&quot;, username, password:len()&gt;0 and password or &quot;&lt;empty&gt;&quot; ) )
      break
    end
    helper:CloseSession()
  end
end
usernames(&quot;reset&quot;)

end

local output = stdnse.format_output(true, valid_accounts)

return output

end '''

description_regex = re.compile(r'description = [[.]]', flags=re.DOTALL) categories_regex = re.compile(r'categories = {.}', flags=re.DOTALL)

script_description = re.search(description_regex, TEXT) print(script_description.group(0)) script_categories = re.search(categories_regex, TEXT) print(script_categories.group(0))

Почему в script_categories попадает весь оставшийся текст после шаблона? А не categories = {"intrusive", "brute"} как было задумано?

insolor
  • 49,104
NordeN
  • 163

1 Answers1

2

"Звездочка" работает в "жадном" (greedy) режиме, и пытается получить как можно больше текста, подходящего под шаблон. В данном случае второй шаблон у вас пытается набрать весь встреченный текст между первой встретившейся открывающейся фигурной скобкой и последней закрывающейся (в строке nmap.registry.afp = {}). Первый шаблон отрабатывает корректно только потому, что в тексте только один раз встречается сочетание ]].

Чтобы получить минимальное количество текста, можно добавить вопрос после звездочки:

description_regex = re.compile(r'description = \[\[.*?\]\]', flags=re.DOTALL)
categories_regex = re.compile(r'categories = \{.*?\}', flags=re.DOTALL)

Вывод:

description = [[
Performs password guessing against Apple Filing Protocol (AFP).
]]
categories = {"intrusive", "brute"}
insolor
  • 49,104