
Introduction
Bruter is a distributed password brute force system for VNC right from home via a TOR+VPN bundle on a virtual machine farm with support for backups, notification to a smartphone via the “pushed” application and filtering masks. The processed masscan log is used as the source of addresses (although you can add addresses and ports with your hands), and the SoftEther VPN application and their wonderful free VPN service, VPN Gate, are used as a VPN, which will help us not pay for a VPN. In addition to this excellent service, SoftEther VPN has a number of other important features — work via socks (TOR), as well as ICMP (ping) support. More on this below.
Like any other distributed system, Bruter consists of a “manager” and “workflows”. “Workflows”, in turn, are divided into “checkers” and “workers”: the first ones check the ip:port lists for the VNC banner (and also delete unnecessary ones and skip inaccessible ones), the second ones go through passwords, and the “manager” runs the whole business. “Workflows” and “manager” communicate with each other through a separate intranet adapter, only the “manager” has direct access to the outside world (to send alerts), the rest see the world only through a TOR+VPN bundle.
Please note that this is a system specifically for “home” use: traffic between the manager and the workflows is not encrypted in any way.
Initially, the system worked without a VPN, directly through TOR (Whonix Gateway), but this imposed a number of restrictions: Whonix “overheated” from the number of connections and required regular reboots, and in addition, the connection to the host on which the search was going on often fell off (TOR tries to change addresses in chains, through this the end node is not always available). With VPN, everything works much more stable and faster: the time required to re-sort the list of addresses for brutus has increased tenfold, i.e. more combinations are sorted in one pass. In addition, TOR does not provide an opportunity to check network availability, unlike VPN, which works fine with ICMP packets.
System requirements
Despite the fact that everything depends heavily on the size of the farm, the general rules are simple: as much RAM and SSD as possible (preferably NVMe, if possible). On my old test bench with Core i7-4790 and 32 GB of RAM, 50 VMs are hosted: Manager (1024 MB), TOR (512 MB), Workers (24×512 MB) and Checkers (24×512 MB).
VM Preparation
To begin with, we transfer the “shared” folder to any convenient location on the SSD. I use VirtualBox myself, so next we’ll talk about it. Windows 7 Compact Edition was chosen as the OS, there are no problems with it. Install the OS, VirtualBox add-ons and add a permanent shared folder with full access, specifying the path to , “shared” in my case, it is mounted on the letter Z. Go to the display settings and on the “Remote access” tab, check the “Enable server” box. Next, clone the image (it is better to choose the name of the type “VM01”) and proceed to configure the “workflows”.
We will need one network adapter for the internal network with the name, say, “brute”. In the “Remote Access” settings, specify port 1001 and launch the OS. Install “SoftEther VPN” on it, change the IP to, say, 172.16.0.1 and the computer name to “VM01”. We add a shortcut to the startup (namely, a shortcut so that we change one file to change the parameters of all VMs) to the file z:\utils\init\vpn.cmd . You also need to add a shortcut to the startup z:\utils\checker.lnk or z:\utils\worker.lnk depending on the type of machine. Turn off the OS and take a snapshot of the system, call it “Snapshot 1” and make a clone called “VM02”. We change the port to 1002 in the “Remote Access” settings, launch the OS and change the address to 172.16.0.2, and the PC name to “VM02”. Repeat the process the required number of times, not forgetting to take a picture at the end and call it “Snapshot 1”. Please note that I myself use different VMs for different types of “workflows”. This is done for a simple reason — network load balancing. For “workers” I use VPNs installed on previously hacked PCs, for “checkers” I use free VPNs with “VPN Gate”. As practice has shown, when using both types of “workflows” at the same time, either abnormal network load is quickly detected, VPN is removed, or the number of connections needs to be reduced. If you have a purchased dedic or only free VPNs, you can safely use one VM for both tasks after playing with the settings beforehand.
Next, let’s infuse TOR. We clone our very first VM, we call it “TOR”. In the “Remote Access” settings, we specify port 1111, and in the Network settings we will need two adapters: the first is NAT, the second is our internal network “brute”. Launch the OS, change the PC name to “TOR”, and the address of the second adapter to 172.16.0.111. Copy the folder z:\utils\tor into the root of the C drive and throw it into the startup and, just in case, a shortcut to the c file on the desktop:\tor\tor.cmd. Turn it off, take a snapshot “Snapshot 1”.
Going back to the first OS, now you don’t have to clone it. In the “Remote Access” settings, specify port 2222. If “pushed” notifications are needed, we also specify two adapters, as in “TOR”; if not needed, we leave only the internal network “brute”. After launching, copy the shortcut to the desktop z:\utils\mgr.lnk , and in the settings of the network adapter of the internal network, specify the address 172.16.0.222.
We put a shortcut for shared\utils\vbox_restart.bat somewhere nearby, say, on the desktop.
Now that all the VMs are ready to work, it’s time to set up mRemoteNG. We add connections for each VM, specifying as the IP address of the PC where VirtualBox is installed, and as the port — the port from the “Remote Access” parameters and RDP as the protocol.

When everything is ready, you can start configuring the system.
Setting up the system
Most of the settings are made in config files in JSON format, many settings can be changed only there, i.e. they do not change on the fly.
Manager
In the “server” section, we are interested in 3 parameters:
server: interface — which interface to listen to ports on. It is better to specify the interface of the internal network (in our case – 172.16.0.0), but you can also specify 0.0.0.0 so that the ports look to the outside world.
server: worker: port – on which port “workers” will be expected
server: checker: port – on which port “checkers” will be expected
the items array will fill itself.

The “notify” section is only needed when using the “pushed” application. The parameters notify: pushed: up_key, notify: pushed: app_secret and notify: pushed: app_alias must be taken from the account pushed.io The notify: pushed:interval parameter specifies how often (in seconds) notifications can be sent.
The notify: found parameter specifies whether to notify about newly selected passwords. I.e., in fact, it enables/disables notification.
The “db” section specifies the full paths to the worker databases.db and checker.db, as well as set
db parameters: clear_flags_on_exit – clear error flags when exiting. The menu item “Clear unsupported RFB flags on unload” from “DB Maintenance” is responsible for this flag. It often happens that today there is RealVNC authentication, and tomorrow something has changed and a supported authentication type has appeared. If you do not clear the flags, the “bad” VNCs will simply not be read from the database at the next launch, so the menu item “Rescan unsupported RFBs” does not take them into account.
db: rebuild_checkers_on_exit – shuffle and compress the table with addresses to check on exit. The menu item “Rebuild Checkers on unload” from “DB Maintenance” is responsible for this flag. I myself prefer to do rebild and compression manually with this script
BEGIN TRANSACTION;
DROP TABLE IF EXISTS new_list;
CREATE TABLE new_list(id INTEGER NOT NULL UNIQUE,ip TEXT NOT NULL,port INTEGER NOT NULL,UNIQUE(ip,port),PRIMARY KEY(id AUTOINCREMENT));
INSERT INTO new_list(ip,port) SELECT ip,port FROM list ORDER BY RANDOM();
DROP TABLE list;
ALTER TABLE new_list RENAME TO list;
COMMIT;
VACUUM;
because my database is quite large (more than 4 GB) and the rebuild takes a lot of time. In addition, repeated passes also bear fruit — both VNC and non-VNC records are found, i.e. the database is being cleaned up.
The “checker” section contains parameters for the operation of “checkers”.
checker: path – the path to the folder where the files of the processed
masscan checker log are dumped: max_items — the size of the cache of “checker” records. It is optimal to specify from the calculation the number of checkers *the number of connections * 2, as much as possible. For example, I have 24*400, but 20000 is indicated, instead of 19200.
checker: read_from_last_id – whether to read the database from the beginning or from the position checker: last_id. It is set by the menu item “Start checking from last ID”. It is disabled for me, because re-passing through old records after a while gives a good result.
The “backup” section is responsible for backup
backup: path — where to copy.
backup: compress is a number from 0 to 9, where 0 is no compression at all, 9 is the maximum. Due to the peculiarities of the database, I don’t see any point in putting it above 5: the speed will drop significantly, and there will be practically no increase in compression.
backup: copies — the number of copies. When the maximum is reached, it will delete the oldest archive.
backup: scheduler: interval — the interval in seconds, how often to copy.
backup: scheduler: on_load — copy on boot. It is set by the menu item “Backup on load”.
backup: scheduler: on_unload — copy when unloading. It is set by the menu item “Backup on unload”.
The “logging” section is clear so — which messages to output in the log. They are set in the “Logging” menu.
The “settings” item sets the path to the window settings file — window locations, selected tabs, and elements.
The “hello_stat” item is responsible for receiving statistics of “workflows” at startup: let’s say you restart manager and instead of 0 found, there will be statistics from “hard workers”.
Worker and Checker have almost identical configs. Let’s first analyze the general parameters:
manager – the address of the manager, the port numbers must match the manager config.
tasks — the number of connections, selected individually.
threads_per_core — the number of threads per processor. Both “checker” and “worker” work on IOCP, so it’s not worth specifying 1000 threads. The optimal number is 2.
timeout — the time to process the connection.
settings — window position and size parameters.
connection_check: enabled — is responsible for enabling/disabling the connection check. If the check is enabled and there is no Internet connection, the tasks will not be processed.
connection_check: timeout — response timeout.
connection_check: address — the address to which we will try to connect to check the connection.
connection_check: reconnect: enabled — enables/disables reconnection in case of a connection failure.
connection_check: reconnect: connection is the name of the VPN network adapter.
connection_check: reconnect: timeout — response timeout.
An attentive reader will immediately ask – “what does ICMP have to do with it, if you check the connection through an attempt to connect, and not by sending pings?” and I will immediately answer him. The fact is that when TOR has already fallen off, and the VPN has not yet arrived, the ping gives errors such as “the specified network is unavailable” and “general failure”. At the same time, the connect() function can hang for a very long time, and the tasks work out instantly — there really is no network. Therefore, the PingThread() thread hangs and waits until the IcmpSendEcho2() function returns ERROR_NETWORK_UNREACHABLE or IP_GENERAL_FAILURE — as soon as this happens, the work is suspended. If connection_check: reconnect: enabled mode is enabled, it reconnects the VPN without waiting for timeouts, if not, it just waits until everything reconnects itself, suspending work.
The “list” parameter for the “worker” sets the full path to the database with passwords. Initially, it was just a text engine, but sqlite works with large amounts of data very efficiently and does not eat up memory, storing everything in it.
The “retry_count” parameter for the “checker” sets the number of attempts to reconnect.
VPN
As an example, a public VPN from VPN Gate is used, if you use your own VPN, just create a connection in the program and export the connection, replacing the desired file with it. So, let’s go to the website vpngate.net (blocked in the Russian Federation) and we are looking for a fresh address. I myself use addresses from subnet 219.100.37.* — there are many of them and they are reliable. You can choose by rating, but I prefer the width of the channel. So, the address is selected — open the file, say, shared\utils\init\01_05.vpn, and change the value of the “string Hostname” parameter to your address.

