Nmap Development mailing list archives

Re: [NSE] DB2 library and scripts


From: Patrick Donnelly <batrick () batbytes com>
Date: Mon, 10 May 2010 18:19:14 -0400

On Mon, May 10, 2010 at 11:03 AM, Patrik Karlsson <patrik () cqure net> wrote:
Hi again,

Here's an updated threaded version of the db2-brute script. It seems to run well and quickly against my test systems.
I failed to get condvar("signal") to work, as in the example, and had to switch to condvar("broadcast") instead.
Can someone provide some insight into why this happens and to what I'm doing wrong?
Also, the mutex I'm using to create and add to the nmap.registry.db2users table, is it necessary, and if it is, is it 
implemented correctly?

Testing, feedback, suggestions and comments are welcome as always.

The condvar "signal" should work in your example. I don't have an explanation.

The mutex is unnecessary as all of your work between mutex calls will
not be interrupted. You would need a mutex if you had a "yielding"
call such as a socket operation. Even then, it's only necessary if the
whole block must be atomic.

As for the parallelism, setting a maximum number of running threads is
ok. Keep in mind though that NSE already has limits (right now 20,
unless changed on the command line) to the number of open sockets. You
could let NSE do the throttling by making a thread for each
username/password combination. Like the book says, threads are cheap
so making a lot is not a big deal.

Taking into account what Fyodor said, it may be better to have your
workers keep asking for work. You can do this with a variation of the
html link coroutine example I give in the book [1]. Here's the gist of
it:

-- at the file chunk level of db2-brute
local function new_usrpwd_iterator (usernames, passwords)
 local function next_username_password ()
   coroutine.yield(true) -- ignore first call, it sets up usernames/passwords
   for username in usernames do
     for password in passwords do
       coroutine.yield(username, password)
     end
   end
   while true do coroutine.yield(nil, nil) end
 end
 return coroutine.wrap(next_username_password);
end

Now your 10 workers will constantly ask for work like so:

doLogin = function( host, port, database, username, valid_accounts,
usrpwd_iterator )
   local condvar = nmap.condvar( valid_accounts )
   local helper = db2.Helper:new()
   local status, response, passwords

   for status, username, password in usrpwd_iterator do
     -- make connection with username/password combination
   end
   condvar "signal"
end

Your action function will call new_usrpwd_iterator and pass the
iterator to all of its children threads. The action function then
needs to just instantiate your MAX_THREADS children and then wait
until all complete.

Question: Why do you break after calling mutex"done"? Do you not want
to grab every possible combination or is one enough? If one is enough
then you want some method of stopping threads from continuing once one
is found. A simple boolean check at the start to cause immediate
return should be sufficient. (The boolean would be kept in a local at
the start of your script.)

[1] http://nmap.org/book/nse-parallelism.html#nse-parallelism-cm

--
- Patrick Donnelly
_______________________________________________
Sent through the nmap-dev mailing list
http://cgi.insecure.org/mailman/listinfo/nmap-dev
Archived at http://seclists.org/nmap-dev/


Current thread: