diff --git a/MemScan.sln b/MemScan.sln
new file mode 100644
index 0000000..ceee094
--- /dev/null
+++ b/MemScan.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.11.35327.3
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MemScan", "MemScan\MemScan.csproj", "{2DFC61BC-9826-4593-8A83-10C3B65851CD}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {2DFC61BC-9826-4593-8A83-10C3B65851CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2DFC61BC-9826-4593-8A83-10C3B65851CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2DFC61BC-9826-4593-8A83-10C3B65851CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2DFC61BC-9826-4593-8A83-10C3B65851CD}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {675AC01E-B62E-4DAA-BA58-7A5D1D81C140}
+ EndGlobalSection
+EndGlobal
diff --git a/MemScan/App.xaml b/MemScan/App.xaml
new file mode 100644
index 0000000..3634926
--- /dev/null
+++ b/MemScan/App.xaml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/MemScan/App.xaml.cs b/MemScan/App.xaml.cs
new file mode 100644
index 0000000..ba43855
--- /dev/null
+++ b/MemScan/App.xaml.cs
@@ -0,0 +1,14 @@
+using System.Configuration;
+using System.Data;
+using System.Windows;
+
+namespace MemScan
+{
+ ///
+ /// Interaction logic for App.xaml
+ ///
+ public partial class App : Application
+ {
+ }
+
+}
diff --git a/MemScan/AssemblyInfo.cs b/MemScan/AssemblyInfo.cs
new file mode 100644
index 0000000..b0ec827
--- /dev/null
+++ b/MemScan/AssemblyInfo.cs
@@ -0,0 +1,10 @@
+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/MemScan/EditStringWindow.xaml b/MemScan/EditStringWindow.xaml
new file mode 100644
index 0000000..deabb80
--- /dev/null
+++ b/MemScan/EditStringWindow.xaml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MemScan/EditStringWindow.xaml.cs b/MemScan/EditStringWindow.xaml.cs
new file mode 100644
index 0000000..b3c07ab
--- /dev/null
+++ b/MemScan/EditStringWindow.xaml.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Windows;
+
+namespace MemScan
+{
+ public partial class EditStringWindow : Window
+ {
+ private IntPtr address;
+ private Process process;
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ private static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out int lpNumberOfBytesWritten);
+
+ public EditStringWindow(string value, IntPtr address, Process process)
+ {
+ InitializeComponent();
+ StringTextBox.Text = value;
+ this.address = address;
+ this.process = process;
+ }
+
+ private void SaveButton_Click(object sender, RoutedEventArgs e)
+ {
+ string newValue = StringTextBox.Text;
+
+ byte[] buffer = Encoding.UTF8.GetBytes(newValue + "\0");
+
+ IntPtr processHandle = process.Handle;
+ if (WriteProcessMemory(processHandle, address, buffer, (uint)buffer.Length, out int bytesWritten))
+ {
+ MessageBox.Show("String successfully written to memory.");
+ Close();
+ }
+ else
+ {
+ MessageBox.Show("Failed to write string to memory.");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/MemScan/MainWindow.xaml b/MemScan/MainWindow.xaml
new file mode 100644
index 0000000..5b92f59
--- /dev/null
+++ b/MemScan/MainWindow.xaml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MemScan/MainWindow.xaml.cs b/MemScan/MainWindow.xaml.cs
new file mode 100644
index 0000000..330333f
--- /dev/null
+++ b/MemScan/MainWindow.xaml.cs
@@ -0,0 +1,145 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media.Imaging;
+using System.Runtime.InteropServices;
+using System.Windows.Interop;
+
+namespace MemScan
+{
+ public partial class MainWindow : Window
+ {
+ private List allProcesses;
+
+ public MainWindow()
+ {
+ InitializeComponent();
+ LoadProcesses();
+ }
+
+ private void LoadProcesses()
+ {
+ allProcesses = new List();
+
+ foreach (var process in Process.GetProcesses())
+ {
+ try
+ {
+ allProcesses.Add(new ProcessInfo
+ {
+ Name = process.ProcessName,
+ PID = process.Id,
+ Icon = GetProcessIcon(process)
+ });
+ }
+ catch
+ {
+ }
+ }
+
+ ProcessListView.ItemsSource = allProcesses;
+ }
+
+ private BitmapSource GetProcessIcon(Process process)
+ {
+ try
+ {
+ return IconExtractor.Extract(process.MainModule.FileName);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"Error extracting icon for process {process.ProcessName}: {ex.Message}");
+ return null;
+ }
+ }
+
+ private void ProcessSearchBox_TextChanged(object sender, TextChangedEventArgs e)
+ {
+ string searchText = ProcessSearchBox.Text.ToLower();
+
+ ProcessListView.ItemsSource = allProcesses
+ .Where(p => p.Name.ToLower().Contains(searchText) || p.PID.ToString().Contains(searchText))
+ .ToList();
+ }
+
+ private void ProcessListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ ScanButton.IsEnabled = ProcessListView.SelectedItem != null;
+ }
+
+ private async void ScanButton_Click(object sender, RoutedEventArgs e)
+ {
+ if (ProcessListView.SelectedItem is ProcessInfo selectedProcess)
+ {
+ // var indexingWindow = new IndexingWindow();
+ // indexingWindow.ShowInTaskbar = false;
+ // indexingWindow.Show();
+ // indexingWindow.StartAnimation("Scanning process for strings");
+
+ try
+ {
+ var results = await Task.Run(() =>
+ {
+ var process = Process.GetProcessById(selectedProcess.PID);
+ return (process, MemoryScanner.ScanProcessForStrings(process));
+ });
+
+ var resultsWindow = new ResultsWindow(results.process);
+ resultsWindow.DisplayResults(results.Item2);
+ resultsWindow.Show();
+ }
+ finally
+ {
+ // indexingWindow.StopAnimation("Scan complete");
+ // indexingWindow.Close();
+ }
+ }
+ }
+ }
+
+ public class ProcessInfo
+ {
+ public string Name { get; set; }
+ public int PID { get; set; }
+ public BitmapSource Icon { get; set; }
+ }
+
+ public static class IconExtractor
+ {
+ [DllImport("Shell32.dll", CharSet = CharSet.Auto)]
+ public static extern IntPtr ExtractIcon(IntPtr hInst, string lpszExeFileName, int nIconIndex);
+
+ public static BitmapSource Extract(string path)
+ {
+ IntPtr hIcon = ExtractIcon(IntPtr.Zero, path, 0);
+ if (hIcon == IntPtr.Zero)
+ {
+ return null;
+ }
+
+ using (var icon = System.Drawing.Icon.FromHandle(hIcon))
+ {
+ using (var bmp = icon.ToBitmap())
+ {
+ var bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(
+ bmp.GetHbitmap(),
+ IntPtr.Zero,
+ System.Windows.Int32Rect.Empty,
+ BitmapSizeOptions.FromEmptyOptions());
+
+ DestroyIcon(hIcon);
+
+ return bitmapSource;
+ }
+ }
+ }
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool DestroyIcon(IntPtr hIcon);
+ }
+}
\ No newline at end of file
diff --git a/MemScan/MemScan.csproj b/MemScan/MemScan.csproj
new file mode 100644
index 0000000..e676357
--- /dev/null
+++ b/MemScan/MemScan.csproj
@@ -0,0 +1,15 @@
+
+
+
+ WinExe
+ net8.0-windows
+ enable
+ enable
+ true
+
+
+
+
+
+
+
diff --git a/MemScan/MemoryScanner.cs b/MemScan/MemoryScanner.cs
new file mode 100644
index 0000000..7756a15
--- /dev/null
+++ b/MemScan/MemoryScanner.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace MemScan
+{
+ public static class MemoryScanner
+ {
+ [DllImport("kernel32.dll")]
+ private static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, int dwSize, out int lpNumberOfBytesRead);
+
+ public static List<(string Value, IntPtr Address)> ScanProcessForStrings(Process process)
+ {
+ var results = new List<(string Value, IntPtr Address)>();
+
+ foreach (ProcessModule module in process.Modules)
+ {
+ IntPtr address = module.BaseAddress;
+ long moduleSize = module.ModuleMemorySize;
+
+ for (long i = 0; i < moduleSize; i += 4096)
+ {
+ var buffer = new byte[4096];
+ if (ReadProcessMemory(process.Handle, address + (int)i, buffer, buffer.Length, out int bytesRead))
+ {
+ string text = Encoding.UTF8.GetString(buffer);
+ foreach (var line in text.Split('\0'))
+ {
+ if (!string.IsNullOrWhiteSpace(line) && line.Length >= 4)
+ {
+ results.Add((line, address + (int)i));
+ }
+ }
+ }
+ }
+ }
+
+ return results;
+ }
+ }
+}
\ No newline at end of file
diff --git a/MemScan/ResultsWindow.xaml b/MemScan/ResultsWindow.xaml
new file mode 100644
index 0000000..1fb41bd
--- /dev/null
+++ b/MemScan/ResultsWindow.xaml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MemScan/ResultsWindow.xaml.cs b/MemScan/ResultsWindow.xaml.cs
new file mode 100644
index 0000000..64c3503
--- /dev/null
+++ b/MemScan/ResultsWindow.xaml.cs
@@ -0,0 +1,48 @@
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace MemScan
+{
+ public partial class ResultsWindow : Window
+ {
+ private List<(string Value, IntPtr Address)> allResults;
+ private Process process;
+
+ public ResultsWindow(Process process)
+ {
+ InitializeComponent();
+ this.process = process;
+ }
+
+ public void DisplayResults(List<(string Value, IntPtr Address)> results)
+ {
+ allResults = results.OrderBy(r => r.Value).ToList();
+ ResultsListBox.ItemsSource = allResults.Select(r => r.Value).ToList();
+ }
+
+ private void ResultsSearchBox_TextChanged(object sender, TextChangedEventArgs e)
+ {
+ string searchText = ResultsSearchBox.Text.ToLower();
+ ResultsListBox.ItemsSource = allResults
+ .Where(r => r.Value.ToLower().Contains(searchText))
+ .Select(r => r.Value)
+ .ToList();
+ }
+
+ private void ResultsListBox_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
+ {
+ if (ResultsListBox.SelectedItem is string selectedString)
+ {
+ var result = allResults.FirstOrDefault(r => r.Value == selectedString);
+ if (result.Value != null)
+ {
+ var editWindow = new EditStringWindow(result.Value, result.Address, process);
+ editWindow.Show();
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/MemScan/Services/Utility.cs b/MemScan/Services/Utility.cs
new file mode 100644
index 0000000..d7af7a3
--- /dev/null
+++ b/MemScan/Services/Utility.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Globalization;
+using System.Windows;
+using System.Windows.Data;
+
+namespace MemScan.Services
+{
+ public class EmptyStringToVisibilityConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value is int length)
+ {
+ return length == 0 ? Visibility.Visible : Visibility.Collapsed;
+ }
+ return Visibility.Collapsed;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
\ No newline at end of file