Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.IO;
- using System.Linq;
- using System.Runtime.ConstrainedExecution;
- using System.Runtime.InteropServices;
- using System.Security;
- using System.Text;
- using System.Text.RegularExpressions;
- using System.Threading.Tasks;
- namespace FFXIVRadar
- {
- static class FFXIVServerScanner
- {
- private static readonly Dictionary<string, string> PatternDictionary = new Dictionary<string, string>()
- {
- //{ "MACRO", "00015B677465715D" },
- { "CHARACTER", "46465849565F434852??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????ED8C8CEC9DB4EB8490ED8C90ED8380ECA7803134" }
- };
- //private static readonly uint MACRO_START = 0x0012;
- //private static readonly uint MACRO_LEN = 0x0668;
- //private static readonly uint MACRO_LINE = 0x0068;
- //private static readonly uint MACRO_LINELEN = 0x10;
- private static readonly uint CHAR_POS = 0x184;
- private static readonly uint SERVER_POS = 0x204;
- private static readonly Dictionary<string, Regex> RegexDict = new Dictionary<string, Regex>()
- {
- { "MAP",
- new Regex(@"%MAP\(MAP\:([0-9]+),IMG\:([0-9]+),X\:([0-9.]+),Y\:([0-9.]+)(?:,Z\:([0-9.]+)|)\)%", RegexOptions.Compiled) },
- { "ITEM",
- new Regex(@"%ITEM\(NO:([0-9]+)(?:,DISPLAY:([0-9]+)|),HQ:([Tt](?:rue|)|[Ff](?:alse|))\)%", RegexOptions.Compiled) },
- { "HEX",
- new Regex(@"HEX\(([^)]+)\)", RegexOptions.Compiled) }
- };
- private static Process currentProcess = null;
- private static IntPtr currentHandle = IntPtr.Zero;
- private static IntPtr CharPointer = IntPtr.Zero;
- public static Tuple<string, string> Scan(Process ffxivProcess)
- {
- if (currentProcess != null && currentProcess.Id != ffxivProcess.Id)
- {
- CloseHandle(currentHandle);
- currentHandle = IntPtr.Zero;
- }
- if (currentHandle == IntPtr.Zero)
- {
- currentHandle = OpenProcess(0x1F0FFF, false, ffxivProcess.Id);
- currentProcess = ffxivProcess;
- CharPointer = IntPtr.Zero;
- }
- var character = GetCharacter(ffxivProcess, currentHandle);
- var server = GetServerInfo(ffxivProcess, currentHandle);
- return character == null || server == null ? null : Tuple.Create(character, server);
- }
- private static string GetCharacter(Process process, IntPtr handle)
- {
- var chrPtr = CharPointer != IntPtr.Zero ? CharPointer : FindByMainModule(process, handle, PatternDictionary["CHARACTER"]);
- if (chrPtr == IntPtr.Zero) return null;
- CharPointer = chrPtr;
- var chruni = new List<byte>();
- var chr = Read(handle, new IntPtr(chrPtr.ToInt64() + CHAR_POS), 0, 24);
- foreach (var c in chr)
- {
- if (c == 0x00) break;
- chruni.Add(c);
- }
- var text = Encoding.UTF8.GetString(chruni.ToArray());
- Debug.WriteLine("[PID: " + process.Id + " CHARNAME: " + text + "]");
- return text;
- }
- private static string GetServerInfo(Process process, IntPtr handle)
- {
- var chrPtr = CharPointer != IntPtr.Zero ? CharPointer : FindByMainModule(process, handle, PatternDictionary["CHARACTER"]);
- if (chrPtr == IntPtr.Zero) return null;
- CharPointer = chrPtr;
- var chruni = new List<byte>();
- var chr = Read(handle, new IntPtr(chrPtr.ToInt64() + SERVER_POS), 0, 96);
- foreach (var c in chr)
- {
- if (c == 0x00) break;
- chruni.Add(c);
- }
- var text = Encoding.UTF8.GetString(chruni.ToArray());
- Debug.WriteLine(text);
- var sp = text.Split('\n');
- foreach (var e in sp)
- {
- if (e.Contains("서버:"))
- {
- return e.Replace("서버:", "").Trim();
- }
- }
- return null;
- }
- /// <summary>
- /// 메모리 패턴으로 포인트 찾기. 패턴을 지정하지 않은 경우 문자열 값으로 초기화 가능 ///
- /// </summary>
- /// <param name="pattern"></param>
- /// <returns></returns>
- public static IntPtr FindByMainModule(Process process, IntPtr handle, string pattern)
- {
- return FindByMainModule(process, handle, new MemoryPattern(pattern));
- }
- /// <summary>
- /// 메모리 패턴으로 포인트 찾기 ///
- /// </summary>
- /// <param name="mp"></param>
- /// <returns></returns>
- private static IntPtr FindByMainModule(Process process, IntPtr handle, MemoryPattern memoryPattern)
- {
- var ModuleAddr = process.MainModule.BaseAddress;
- var ModuleSize = process.MainModule.ModuleMemorySize;
- var patternBuffer = new byte[memoryPattern.Length];
- var buffer = new byte[0x1000];
- var read = IntPtr.Zero;
- var seek = ModuleAddr;
- var index = 0;
- var readmax = ModuleAddr.ToInt64() + ModuleSize - memoryPattern.Length;
- try
- {
- while (seek.ToInt64() < readmax)
- {
- read = new IntPtr(Math.Min(ModuleSize - (read.ToInt64() + memoryPattern.Length), 0x1000));
- if (ReadProcessMemory(handle, seek, buffer, read, out read))
- {
- index = SearchPattern(buffer, memoryPattern);
- if (index != -1)
- {
- return new IntPtr(seek.ToInt64() + index);
- }
- }
- seek = new IntPtr(seek.ToInt64() + read.ToInt64() - memoryPattern.Length + 1);
- }
- }
- catch (Exception ex)
- {
- Debug.WriteLine(ex);
- }
- return IntPtr.Zero;
- }
- /// <summary>
- /// 패턴을 찾는 함수 (바이트 배열로 직접 찾기) ///
- /// </summary>
- /// <param name="buffer"></param>
- /// <param name="patternArray"></param>
- /// <returns></returns>
- private static int SearchPattern(byte[] buffer, byte?[] patternArray)
- {
- int i, j;
- // buff loop
- for (i = 0; i < buffer.Length - patternArray.Length; i++)
- {
- for (j = 0; j < patternArray.Length; j++)
- if (patternArray[j].HasValue && buffer[i + j] != patternArray[j].Value) // null 이 아니면서 값이 다른 경우 비교를 중지
- break;
- if (j == patternArray.Length) // 끝까지 같았으면 위치 반환
- return i;
- }
- return -1; // 아니면 -1
- }
- /// <summary>
- /// 패턴을 찾는 함수 ///
- /// </summary>
- /// <param name="buffer"></param>
- /// <param name="mp"></param>
- /// <returns></returns>
- private static int SearchPattern(byte[] buffer, MemoryPattern mp)
- {
- return SearchPattern(buffer, mp.ToNullableByteArray());
- }
- /// <summary>
- /// 프로세서의 메모리 영역을 지정해 메모리를 읽어옴 ///
- /// </summary>
- /// <param name="ptr">읽기 시작할 위치</param>
- /// <param name="start">추가값</param>
- /// <param name="length">길이</param>
- /// <returns></returns>
- private static byte[] Read(IntPtr handle, IntPtr ptr, int start, int length)
- {
- var b = new byte[length];
- var size = new IntPtr(length);
- if (!ReadProcessMemory(handle, ptr, b, size, out size))
- {
- Debug.WriteLine("Can't Access Process Memory");
- }
- return b;
- }
- //DLL IMPORT
- [DllImport("kernel32.dll", SetLastError = true)]
- private static extern IntPtr OpenProcess(int AccFlag, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int procID);
- [DllImport("kernel32.dll", SetLastError = true)]
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
- [SuppressUnmanagedCodeSecurity]
- [return: MarshalAs(UnmanagedType.Bool)]
- static extern bool CloseHandle(IntPtr hObject);
- [DllImport("kernel32.dll", SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- private static extern bool ReadProcessMemory(IntPtr proc, IntPtr lpBaseAddress, [Out] byte[] lpBuffer, IntPtr bsize, out IntPtr lpNumberOfBytesRead);
- //
- private class MemoryPattern
- {
- public List<PatternData> Pattern { get; set; }
- public long Length { get; private set; }
- public MemoryPattern(string pattern)
- {
- Pattern = new List<PatternData>();
- var bytearray = new Regex(@"[0-9A-Fa-f]{2}|\*\*|\?\?", RegexOptions.Compiled);
- var array = bytearray.Matches(pattern);
- var tmpbyte = new List<byte>();
- var skiplen = 0;
- Length = array.Count;
- for (var x = 0; x < array.Count; x++)
- {
- Match i = array[x];
- if (i.Value != "??" && i.Value != "**" && skiplen == 0)
- {
- tmpbyte.Add(byte.Parse(i.Value, System.Globalization.NumberStyles.AllowHexSpecifier));
- }
- else if (i.Value != "??" && i.Value != "**" && skiplen > 0)
- {
- var ptn = new PatternData();
- ptn.NextSkipLength = skiplen;
- ptn.Data = tmpbyte.ToArray();
- Pattern.Add(ptn);
- tmpbyte.Clear();
- skiplen = 0;
- tmpbyte.Add(byte.Parse(i.Value, System.Globalization.NumberStyles.AllowHexSpecifier));
- }
- else
- {
- skiplen++;
- }
- }
- var lastpattern = new PatternData();
- lastpattern.NextSkipLength = skiplen;
- lastpattern.Data = tmpbyte.ToArray();
- Pattern.Add(lastpattern);
- tmpbyte.Clear();
- }
- public byte?[] ToNullableByteArray()
- {
- var l = new List<byte?>();
- foreach (var i in Pattern)
- {
- foreach (var b in i.Data)
- l.Add(b);
- if (i.NextSkipLength == 0) continue;
- for (var x = 0; x < i.NextSkipLength; x++)
- l.Add(null);
- }
- return l.ToArray();
- }
- }
- private class PatternData
- {
- public byte[] Data { get; set; }
- public int NextSkipLength { get; set; }
- }
- }
- }
Add Comment
Please, Sign In to add comment