📶 [WIP] RouterOS WinBox bruteforce
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
mtbf/thread.go

113 lines
2.7 KiB

2 years ago
package main
import (
"net"
"sync"
"time"
)
// threadWork processes a single work item for a thread.
func threadWork(dialer *net.Dialer) bool {
readTimeout := CfgGetDurationMS("read-timeout-ms")
task, delay := CreateTask()
if task == nil {
if delay > 0 {
log("thread", 3, "no endpoints available, sleeping for %v", delay)
time.Sleep(delay)
return true
} else {
log("thread", 3, "no endpoints available, stopping thread loop")
return false
}
}
conn, err := dialer.Dial("tcp", task.e.String())
if err != nil {
task.Event(TE_NoResponse)
log("thread", 2, "cannot connect to \"%v\": %v", task.e, err.Error())
return true
}
defer conn.Close()
task.conn = conn
task.Event(TN_Connected)
conn.SetReadDeadline(time.Now().Add(readTimeout)) // should be just before Send() call...
log("thread", 2, "trying %v:%v on \"%v\"", task.login, task.password, task.e)
// TODO: multiple services (currently just WinBox)
res, err := TryLogin(task, conn)
if err != nil {
task.Event(TE_ProtocolError)
} else {
if res && err == nil {
task.EventWithParm(TE_Good, task.login)
} else {
task.EventWithParm(TE_Bad, task.login)
}
}
return true
}
// threadLoop calls threadWork in a loop, until the endpoints are exhausted,
// a pause/stop signal has been raised, or an exception has occurred in threadWork.
func threadLoop(dialer *net.Dialer) {
for threadWork(dialer) {
// TODO: pause/stop signal
// TODO: exception handling
}
}
// threadEntryPoint is the main entrypoint for a work thread.
func threadEntryPoint(c chan bool, threadIdx int, wg *sync.WaitGroup) {
<-c
log("thread", 3, "starting loop for thread %v", threadIdx)
connectTimeout := time.Duration(CfgGetInt("connect-timeout-ms")) * time.Millisecond
dialer := net.Dialer{Timeout: connectTimeout, KeepAlive: -1}
threadLoop(&dialer)
log("thread", 3, "exiting thread %v", threadIdx)
wg.Done()
}
// InitializeThreads creates and starts up all threads.
func InitializeThreads() *sync.WaitGroup {
numThreads := CfgGetInt("threads")
failIf(numThreads > maxSafeThreads, "too many threads (max %v)", maxSafeThreads)
log("thread", 0, "initializing %v threads", numThreads)
c := make(chan bool)
var wg sync.WaitGroup
for i := 1; i <= numThreads; i++ {
wg.Add(1)
go threadEntryPoint(c, i, &wg)
}
threadDelay := CfgGetDurationMS("thread-delay-ms")
log("thread", 0, "starting %v threads", numThreads)
for i := 1; i <= numThreads; i++ {
c <- true
if threadDelay > 0 {
time.Sleep(threadDelay)
}
}
log("thread", 0, "started")
return &wg
}
// WaitForThreads enters a wait state and keeps it until
// all threads have exited.
func WaitForThreads(wg *sync.WaitGroup) {
log("thread", 1, "waiting for threads")
wg.Wait()
log("thread", 1, "finished waiting for threads")
}