I forgot to mention it. The TOR proxy address is already registered in the above config, it is also worth paying attention to. If you replace it with your non-public VPN, you can only replace the address, username and password, leaving the file as a template.
TOR
Everything is quite simple here. In my country, TOR is blocked, so it needs bridges. It is also necessary to be able to change them quickly and seamlessly (this is another reason why I moved away from Whonix Gateway). So, let’s go to shared\utils\init\bridges.txt and we enter the current bridges. It doesn’t matter how you get them — telegram, email, torproject website or tor_relay_scanner, the main thing is to specify the type of bridge. If you don’t need bridges, just specify UseBridges 0 or delete the line with the import of this file from torcc altogether.
Getting to work
So, when everything is set up, I suggest you start. Run the vbox_restart.bat file, open the connection to “tor” in mRemoteNG and wait until it boots up and is 100% connected to the network. From time to time, auto-upload does not work (most likely it cannot read the file bridges.txt and you need to run the tor with your hands — that’s what the delay is for in the script). When TOR is running, press enter in the script and wait for the rest of the OS to boot. We connect to the “manager” and launch it. Working with programs is elementary and (hopefully) it is intuitive. There is not much to tell about the “worker” and “checker”, they look something like this and they have practically no settings.


The only thing that can be configured here is the “on top of all windows” mode (enabled in the system menu) and the position of the window (up to the minimized tray).
The situation with the “manager” is more interesting.
You can navigate through the tabs using both the mouse and hotkeys: ctrl + tab – the next tab, ctrl + 1-4 – go to the tab from 1 to 4.

