写了一个内存地址特征码搜索工具
实现了
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
- 下一篇: 匹配路径特征的文件搜索