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