When you right-click on the root element, the context menu with the ability to display/hide offline and stop/start the “worker”.


To clear the results, you can select an entry and press del. Alternatively, you can press del without highlighting and then all entries will be deleted.



Both “Workers” and “Checkers” can be given names, just click on the already selected element a second time and enter a name (in my case, the VM name).

The same rules apply in this tab as in the “Workers” tab – you can delete with the del key.
results_panel.PNG
Let’s go through the toolbar of the “Results” tab. The first button is responsible for adding a fresh address to the list on brut (if there is no such address yet, of course). If the address has already been reset, but we were burned and the password was changed, we will be asked to start from the place where the first password was found. Why is this necessary? It happens that the host cannot be reached for several days and when it appears on the network, it turns out that the password is only for viewing, so it is logical to continue searching from where you left off last time. The next two buttons mark the host as “interesting” and as “blocked” (it is quite common when there is not a wallet with a crypt on the screen, but a login screen). The fourth button simply clears the item from the list, the fifth one continues scanning (if access is only for viewing), the sixth one adds filtering to the list (see below), the last one simply clears the entire log.

To clear the log, just press ctrl+x or by calling the context menu and clicking “Clear”.
As you can see, all the “workflows” have icons with statuses from ICQ. The green one is at work, the red one is offline, the green one with a red cross — the Internet has fallen off, the green one with a leaflet — there are no tasks (perhaps there is also no network — I just haven’t had time to restart the connection yet, or the Internet has just appeared / came online).
All this stuff works on the principle of a “carousel”: we go in a circle, as soon as we reach the end – the “workers” are sorted by the time of the last appeal (the old people go ahead), the “checkers” just walk in a circle. If the checker has found a new address in the process of work, it is immediately given to the worker. If files were thrown to the checker in the process of work .masscan – their contents will be fed to the “checkers” first.
I almost forgot when the checkers check the latest ip:port pairs — there will be an asterisk (*) next to the percentages. This is only necessary in order to wait for the scanning of fresh addresses to complete and not turn off the program before completion, so as not to re-sort the checker database once again. It is also worth noting that there is some inertia — the asterisk disappears as soon as the base boundary is reached, but the cache is still in the scanning process, so at least 20,000 records (in my case) It has yet to be verified.
When the next unfiltered desktop is located on the “Results” tab, access to the “Ignore desktop” button opens, it is worth telling you more about it.

