Wherein we take the multithread concept, and run like blazes.
This article uses some of the files from Multithreading in Batch Script, Part 1: An Example; so before you get deep into it, grab the master.bat and computers.csv from there.
This thread script:
- takes a given PC name, pings it and reverse-resolves it.
- logs it as responsive or unresponsive (if unresponsive, it quits)
- maps a drive to the PC, with the same letter as the thread
- runs arbitrary code against the pc
- unwinds
- deletes itself
The drive mapping can take a list of username/password combinations, starting with the user who runs it.
@ECHO OFF
(set ip=%3)
(set pcname=%3)
(set drive=%2)
(set num=00000%1)
(set logfile=logs\%num%.txt)
(set outputname=thread)
(Set outputfile=.\log.csv)
:::::::::::::::::::::::::::::::::::::::::::::::
:: 1) Set variables above. This file called as;
:: newletter.bat count newletter LineFromCSV
:: parameters are %1 %2 %3,%4...
::
:: 2) Write a batch file that scans what you
:: need locally, and uses the variables above.
::
:: 3) Update the ":::Variable Part:::" section
:: with your batch file.
:::::::::::::::::::::::::::::::::::::::::::::::
ECHO. %*
set num=%num:~-5%
(SET pingnum=1)
set pingtarget=%pcname%
:PINGSTAT
@for /F "delims=" %%A in ('ping -n %pingnum% -a %pingtarget%') do (
call :log xxxLx "%%A"
@for /F "tokens=1,3,11" %%B in ("%%A") do (
@IF "%%B"=="Pinging" (SET resolvedip=%%C)
@IF "%%B"=="Packets:" (SET percentloss=%%D)
))
if DEFINED percentloss (SET percentloss=%percentloss:~1,-1%)
if DEFINED resolvedip (SET ip=%resolvedip:~1,-1%)
IF NOT "%percentloss%"=="100" GOTO :RESPONSIVE
:: quarter ping failed. Check for partial connectivity.
:: if full ping failed, exit.
call :log xxxLx "%pcname% Failed ping [*%pingnum%]"
@if "%pingnum%"=="1" (
(SET pingnum=4)
call :log xxxLx "retrying with 4 pings . . ."
GOTO :PINGSTAT
)
call :log xxULC "%num%,%pcname%,%ip%,Unavailable. Lost %percentloss% percent of %pingnum% pings"
GOTO :END
:Responsive
call :log xxxLx "%percentloss% percent Loss"
IF ""=="%percentloss%" (
call :log xxULC "%num%,%pcname%,%ip%,Not Found"
GOTO :END
)
:: At this point, the machine is online and available
::::::::::::: connect drive :::::::::::::
if NOT exist %drive%:\nul GOTO ADDDRIVE
:DRIVEEXISTS
call :log xxxLx "%drive% exists . . ."
@for /F "delims=" %%A in ('net use %drive%: /delete /y') do (call :log xxxLx "%%A")
if exist %drive%:\nul (
ping -n 3 localhost >null
goto :DRIVEEXISTS
)
call :log xxxLx "%drive%:\nul doesn't exist"
:ADDDRIVE
call :log xxxLx "attaching \\%pcname%\c$ to %drive%:"
FOR %%A in ("%USERID% %PASSWORD%","%pcname%\Administrator Password") do (
For /F "tokens=1,2" %%B in (%%A) do (
call :connect %%B %%C
))
IF "%ERR%"=="0" goto :MAIN
call :log xxxLC "%num%,%pcname%,%IP%,Can't Connect"
Goto :End
::::::::::::: /connect drive :::::::::::::
:MAIN
call :log xxxLx "Entering Main . . . "
del netuse%drive%.txt -y
:::::::::::::::::: Variable part ::::::::::::::::::
:: Log success
call :log SxxLC "%num%,%pcname%,%ip%
:::::::::::::::::: /Variable part ::::::::::::::::::
call :log xxxLx "Disconnecting . . . "
net use %drive%: /delete /y
GOTO :END
:log
:: SFUL (Success Failure Unavailable LogDetails CommonOutput) "Message"
(set log=%1)
echo %~2
if "%log:~0,1%"=="S" ECHO.%~2>>%outputname%.Updated.log
if "%log:~1,1%"=="F" ECHO.%~2>>%outputname%.Noupdate.log
if "%log:~2,1%"=="U" ECHO.%~2>>%outputname%.Unavail.log
if "%log:~3,1%"=="L" if defined logfile ECHO.%~2>>%logfile%
if "%log:~4,1%"=="C" if defined outputfile ECHO.%~2>>%outputfile%
Goto :EOF
:connect
if EXIST %drive%:\nul Goto :EOF
call Set USER=%1
call Set PWD=%2
call :log xxxLx "connecting as %USER%"
if "%USER%"=="" (
net use %drive%: \\%pcname%\c$ > netuse%drive%.txt 2>&1
) ELSE (
net use %drive%: \\%pcname%\c$ /USER:%USER% %PWD% > netuse%drive%.txt 2>&1
)
(set ERR=%ERRORLEVEL%)
call :log xxxLx "netuse returns '%ERR%'"
type netuse%drive%.txt
if defined logfile type netuse%drive%.txt>>%logfile%
IF "%ERR%"=="0" (
call :log xxxLx "Connected as %USER%."
del netuse%drive%.txt -y
goto :EOF
)
FOR /F "tokens=3 skip=1" %%p IN ('Find /I "System Error" netuse%drive%.txt') DO (SET NETUSEERR=%%p)
call :log xxxLx "NETUSEERR = %NETUSEERR%"
FOR /F "delims==" %%p IN ('net helpmsg %NETUSEERR%') DO (
SET NETUSEDESC=%%p
)
(SET NETUSEERR=[%NETUSEERR%] %NETUSEDESC:,=%)
del netuse%drive%.txt -y
call :log xxULx "%num%,%pcname%,%ip%,Doesn't Connect as %USER%. '%NETUSEERR%'"
Goto :EOF
:END
call :log xxxLx "Done."
del %0
This code does nothing to the target machines; it assumes that if it’s made it as far as a mapped drive, it’s finished. You can actually run just about anything against the machines: write a batch file to do *stuff* and use the variables listed in the block at the beginning of this script. When it works, plug it into this script, in the section marked
:::::::::::::::::: Variable part ::::::::::::::::::
if you need to execute a process on the target machines, you can do so with psexec or beyondexec. You can with rclient, also, but it’s turning into a security liability, at this age.
5 responses so far ↓
1 Brian // Sep 10, 2008 at 7:29 pm
I have been needed to work on adding some multi threading to a script of mine so this will be very helpfull.
But I have a issue that I wonder if you can help with.
I need to have a script check to see if a username/password work. Just so it does not lock out a account. Have you came accross anything like that before? Any help would be wonderfull.
2 Neil // Sep 12, 2008 at 7:12 pm
Brian,
I hope it’s helpful. It’s more of an oddity than anything else: I use it for quick ‘batch scanners’ to quickly gather data on a lot of machines (such as if software installed correctly) but I wouldn’t do a long-standing project with it.
As far as checking a password (the gotcha is below), the standard (not batch) thing to do would be to verify it with one of the LogonUser APIs. With scripts, you don’t have so many options (and normally wouldn’t want to use them. Putting passwords in text files is working against yourself). You can use the NET USE command, and try to attach a share, or similar things.
All of the methods that I know of will lockout an account, if they use the wrong password N times. I don’t think you’re going to bypass that (and I have looked for exactly the same thing)–if you could, it would render useless locking out the passwords at all. If your password locks out after three wrong guesses, (to keep brute force attacks from working) then a function that allows you to just test a password completely bypasses the usefullness of that.
If you are using scripts to access file on shares, etc, your best option is to create a user/password for that function, give it the minimal rights it needs to fulfill it’s tasks, and don’t give it rights to anywhere else.
3 DarC // Mar 11, 2009 at 5:39 pm
Wondering if there is a way to brute force a 7z or RaR archive with a Bat script…
4 Neil // Mar 12, 2009 at 2:49 pm
DarC, I assume you mean brute-forcing the password.
You probably could (you can do pretty much anything in any language, with enough effort, and possibly some extensions). Thing is, it wouldn’t be worthwhile.
You can do loops, and pass parameters in bat, so you could drive a command-line version of rar or 7z; but it wouldn’t be any easier than in other languages.
You can read dictionaries from bat, or make up sequences, but it tends to be harder than in other languages.
You could get it all together, but it will tend to be slower than in other languages.
Those sort of things will get written in better, faster, more powerful languages, because they really need that.
5 Awesome Find #7: Multithreading in Batch Scripts | Daily Cup of Tech // Mar 26, 2009 at 9:01 am
[...] Part 2 [...]
Leave a Comment