Hay muchas, pero muchísimas cosas inapropiadas en el código fuente que has compartido.
1.
El textbox de tu aplicación está limitado a 32.767 caracteres (Int16), no sirve de mucho si intentas cargar una lista de passwords personalizada.
De hecho no es ninguna buena idea intentar mostrar una lista entera de passwords en el layout de un control, por que se hace muy pesado con listas largas, y esto limitará mucho tu aplicación, pero bueno, puedes aumentar el límite al máximo permitido de esta manera:
Me.TextBox1.MaxLength = Integer.MaxValue
2.
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim fic As String = System.AppDomain.CurrentDomain.BaseDirectory.ToString & "diccionario.lst"
Dim sr1 As New System.IO.StreamReader(fic)
Dim texto As String
TextBox3.Text = fic
Label1.Text = ""
texto = sr1.ReadToEnd()
sr1.Close()
TextBox1.Text = texto
End Sub
Primero lees el archivo que almacena las combinaciones en la variable
texto, luego pasas el valor de la variable a la lógica de un textbox, y por último, en otra parte del código, interactuas con el texto contenido en el TextBox para procesar cada linea de passwords.
¿te das cuenta de lo inapropiado que resulta hacer todo eso, si por ejemplo la lista de passwords fuese de +100.000?, supone una disminuición de rendimiento tanto por la sobre-carga/saturación del textbox como por el tiempo de ejecución que consumes al partir el texto del textbox por cada uno de los passwords que haya escrito, no hay necesidad de realizar tantas operaciones ni hacerlo de esa manera.
He modificado el código para estructuarlo mejor y otras mejoras de rendimiento:
Private passFilepath As String = Path.Combine(Application.StartupPath, "diccionario.lst")
Private passwordList As IEnumerable(Of String)
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) _
Handles MyBase.Load
Me.LoadDefaults()
End Sub
Private Sub LoadDefaults()
Me.Label1.ResetText()
Me.tb_PassFilepath.Text = Me.passFilepath
Try
Me.passwordList = Me.GetPasswordList(Me.passFilepath)
Catch ex As Exception
Throw
End Try
With Me.tb_PasswordList
.MaxLength = Integer.MaxValue
.SuspendLayout()
.Text = String.Join(ControlChars.NewLine, Me.passwordList)
.ResumeLayout()
End With
End Sub
''' <summary>
''' Gets the password list.
''' </summary>
''' <param name="passFilepath">The passwords filepath.</param>
''' <returns>IEnumerable(Of System.String).</returns>
Private Iterator Function GetPasswordList(ByVal passFilepath As String) As IEnumerable(Of String)
Using sr As New StreamReader(passFilepath, Encoding.Default)
Do Until sr.EndOfStream
Yield sr.ReadLine
Loop
End Using
End Function
Nota: te recuerdo que el textbox está LIMITADO, así que en la práctica real no sirve con niguna lista de passwords de las que se suelen utilizar para un ataque de este tipo, utiliza la variable de la colección de passwords, que tiene una muy mayor capacidad.
3.
El método
Application.DoEvents() no cumple la misma funcionalidad que en VB6, y en VB.Net se suele utilizar (o mejor dicho se suele recurrir cómo último recurso a su utilización) para evitar cuelgues (detenciones) en el hilo del Form debido a un mal diseño de la aplicación por parte del programador, pero en tu caso ni siquiera necesitas recurrir a su utilización por que no estás desarrollando una aplicación multi-threading, ¿por qué lo utilizas?, no lo hagas, sea por el motivo que sea, puedes solucionarlo debidamente.
4.
Saca todas las requests fuera de los event-handlers, TODAS, sacalas, y añadelas en distintos métodos que cumplan sus distintas funcionalidades, es horrible tal y cómo está.
Además estás accediendo continuamente a las propiedades
.Text de los contorles, no lo hagas, inicializa las variables necesarias para asignar esos valores y usa esas variables.
Hay que intentar separar los Datos, de la UI, pero los programadores de WinForms no solemos hacernos una idea muy clara de este concepto debido a la propia naturaleza de la tecnología WinForms y los malos hábitos de programación que ello supone.
5.
Elimina las importaciones de estos namespaces, no los estás utilizando:
Imports System.ComponentModel
Imports System.Data
6.
Public Sub button1_Click(sender As Object, e As EventArgs) Handles button1.Click
If File.
Exists(tb_PassFilepath.
Text) Then ' ...
sText = Split(tb_PasswordList.Text, vbCrLf)
textBox_pass.Text = sText(i)
' ...
Dim request As HttpWebRequest = DirectCast(WebRequest.Create(URL), HttpWebRequest)
' ...
If DirectCast(response, HttpWebResponse).StatusCode = HttpStatusCode.Redirect Then
' ...
Else
i += 1
' ...
button1.PerformClick()
End If
Else
' ...
End If
End Sub
Esa es la parte más problemática del código y por la que has formulado tu duda.
Al leer y analizar esa parte del código simplemente no podia creerme lo que estaba viendo, si no recuerdo mal vienes de VB6 y eso significa que sabes perfectamente como desarrollar un búcle normal y corriente para iterar la colección de passwords, pero en lugar de eso has preferido recurrir a la manera más rebuscada que yo he visto para llevar a cabo una operación repetitiva, interactuando innecesariamente con la UI (con el botón) y partiendo el texto del textbox de manera continua, ¡muy mal!.
Realmente tienes que tratar de modificar (mejorar) toda la lógica que estás empleando en el desarrollo de la aplicación, de todo el código.
Te muestro un ejemplo de cómo podrías estructurarlo:
Public Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) _
Handles button1.Click
Me.TestPasswordList(Me.passwordList)
End Sub
Private Sub TestPasswordList(ByVal passwordList As IEnumerable(Of String))
Dim cookies As CookieContainer = Nothing
For Each password As String In passwordList
If Me.TestPassword(password, cookies) Then
Me.ReportSuccessPassword(password)
Exit Sub
End If
Next password
Me.ReportFailedPassword()
End Sub
''' <summary>
''' Tests the current password.
''' </summary>
''' <param name="password">The password.</param>
''' <param name="cookies">The byreferred cookie container.</param>
''' <returns><c>true</c> if password successful, <c>false</c> otherwise.</returns>
Private Function TestPassword(ByVal password As String,
ByRef cookies As CookieContainer) As Boolean
' tus llamadas a los métodos de las querys para testear el password actual, aquí.
Me.SetCookies(cookies)
Dim response As HttpWebResponse = Me.GetLoginResponse(cookies)
' etc...
Return (response.StatusCode = HttpStatusCode.Redirect)
End Function
Private Sub SetCookies(ByRef cookies As CookieContainer)
If cookies Is Nothing Then
cookies = New CookieContainer
' tu query para setear el contenedor de cookies aquí.
Else
' salgo, dando por hecho que la sesión de la cookie no haya expirado.
Exit Sub
End If
End Sub
Private Function GetLoginResponse(ByVal cookies As CookieContainer) As HttpWebResponse
' tu query POST de login aquí.
Return DirectCast(response, HttpWebResponse)
End Function
Private Sub ReportSuccessPassword(ByVal password As String)
MessageBox.Show(String.Format("Contraseña aceptada: ""{0}""", password), Me.Text,
MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
Private Sub ReportFailedPassword()
MessageBox.Show("Ninguna contraseña aceptada.", Me.Text,
MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
End Sub
7.
Me pregunto si las peticiones que haces realmente servirán para algo puesto que FaceBook, al igual que cualquier otro servicio tan popular, tiene un límite de intentos de login y suelen hacer bloqueos del usuario (no basados en la ip que efectua el intento).
Por ende, si no me equivoco, yo imagino (no lo he testeado) que en algún momento el "ataque" no servirá practicamente para nada, puesto que a partir de aquí, desgraciadamente todo dejaría de ser útil tras llegar al límite de intentos del servicio:
Dim loginURL As String = "https://www.facebook.com/login.php?login_attempt=1"
request...
response...
PD: Hay bastantes cosas más en el source que necesitarían un arreglo, pero me ahorro los comentarios porque no quiero abusar xD y también por que son fallos menos relevantes que no afectan al
core.
Saludos!