In general, setting up filters is an intimate matter and everyone makes up their own rules. What I don’t need is needed by someone else, otherwise why would it be in such quantities? I’ll tell you about the built—in filters and the general rules for composing filters.
{hex} — filters out shit like
2499F83, 24CAA81, 2E48843, 2F66A01, 30E5C81, 35CCAC1, 3630B01, 3693941, 3838F02, 3905901, 3A78802, 3ABFB41, 3C3DB81, 4046F41, 40B6841, 4238C43, 4629C81, 462A981, 4683B81, 4860D41, 490ED41, 4C97C03, 4CC68C1 , 4F2A881, 500294, 500431, 50BDF81 and thousands of others. There is an HMI hidden behind these beautiful names, which I personally don’t need.
{ip} — the IP address, usually 192.168.., less often — the address of the server itself or other ranges of local networks. It is impossible to see what is hidden behind these addresses with standard browsers, so I just skip it.
{lettercase} — desktops of the type “44.107 ThanhNienMusic”, i.e. with different case in writing. Standard VNC servers for Windows use either uppercase letters only or lowercase letters only. Otherwise it’s either *nix (mac?) or HMI – I skip.
I’m only interested in windows machines, so I use masks as well. */*, *:*, *#* and @.
By the way, after the story with the “Pension” folder and the code words for a wallet with a bunch of crypts on it (received as a bribe) in this folder on a Macbook from one representative of law enforcement, you involuntarily think about probing non-Windows machines.
Hosts with an empty desktop are ignored by default.
A more interesting example. There is a whole bed of cars that I am not interested in, in particular
user-wks2 ( 192.168.10.12 ) - service mode
order-wks1 ( 192.168.10.12 ) - service mode
user-wks2 ( 192.168.10.12 ) - service mode
user-wks1 ( 192.168.10.11 ) - service mode
the filter for such machines may look like this: “*-wks? ( * )*”
I rarely see cars with the same name, as a rule it is some kind of template. But there is also a funny exception: the lenovo-pc desktop. This is a very strange PC without a password, which hangs on about 10 addresses and random ports (new entries appear every day — at the moment there are more than a thousand) Here is an incomplete list:
118.40.40.109:11111 lenovo-pc
118.40.40.123:100 lenovo-pc
118.40.40.168:10 lenovo-pc
118.40.40.192:10250 lenovo-pc
183.105.12.119:123 lenovo-pc
183.105.12.177:5954 lenovo-pc
183.105.12.185:28015 lenovo-pc
183.105.12.202:1994 lenovo-pc
218.149.81.38:4433 lenovo-pc
It is unclear what it is, why and to whom it is needed.
In any case, it’s worth looking through the “good_ignored” list for interesting finds.
More than once I came across the opinion that “pseudo-servers with empty passwords are not needed” and even saw options for ignoring empty passwords in the bruters. I will tell you from my experience of 6 years — I come across very interesting specimens. I regularly see that a host with an empty password and an index of several hundred thousand is available without a password — that is, I conditionally searched it for a month, and it either reinstalled something or reset the settings and became available without a password. I see in the registry or config that there is a password (and it is not a dictionary one), but the authorization function is disabled for some reason.
Moreover, no later than December 2022, citizen Anthony “Ant” Renicks (cornucopias) had several bits and NFT pulled by me for the same amount in ADA, just because of access without a password. Yes, this is rather an exception, but ignoring hosts with empty passwords is stupid, it is much more effective to filter by desktop name.
In addition to the “official” method of adding filter masks, there is also an alternative — by hand to the table. I myself use the “DB Browser for SQLite” for this purpose. Just in the worker database.db we add a new mask to the ignore table/edit the old one. I highly recommend not to get your hands into a “working” database, it is better to first complete the work of the “manager” if for some reason such a need arose. When the changes are made, the “DB Maintenance” menu and the “Worker” submenu come to our aid. Here, for example, in the “Rebuild” section, we can sort alphabetically the list of filters (“Rebuild Ignore masks”), as well as other tables. In fact, this (apart from alphabetical sorting, it makes little sense to me personally): the “manager” will rebuild all the tables himself at the end of the work if a sufficient number of changes have been made (the value 1000 is fixed in the code, i.e. 1000+ additions/deletions). But the menu item “Rescan ignored list” in this case will be very useful to us — it will go through the “good” list in a new way and apply fresh filtering rules, if fresh filtered ones are found, they will be moved to the “good_ignored” table and both tables will be reassembled and the database compressed.
I’ll say a few words about restarting the farm. It is very important to complete the “manager” correctly, because it works with databases and can break something. If the “manager” has fallen off for some reason, the “workers” will continue to drive their tasks around, and when he returns, they will give the results (password indexes or a list of deleted machines). If this suddenly happens — probably a bunch of messages will fall into the log that the address has not been assigned to anyone — it is better to disable the “Error log” for a while. If you need to restart the system (for example, the VPN has fallen off and you are too lazy to manually run the vpn.cmd script on all machines), you do not have to close the “manager” — you can simply pause (the “Stop” button in the context menu of the root element on the “Workers” and “Checkers” tabs), wait for the stop and run the vbox_restart.bat script. I just noticed that bat is somewhere, and cmd is somewhere. But, of course, I won’t redo anything.
masscan
Summing up, I will tell you a little about access mining. I myself use a massage machine installed on hacked machines. It has one significant drawback — it does not save logs too regularly. I.e., in case of a sudden stop, it simply does not remember the current position (after working for a couple of weeks). To avoid this, it is necessary to slightly upgrade the source code and rebuild masscan. Unfortunately, according to the terms of the contest, I cannot upload the code from the github, therefore I will only tell you what I have corrected. In the main.c file in the main_scan function in the variable declaration block between uint64_t range; and unsigned index; inserting uint32_t updates; to make it look like this:
uint64_t range;
uint32_t updates;
unsigned index;
next, while (!is_tx_done && massscan->output.is_status_updates) BOS updates installed = 0;
updates = 0;
while (!is_tx_done && masscan->output.is_status_updates) {
and finally we change it
if (masscan->output.is_status_updates)
status_print(&status, min_index, range, rate,
total_tcbs, total_synacks, total_syns,
0, masscan->output.is_status_ndjson);
on
if (masscan->output.is_status_updates) {
status_print(&status, min_index, range, rate,
total_tcbs, total_synacks, total_syns,
0, masscan->output.is_status_ndjson);
updates++;
if (updates == 61) {
masscan->resume.index = min_index;
masscan_save_state(masscan);
updates = 0;
}
}
All. Now it will save the state every minute. Alternatively, you can take the collected masscan from the archive.
We got distracted. Masscan must save logs in -oB mode, i.e. in binary format! When the masscan log is ready, put it in the ms\done folder and run the read.bat script. Next, when the script finishes working, we transfer the contents of the ms\masscan folder to the shared\masscan folder and wait until the files disappear. These files are read from the end and, upon completion, are “trimmed” to the place where the unread piece is located. If the file extension has been changed to malformed, the file has the wrong length and probably the wrong format.
For beginners who do not have addresses for brutus at all, the following algorithm of actions will be optimal. We take any interesting country/city and scan it for ports, say 5900-5910. Next, we feed the result to the “checkers”. When the entire specified range is scanned, we open the ms\total_db\total.sqbpro file using “DB Browser for SQLite” (after replacing my path X in it:\shared\worker.db to your own with any text editor) and, if this is the first launch, on the “SQL” tab, immediately go to the third point, “3. total1 rebuld” – this query will select all ip that have VNC. We unload the “total” table and scan it using masscan to all ports (-p1-65535), also feeding the results to the “checker”. After scanning new countries/cities, we start from the first tab, “1. total2 rebuild” and execute all three queries, only this time we export the “total3” table, which will contain only those addresses that have recently appeared — we also send them to scan all ports.
The archive with binaries can be downloaded on our private channel.
THE NOTE This article is for informational purposes only. We do not encourage you to commit any hacking. Everything you do is your responsibility.
TOX : 340EF1DCEEC5B395B9B45963F945C00238ADDEAC87C117F64F46206911474C61981D96420B72
Telegram : @DevSecAS
More from Uncategorized
Fortinet FortiOS / FortiProxy Unauthorized RCE
CVE-2024-21762 is a buffer overflow write vulnerability in Fortinet Fortigate and FortiProxy. This vulnerability allows an unauthorized attacker to execute …
Active Directory Dumper 2
We check the architecture for strength – an attempt to cram in the unintelligible – we fasten the network resource …
Active Directory Dumper
The purpose of this article is to show the use of the principles of building an application architecture. 1.1.1 What we …