This commit is contained in:
ApfelTeeSaft
2024-11-04 10:22:35 +01:00
parent 89e76d5a0b
commit ae92d5acc7
13 changed files with 448 additions and 0 deletions
+25
View File
@@ -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
+9
View File
@@ -0,0 +1,9 @@
<Application x:Class="MemScan.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MemScan"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>
+14
View File
@@ -0,0 +1,14 @@
using System.Configuration;
using System.Data;
using System.Windows;
namespace MemScan
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
}
+10
View File
@@ -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)
)]
+9
View File
@@ -0,0 +1,9 @@
<Window x:Class="MemScan.EditStringWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Edit String" Height="200" Width="400">
<Grid>
<TextBox x:Name="StringTextBox" Width="300" Height="30" Margin="10" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Button Content="Save" Width="100" Height="30" Margin="10" HorizontalAlignment="Center" VerticalAlignment="Bottom" Click="SaveButton_Click"/>
</Grid>
</Window>
+43
View File
@@ -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.");
}
}
}
}
+41
View File
@@ -0,0 +1,41 @@
<Window x:Class="MemScan.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:services="clr-namespace:MemScan.Services"
Title="Process List" Height="500" Width="600">
<Window.Resources>
<services:EmptyStringToVisibilityConverter x:Key="EmptyStringToVisibilityConverter"/>
</Window.Resources>
<Grid>
<Grid>
<TextBox x:Name="ProcessSearchBox" Width="200" Height="30" Margin="10,10,10,0" VerticalAlignment="Top"
TextChanged="ProcessSearchBox_TextChanged"/>
<TextBlock Text="Search Processes..." Margin="14,14,0,0" VerticalAlignment="Top" TextAlignment="Center"
Foreground="Gray" IsHitTestVisible="False"
Visibility="{Binding Text.Length, ElementName=ProcessSearchBox, Converter={StaticResource EmptyStringToVisibilityConverter}}"/>
</Grid>
<ListView x:Name="ProcessListView" Margin="10,50,10,10" Height="350"
VerticalAlignment="Top" SelectionChanged="ProcessListView_SelectionChanged">
<ListView.View>
<GridView>
<GridViewColumn Header="Icon" Width="50">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Image Source="{Binding Icon}" Width="32" Height="32"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Process Name" DisplayMemberBinding="{Binding Name}" Width="250"/>
<GridViewColumn Header="PID" DisplayMemberBinding="{Binding PID}" Width="100"/>
</GridView>
</ListView.View>
</ListView>
<Button x:Name="ScanButton" Content="Scan for Strings" Width="150" Height="30"
HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="10"
IsEnabled="False" Click="ScanButton_Click"/>
</Grid>
</Window>
+145
View File
@@ -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<ProcessInfo> allProcesses;
public MainWindow()
{
InitializeComponent();
LoadProcesses();
}
private void LoadProcesses()
{
allProcesses = new List<ProcessInfo>();
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);
}
}
+15
View File
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Drawing.Common" Version="8.0.10" />
</ItemGroup>
</Project>
+43
View File
@@ -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;
}
}
}
+22
View File
@@ -0,0 +1,22 @@
<Window x:Class="MemScan.ResultsWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:services="clr-namespace:MemScan.Services"
Title="Scan Results" Height="400" Width="600">
<Window.Resources>
<services:EmptyStringToVisibilityConverter x:Key="EmptyStringToVisibilityConverter"/>
</Window.Resources>
<Grid>
<Grid>
<TextBox x:Name="ResultsSearchBox" Width="200" Height="30" Margin="10,10,10,0" VerticalAlignment="Top"
TextChanged="ResultsSearchBox_TextChanged" VerticalContentAlignment="Center"/>
<TextBlock Text="Search Results..." Margin="14,14,0,0" VerticalAlignment="Top"
Foreground="Gray" IsHitTestVisible="False"
Visibility="{Binding Text.Length, ElementName=ResultsSearchBox, Converter={StaticResource EmptyStringToVisibilityConverter}}"/>
</Grid>
<ListBox x:Name="ResultsListBox" Margin="10,50,10,10" VerticalAlignment="Stretch"
MouseDoubleClick="ResultsListBox_MouseDoubleClick"/>
</Grid>
</Window>
+48
View File
@@ -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();
}
}
}
}
}
+24
View File
@@ -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();
}
}
}