//Get ready to scan the memory for the string value. public void StartScanForString(string stringValue, int maxResults = -1) { //Check if the thread is already defined or not. if (thread != null) { //If the thread is already defined and is Alive, if (thread.IsAlive) { //raise the event that shows that the last scan task is canceled //(because a new task is going to be started as wanted), ScanCanceledEventArgs cancelEventArgs = new ScanCanceledEventArgs(); ScanCanceled(this, cancelEventArgs); //and then abort the alive thread and so cancel last scan task. thread.Abort(); } } //Set the thread object as a new instant of the Thread class and pass //a new ParameterizedThreadStart class object with the needed method passed to it //to run in the new thread. thread = new Thread(new ParameterizedThreadStart(StringScanner)); thread.IsBackground = true; //Start the new thread and set the 32 bit value to look for. ScanThreadParams newParameters = new ScanThreadParams(); newParameters.target = stringValue; newParameters.maxResults = maxResults; thread.Start(newParameters); }
private void StringScanner(object _parameters) { ScanThreadParams parameters = (ScanThreadParams)_parameters; //Get the value out of the object to look for it. string stringValue = (string)parameters.target; byte[] bytes = System.Text.Encoding.ASCII.GetBytes(stringValue); ScanThreadParams newParams = new ScanThreadParams(); newParams.target = bytes; newParams.maxResults = parameters.maxResults; ByteArrayScanner(newParams); }
private void FloatPatternScanner(object _parameters) { ScanThreadParams parameters = (ScanThreadParams)_parameters; List <FloatPatternStep> pattern = (List <FloatPatternStep>)parameters.target; int bytesCount = 4; // only searching for floats foreach (FloatPatternStep step in pattern) { bytesCount += step.byteOffset; } //The difference of scan start point in all loops except first loop, //that doesn't have any difference, is type's Bytes count minus 1. int arraysDifference = 3;// bytesCount - 1; //prealloc buffer byte[] buffer = new byte[ReadStackSize + arraysDifference]; //Define a List object to hold the found memory addresses. List <Int64> finalList = new List <Int64>(); //Open the pocess to read the memory. reader.OpenProcess(); //Create a new instant of the ScanProgressEventArgs class to be used to raise the //ScanProgressed event and pass the percentage of scan, during the scan progress. ScanProgressChangedEventArgs scanProgressEventArgs; Int64 MaxAddress = (Int64)lastAddress; Int64 address = 0; Int64 totalScanned = 0; do { int patternStep = 0; uint infoSize = (uint)Marshal.SizeOf(typeof(ProcessMemoryReader.ProcessMemoryReaderApi.MEMORY_BASIC_INFORMATION64)); ProcessMemoryReader.ProcessMemoryReaderApi.MEMORY_BASIC_INFORMATION64 m = new ProcessMemoryReader.ProcessMemoryReaderApi.MEMORY_BASIC_INFORMATION64(); int result = ProcessMemoryReader.ProcessMemoryReaderApi.VirtualQueryEx(reader.ReadProcess.Handle, (IntPtr)address, out m, infoSize); if (result != infoSize) { int lastError = Marshal.GetLastWin32Error(); break; } // Console.WriteLine("{0}-{1} : {2} bytes {3}", m.BaseAddress.ToString("X"), ((uint)m.BaseAddress + (uint)m.RegionSize - 1).ToString("X"), m.RegionSize, m.State == (int)ProcessMemoryReader.ProcessMemoryReaderApi.InfoState.MEM_COMMIT ? "COMMIT" : "FREE"); startAddress = (IntPtr)(Int64)address;// m.BaseAddress; lastAddress = (IntPtr)((Int64)address + (Int64)m.RegionSize); address = (Int64)m.BaseAddress + (Int64)m.RegionSize; /* * if (!(m.State == (int)ProcessMemoryReader.ProcessMemoryReaderApi.InfoState.MEM_COMMIT && * (m.Type == (int)ProcessMemoryReader.ProcessMemoryReaderApi.InfoType.MEM_MAPPED || m.Type == (int)ProcessMemoryReader.ProcessMemoryReaderApi.InfoType.MEM_PRIVATE))) * continue; * */ if (m.State != (int)ProcessMemoryReader.ProcessMemoryReaderApi.InfoState.MEM_COMMIT) { continue; } totalScanned += (Int64)m.RegionSize; //Calculate the size of memory to scan. Int64 memorySize = (Int64)((Int64)lastAddress - (Int64)startAddress); bool found = false; //If more that one block of memory is required to be read, if (memorySize >= ReadStackSize) { //Count of loops to read the memory blocks. Int64 loopsCount = memorySize / ReadStackSize; //Look to see if there is any other bytes let after the loops. Int64 outOfBounds = memorySize % ReadStackSize; //extra loop for out of bounds bytes if (outOfBounds != 0) { loopsCount++; } //Set the currentAddress to first address. Int64 currentAddress = (Int64)startAddress; //This will be used to check if any bytes have been read from the memory. Int64 bytesReadSize; //Set the size of the bytes blocks. Int64 bytesToRead = ReadStackSize; //An array to hold the bytes read from the memory. byte[] array; //Progress percentage. int progress; Int64 jStart = 0; for (Int64 i = 0; i < loopsCount; i++) { bool skipAddressOffset = false; //if (found) // break; //Calculte and set the progress percentage. progress = (int)(((double)(currentAddress - (Int64)startAddress) / (double)memorySize) * 100d); //Prepare and set the ScanProgressed event and raise the event. scanProgressEventArgs = new ScanProgressChangedEventArgs(progress, currentAddress); ScanProgressChanged(this, scanProgressEventArgs); //Read the bytes from the memory. reader.ReadProcessMemory((IntPtr)currentAddress, (UInt64)((i == loopsCount - 1) && outOfBounds != 0 ? outOfBounds : bytesToRead), out bytesReadSize, buffer); array = buffer; //If any byte is read from the memory (there has been any bytes in the memory block), if (bytesReadSize > 0) { //Loop through the bytes 4 at a time to look for the values. for (Int64 j = jStart; j < array.Length - arraysDifference; j += 4) //4 bytes at a time { float memoryValue = System.BitConverter.ToSingle(array, (int)j); FloatPatternStep currStep = pattern[patternStep]; switch (currStep.type) { case FloatPatternStep.Type.Absolute: { memoryValue = Math.Abs(memoryValue); break; } } if (memoryValue <= currStep.maxValue && memoryValue >= currStep.minValue) { currStep.foundAddress = currentAddress + j; currStep.foundValue = memoryValue; //save where we found first value if (patternStep == 0) { currStep.blockFoundLoop = i; currStep.blockAddress = currentAddress; currStep.blockBytesToRead = bytesToRead; currStep.foundJ = j; } patternStep++; //found pattern if (patternStep >= pattern.Count) { found = true; Debug.WriteLine("Found pattern"); finalList.Add(pattern[0].foundAddress); Debug.Flush(); //need to skip back some loops if (i != pattern[0].blockFoundLoop) { patternStep = 0; i = pattern[0].blockFoundLoop; jStart = pattern[0].foundJ + 4; skipAddressOffset = true; break; } else //ok to continue same loop { patternStep = 0; j = pattern[0].foundJ; continue; } } currStep = pattern[patternStep]; j += currStep.byteOffset - 4; continue; } else { if (patternStep != 0) { //need to skip back some loops if (i != pattern[0].blockFoundLoop) { patternStep = 0; i = pattern[0].blockFoundLoop; jStart = pattern[0].foundJ + 4; skipAddressOffset = true; break; } else //ok to continue same loop { patternStep = 0; j = pattern[0].foundJ; } } } } } if (skipAddressOffset) { continue; } //Move currentAddress after the block already scaned, but //move it back some steps backward (as much as arraysDifference) //to avoid loosing any values at the end of the array. currentAddress += array.Length - arraysDifference; //Set the size of the read block, bigger, to the steps backward. //Set the size of the read block, to fit the back steps. bytesToRead = ReadStackSize + arraysDifference; jStart = 0; } /* * //If there is any more bytes than the loops read, * if (!found && outOfBounds > 0) * { * //Read the additional bytes. * reader.ReadProcessMemory((IntPtr)currentAddress, (UInt64)((Int64)lastAddress - currentAddress), out bytesReadSize, buffer); * byte[] outOfBoundsBytes = buffer; * * //If any byte is read from the memory (there has been any bytes in the memory block), * if (bytesReadSize > 0) * { * * //Loop through the bytes 4 at a time to look for the values. * for (Int64 j = 0; j < outOfBoundsBytes.Length - arraysDifference; j += 4) //4 bytes at a time * { * float memoryValue = System.BitConverter.ToSingle(outOfBoundsBytes, (int)j); * * FloatPatternStep currStep = pattern[patternStep]; * * if (memoryValue <= currStep.maxValue && memoryValue >= currStep.minValue) * { * currStep.foundAddress = currentAddress + j; * currStep.foundValue = memoryValue; * //save where we found first value * if (patternStep == 0) * { * currStep.blockFoundLoop = 0; * currStep.blockAddress = currentAddress; * currStep.blockBytesToRead = bytesToRead; * } * patternStep++; * * if (patternStep >= pattern.Count) * { * found = true; * Debug.WriteLine("Found Pattern"); * finalList.Add(j + (Int64)currentAddress); * Debug.Flush(); * patternStep = 0; * * break; * } * currStep = pattern[patternStep]; * j += currStep.byteOffset - 4; * continue; * } * else * { * patternStep = 0; * * if(currentAddress != pattern[0].blockAddress) * { * //this is a problem * bool boo = true; * boo = false; * } * * j = (pattern[0].blockAddress - pattern[0].foundAddress); * } * } * * } * }*/ //reset pattern step if not found for this entire block if (!found) { patternStep = 0; } } //If the block could be read in just one read, else { //Calculate the memory block's size. Int64 blockSize = memorySize % ReadStackSize; //Set the currentAddress to first address. Int64 currentAddress = (Int64)startAddress; //Holds the count of bytes read from the memory. Int64 bytesReadSize; //If the memory block can contain at least one 64 bit variable. if (blockSize > bytesCount) { //Read the bytes to the array. reader.ReadProcessMemory((IntPtr)currentAddress, (UInt64)blockSize, out bytesReadSize, buffer); byte[] array = buffer; //If any byte is read, if (bytesReadSize > 0) { //Loop through the bytes 4 at a time to look for the values. for (Int64 j = 0; j < array.Length - arraysDifference; j += 4) //4 bytes at a time { float memoryValue = System.BitConverter.ToSingle(array, (int)j); FloatPatternStep currStep = pattern[patternStep]; switch (currStep.type) { case FloatPatternStep.Type.Absolute: { memoryValue = Math.Abs(memoryValue); break; } } if (memoryValue <= currStep.maxValue && memoryValue >= currStep.minValue) { currStep.foundAddress = currentAddress + j; currStep.foundValue = memoryValue; //save where we found first value if (patternStep == 0) { currStep.blockFoundLoop = 0; currStep.blockAddress = currentAddress; currStep.blockBytesToRead = blockSize; currStep.foundJ = j; } patternStep++; if (patternStep >= pattern.Count) { found = true; Debug.WriteLine("Found Pattern"); finalList.Add(pattern[0].foundAddress); Debug.Flush(); j = pattern[0].foundJ; patternStep = 0; continue; } currStep = pattern[patternStep]; j += currStep.byteOffset - 4; continue; } else { if (patternStep != 0) { j = pattern[0].foundJ; } patternStep = 0; } } //reset pattern step here because couldn't find it in entire block if (!found) { patternStep = 0; } } } } } while (address <= MaxAddress); Console.WriteLine("Total Bytes Scanned = " + totalScanned); //Close the handle to the process to avoid process errors. reader.CloseHandle(); //Prepare the ScanProgressed and set the progress percentage to 100% and raise the event. scanProgressEventArgs = new ScanProgressChangedEventArgs(100, 0); ScanProgressChanged(this, scanProgressEventArgs); //Prepare and raise the ScanCompleted event. ScanCompletedEventArgs scanCompleteEventArgs = new ScanCompletedEventArgs(finalList.ToArray()); ScanCompleted(this, scanCompleteEventArgs); }
private void ByteArrayScanner(object _parameters) { ScanThreadParams parameters = (ScanThreadParams)_parameters; byte[] bytes = (byte[])parameters.target; int bytesCount = bytes.Length; //The difference of scan start point in all loops except first loop, //that doesn't have any difference, is type's Bytes count minus 1. int arraysDifference = bytesCount - 1; //prealloc buffer byte[] buffer = new byte[ReadStackSize + arraysDifference]; //Define a List object to hold the found memory addresses. List <Int64> finalList = new List <Int64>(); //Open the pocess to read the memory. reader.OpenProcess(); //Create a new instant of the ScanProgressEventArgs class to be used to raise the //ScanProgressed event and pass the percentage of scan, during the scan progress. ScanProgressChangedEventArgs scanProgressEventArgs; Int64 MaxAddress = (Int64)lastAddress;//last as in 'final' not as in 'previous' Int64 address = (Int64)startAddress; Int64 totalScanned = 0; do { uint infoSize = (uint)Marshal.SizeOf(typeof(ProcessMemoryReader.ProcessMemoryReaderApi.MEMORY_BASIC_INFORMATION64)); ProcessMemoryReader.ProcessMemoryReaderApi.MEMORY_BASIC_INFORMATION64 m = new ProcessMemoryReader.ProcessMemoryReaderApi.MEMORY_BASIC_INFORMATION64(); int result = ProcessMemoryReader.ProcessMemoryReaderApi.VirtualQueryEx(reader.ReadProcess.Handle, (IntPtr)address, out m, infoSize); if (result != infoSize) { int lastError = Marshal.GetLastWin32Error(); break; } // Console.WriteLine("{0}-{1} : {2} bytes {3}", m.BaseAddress.ToString("X"), ((uint)m.BaseAddress + (uint)m.RegionSize - 1).ToString("X"), m.RegionSize, m.State == (int)ProcessMemoryReader.ProcessMemoryReaderApi.InfoState.MEM_COMMIT ? "COMMIT" : "FREE"); //Start and end of this sub-scan startAddress = (IntPtr)(Int64)address;// m.BaseAddress; lastAddress = (IntPtr)((Int64)address + (Int64)m.RegionSize); //m.BaseAddress doesn't appear to be set, and baseAddress is a member of this class address = (Int64)m.BaseAddress + (Int64)m.RegionSize;//A better name is 'StartAddress' /* * if (!(m.State == (int)ProcessMemoryReader.ProcessMemoryReaderApi.InfoState.MEM_COMMIT && * (m.Type == (int)ProcessMemoryReader.ProcessMemoryReaderApi.InfoType.MEM_MAPPED || m.Type == (int)ProcessMemoryReader.ProcessMemoryReaderApi.InfoType.MEM_PRIVATE))) * continue; * */ if (m.State != (int)ProcessMemoryReader.ProcessMemoryReaderApi.InfoState.MEM_COMMIT) { continue; } totalScanned += (Int64)m.RegionSize; //Calculate the size of memory to scan. Int64 memorySize = (Int64)((Int64)lastAddress - (Int64)startAddress); bool found = false; //If more that one block of memory is requered to be read, if (memorySize >= ReadStackSize) { //Count of loops to read the memory blocks. Int64 loopsCount = memorySize / ReadStackSize; //Look to see if there is any other bytes let after the loops. Int64 outOfBounds = memorySize % ReadStackSize; if (outOfBounds != 0) { loopsCount++; } //Set the currentAddress to first address. Int64 currentAddress = (Int64)startAddress; //This will be used to check if any bytes have been read from the memory. Int64 bytesReadSize; //Set the size of the bytes blocks. Int64 bytesToRead = ReadStackSize; //An array to hold the bytes read from the memory. byte[] array; //Progress percentage. int progress; for (Int64 i = 0; i < loopsCount; i++) { if (found) { break; } //Calculate and set the progress percentage. progress = (int)(((double)(currentAddress - (Int64)startAddress) / (double)memorySize) * 100d); //Prepare and set the ScanProgressed event and raise the event. scanProgressEventArgs = new ScanProgressChangedEventArgs(progress, currentAddress); ScanProgressChanged(this, scanProgressEventArgs); //Read the bytes from the memory. reader.ReadProcessMemory((IntPtr)currentAddress, (UInt64)((i == loopsCount - 1) && outOfBounds != 0 ? outOfBounds : bytesToRead), out bytesReadSize, buffer); array = buffer; //If any byte is read from the memory (there has been any bytes in the memory block), if (bytesReadSize > 0) { //Loop through the bytes one by one to look for the values. for (Int64 j = 0; j < array.Length - arraysDifference; j++) { int matches = 0; for (Int64 b = 0; b < bytes.Length && (j + b) < array.Length - arraysDifference; b++) { if (bytes[b] != array[j + b]) { found = false; break; } else { matches++; } } if (matches == bytes.Length) { Debug.WriteLine("Found string: " + System.Text.Encoding.ASCII.GetString(array, (int)j, bytes.Length).Replace(Convert.ToChar(0x0).ToString(), " ")); finalList.Add(j + (Int64)currentAddress); Debug.Flush(); found = true; j += matches - 1; if (finalList.Count >= parameters.maxResults && parameters.maxResults != -1) { break; } } } } //Move currentAddress after the block already scaned, but //move it back some steps backward (as much as arraysDifference) //to avoid loosing any values at the end of the array. currentAddress += array.Length - arraysDifference; //Set the size of the read block, bigger, to the steps backward. //Set the size of the read block, to fit the back steps. bytesToRead = ReadStackSize + arraysDifference; if (found == true && finalList.Count >= parameters.maxResults && parameters.maxResults != -1) { break; } } /* * //If there is any more bytes than the loops read, * if (!found && outOfBounds > 0) * { * //Read the additional bytes. * reader.ReadProcessMemory((IntPtr)currentAddress, (UInt64)((Int64)lastAddress - currentAddress), out bytesReadSize, buffer); * byte[] outOfBoundsBytes = buffer; * * //If any byte is read from the memory (there has been any bytes in the memory block), * if (bytesReadSize > 0) * { * //Loop through the bytes one by one to look for the values. * for (Int64 j = 0; j < outOfBoundsBytes.Length - arraysDifference; j++) * { * int matches = 0; * for (Int64 b = 0; b < bytes.Length && (j + b) < outOfBoundsBytes.Length - arraysDifference; b++) * { * if (bytes[b] != outOfBoundsBytes[j + b]) * { * found = false; * break; * } * else * { * matches++; * } * } * * if (matches == bytes.Length) * { * finalList.Add(j + currentAddress); * j = j + b; * } * * } * } * } */ } //If the block could be read in just one read, else { //Calculate the memory block's size. Int64 blockSize = memorySize % ReadStackSize; //Set the currentAddress to first address. Int64 currentAddress = (Int64)startAddress; //Holds the count of bytes read from the memory. Int64 bytesReadSize; //If the memory block can contain at least one 64 bit variable. if (blockSize > bytesCount) { //Read the bytes to the array. reader.ReadProcessMemory((IntPtr)currentAddress, (UInt64)blockSize, out bytesReadSize, buffer); byte[] array = buffer; //If any byte is read, if (bytesReadSize > 0) { //Loop through the array to find the values. for (int j = 0; j < array.Length - arraysDifference; j++) { int matches = 0; for (int b = 0; b < bytes.Length && (j + b) < array.Length - arraysDifference; b++) { if (bytes[b] != array[j + b]) { found = false; break; } else { matches++; } } if (matches == bytes.Length) { Debug.WriteLine("Found string: " + System.Text.Encoding.ASCII.GetString(array, j, bytes.Length)); finalList.Add(j + currentAddress); Debug.Flush(); found = true; j += matches - 1; if (finalList.Count >= parameters.maxResults && parameters.maxResults != -1) { break; } } } } } } if (found == true && finalList.Count >= parameters.maxResults && parameters.maxResults != -1) { break; } } while (address <= MaxAddress); Console.WriteLine("Total Bytes Scanned = " + totalScanned); //Close the handle to the process to avoid process errors. reader.CloseHandle(); //Prepare the ScanProgressed and set the progress percentage to 100% and raise the event. scanProgressEventArgs = new ScanProgressChangedEventArgs(100, 0); ScanProgressChanged(this, scanProgressEventArgs); //Prepare and raise the ScanCompleted event. ScanCompletedEventArgs scanCompleteEventArgs = new ScanCompletedEventArgs(finalList.ToArray()); ScanCompleted(this, scanCompleteEventArgs); }