mirror of
https://github.com/Stone-Red-Code/FraudCapturer.git
synced 2026-09-04 17:16:05 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fdaaec8c51 | ||
|
|
591c7055e9 | ||
|
|
e9147ff2b7 | ||
|
|
48304bb030 | ||
|
|
0b09e749bc | ||
|
|
4b80b801fb |
@@ -0,0 +1,42 @@
|
|||||||
|
namespace FraudCapturer.Configuration;
|
||||||
|
|
||||||
|
internal class BlockConfig
|
||||||
|
{
|
||||||
|
public BlockConfigSet LowRiskSet { get; set; } = new BlockConfigSet(false, true, false);
|
||||||
|
public BlockConfigSet MeduimRiskSet { get; set; } = new BlockConfigSet(false, true, true);
|
||||||
|
public BlockConfigSet HighRiskSet { get; set; } = new BlockConfigSet(true, true, true);
|
||||||
|
|
||||||
|
public bool CheckIfBlock(IpInfo ipInfo)
|
||||||
|
{
|
||||||
|
if (ipInfo.Risk <= 33)
|
||||||
|
{
|
||||||
|
return CheckIfBlockSet(ipInfo, LowRiskSet);
|
||||||
|
}
|
||||||
|
else if (ipInfo.Risk >= 67)
|
||||||
|
{
|
||||||
|
return CheckIfBlockSet(ipInfo, HighRiskSet);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return CheckIfBlockSet(ipInfo, MeduimRiskSet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool CheckIfBlockSet(IpInfo ipInfo, BlockConfigSet blockConfigSet)
|
||||||
|
{
|
||||||
|
if (ipInfo.Type == "VPN" && blockConfigSet.BlockIfVpn)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (ipInfo.IsProxy && blockConfigSet.BlockIfProxy)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (!ipInfo.IsProxy && blockConfigSet.BlockIfNotProxy)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
namespace FraudCapturer.Configuration;
|
||||||
|
|
||||||
|
internal class BlockConfigSet
|
||||||
|
{
|
||||||
|
public BlockConfigSet(bool blockIfNotProxy, bool blockIfProxy, bool blockIfVpn)
|
||||||
|
{
|
||||||
|
BlockIfNotProxy = blockIfNotProxy;
|
||||||
|
BlockIfProxy = blockIfProxy;
|
||||||
|
BlockIfVpn = blockIfVpn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockConfigSet()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool BlockIfNotProxy { get; set; }
|
||||||
|
public bool BlockIfProxy { get; set; }
|
||||||
|
public bool BlockIfVpn { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
namespace FraudCapturer.Configuration;
|
||||||
|
|
||||||
|
internal static class Configurator
|
||||||
|
{
|
||||||
|
public static BlockConfig GetConfig()
|
||||||
|
{
|
||||||
|
BlockConfig blockConfig = new BlockConfig();
|
||||||
|
|
||||||
|
Console.WriteLine("Configuration:");
|
||||||
|
Console.WriteLine();
|
||||||
|
|
||||||
|
Console.WriteLine("High risk rules (>=66%):");
|
||||||
|
Console.WriteLine("----------------------------------------------------");
|
||||||
|
blockConfig.HighRiskSet = GetBlockConfigSetFromConsole(true, true, true);
|
||||||
|
|
||||||
|
Console.WriteLine("High medium rules (>33% & <66%):");
|
||||||
|
Console.WriteLine("----------------------------------------------------");
|
||||||
|
blockConfig.MeduimRiskSet = GetBlockConfigSetFromConsole(false, true, true);
|
||||||
|
|
||||||
|
Console.WriteLine("High low rules (<=33%):");
|
||||||
|
Console.WriteLine("----------------------------------------------------");
|
||||||
|
blockConfig.LowRiskSet = GetBlockConfigSetFromConsole(false, true, false);
|
||||||
|
|
||||||
|
return blockConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BlockConfigSet GetBlockConfigSetFromConsole(bool ifNotProxyDefault, bool ifproxyDefault, bool ifVpnDeault)
|
||||||
|
{
|
||||||
|
BlockConfigSet blockConfigSet = new BlockConfigSet();
|
||||||
|
Console.WriteLine($"Block if no Proxy detected {GetDefaultHintString(ifNotProxyDefault)}:");
|
||||||
|
blockConfigSet.BlockIfNotProxy = GetBoolValueFromConsole(ifNotProxyDefault);
|
||||||
|
|
||||||
|
Console.WriteLine($"Block if Proxy detected {GetDefaultHintString(ifproxyDefault)}:");
|
||||||
|
blockConfigSet.BlockIfProxy = GetBoolValueFromConsole(ifproxyDefault);
|
||||||
|
|
||||||
|
Console.WriteLine($"Block if VPN detected {GetDefaultHintString(ifVpnDeault)}:");
|
||||||
|
blockConfigSet.BlockIfVpn = GetBoolValueFromConsole(ifVpnDeault);
|
||||||
|
|
||||||
|
return blockConfigSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool GetBoolValueFromConsole(bool defaultValue)
|
||||||
|
{
|
||||||
|
string input = Console.ReadLine() ?? string.Empty;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(input))
|
||||||
|
{
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (input.ToLower() is not "y" and not "n")
|
||||||
|
{
|
||||||
|
input = Console.ReadLine() ?? string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
return input.ToLower() == "y";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetDefaultHintString(bool defaultValue)
|
||||||
|
{
|
||||||
|
return defaultValue ? "[Y/n]" : "[y/N]";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
using System.Net;
|
|
||||||
|
|
||||||
namespace FraudCapturer;
|
|
||||||
|
|
||||||
internal class FirewallHelper
|
|
||||||
{
|
|
||||||
public static void BlockIp(IPAddress? ipAddress)
|
|
||||||
{
|
|
||||||
if (ipAddress is null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(ipAddress));
|
|
||||||
}
|
|
||||||
|
|
||||||
AddRuleIfDoesnotExist(ipAddress);
|
|
||||||
|
|
||||||
File.AppendAllText(Program.IpStorePath, $"{Environment.NewLine}{ipAddress}");
|
|
||||||
|
|
||||||
string[] iPs = File.ReadAllLines(Program.IpStorePath);
|
|
||||||
|
|
||||||
System.Diagnostics.Process process = new System.Diagnostics.Process();
|
|
||||||
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo
|
|
||||||
{
|
|
||||||
WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden,
|
|
||||||
FileName = "cmd.exe",
|
|
||||||
Arguments = $"/C netsh advfirewall firewall set rule name=\"{Program.AppName} IP Block\" new remoteIp={string.Join(',', iPs)}"
|
|
||||||
};
|
|
||||||
process.StartInfo = startInfo;
|
|
||||||
_ = process.Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void UnblockIp(IPAddress? ipAddress)
|
|
||||||
{
|
|
||||||
if (ipAddress is null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(ipAddress));
|
|
||||||
}
|
|
||||||
|
|
||||||
List<string> iPs = File.ReadAllLines(Program.IpStorePath).ToList();
|
|
||||||
iPs.Remove(ipAddress.ToString());
|
|
||||||
|
|
||||||
File.WriteAllLines(Program.IpStorePath, iPs);
|
|
||||||
|
|
||||||
System.Diagnostics.Process process = new System.Diagnostics.Process();
|
|
||||||
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo
|
|
||||||
{
|
|
||||||
WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden,
|
|
||||||
FileName = "cmd.exe",
|
|
||||||
Arguments = $"/C netsh advfirewall firewall set rule name=\"{Program.AppName} IP Block\" new remoteIp={string.Join(',', iPs.ToArray())}"
|
|
||||||
};
|
|
||||||
process.StartInfo = startInfo;
|
|
||||||
_ = process.Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void AddRuleIfDoesnotExist(IPAddress ipAddress)
|
|
||||||
{
|
|
||||||
System.Diagnostics.Process process = new System.Diagnostics.Process();
|
|
||||||
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo
|
|
||||||
{
|
|
||||||
WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden,
|
|
||||||
FileName = "cmd.exe",
|
|
||||||
Arguments = $"/C netsh advfirewall firewall show rule name=\"{Program.AppName} IP Block\" >nul || netsh advfirewall firewall add rule name=\"{Program.AppName} IP Block\" dir=in interface=any action=block remoteIp={ipAddress} && netsh advfirewall firewall add rule name=\"{Program.AppName} IP Block\" dir=out interface=any action=block remoteIp={ipAddress}"
|
|
||||||
};
|
|
||||||
process.StartInfo = startInfo;
|
|
||||||
_ = process.Start();
|
|
||||||
process.WaitForExit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="SharpPcap" Version="6.1.0" />
|
<PackageReference Include="SharpPcap" Version="6.1.0" />
|
||||||
|
<PackageReference Include="Stone_Red-C-Sharp-Utilities" Version="1.0.3.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// This file is used by Code Analysis to maintain SuppressMessage
|
||||||
|
// attributes that are applied to this project.
|
||||||
|
// Project-level suppressions either have no target or are given
|
||||||
|
// a specific target and scoped to a namespace, type, member, etc.
|
||||||
|
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
|
[assembly: SuppressMessage("Minor Code Smell", "S1075:URIs should not be hardcoded", Justification = "<Pending>", Scope = "member", Target = "~F:FraudCapturer.Program.AppUrl")]
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
using PacketDotNet;
|
using PacketDotNet;
|
||||||
|
|
||||||
|
using Stone_Red_Utilities.ConsoleExtentions;
|
||||||
|
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -7,22 +9,18 @@ using System.Text.Json;
|
|||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace FraudCapturer;
|
namespace FraudCapturer.Helpers;
|
||||||
|
|
||||||
internal class DomainHelper
|
internal class DomainHelper
|
||||||
{
|
{
|
||||||
public static string[] GetDomainsFromDnsReqest(TransportPacket transportPacket)
|
public static string[] GetDomainsFromDnsReqest(TransportPacket transportPacket)
|
||||||
{
|
{
|
||||||
List<string> domains = new();
|
|
||||||
MatchCollection matchCollection = Regex.Matches(transportPacket.GetPayloadAsString().ToLower(), @"(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]");
|
MatchCollection matchCollection = Regex.Matches(transportPacket.GetPayloadAsString().ToLower(), @"(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]");
|
||||||
foreach (Match match in matchCollection)
|
List<string> domains = matchCollection.Select(match => match.Value).ToList();
|
||||||
{
|
|
||||||
domains.Add(match.Value);
|
|
||||||
}
|
|
||||||
return domains.Distinct().ToArray();
|
return domains.Distinct().ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DomainInfo? GetDomainReputation(string domain)
|
public static async Task<DomainInfo?> GetDomainReputation(string domain)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -41,10 +39,19 @@ internal class DomainHelper
|
|||||||
};
|
};
|
||||||
|
|
||||||
HttpContent httpContent = new StringContent(JsonSerializer.Serialize(reqestBody), Encoding.UTF8, "application/json");
|
HttpContent httpContent = new StringContent(JsonSerializer.Serialize(reqestBody), Encoding.UTF8, "application/json");
|
||||||
|
HttpResponseMessage responseMessage;
|
||||||
|
|
||||||
HttpResponseMessage responseMessage = httpClient.PostAsync("https://anti-fish.bitflow.dev/check", httpContent).GetAwaiter().GetResult(); ;
|
try
|
||||||
|
{
|
||||||
|
responseMessage = await httpClient.PostAsync("https://anti-fish.bitflow.dev/check", httpContent);
|
||||||
|
}
|
||||||
|
catch (HttpRequestException ex)
|
||||||
|
{
|
||||||
|
ConsoleExt.WriteLine($"error: {ex.Message}", ConsoleColor.Gray);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
string resultString = responseMessage.Content.ReadAsStringAsync().GetAwaiter().GetResult(); ;
|
string resultString = await responseMessage.Content.ReadAsStringAsync();
|
||||||
AntiFishResultBody? resultBody = JsonSerializer.Deserialize<AntiFishResultBody>(resultString);
|
AntiFishResultBody? resultBody = JsonSerializer.Deserialize<AntiFishResultBody>(resultString);
|
||||||
|
|
||||||
AntiFishResult? result = resultBody?.Matches?.FirstOrDefault(m => m.Domain == domain);
|
AntiFishResult? result = resultBody?.Matches?.FirstOrDefault(m => m.Domain == domain);
|
||||||
@@ -63,18 +70,18 @@ internal class DomainHelper
|
|||||||
}
|
}
|
||||||
catch (SocketException ex)
|
catch (SocketException ex)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"error: {ex.Message} ({domain})");
|
ConsoleExt.WriteLine($"error: {ex.Message} ({domain})", ConsoleColor.Gray);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AntiFishReqestBody
|
private sealed class AntiFishReqestBody
|
||||||
{
|
{
|
||||||
[JsonPropertyName("message")]
|
[JsonPropertyName("message")]
|
||||||
public string? Message { get; set; }
|
public string? Message { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AntiFishResult
|
private sealed class AntiFishResult
|
||||||
{
|
{
|
||||||
[JsonPropertyName("followed")]
|
[JsonPropertyName("followed")]
|
||||||
public bool Followed { get; set; }
|
public bool Followed { get; set; }
|
||||||
@@ -92,7 +99,7 @@ internal class DomainHelper
|
|||||||
public double TrustRating { get; set; }
|
public double TrustRating { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AntiFishResultBody
|
private sealed class AntiFishResultBody
|
||||||
{
|
{
|
||||||
[JsonPropertyName("match")]
|
[JsonPropertyName("match")]
|
||||||
public bool Match { get; set; }
|
public bool Match { get; set; }
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace FraudCapturer.Helpers;
|
||||||
|
|
||||||
|
internal static class FirewallHelper
|
||||||
|
{
|
||||||
|
public static void BlockIp(IPAddress? ipAddress)
|
||||||
|
{
|
||||||
|
if (ipAddress is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(ipAddress));
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (Program.IpStorePath)
|
||||||
|
{
|
||||||
|
AddRuleIfDoesnotExist(ipAddress);
|
||||||
|
|
||||||
|
File.AppendAllText(Program.IpStorePath, $"{Environment.NewLine}{ipAddress}");
|
||||||
|
|
||||||
|
string[] iPs = File.ReadAllLines(Program.IpStorePath);
|
||||||
|
|
||||||
|
System.Diagnostics.Process process = new System.Diagnostics.Process();
|
||||||
|
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo
|
||||||
|
{
|
||||||
|
WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden,
|
||||||
|
FileName = "cmd.exe",
|
||||||
|
Arguments = $"/C netsh advfirewall firewall set rule name=\"{Program.AppName} IP Block\" new remoteIp={string.Join(',', iPs)}"
|
||||||
|
};
|
||||||
|
process.StartInfo = startInfo;
|
||||||
|
_ = process.Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void UnblockIp(IPAddress? ipAddress)
|
||||||
|
{
|
||||||
|
if (ipAddress is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(ipAddress));
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (Program.IpStorePath)
|
||||||
|
{
|
||||||
|
List<string> iPs = File.ReadAllLines(Program.IpStorePath).ToList();
|
||||||
|
_ = iPs.Remove(ipAddress.ToString());
|
||||||
|
|
||||||
|
File.WriteAllLines(Program.IpStorePath, iPs);
|
||||||
|
|
||||||
|
System.Diagnostics.Process process = new System.Diagnostics.Process();
|
||||||
|
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo
|
||||||
|
{
|
||||||
|
WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden,
|
||||||
|
FileName = "cmd.exe",
|
||||||
|
Arguments = $"/C netsh advfirewall firewall set rule name=\"{Program.AppName} IP Block\" new remoteIp={string.Join(',', iPs.ToArray())}"
|
||||||
|
};
|
||||||
|
process.StartInfo = startInfo;
|
||||||
|
_ = process.Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void AddRuleIfDoesnotExist(IPAddress ipAddress)
|
||||||
|
{
|
||||||
|
lock (Program.IpStorePath)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Process process = new System.Diagnostics.Process();
|
||||||
|
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo
|
||||||
|
{
|
||||||
|
WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden,
|
||||||
|
FileName = "cmd.exe",
|
||||||
|
Arguments = $"/C netsh advfirewall firewall show rule name=\"{Program.AppName} IP Block\" >nul || netsh advfirewall firewall add rule name=\"{Program.AppName} IP Block\" dir=in interface=any action=block remoteIp={ipAddress} && netsh advfirewall firewall add rule name=\"{Program.AppName} IP Block\" dir=out interface=any action=block remoteIp={ipAddress}"
|
||||||
|
};
|
||||||
|
process.StartInfo = startInfo;
|
||||||
|
_ = process.Start();
|
||||||
|
process.WaitForExit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,17 +1,28 @@
|
|||||||
using System.Net;
|
using Stone_Red_Utilities.ConsoleExtentions;
|
||||||
|
|
||||||
|
using System.Net;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
|
||||||
namespace FraudCapturer;
|
namespace FraudCapturer.Helpers;
|
||||||
|
|
||||||
internal class IpHelper
|
internal static class IpHelper
|
||||||
{
|
{
|
||||||
public static string? ProxycheckApiKey { get; set; }
|
public static string? ProxycheckApiKey { get; set; }
|
||||||
|
|
||||||
public static IpInfo? GetIpReputation(IPAddress ipAddress)
|
public static async Task<IpInfo?> GetIpReputation(IPAddress ipAddress)
|
||||||
{
|
{
|
||||||
HttpClient httpClient = new HttpClient();
|
HttpClient httpClient = new HttpClient();
|
||||||
|
string rawResponseData;
|
||||||
|
|
||||||
string rawResponseData = httpClient.GetStringAsync($"http://proxycheck.io/v2/{ipAddress}?key={ProxycheckApiKey}&risk=2&vpn=1&asn=1&tag={Program.AppName}({Environment.MachineName})").GetAwaiter().GetResult();
|
try
|
||||||
|
{
|
||||||
|
rawResponseData = await httpClient.GetStringAsync($"http://proxycheck.io/v2/{ipAddress}?key={ProxycheckApiKey}&risk=2&vpn=1&asn=1&tag={Program.AppName}({Environment.MachineName})");
|
||||||
|
}
|
||||||
|
catch (HttpRequestException ex)
|
||||||
|
{
|
||||||
|
ConsoleExt.WriteLine($"error: {ex.Message}", ConsoleColor.Gray);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
JsonDocument responseData = JsonDocument.Parse(rawResponseData);
|
JsonDocument responseData = JsonDocument.Parse(rawResponseData);
|
||||||
|
|
||||||
@@ -22,10 +33,10 @@ internal class IpHelper
|
|||||||
|
|
||||||
if (statusValue.GetString() != "ok")
|
if (statusValue.GetString() != "ok")
|
||||||
{
|
{
|
||||||
Console.Write(statusValue.GetString());
|
ConsoleExt.Write(statusValue.GetString(), ConsoleColor.Gray);
|
||||||
if (responseData.RootElement.TryGetProperty("message", out JsonElement messageValue))
|
if (responseData.RootElement.TryGetProperty("message", out JsonElement messageValue))
|
||||||
{
|
{
|
||||||
Console.WriteLine($": {messageValue.GetString()}");
|
ConsoleExt.WriteLine($": {messageValue.GetString()}", ConsoleColor.Gray);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -87,21 +98,13 @@ internal class IpHelper
|
|||||||
}
|
}
|
||||||
|
|
||||||
byte[] ip = IPAddress.Parse(ipAdress).GetAddressBytes();
|
byte[] ip = IPAddress.Parse(ipAdress).GetAddressBytes();
|
||||||
switch (ip[0])
|
return ip[0] switch
|
||||||
{
|
{
|
||||||
case 10:
|
10 or 127 => true,
|
||||||
case 127:
|
172 => ip[1] is >= 16 and < 32,
|
||||||
return true;
|
192 => ip[1] == 168,
|
||||||
|
_ => false,
|
||||||
case 172:
|
};
|
||||||
return ip[1] >= 16 && ip[1] < 32;
|
|
||||||
|
|
||||||
case 192:
|
|
||||||
return ip[1] == 168;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsLocalIpAddress(string host)
|
public static bool IsLocalIpAddress(string host)
|
||||||
@@ -121,16 +124,14 @@ internal class IpHelper
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (IPAddress localIP in localIPs)
|
return localIPs.Any(i => i.Equals(hostIP));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
{
|
{
|
||||||
if (hostIP.Equals(localIP))
|
return false;
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,31 +2,31 @@
|
|||||||
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace FraudCapturer;
|
namespace FraudCapturer.Helpers;
|
||||||
|
|
||||||
internal static class PackageHelper
|
internal static class PackageHelper
|
||||||
{
|
{
|
||||||
public static string GetPayloadAsString(this TransportPacket transportPacket)
|
public static string GetPayloadAsString(this TransportPacket transportPacket)
|
||||||
{
|
{
|
||||||
byte[] data = transportPacket.PayloadData;
|
byte[] data = transportPacket.PayloadData;
|
||||||
string bytes = "";
|
StringBuilder bytes = new StringBuilder();
|
||||||
string ascii = "";
|
StringBuilder ascii = new StringBuilder();
|
||||||
|
|
||||||
for (int i = 1; i <= data.Length; i++)
|
for (int i = 1; i <= data.Length; i++)
|
||||||
{
|
{
|
||||||
// add the current byte to the bytes hex string
|
// add the current byte to the bytes hex string
|
||||||
bytes += data[i - 1].ToString("x").PadLeft(2, '0') + " ";
|
_ = bytes.Append(data[i - 1].ToString("x").PadLeft(2, '0') + " ");
|
||||||
|
|
||||||
// add the current byte to the asciiBytes array for later processing
|
// add the current byte to the asciiBytes array for later processing
|
||||||
if (data[i - 1] < 0x21 || data[i - 1] > 0x7e)
|
if (data[i - 1] is < 0x21 or > 0x7e)
|
||||||
{
|
{
|
||||||
ascii += ".";
|
_ = ascii.Append('.');
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ascii += Encoding.ASCII.GetString(new[] { data[i - 1] });
|
_ = ascii.Append(Encoding.ASCII.GetString(new[] { data[i - 1] }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ascii.Trim('.');
|
return ascii.ToString().Trim('.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+67
-46
@@ -1,26 +1,32 @@
|
|||||||
|
using FraudCapturer.Configuration;
|
||||||
|
using FraudCapturer.Helpers;
|
||||||
|
|
||||||
using PacketDotNet;
|
using PacketDotNet;
|
||||||
|
|
||||||
using SharpPcap;
|
using SharpPcap;
|
||||||
|
|
||||||
|
using Stone_Red_Utilities.ConsoleExtentions;
|
||||||
|
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
namespace FraudCapturer;
|
namespace FraudCapturer;
|
||||||
|
|
||||||
/// <summary>
|
public static class Program
|
||||||
/// Example showing packet manipulation
|
|
||||||
/// </summary>
|
|
||||||
public class Program
|
|
||||||
{
|
{
|
||||||
public const string AppName = "FraudCapturer";
|
public const string AppName = "FraudCapturer";
|
||||||
public const string AppUrl = "https://github.com/Stone-Red-Code/FraudCapturer";
|
public const string AppUrl = "https://github.com/Stone-Red-Code/FraudCapturer";
|
||||||
public const string IpStorePath = "ipAdresses.txt";
|
public const string IpStorePath = "ipAdresses.txt";
|
||||||
|
public const string ConfigStorePath = "config.txt";
|
||||||
|
|
||||||
private static DateTime lastCacheClear;
|
private static DateTime lastCacheClear;
|
||||||
private static string lastDomain = string.Empty;
|
private static string lastDomain = string.Empty;
|
||||||
|
|
||||||
private static readonly List<string> capturedIpsCache = new();
|
private static readonly ConcurrentBag<string> capturedIpsCache = new();
|
||||||
private static readonly Dictionary<string, DomainInfo> capturedDomainsCache = new();
|
private static readonly ConcurrentDictionary<string, DomainInfo?> capturedDomainsCache = new();
|
||||||
|
|
||||||
|
private static BlockConfig blockConfig = new BlockConfig();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The main entry point for the application.
|
/// The main entry point for the application.
|
||||||
@@ -35,18 +41,30 @@ public class Program
|
|||||||
// Retrieve the device list
|
// Retrieve the device list
|
||||||
CaptureDeviceList devices = CaptureDeviceList.Instance;
|
CaptureDeviceList devices = CaptureDeviceList.Instance;
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(args.FirstOrDefault()))
|
if (args.FirstOrDefault() == "config")
|
||||||
{
|
{
|
||||||
Console.ForegroundColor = ConsoleColor.Red;
|
blockConfig = Configurator.GetConfig();
|
||||||
Console.WriteLine("No proxycheck api key provided! You are limited to 100 IP checks per day. Get one for free at proxycheck.io.");
|
string jsonConfig = JsonSerializer.Serialize(blockConfig);
|
||||||
|
File.WriteAllText(ConfigStorePath, jsonConfig);
|
||||||
|
|
||||||
|
Console.WriteLine("-- Configuration saved!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (string.IsNullOrWhiteSpace(args.FirstOrDefault()))
|
||||||
|
{
|
||||||
|
ConsoleExt.WriteLine("No proxycheck api key provided! You are limited to 100 IP checks per day. Get one for free at proxycheck.io.", ConsoleColor.Red);
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
Console.ResetColor();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
IpHelper.ProxycheckApiKey = args.FirstOrDefault();
|
IpHelper.ProxycheckApiKey = args.FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (File.Exists(ConfigStorePath))
|
||||||
|
{
|
||||||
|
blockConfig = JsonSerializer.Deserialize<BlockConfig>(File.ReadAllText(ConfigStorePath)) ?? new BlockConfig();
|
||||||
|
}
|
||||||
|
|
||||||
// If no devices were found print an error
|
// If no devices were found print an error
|
||||||
if (devices.Count < 1)
|
if (devices.Count < 1)
|
||||||
{
|
{
|
||||||
@@ -92,7 +110,7 @@ public class Program
|
|||||||
device.Open();
|
device.Open();
|
||||||
|
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
Console.WriteLine("-- Listening on {0}, hit 'Ctrl-C' to exit...", device.Description);
|
Console.WriteLine($"-- Listening on {device.Description}, hit 'Ctrl-C' to exit...");
|
||||||
|
|
||||||
// Start capture of packets
|
// Start capture of packets
|
||||||
device.Capture();
|
device.Capture();
|
||||||
@@ -101,6 +119,11 @@ public class Program
|
|||||||
private static void Device_OnPacketArrival(object sender, PacketCapture e)
|
private static void Device_OnPacketArrival(object sender, PacketCapture e)
|
||||||
{
|
{
|
||||||
RawCapture rawPacket = e.GetPacket();
|
RawCapture rawPacket = e.GetPacket();
|
||||||
|
_ = ProcessRawPacket(rawPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task ProcessRawPacket(RawCapture rawPacket)
|
||||||
|
{
|
||||||
Packet packet = Packet.ParsePacket(rawPacket.LinkLayerType, rawPacket.Data);
|
Packet packet = Packet.ParsePacket(rawPacket.LinkLayerType, rawPacket.Data);
|
||||||
if (packet is EthernetPacket)
|
if (packet is EthernetPacket)
|
||||||
{
|
{
|
||||||
@@ -133,74 +156,73 @@ public class Program
|
|||||||
capturedIpsCache.Clear();
|
capturedIpsCache.Clear();
|
||||||
capturedDomainsCache.Clear();
|
capturedDomainsCache.Clear();
|
||||||
File.WriteAllText(IpStorePath, string.Empty);
|
File.WriteAllText(IpStorePath, string.Empty);
|
||||||
Console.WriteLine("Cleared cache");
|
ConsoleExt.WriteLine("Cleared cache", ConsoleColor.Gray);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Check if a DNS packet contains a "dangerous" domain.
|
//Check if a DNS packet contains a "dangerous" domain.
|
||||||
CheckDns(packet, remoteIpAddress, direction);
|
await CheckDns(packet, remoteIpAddress, direction);
|
||||||
|
|
||||||
if (capturedIpsCache.Contains(remoteIpAddress.ToString()))
|
if (capturedIpsCache.Contains(remoteIpAddress.ToString()))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeSpan timeRemainingUntilCacheReset = new TimeSpan(0, 10, 0) - (DateTime.Now - lastCacheClear);
|
|
||||||
Console.WriteLine($"Next cache reset in {timeRemainingUntilCacheReset.Minutes} minute(s) and {timeRemainingUntilCacheReset.Seconds} second(s)");
|
|
||||||
|
|
||||||
capturedIpsCache.Add(remoteIpAddress.ToString());
|
capturedIpsCache.Add(remoteIpAddress.ToString());
|
||||||
|
|
||||||
//Check if ip address is "dangerous" or blocked
|
//Check if ip address is "dangerous" or blocked
|
||||||
CheckIpAddress(remoteIpAddress, direction);
|
await CheckIpAddress(remoteIpAddress, direction);
|
||||||
|
|
||||||
|
TimeSpan timeRemainingUntilCacheReset = new TimeSpan(0, 10, 0) - (DateTime.Now - lastCacheClear);
|
||||||
|
ConsoleExt.WriteLine($"Next cache reset in {timeRemainingUntilCacheReset.Minutes} minute(s) and {timeRemainingUntilCacheReset.Seconds} second(s)", ConsoleColor.Gray);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CheckIpAddress(IPAddress remoteIpAddress, string direction)
|
private static async Task CheckIpAddress(IPAddress remoteIpAddress, string direction)
|
||||||
{
|
{
|
||||||
IpInfo? ipInfo = IpHelper.GetIpReputation(remoteIpAddress);
|
IpInfo? ipInfo = await IpHelper.GetIpReputation(remoteIpAddress);
|
||||||
|
|
||||||
if (IpHelper.IsInternalIpAddress(remoteIpAddress.ToString()))
|
if (IpHelper.IsInternalIpAddress(remoteIpAddress.ToString()))
|
||||||
{
|
{
|
||||||
Console.ForegroundColor = ConsoleColor.Cyan;
|
ConsoleExt.WriteLine($"[{direction}] [Internal] {remoteIpAddress}", ConsoleColor.Cyan);
|
||||||
Console.WriteLine($"[{direction}] [Internal] {remoteIpAddress}");
|
|
||||||
}
|
}
|
||||||
else if (ipInfo is not null)
|
else if (ipInfo is not null)
|
||||||
{
|
{
|
||||||
bool block = false;
|
bool block = false;
|
||||||
if (ipInfo.Risk >= 67)
|
ConsoleColor consoleColor;
|
||||||
|
|
||||||
|
if (ipInfo.Risk >= 67 && BlockConfig.CheckIfBlockSet(ipInfo, blockConfig.HighRiskSet))
|
||||||
{
|
{
|
||||||
FirewallHelper.BlockIp(remoteIpAddress);
|
FirewallHelper.BlockIp(remoteIpAddress);
|
||||||
Console.ForegroundColor = ConsoleColor.Red;
|
consoleColor = ConsoleColor.Red;
|
||||||
block = true;
|
block = true;
|
||||||
}
|
}
|
||||||
else if (ipInfo.Risk >= 34 && ipInfo.IsProxy)
|
else if (ipInfo.Risk <= 33 && BlockConfig.CheckIfBlockSet(ipInfo, blockConfig.LowRiskSet))
|
||||||
{
|
{
|
||||||
FirewallHelper.BlockIp(remoteIpAddress);
|
FirewallHelper.BlockIp(remoteIpAddress);
|
||||||
Console.ForegroundColor = ConsoleColor.DarkYellow;
|
consoleColor = ConsoleColor.Yellow;
|
||||||
block = true;
|
block = true;
|
||||||
}
|
}
|
||||||
else if (ipInfo.IsProxy && ipInfo.Type != "VPN")
|
else if (BlockConfig.CheckIfBlockSet(ipInfo, blockConfig.MeduimRiskSet))
|
||||||
{
|
{
|
||||||
FirewallHelper.BlockIp(remoteIpAddress);
|
FirewallHelper.BlockIp(remoteIpAddress);
|
||||||
Console.ForegroundColor = ConsoleColor.DarkYellow;
|
consoleColor = ConsoleColor.DarkYellow;
|
||||||
block = true;
|
block = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.ForegroundColor = ConsoleColor.Green;
|
consoleColor = ConsoleColor.Green;
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine($"[{direction}] [Provider: {ipInfo.Provider}] [Risk: {ipInfo.Risk}] [Proxy: {ipInfo.IsProxy}] [Type: {ipInfo.Type}] [Block: {block}] {remoteIpAddress}");
|
ConsoleExt.WriteLine($"[{direction}] [Provider: {ipInfo.Provider}] [Risk: {ipInfo.Risk}] [Proxy: {ipInfo.IsProxy}] [Type: {ipInfo.Type}] [Block: {block}] {remoteIpAddress}", consoleColor);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.ForegroundColor = ConsoleColor.Magenta;
|
ConsoleExt.WriteLine($"[{direction}] [Invalid] {remoteIpAddress}", ConsoleColor.Magenta);
|
||||||
Console.WriteLine($"[{direction}] [Invalid] {remoteIpAddress}");
|
|
||||||
}
|
}
|
||||||
Console.ResetColor();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CheckDns(Packet packet, IPAddress remoteIpAddress, string direction)
|
private static async Task CheckDns(Packet packet, IPAddress remoteIpAddress, string direction)
|
||||||
{
|
{
|
||||||
TransportPacket transportPacket = packet.Extract<TcpPacket>();
|
TransportPacket transportPacket = packet.Extract<TcpPacket>();
|
||||||
transportPacket ??= packet.Extract<UdpPacket>();
|
transportPacket ??= packet.Extract<UdpPacket>();
|
||||||
@@ -219,54 +241,53 @@ public class Program
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
domainInfo = DomainHelper.GetDomainReputation(domain);
|
domainInfo = await DomainHelper.GetDomainReputation(domain);
|
||||||
|
_ = capturedDomainsCache.TryAdd(domain, domainInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (domainInfo is null)
|
if (domainInfo is null)
|
||||||
{
|
{
|
||||||
Console.ForegroundColor = ConsoleColor.Magenta;
|
|
||||||
if (lastDomain != domain)
|
if (lastDomain != domain)
|
||||||
{
|
{
|
||||||
lastDomain = domain;
|
lastDomain = domain;
|
||||||
Console.WriteLine($"[{direction}] [Dns] [Invalid] [Domain: {domain}] {remoteIpAddress}");
|
ConsoleExt.WriteLine($"[{direction}] [Dns] [Invalid] [Domain: {domain}] {remoteIpAddress}", ConsoleColor.Magenta);
|
||||||
}
|
}
|
||||||
Console.ResetColor();
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (domainInfo.IsMatch == false)
|
if (!domainInfo.IsMatch)
|
||||||
{
|
{
|
||||||
Console.ForegroundColor = ConsoleColor.Green;
|
|
||||||
if (lastDomain != domain)
|
if (lastDomain != domain)
|
||||||
{
|
{
|
||||||
lastDomain = domain;
|
lastDomain = domain;
|
||||||
Console.WriteLine($"[{direction}] [Dns] [Domain: {domain}] [Type: Undetected] [Block: {block}] {remoteIpAddress}");
|
ConsoleExt.WriteLine($"[{direction}] [Dns] [Domain: {domain}] [Type: Undetected] [Block: {block}] {remoteIpAddress}", ConsoleColor.Green);
|
||||||
}
|
}
|
||||||
Console.ResetColor();
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ConsoleColor consoleColor;
|
||||||
|
|
||||||
if (domainInfo.TrustRating >= 0.9)
|
if (domainInfo.TrustRating >= 0.9)
|
||||||
{
|
{
|
||||||
FirewallHelper.BlockIp(domainInfo.IpAddress);
|
FirewallHelper.BlockIp(domainInfo.IpAddress);
|
||||||
Console.ForegroundColor = ConsoleColor.Red;
|
consoleColor = ConsoleColor.Red;
|
||||||
block = true;
|
block = true;
|
||||||
}
|
}
|
||||||
else if (domainInfo.TrustRating >= 0.5)
|
else if (domainInfo.TrustRating >= 0.5)
|
||||||
{
|
{
|
||||||
FirewallHelper.BlockIp(domainInfo.IpAddress);
|
FirewallHelper.BlockIp(domainInfo.IpAddress);
|
||||||
Console.ForegroundColor = ConsoleColor.DarkYellow;
|
consoleColor = ConsoleColor.DarkYellow;
|
||||||
block = true;
|
block = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.ForegroundColor = ConsoleColor.Green;
|
consoleColor = ConsoleColor.Green;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastDomain != domain)
|
if (lastDomain != domain)
|
||||||
{
|
{
|
||||||
lastDomain = domain;
|
lastDomain = domain;
|
||||||
Console.WriteLine($"[{direction}] [Dns] [Domain: {domain}] [Type: {domainInfo.Type}] [Source: {domainInfo.Source}] [Source Trust: {domainInfo.TrustRating * 100d}] [Block: {block}] {remoteIpAddress}");
|
ConsoleExt.WriteLine($"[{direction}] [Dns] [Domain: {domain}] [Type: {domainInfo.Type}] [Source: {domainInfo.Source}] [Source Trust: {domainInfo.TrustRating * 100d}] [Block: {block}] {remoteIpAddress}", consoleColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.ResetColor();
|
Console.ResetColor();
|
||||||
|
|||||||
Reference in New Issue
Block a user