From 2b943385bb49059ab10eae1baad3f455fbc49fe3 Mon Sep 17 00:00:00 2001
From: Stone_Red <56473591+Stone-Red-Code@users.noreply.github.com>
Date: Sat, 8 Jan 2022 00:51:05 +0100
Subject: [PATCH] - Switch to console based application - Add automatic IP
blocking - Add automatic domain blocking
---
FraudCapturer.sln | 16 +-
FraudCapturer/App.xaml | 8 -
FraudCapturer/App.xaml.cs | 15 --
FraudCapturer/AssemblyInfo.cs | 10 -
FraudCapturer/DomainHelper.cs | 103 ++++++++
FraudCapturer/DomainInfo.cs | 12 +
FraudCapturer/FirewallHelper.cs | 67 +++++
FraudCapturer/FraudCapturer - Backup.csproj | 20 --
FraudCapturer/FraudCapturer.csproj | 16 +-
FraudCapturer/IpHelper.cs | 134 ++++++++++
FraudCapturer/IpInfo.cs | 9 +
FraudCapturer/MainWindow.xaml | 16 --
FraudCapturer/MainWindow.xaml.cs | 26 --
FraudCapturer/MainWindowViewModel.cs | 147 -----------
FraudCapturer/PackageHelper.cs | 32 +++
FraudCapturer/Program.cs | 265 ++++++++++++++++++++
FraudCapturer/ReqestBody.cs | 9 -
FraudCapturer/Result.cs | 21 --
FraudCapturer/ResultBody.cs | 13 -
FraudCapturer/ScreenshotHandler.cs | 5 -
20 files changed, 633 insertions(+), 311 deletions(-)
delete mode 100644 FraudCapturer/App.xaml
delete mode 100644 FraudCapturer/App.xaml.cs
delete mode 100644 FraudCapturer/AssemblyInfo.cs
create mode 100644 FraudCapturer/DomainHelper.cs
create mode 100644 FraudCapturer/DomainInfo.cs
create mode 100644 FraudCapturer/FirewallHelper.cs
delete mode 100644 FraudCapturer/FraudCapturer - Backup.csproj
create mode 100644 FraudCapturer/IpHelper.cs
create mode 100644 FraudCapturer/IpInfo.cs
delete mode 100644 FraudCapturer/MainWindow.xaml
delete mode 100644 FraudCapturer/MainWindow.xaml.cs
delete mode 100644 FraudCapturer/MainWindowViewModel.cs
create mode 100644 FraudCapturer/PackageHelper.cs
create mode 100644 FraudCapturer/Program.cs
delete mode 100644 FraudCapturer/ReqestBody.cs
delete mode 100644 FraudCapturer/Result.cs
delete mode 100644 FraudCapturer/ResultBody.cs
delete mode 100644 FraudCapturer/ScreenshotHandler.cs
diff --git a/FraudCapturer.sln b/FraudCapturer.sln
index 66a0923..eb80e06 100644
--- a/FraudCapturer.sln
+++ b/FraudCapturer.sln
@@ -3,24 +3,18 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.32014.148
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FraudCapturer", "FraudCapturer\FraudCapturer.csproj", "{B7D42E3E-C88C-4043-BA19-3B5BCA3E2EB8}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FraudCapturer", "FraudCapturer\FraudCapturer.csproj", "{28BC39A1-7295-4270-8A30-BA5DCDD8EF54}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
- Debug|x64 = Debug|x64
Release|Any CPU = Release|Any CPU
- Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {B7D42E3E-C88C-4043-BA19-3B5BCA3E2EB8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {B7D42E3E-C88C-4043-BA19-3B5BCA3E2EB8}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {B7D42E3E-C88C-4043-BA19-3B5BCA3E2EB8}.Debug|x64.ActiveCfg = Debug|x64
- {B7D42E3E-C88C-4043-BA19-3B5BCA3E2EB8}.Debug|x64.Build.0 = Debug|x64
- {B7D42E3E-C88C-4043-BA19-3B5BCA3E2EB8}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {B7D42E3E-C88C-4043-BA19-3B5BCA3E2EB8}.Release|Any CPU.Build.0 = Release|Any CPU
- {B7D42E3E-C88C-4043-BA19-3B5BCA3E2EB8}.Release|x64.ActiveCfg = Release|x64
- {B7D42E3E-C88C-4043-BA19-3B5BCA3E2EB8}.Release|x64.Build.0 = Release|x64
+ {28BC39A1-7295-4270-8A30-BA5DCDD8EF54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {28BC39A1-7295-4270-8A30-BA5DCDD8EF54}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {28BC39A1-7295-4270-8A30-BA5DCDD8EF54}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {28BC39A1-7295-4270-8A30-BA5DCDD8EF54}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/FraudCapturer/App.xaml b/FraudCapturer/App.xaml
deleted file mode 100644
index 97846e1..0000000
--- a/FraudCapturer/App.xaml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/FraudCapturer/App.xaml.cs b/FraudCapturer/App.xaml.cs
deleted file mode 100644
index 49a25f8..0000000
--- a/FraudCapturer/App.xaml.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Configuration;
-using System.Data;
-using System.Linq;
-using System.Threading.Tasks;
-using System.Windows;
-
-namespace FraudCapturer;
-///
-/// Interaction logic for App.xaml
-///
-public partial class App : Application
-{
-}
diff --git a/FraudCapturer/AssemblyInfo.cs b/FraudCapturer/AssemblyInfo.cs
deleted file mode 100644
index 8b5504e..0000000
--- a/FraudCapturer/AssemblyInfo.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using System.Windows;
-
-[assembly: ThemeInfo(
- ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
- //(used if a resource is not found in the page,
- // or application resource dictionaries)
- ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
- //(used if a resource is not found in the page,
- // app, or any theme specific resource dictionaries)
-)]
diff --git a/FraudCapturer/DomainHelper.cs b/FraudCapturer/DomainHelper.cs
new file mode 100644
index 0000000..ee6b083
--- /dev/null
+++ b/FraudCapturer/DomainHelper.cs
@@ -0,0 +1,103 @@
+using PacketDotNet;
+
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+using System.Text.RegularExpressions;
+
+namespace FraudCapturer;
+
+internal class DomainHelper
+{
+ public static string[] GetDomainsFromDnsReqest(TransportPacket transportPacket)
+ {
+ List 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]");
+ foreach (Match match in matchCollection)
+ {
+ domains.Add(match.Value);
+ }
+ return domains.Distinct().ToArray();
+ }
+
+ public static DomainInfo? GetDomainReputation(string domain)
+ {
+ try
+ {
+ IPAddress[] addresslist = Dns.GetHostAddresses(domain);
+ DomainInfo domainInfo = new DomainInfo
+ {
+ IpAddress = addresslist[0]
+ };
+
+ HttpClient httpClient = new HttpClient();
+ httpClient.DefaultRequestHeaders.Add("User-Agent", $"{Program.AppName} - (coming soon)");
+
+ AntiFishReqestBody reqestBody = new AntiFishReqestBody()
+ {
+ Message = domain
+ };
+
+ HttpContent httpContent = new StringContent(JsonSerializer.Serialize(reqestBody), Encoding.UTF8, "application/json");
+
+ HttpResponseMessage responseMessage = httpClient.PostAsync("https://anti-fish.bitflow.dev/check", httpContent).GetAwaiter().GetResult(); ;
+
+ string resultString = responseMessage.Content.ReadAsStringAsync().GetAwaiter().GetResult(); ;
+ AntiFishResultBody? resultBody = JsonSerializer.Deserialize(resultString);
+
+ AntiFishResult? result = resultBody?.Matches?.FirstOrDefault(m => m.Domain == domain);
+
+ if (result is null)
+ {
+ return domainInfo;
+ }
+
+ domainInfo.IsMatch = true;
+ domainInfo.TrustRating = result.TrustRating;
+ domainInfo.Source = result.Source;
+ domainInfo.Type = result.Type;
+
+ return domainInfo;
+ }
+ catch (SocketException ex)
+ {
+ Console.WriteLine($"error: {ex.Message} ({domain})");
+ return null;
+ }
+ }
+
+ private class AntiFishReqestBody
+ {
+ [JsonPropertyName("message")]
+ public string? Message { get; set; }
+ }
+
+ private class AntiFishResult
+ {
+ [JsonPropertyName("followed")]
+ public bool Followed { get; set; }
+
+ [JsonPropertyName("domain")]
+ public string? Domain { get; set; }
+
+ [JsonPropertyName("source")]
+ public string? Source { get; set; }
+
+ [JsonPropertyName("type")]
+ public string? Type { get; set; }
+
+ [JsonPropertyName("trust_rating")]
+ public double TrustRating { get; set; }
+ }
+
+ private class AntiFishResultBody
+ {
+ [JsonPropertyName("match")]
+ public bool Match { get; set; }
+
+ [JsonPropertyName("matches")]
+ public List? Matches { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/FraudCapturer/DomainInfo.cs b/FraudCapturer/DomainInfo.cs
new file mode 100644
index 0000000..c9a0465
--- /dev/null
+++ b/FraudCapturer/DomainInfo.cs
@@ -0,0 +1,12 @@
+using System.Net;
+
+namespace FraudCapturer;
+
+internal class DomainInfo
+{
+ public string? Type { get; set; }
+ public string? Source { get; set; }
+ public double TrustRating { get; set; }
+ public bool IsMatch { get; set; }
+ public IPAddress? IpAddress { get; set; }
+}
\ No newline at end of file
diff --git a/FraudCapturer/FirewallHelper.cs b/FraudCapturer/FirewallHelper.cs
new file mode 100644
index 0000000..b4e678e
--- /dev/null
+++ b/FraudCapturer/FirewallHelper.cs
@@ -0,0 +1,67 @@
+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 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();
+ }
+}
\ No newline at end of file
diff --git a/FraudCapturer/FraudCapturer - Backup.csproj b/FraudCapturer/FraudCapturer - Backup.csproj
deleted file mode 100644
index d985707..0000000
--- a/FraudCapturer/FraudCapturer - Backup.csproj
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
- WinExe
- 8.0
- net6.0-windows
- enable
- true
- AnyCPU;x64
-
-
-
-
-
-
-
-
-
-
-
diff --git a/FraudCapturer/FraudCapturer.csproj b/FraudCapturer/FraudCapturer.csproj
index 6c55889..6f4a3ce 100644
--- a/FraudCapturer/FraudCapturer.csproj
+++ b/FraudCapturer/FraudCapturer.csproj
@@ -1,18 +1,14 @@
-
+
- WinExe
- net6.0-windows
+ Exe
+ net6.0
+ enable
enable
- true
- AnyCPU;x64
+
-
-
-
-
-
+
diff --git a/FraudCapturer/IpHelper.cs b/FraudCapturer/IpHelper.cs
new file mode 100644
index 0000000..c974b6f
--- /dev/null
+++ b/FraudCapturer/IpHelper.cs
@@ -0,0 +1,134 @@
+using System.Net;
+using System.Text.Json;
+
+namespace FraudCapturer;
+
+internal class IpHelper
+{
+ public static IpInfo? GetIpReputation(IPAddress ipAddress)
+ {
+ HttpClient httpClient = new HttpClient();
+
+ string rawResponseData = httpClient.GetStringAsync($"http://proxycheck.io/v2/{ipAddress}?key=65019k-719i38-2k0r91-36q7o7&risk=2&vpn=1&asn=1&tag={Program.AppName}").GetAwaiter().GetResult();
+
+ JsonDocument responseData = JsonDocument.Parse(rawResponseData);
+
+ if (!responseData.RootElement.TryGetProperty("status", out JsonElement statusValue))
+ {
+ return null;
+ }
+
+ if (statusValue.GetString() != "ok")
+ {
+ Console.Write(statusValue.GetString());
+ if (responseData.RootElement.TryGetProperty("message", out JsonElement messageValue))
+ {
+ Console.WriteLine($": {messageValue.GetString()}");
+ }
+ else
+ {
+ Console.WriteLine();
+ }
+ }
+
+ if (!responseData.RootElement.TryGetProperty(ipAddress.ToString(), out JsonElement jsonElement))
+ {
+ return null;
+ }
+
+ string type = string.Empty;
+ string provider = string.Empty;
+ bool isProxy = false;
+ int risk = 0;
+
+ if (jsonElement.TryGetProperty("type", out JsonElement typeValue))
+ {
+ type = typeValue.ToString();
+ }
+
+ if (jsonElement.TryGetProperty("provider", out JsonElement providerValue))
+ {
+ provider = providerValue.ToString();
+ }
+
+ if (jsonElement.TryGetProperty("proxy", out JsonElement proxyValue))
+ {
+ isProxy = proxyValue.GetString() == "yes";
+ }
+
+ if (jsonElement.TryGetProperty("risk", out JsonElement riskValue))
+ {
+ risk = riskValue.GetInt32();
+ }
+
+ if (string.IsNullOrWhiteSpace(provider))
+ {
+ provider = "Unknown";
+ }
+
+ IpInfo ipInfo = new IpInfo()
+ {
+ Type = type,
+ IsProxy = isProxy,
+ Provider = provider,
+ Risk = risk
+ };
+
+ return ipInfo;
+ }
+
+ public static bool IsInternalIpAddress(string ipAdress)
+ {
+ if (ipAdress == "::1")
+ {
+ return true;
+ }
+
+ byte[] ip = IPAddress.Parse(ipAdress).GetAddressBytes();
+ switch (ip[0])
+ {
+ case 10:
+ case 127:
+ return true;
+
+ case 172:
+ return ip[1] >= 16 && ip[1] < 32;
+
+ case 192:
+ return ip[1] == 168;
+
+ default:
+ return false;
+ }
+ }
+
+ public static bool IsLocalIpAddress(string host)
+ {
+ try
+ {
+ // get host IP addresses
+ IPAddress[] hostIPs = Dns.GetHostAddresses(host);
+ // get local IP addresses
+ IPAddress[] localIPs = Dns.GetHostAddresses(Dns.GetHostName());
+
+ // test if any host IP equals to any local IP or to localhost
+ foreach (IPAddress hostIP in hostIPs)
+ {
+ if (IPAddress.IsLoopback(hostIP))
+ {
+ return true;
+ }
+
+ foreach (IPAddress localIP in localIPs)
+ {
+ if (hostIP.Equals(localIP))
+ {
+ return true;
+ }
+ }
+ }
+ }
+ catch { }
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/FraudCapturer/IpInfo.cs b/FraudCapturer/IpInfo.cs
new file mode 100644
index 0000000..4f2a7d3
--- /dev/null
+++ b/FraudCapturer/IpInfo.cs
@@ -0,0 +1,9 @@
+namespace FraudCapturer;
+
+internal class IpInfo
+{
+ public bool IsProxy { get; set; }
+ public string? Type { get; set; }
+ public string? Provider { get; set; }
+ public int Risk { get; set; }
+}
\ No newline at end of file
diff --git a/FraudCapturer/MainWindow.xaml b/FraudCapturer/MainWindow.xaml
deleted file mode 100644
index d9f569e..0000000
--- a/FraudCapturer/MainWindow.xaml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/FraudCapturer/MainWindow.xaml.cs b/FraudCapturer/MainWindow.xaml.cs
deleted file mode 100644
index 3e4672a..0000000
--- a/FraudCapturer/MainWindow.xaml.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Data;
-using System.Windows.Documents;
-using System.Windows.Input;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
-using System.Windows.Navigation;
-using System.Windows.Shapes;
-
-namespace FraudCapturer;
-///
-/// Interaction logic for MainWindow.xaml
-///
-public partial class MainWindow : Window
-{
- public MainWindow()
- {
- InitializeComponent();
- }
-}
diff --git a/FraudCapturer/MainWindowViewModel.cs b/FraudCapturer/MainWindowViewModel.cs
deleted file mode 100644
index 49e9928..0000000
--- a/FraudCapturer/MainWindowViewModel.cs
+++ /dev/null
@@ -1,147 +0,0 @@
-using IronOcr;
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Drawing;
-using System.Drawing.Imaging;
-using System.Net.Http;
-using System.Text;
-using System.Text.Json;
-using System.Text.RegularExpressions;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-
-namespace FraudCapturer;
-
-internal class MainWindowViewModel
-{
- private readonly Dictionary domainCache = new();
-
- public MainWindowViewModel()
- {
- Run();
- }
-
- private Task Run()
- {
- return Task.Run(async () =>
- {
- Dictionary results = await ProcessScreenshot();
-
- if (results.Count == 0)
- {
- return;
- }
- else
- {
- string alarmText = string.Empty;
-
- foreach (Result result in results.Values)
- {
- alarmText += Environment.NewLine;
- alarmText += $"{Environment.NewLine}Domain: {result.Domain}";
- alarmText += $"{Environment.NewLine}Type: {result.Type}";
- alarmText += $"{Environment.NewLine}TrustRating: {result.TrustRating}";
- alarmText += $"{Environment.NewLine}Followed: {result.Followed}";
- alarmText += $"{Environment.NewLine}Source: {result.Source}";
- }
-
- MessageBox.Show(alarmText.Trim(), "Alarm!", MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);
- }
- }).ContinueWith(t => Run());
- }
-
- private int count = 0;
-
- private async Task> ProcessScreenshot()
- {
- count++;
- Debug.WriteLine(count);
-
- Rectangle rect = new Rectangle(Cursor.Position.X - 300, Cursor.Position.Y - 300, 600, 600);
- Bitmap bitmap = new Bitmap(rect.Width, rect.Height, PixelFormat.Format32bppArgb);
- Graphics g = Graphics.FromImage(bitmap);
- g.CopyFromScreen(rect.Left, rect.Top, 0, 0, bitmap.Size, CopyPixelOperation.SourceCopy);
-
- string resultText;
-
- IronTesseract? ocr = new IronTesseract();
-
- using OcrInput? input = new OcrInput(bitmap);
-
- // Fast Dictionary
- ocr.Language = OcrLanguage.EnglishFast;
-
- // Latest Engine
- ocr.Configuration.TesseractVersion = TesseractVersion.Tesseract5;
-
- //AI OCR only without font analysis
- ocr.Configuration.EngineMode = TesseractEngineMode.LstmOnly;
-
- //Turn off unneeded options
- ocr.Configuration.ReadBarCodes = false;
- ocr.Configuration.RenderSearchablePdfsAndHocr = false;
-
- // Assume text is laid out neatly in an orthagonal document
- ocr.Configuration.PageSegmentationMode = TesseractPageSegmentationMode.SparseText;
-
- OcrResult? result = ocr.Read(input);
- resultText = result.Text;
- Debug.WriteLine(resultText);
- return await ProcessMatches(resultText);
- }
-
- private async Task> ProcessMatches(string text)
- {
- string newDomains = string.Empty;
- Dictionary results = new();
- MatchCollection matchCollection = Regex.Matches(text.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)
- {
- if (domainCache.ContainsKey(match.Value))
- {
- results.Add(match.Value, domainCache[match.Value]);
- continue;
- }
-
- newDomains += $"{match.Value} ";
- }
- if (!string.IsNullOrWhiteSpace(newDomains))
- {
- HttpClient httpClient = new HttpClient();
- httpClient.DefaultRequestHeaders.Add("User-Agent", "FraudCapturer - (coming soon)");
-
- ReqestBody reqestBody = new ReqestBody()
- {
- Message = newDomains
- };
-
- HttpContent httpContent = new StringContent(JsonSerializer.Serialize(reqestBody), Encoding.UTF8, "application/json");
-
- HttpResponseMessage responseMessage = await httpClient.PostAsync("https://anti-fish.bitflow.dev/check", httpContent);
-
- string resultString = await responseMessage.Content.ReadAsStringAsync();
- ResultBody? resultBody = JsonSerializer.Deserialize(resultString);
-
- if (resultBody is null || resultBody.Matches is null || resultBody.Match == false)
- {
- return results;
- }
-
- foreach (Result result in resultBody.Matches)
- {
- if (result?.Domain is null)
- {
- continue;
- }
-
- domainCache.Add(result.Domain, result);
- results.Add(result.Domain, result);
- }
- }
-
- return results;
- }
-}
\ No newline at end of file
diff --git a/FraudCapturer/PackageHelper.cs b/FraudCapturer/PackageHelper.cs
new file mode 100644
index 0000000..b4e824b
--- /dev/null
+++ b/FraudCapturer/PackageHelper.cs
@@ -0,0 +1,32 @@
+using PacketDotNet;
+
+using System.Text;
+
+namespace FraudCapturer;
+
+internal static class PackageHelper
+{
+ public static string GetPayloadAsString(this TransportPacket transportPacket)
+ {
+ byte[] data = transportPacket.PayloadData;
+ string bytes = "";
+ string ascii = "";
+
+ for (int i = 1; i <= data.Length; i++)
+ {
+ // add the current byte to the bytes hex string
+ bytes += data[i - 1].ToString("x").PadLeft(2, '0') + " ";
+
+ // add the current byte to the asciiBytes array for later processing
+ if (data[i - 1] < 0x21 || data[i - 1] > 0x7e)
+ {
+ ascii += ".";
+ }
+ else
+ {
+ ascii += Encoding.ASCII.GetString(new[] { data[i - 1] });
+ }
+ }
+ return ascii.Trim('.');
+ }
+}
\ No newline at end of file
diff --git a/FraudCapturer/Program.cs b/FraudCapturer/Program.cs
new file mode 100644
index 0000000..2fb7942
--- /dev/null
+++ b/FraudCapturer/Program.cs
@@ -0,0 +1,265 @@
+
+using PacketDotNet;
+
+using SharpPcap;
+
+using System.Net;
+
+namespace FraudCapturer;
+
+///
+/// Example showing packet manipulation
+///
+public class Program
+{
+ public const string AppName = "FraudCapturer";
+ public const string IpStorePath = "ipAdresses.txt";
+
+ private static DateTime lastCacheClear;
+ private static string lastDomain = string.Empty;
+
+ private static readonly List capturedIpsCache = new();
+ private static readonly Dictionary capturedDomainsCache = new();
+
+ ///
+ /// The main entry point for the application.
+ ///
+ private static void Main()
+ {
+ Console.OutputEncoding = System.Text.Encoding.UTF8;
+ // Print SharpPcap version
+ Console.WriteLine(AppName);
+ Console.WriteLine();
+
+ // Retrieve the device list
+ CaptureDeviceList devices = CaptureDeviceList.Instance;
+
+ // If no devices were found print an error
+ if (devices.Count < 1)
+ {
+ Console.WriteLine("No devices were found on this machine");
+ return;
+ }
+
+ Console.WriteLine("The following devices are available on this machine:");
+ Console.WriteLine("----------------------------------------------------");
+ Console.WriteLine();
+
+ int i = 0;
+
+ // Print out the available devices
+ foreach (ILiveDevice dev in devices)
+ {
+ Console.WriteLine("{0}) {1}", i, dev.Description);
+ i++;
+ }
+
+ Console.WriteLine();
+
+ int choice = -1;
+ while (choice < 0 || choice >= devices.Count)
+ {
+ Console.Write("-- Please choose a device to capture: ");
+ bool valid = int.TryParse(Console.ReadLine(), out choice);
+
+ if (!valid)
+ {
+ choice = -1;
+ }
+ }
+
+ ICaptureDevice? device = null;
+
+ device = devices[choice];
+
+ //Register our handler function to the 'packet arrival' event
+ device.OnPacketArrival +=
+ new PacketArrivalEventHandler(Device_OnPacketArrival);
+
+ // Open the device for capturing
+ device.Open();
+
+ Console.WriteLine();
+ Console.WriteLine("-- Listening on {0}, hit 'Ctrl-C' to exit...", device.Description);
+
+ // Start capture 'INFINTE' number of packets
+ device.Capture();
+
+ // Close the pcap device
+ // (Note: this line will never be called since
+ // we're capturing infinite number of packets
+ device.Close();
+ }
+
+ private static void Device_OnPacketArrival(object sender, PacketCapture e)
+ {
+ RawCapture rawPacket = e.GetPacket();
+ Packet packet = Packet.ParsePacket(rawPacket.LinkLayerType, rawPacket.Data);
+ if (packet is EthernetPacket)
+ {
+ IPPacket ip = packet.Extract();
+ if (ip != null)
+ {
+ IPAddress remoteIpAddress;
+ string direction;
+
+ if (IpHelper.IsLocalIpAddress(ip.SourceAddress.ToString()))
+ {
+ remoteIpAddress = ip.DestinationAddress;
+ direction = "Out";
+ }
+ else if (IpHelper.IsLocalIpAddress(ip.DestinationAddress.ToString()))
+ {
+ remoteIpAddress = ip.SourceAddress;
+ direction = "In";
+ }
+ else
+ {
+ return;
+ }
+
+ if (DateTime.Now - lastCacheClear >= new TimeSpan(0, 10, 0))
+ {
+ lastCacheClear = DateTime.Now;
+ capturedIpsCache.Clear();
+ capturedDomainsCache.Clear();
+ File.WriteAllText(IpStorePath, string.Empty);
+ Console.WriteLine("Cleared cache");
+ }
+
+ CheckDns(packet, remoteIpAddress, direction);
+
+ if (capturedIpsCache.Contains(remoteIpAddress.ToString()))
+ {
+ 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());
+
+ CheckIpAddress(remoteIpAddress, direction);
+ }
+ }
+ }
+
+ private static void CheckIpAddress(IPAddress remoteIpAddress, string direction)
+ {
+ IpInfo? ipInfo = IpHelper.GetIpReputation(remoteIpAddress);
+
+ if (IpHelper.IsInternalIpAddress(remoteIpAddress.ToString()))
+ {
+ Console.ForegroundColor = ConsoleColor.Cyan;
+ Console.WriteLine($"[{direction}] [Internal] {remoteIpAddress}");
+ }
+ else if (ipInfo is not null)
+ {
+ bool block = false;
+ if (ipInfo.Risk >= 67)
+ {
+ FirewallHelper.BlockIp(remoteIpAddress);
+ Console.ForegroundColor = ConsoleColor.Red;
+ block = true;
+ }
+ else if (ipInfo.Risk >= 34 && ipInfo.IsProxy)
+ {
+ FirewallHelper.BlockIp(remoteIpAddress);
+ Console.ForegroundColor = ConsoleColor.DarkYellow;
+ block = true;
+ }
+ else if (ipInfo.IsProxy && ipInfo.Type != "VPN")
+ {
+ FirewallHelper.BlockIp(remoteIpAddress);
+ Console.ForegroundColor = ConsoleColor.DarkYellow;
+ block = true;
+ }
+ else
+ {
+ Console.ForegroundColor = ConsoleColor.Green;
+ }
+
+ Console.WriteLine($"[{direction}] [Provider: {ipInfo.Provider}] [Risk: {ipInfo.Risk}] [Proxy: {ipInfo.IsProxy}] [Type: {ipInfo.Type}] [Block: {block}] {remoteIpAddress}");
+ }
+ else
+ {
+ Console.ForegroundColor = ConsoleColor.Magenta;
+ Console.WriteLine($"[{direction}] [Invalid] {remoteIpAddress}");
+ }
+ Console.ResetColor();
+ }
+
+ private static void CheckDns(Packet packet, IPAddress remoteIpAddress, string direction)
+ {
+ TransportPacket transportPacket = packet.Extract();
+ transportPacket ??= packet.Extract();
+
+ if (transportPacket != null && transportPacket.DestinationPort == 53)
+ {
+ string[] domains = DomainHelper.GetDomainsFromDnsReqest(transportPacket);
+ foreach (string domain in domains)
+ {
+ DomainInfo? domainInfo;
+ bool block = false;
+
+ if (capturedDomainsCache.ContainsKey(domain))
+ {
+ domainInfo = capturedDomainsCache[domain];
+ }
+ else
+ {
+ domainInfo = DomainHelper.GetDomainReputation(domain);
+ }
+
+ if (domainInfo is null)
+ {
+ Console.ForegroundColor = ConsoleColor.Magenta;
+ if (lastDomain != domain)
+ {
+ lastDomain = domain;
+ Console.WriteLine($"[{direction}] [Dns] [Invalid] [Domain: {domain}] {remoteIpAddress}");
+ }
+ Console.ResetColor();
+ continue;
+ }
+
+ if (domainInfo.IsMatch == false)
+ {
+ Console.ForegroundColor = ConsoleColor.Green;
+ if (lastDomain != domain)
+ {
+ lastDomain = domain;
+ Console.WriteLine($"[{direction}] [Dns] [Domain: {domain}] [Type: Undetected] [Block: {block}] {remoteIpAddress}");
+ }
+ Console.ResetColor();
+ continue;
+ }
+
+ if (domainInfo.TrustRating >= 0.9)
+ {
+ FirewallHelper.BlockIp(domainInfo.IpAddress);
+ Console.ForegroundColor = ConsoleColor.Red;
+ block = true;
+ }
+ else if (domainInfo.TrustRating >= 0.5)
+ {
+ FirewallHelper.BlockIp(domainInfo.IpAddress);
+ Console.ForegroundColor = ConsoleColor.DarkYellow;
+ block = true;
+ }
+ else
+ {
+ Console.ForegroundColor = ConsoleColor.Green;
+ }
+
+ if (lastDomain != domain)
+ {
+ lastDomain = domain;
+ Console.WriteLine($"[{direction}] [Dns] [Domain: {domain}] [Type: {domainInfo.Type}] [Source: {domainInfo.Source}] [Source Trust: {domainInfo.TrustRating * 100d}] [Block: {block}] {remoteIpAddress}");
+ }
+
+ Console.ResetColor();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/FraudCapturer/ReqestBody.cs b/FraudCapturer/ReqestBody.cs
deleted file mode 100644
index 0ddc9c3..0000000
--- a/FraudCapturer/ReqestBody.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using System.Text.Json.Serialization;
-
-namespace FraudCapturer;
-
-internal class ReqestBody
-{
- [JsonPropertyName("message")]
- public string? Message { get; set; }
-}
\ No newline at end of file
diff --git a/FraudCapturer/Result.cs b/FraudCapturer/Result.cs
deleted file mode 100644
index 05aab3e..0000000
--- a/FraudCapturer/Result.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using System.Text.Json.Serialization;
-
-namespace FraudCapturer;
-
-internal class Result
-{
- [JsonPropertyName("followed")]
- public bool Followed { get; set; }
-
- [JsonPropertyName("domain")]
- public string? Domain { get; set; }
-
- [JsonPropertyName("source")]
- public string? Source { get; set; }
-
- [JsonPropertyName("type")]
- public string? Type { get; set; }
-
- [JsonPropertyName("trust_rating")]
- public double TrustRating { get; set; }
-}
\ No newline at end of file
diff --git a/FraudCapturer/ResultBody.cs b/FraudCapturer/ResultBody.cs
deleted file mode 100644
index 47aae26..0000000
--- a/FraudCapturer/ResultBody.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using System.Collections.Generic;
-using System.Text.Json.Serialization;
-
-namespace FraudCapturer;
-
-internal class ResultBody
-{
- [JsonPropertyName("match")]
- public bool Match { get; set; }
-
- [JsonPropertyName("matches")]
- public List? Matches { get; set; }
-}
\ No newline at end of file
diff --git a/FraudCapturer/ScreenshotHandler.cs b/FraudCapturer/ScreenshotHandler.cs
deleted file mode 100644
index 57251ce..0000000
--- a/FraudCapturer/ScreenshotHandler.cs
+++ /dev/null
@@ -1,5 +0,0 @@
-namespace FraudCapturer;
-
-internal class ScreenshotHandler
-{
-}
\ No newline at end of file