写了一个内存地址特征码搜索工具
实现了
1.搜索汇编上的地址
2.搜索匹配特征的内存地址
3.搜索到的地址再做+法计算,还没做读取内存指针,是直接16进制加法
4.支持通配符(就是用正则表达式来做的)
现在还不是很完善,因为一边学一边做,总觉得欠缺了啥,一些地方还得优化,先上图,过几天放源码
搜索界面:
搜索结果图:搜索运用了线程同时处理,用时单位是毫秒
生成规则界面:
这一版本的操作类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.ComponentModel;
using System.Globalization;
using System.Reflection;
public class Scan
{
/// <summary>
/// 所有需要扫描的列表
/// </summary>
private List<ScanCode> _scode;
public List<ScanCode> scode
{
get { return this._scode; }
set { this._scode = value; }
}
/// <summary>
/// 打开文件的byte[]数组
/// </summary>
private byte[] _fileBytes;
public byte[] fileBytes
{
get { return this._fileBytes; }
}
/// <summary>
/// 打开文件的16进制全字符串
/// </summary>
private string _fileHex;
public string fileHex
{
get { return this._fileHex; }
}
/// <summary>
/// 文件流的起始十六进制
/// </summary>
private int _beginHex;
public int beginHex
{
get { return this._beginHex; }
set { this._beginHex = value; }
}
/// <summary>
/// 文件缓冲区大小
/// </summary>
private int _bufferSize;
public int bufferSize
{
get { return this._beginHex; }
set { this._beginHex = value; }
}
/// <summary>
/// 当前扫描线程数
/// </summary>
private int _threadCount;
public int threadCount
{
get { return this._threadCount; }
set { this._threadCount = value; }
}
/// <summary>
/// 初始化
/// </summary>
/// <param name="filePath">打开应用程序文件</param>
/// <param name="beginHex">应用程序起始地址</param>
public Scan(string filePath, int beginHex)
{
this._beginHex = beginHex;
this._scode = new List<ScanCode>();
//打开文件
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
int fsLength = (int)fs.Length;
//读取文件的byte[] 耗时约 1000ms 内
fs.Seek(0, SeekOrigin.Begin);
this._fileBytes = new byte[fsLength];
fs.Read(this._fileBytes, 0, fsLength);
//通过byte[]转成string的16进制 耗时约 7M = 20s
fs.Seek(0, SeekOrigin.Begin);
int atIndex;
List<string> tmpHex = new List<string>();
atIndex = fs.ReadByte();
while (atIndex != -1)
{
tmpHex.Add(string.Format("{0:X2} ", atIndex));
atIndex = fs.ReadByte();
}
this._fileHex = string.Join("", tmpHex).Replace(" ", "");
this._bufferSize = 4096;
}
}
/// <summary>
/// 启动扫描
/// </summary>
public void Start()
{
this.threadCount = 0;
foreach (ScanCode c in this.scode)
{
//取自定义的开始位置和结束位置中的16进制//
if (c.start < 0 || c.end < c.start)
c.hexString = this._fileHex;
else
c.hexString = this._fileHex.Substring(c.start - this._beginHex, c.end - c.start);
c.callback = CallBack;
c.beginhex = this._beginHex;
c.buffersize = this._bufferSize;
Thread t = new Thread(new ThreadStart(c.Scan));
t.Start();
threadCount++;
}
}
//线程回调方法
private void CallBack()
{
threadCount--;
}
}
public class ScanCode
{
public delegate void CallBackDelegate();
#region 属性
/// <summary>
/// 名称
/// </summary>
[DisplayNameAttribute("名称"), CategoryAttribute("重要属性"), ReadOnlyAttribute(false), DescriptionAttribute("便于您识别的名称命名")]
public string name { get; set; }
/// <summary>
/// 实际变量
/// </summary>
[DisplayNameAttribute("变量名"), CategoryAttribute("重要属性"), DescriptionAttribute("最终格式化的变量名称")]
public string variable { get; set; }
/// <summary>
/// 输入的特征码
/// </summary>
[DisplayNameAttribute("特征码"), CategoryAttribute("重要属性"), DescriptionAttribute("特征码,通配符请用*号代替")]
public string code { get; set; }
/// <summary>
/// 用于搜索的特征码
/// </summary>
[BrowsableAttribute(false)]
public string scancode { get { return formatCode(this.code).ToUpper(); } }
/// <summary>
/// 代表程序的内存起始位
/// </summary>
[BrowsableAttribute(false)]
public int beginhex { get; set; }
/// <summary>
/// 代码程序的内存缓冲区
/// </summary>
[BrowsableAttribute(false)]
public int buffersize { get; set; }
/// <summary>
/// 扫描开始值 16进制
/// </summary>
[DisplayNameAttribute("A扫描开始段"), CategoryAttribute("地址设置"), DescriptionAttribute("代表程序从您设置的地址开始扫描")]
[TypeConverter(typeof(HexConverter))]
public int start { get; set; }
/// <summary>
/// 扫描结束值 16进制
/// </summary>
[DisplayNameAttribute("B扫描结束段"), CategoryAttribute("地址设置"), DescriptionAttribute("代表程序开始扫描到您设置的地址结束")]
[TypeConverter(typeof(HexConverter))]
public int end { get; set; }
/// <summary>
/// 返回值
/// </summary>
///[BrowsableAttribute(false)]
[DisplayNameAttribute("结果值"), DescriptionAttribute("制作时候不需要填写")]
public string value { get; set; }
/// <summary>
/// 说明
/// </summary>
[DisplayNameAttribute("说明"), CategoryAttribute("其他"), DescriptionAttribute("简要说明或备注,也作为注释的功能")]
public string explain { get; set; }
/// <summary>
/// 偏移量
/// </summary>
[DisplayNameAttribute("附加属性"), CategoryAttribute("附加"), DescriptionAttribute("一些附加的应用属性")]
[TypeConverterAttribute(typeof(ScanAdditionConverter))]
public ScanAddition append { get; set; }
/// <summary>
/// 扫描用时
/// </summary>
[DisplayNameAttribute("扫描用时"), DescriptionAttribute("制作时候不需要填写")]
public int time { get; set; }
/// <summary>
/// 扫描类型
/// </summary>
[DisplayNameAttribute("扫描方式"), CategoryAttribute("重要属性"), DefaultValue(typeof(ScanType), "Address"), DescriptionAttribute("这个特征码所要扫描的地址类型")]
public ScanType type { get; set; }
/// <summary>
/// 是否可用
/// </summary>
[DisplayNameAttribute("是否生效"), CategoryAttribute("其他"), DefaultValue(true), DescriptionAttribute("失效时不会被载入扫描列队")]
public bool status { get; set; }
/// <summary>
/// 搜索段
/// </summary>
[BrowsableAttribute(false)]
public string hexString { get; set; }
/// <summary>
/// 搜索结果匹配项
/// </summary>
[DisplayNameAttribute("匹配总数"), DescriptionAttribute("制作时候不需要填写")]
public int matchCount { get; set; }
/// <summary>
/// 线程结束回调
/// </summary>
[BrowsableAttribute(false)]
public CallBackDelegate callback { get; set; }
#endregion
#region 方法
/// <summary>
/// 格式化特征码中的*号为正则表达式的符号
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
private string formatCode(string value)
{
string r = "";
int index = 0;
for (int i = 0; i < value.Length; i++)
{
if (value[i] != "*")
{
if (index > 0)
{
r += "(.{" + index.ToString() + "})";
index = 0;
}
r += value[i];
}
else
index++;
}
return r;
}
/// <summary>
/// 简易的16进制2/2翻转
/// </summary>
/// <param name="value"></param>
/// <param name="bit"></param>
/// <returns></returns>
private string turnHex(string value, int bit)
{
string r = "";
int sbit = value.Length;
while (sbit > 0)
{
r += value.Substring(sbit - bit, bit);
sbit = sbit - bit;
}
return r;
}
#endregion
public ScanCode()
{ }
public ScanCode(string c)
{
string[] t = c.Split("|");
name = t[0].TrimStart("/");
variable = t[1];
code = t[2];
start = Convert.ToInt32(t[3], 16);
end = Convert.ToInt32(t[4], 16);
type = (ScanType)Convert.ToInt32(t[5]);
append = new ScanAddition(t[6]);
explain = t[7];
status = c.StartsWith("//") ? false : true;
}
public override string ToString()
{
return string.Format("{0}{1}|{2}|{3}|{4}|{5}|{6}|{7}|{8}",
status ? "" : "//",
name,
variable,
code,
string.Format("{0:X2}", start),
string.Format("{0:X2}", end),
(int)type,
append.ToString(),
explain);
}
public void Scan()
{
Stopwatch cl = new Stopwatch();
cl.Start();
Regex rx = new Regex(this.scancode);
MatchCollection matches = rx.Matches(this.hexString);
this.matchCount = matches.Count;
//string.Format("找到 {0} 匹配项:
", matches.Count);
int m = 1;
foreach (Match match in matches)
{
//string.Format("
匹配项 {0} 的详情:
", m.ToString());
GroupCollection groups = match.Groups;
int i = 0;
foreach (Group v in groups)
{
//string.Format("值{2}: {0} 位于坐标 {1}
", v.Value, v.Index, i.ToString());
switch (this.type)
{
case ScanType.Address:
if (m == this.append.matchItem && i == this.append.matchPoint)
this.value = turnHex(v.Value, 2).TrimStart("0");
break;
case ScanType.Call:
if (m == this.append.matchItem && i == 0)
{
if (this.append.OffsetPosition == ScanOffset.Up)
this.value = (this.beginhex + (this.start - this.beginhex) + v.Index - this.buffersize - 1 + this.append.OffsetQTY).ToString("X2");
else
this.value = (this.beginhex + (this.start - this.beginhex) + v.Index + v.Length - this.buffersize - 1 + this.append.OffsetQTY).ToString("X2");
}
break;
case ScanType.Calculate:
if (m == this.append.matchItem && i == this.append.matchPoint)
this.value = (Convert.ToInt32(turnHex(v.Value, 2), 16) + this.append.CalcPointer).ToString("X2");
break;
}
i++;
}
m++;
}
cl.Stop();
this.time = Convert.ToInt32(cl.ElapsedMilliseconds);
CallBackDelegate cb = this.callback as CallBackDelegate;
cb();
}
}
public class ScanAddition
{
#region 属性
[DisplayNameAttribute("匹配项"), DescriptionAttribute("地址和CALL的共用参数,意思:取结果集中的第几个匹配项"), DefaultValue(1)]
public int matchItem { get; set; }
[DisplayNameAttribute("匹配位"), DescriptionAttribute("地址的参数,意思:取结果中的第几个通配符得出的结果,0为完全结果"), DefaultValue(1)]
public int matchPoint { get; set; }
[DisplayNameAttribute("偏移位"), DescriptionAttribute("CALL的参数,意思:从结果的地址上方还是下方开始计算偏移量"), DefaultValue(typeof(ScanOffset), "Up")]
public ScanOffset OffsetPosition { get; set; }
[DisplayNameAttribute("偏移量"), DescriptionAttribute("CALL的参数,意思:取值做最后的偏移量地址,16进制,整数"), DefaultValue(0)]
[TypeConverter(typeof(HexConverter))]
public int OffsetQTY { get; set; }
[DisplayNameAttribute("计算指针"), DescriptionAttribute("组合的参数,意思:Address + this.value"), DefaultValue(0)]
[TypeConverter(typeof(HexConverter))]
public int CalcPointer { get; set; }
#endregion
public ScanAddition() { OffsetPosition = ScanOffset.Up; matchPoint = 1; matchItem = 1; }
public ScanAddition(string value)
{
OffsetPosition = ScanOffset.Up; matchPoint = 1; matchItem = 1;
string[] arr = value.Split("~");
if (arr.Length == 5)
{
matchItem = Convert.ToInt32(arr[0]);
matchPoint = Convert.ToInt32(arr[1]);
OffsetPosition = (ScanOffset)Convert.ToInt32(arr[2]);
OffsetQTY = Convert.ToInt32(arr[3], 16);
CalcPointer = Convert.ToInt32(arr[4], 16);
}
}
public override string ToString()
{
return string.Format("{0}~{1}~{2}~{3}~{4}", matchItem.ToString(), matchPoint.ToString(), (int)OffsetPosition, string.Format("{0:X2}", OffsetQTY), string.Format("{0:X2}", CalcPointer));
}
}
/// <summary>
/// 扫描附加属性转换器
/// </summary>
public class ScanAdditionConverter : ExpandableObjectConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context,
System.Type destinationType)
{
if (destinationType == typeof(ScanAddition))
return true;
return base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture,
object value, System.Type destinationType)
{
if (destinationType == typeof(System.String) &&
value is ScanAddition)
{
ScanAddition so = (ScanAddition)value;
return "";
}
return base.ConvertTo(context, culture, value, destinationType);
}
public override bool CanConvertFrom(ITypeDescriptorContext context, System.Type sourceType)
{
if (sourceType == typeof(string))
return true;
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value is string)
{
try
{
string s = (string)value;
}
catch
{
throw new ArgumentException(
"无法将“" + (string)value +
"”转换为 ScanAddition 类型");
}
}
return base.ConvertFrom(context, culture, value);
}
}
/// <summary>
/// 扫描类型枚举
/// </summary>
public enum ScanType
{
[DescriptionAttribute("地址")]
Address = 1,
[DescriptionAttribute("CALL")]
Call = 2,
[DescriptionAttribute("计算")]
Calculate = 3,
}
/// <summary>
/// CALL扫描结果取值方式
/// </summary>
public enum ScanOffset
{
Up = 1,
Down = 2,
}
/// <summary>
/// 16进制属性值转换器
/// </summary>
public class HexConverter : Int32Converter
{
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
if (!string.IsNullOrWhiteSpace(value.ToString()))
return GetInt(value);
return base.ConvertFrom(context, culture, value);
}
public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
{
if (!string.IsNullOrWhiteSpace(value.ToString()))
return string.Format("{0:X2}", value);
return base.ConvertTo(context, culture, value, destinationType);
}
public static int GetInt(object value)
{
return Convert.ToInt32(value.ToString(), 16);
}
}
小弟不才,如果更好的优化方案,请大虾们批评指证。
源码包和DEMO届时再放!
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。
- 上一篇: tp基本的增删改查的操作demo
- 下一篇: 匹配路径特征的文件搜索
