November 10, 2020

Секретный сервис 700

Не все сервисы TwinCAT описаны в документации. В старых исходниках библиотеки AdsClient, в файле AdsSpecial.cs, есть любопытная функция public string GetTargetDesc(). Описание функции гласит: "Get an xml description of the plc...". Посмотрим, какое именно описание отдаст нам контроллер.

Начнем с системного сервиса, порт номер R3_CTRLPROG = 10000. Официальное описание списка функций заканчивается номером 600 (см. таблицу System Service Index Groups). Мы же прочитаем индекс 700 (0x02BChex). Настраиваем роутинг и начинаем читать. Код C# программы:

using System;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using TwinCAT.Ads; // v4.4.0.0
namespace AdsReadSystemConfig
{
class Program
{
const string TARGET_AMS = "127.0.0.1.1.1";
const uint READDEVDESCRIPTION_IDX = 0x0000_02bc;
const uint READDEVDESCRIPTION_OFF = 0x0000_0001;
static void Main()
{
var client = new TcAdsClient();
var ams = new AmsAddress(TARGET_AMS, AmsPort.R3_CTRLPROG);
client.Connect(ams);
// length of the plc's xml description
int length = (int)client.ReadAny(READDEVDESCRIPTION_IDX, READDEVDESCRIPTION_OFF, typeof(int));
var adsStream = new AdsStream(length);
client.Read(READDEVDESCRIPTION_IDX, READDEVDESCRIPTION_OFF, adsStream);
string description = Encoding.UTF8.GetString(adsStream.ToArray()).TrimEnd('\0');
var xdoc = XDocument.Parse(description);
var elements = xdoc.Descendants();
Console.WriteLine(xdoc);
Console.WriteLine();
// looking for the name of PLC's OS
var osName = elements.FirstOrDefault(x => x.Name == "OsName")?.Value ?? "<Unknown>";
Console.WriteLine("Press [Enter] to close...");
Console.ReadLine();
}
}
}

 

Первый запрос отправляем с параметром typeof(int). Где-то внутри библиотеки это транслируется в параметр команды равный 4 — это длина типа данных int в байтах. В ответ, запрос вернет длину XML текста с описанием устройства. Зная размер, мы отправляем второй запрос в тот же порт-индекс-смещение, но в качестве параметра передаем длину описания, полученного на предыдущем шаге. Результат парсим. С помощью LINQ ищем и вытаскиваем интересующие нас поля описания.

Контроллер CX9020 вернул такой XML:

<TcTargetDesc>
<TargetType>CX9020-M510-CE</TargetType>
<TargetVersion>
<Version>3</Version>
<Revision>1</Revision>
<Build>4024</Build>
</TargetVersion>
<TargetFeatures>
<NetId>5.59.222.141.1.1</NetId>
</TargetFeatures>
<Hardware>
<Model>CX9020-M510</Model>
<SerialNo>79307</SerialNo>
<CPUVersion>2.9</CPUVersion>
<Date>15.10.18</Date>
<CPUArchitecture>5</CPUArchitecture>
</Hardware>
<OsImage>
<ImageDevice>CX9020</ImageDevice>
<ImageVersion>6.08g</ImageVersion>
<ImageLevel>HPS</ImageLevel>
<OsName>Windows CE</OsName>
<OsVersion>7.0</OsVersion>
</OsImage>
</TcTargetDesc>

 

Сравним описания от CX9020 (Win CE) и ноутбука (Windows 10). Чтобы отследить различия, сохраним XML в отдельный файл: xdoc.Save( "cx9020.xml" ); и воспользуемся программой WinMerge:


TС/BSD

Новая, перспективная и все еще недоступная операционная система выдает следующее описание:

<TcTargetDesc>
<TargetType>TC/BSD-OS</TargetType>
<TargetVersion>
<Version>3</Version>
<Revision>1</Revision>
<Build>4024</Build>
</TargetVersion>
<TargetFeatures>
<NetId>39.159.94.42.1.1</NetId>
</TargetFeatures>
<Hardware>
<Model>0</Model>
<SerialNo>0</SerialNo>
<CPUVersion>0.0</CPUVersion>
<Date>0.0.00</Date>
<CPUArchitecture>9</CPUArchitecture>
</Hardware>
<OsImage>
<ImageVersion>12.1.20200716091138,1</ImageVersion>
<OsName>TC/BSD</OsName>
<OsVersion>12.1</OsVersion>
</OsImage>
</TcTargetDesc>

 

Пропали элементы `ImageDevice`, `ImageLevel`. Значение `CPUArchitecture` стало более осмысленным, но что такое 9 все еще непонятно.


Тоже сервисы

Можно найти еще несколько интересных сервисов, если копнуть глубже. Для раскопок пригодится какой-нибудь HEX-вьюер (VSCode hexdump) и следующая строка: File.WriteAllBytes( $"idx_{READDEVDESCRIPTION_IDX}.bin", adsStream.ToArray() ); // Начинайте копать.

Индекс 701 выдаст список всех сетевых интерфейсов доступных на устройстве. IP-адреса, маски подсети и что-то еще. Формат неизвестен, но можно разобраться самостоятельно. Копайте.

Из любопытного, для TC/BSD сервис возвращает название сетевого интерфейса в юникс стиле — `em0`.
А для Windows возвращает GUID: "{7D8FDCBA-6250-8DFF-4089-AB0845B12EDC} Qualcomm Atheros AR5BWB222 Wireless Network Adapter 192.168.2.177 255.255.255.0".

Индекс 702 отдает имя целевой машины: PC-8E5B1A, CX-3F5BC9... Строка заканчивается '\0', не забывайте про .TrimEnd('\0'); Продолжайте копать.


No comments

Post a Comment

Note: Only a member of this blog may post a comment.