Раз пошла такая пьянка, предложу вариант без регулярных выражений:
// входящие данные
string data = "0x00 00 00 00 00 00 00 00 00 00 00 00 00 00 30 39 ..............09";
// получаем позицию первой найденной точки
int endIndex = data.IndexOf(".");
// получаем позицию первого вхождения символов 00
// с конца строки начиная с endIndex
int startIndex = data.LastIndexOf("00", endIndex) + 2; // + размер искомых символов
// выделяем часть строки и удаляем лишние пробелы по бокам
string result = data.Substring(startIndex, endIndex - startIndex).Trim();
// выводим результат
Console.WriteLine(result);
// можно одной строкой написать, но так проще понять
Посмотреть, как это работает, можно
тут.
Регулярные выражения имеет смысл использовать, если шаблон поиска и/или данные будут сложными. В рамках текущего вопроса, все вроде бы просто, можно без потенциально опасных регулярных выражений обойтись (прожорливость, зацикливание).
Еще вот такой можно сделать вариант:
string data = "0x00 00 00 00 00 00 00 00 00 00 00 00 00 3D 12 7E ..............01";
string result = data.Replace("0x", "").Replace("00", "").TrimEnd("0123456789.".ToCharArray()).Trim();
Console.WriteLine(result);
Или:
string data = "0x00 00 00 00 00 00 00 00 00 00 00 00 00 3D 12 7E ..............00";
string result = data.Substring(2).TrimStart("0 ".ToCharArray()).TrimEnd("0123456789.".ToCharArray()).Trim();
Console.WriteLine(result);