Вроде были вопросы о том, как сделать программу работоспособной только на одном/нескольких контроллерах, то есть предотвратить её выполнение на других контроллерах той же модели с той же прошивкой. Консенсус был таков, что уникальных ключей у идентичных контроллеров нет, и нужно использовать внешний (аппаратный) ключ.

Но кажется, у меня получилось организовать чисто программную проверку заводского MAC-адреса ПЛК серий 110 и 160. Вкратце: заводской MAC-адрес обнаружился по адресам 2069CD2E у ПЛК160 и 2060E5B0 у ПЛК110-32.

Подробнее... Я поставил задачу найти заводской MAC-адрес в оперативной памяти ПЛК после того, как адрес в файле local_addres.dat был изменён (естественно, не натыкаясь на константы в своей же программе). На коленке был написан вот такой сканирующий память код:
Код:
VAR
	i, g, c: DWORD;
	go: BOOL;
	mac0: ARRAY[0..5] OF BYTE;
END_VAR
VAR CONSTANT
	MAC: ARRAY[0..5] OF BYTE := 16#6A, 16#77, 16#00, 16#00, 16#00, 16#F8;
END_VAR

IF go THEN
	g := i + 2000;
	FOR i := i TO g DO
		SysMemCpy(ADR(mac0), i, SIZEOF(mac0));
		go := NOT(mac0[0] = MAC[0] AND mac0[1] = MAC[1] AND mac0[5] = MAC[5] AND i <> ADR(MAC));
		IF NOT go THEN
			c := i;
			i := i + 1;
			EXIT;
		END_IF
	END_FOR
END_IF
В константах записан заводской адрес контроллера с изменёнными 4 и 5 байтами. Программа ищет совпадение в памяти по первому, второму и шестому байтам. Если при нахождении адреса мы наблюдаем в mac0 заводской адрес, и после перезагрузки результат получается тот же самый, то можно из своей программы удостоверяться в подлинности контроллера по этому адресу. Что-то вроде genuine := SysMemCmp(16#2060E5B0, ADR(MAC), SIZEOF(MAC)) = 0; Конечно, в боевой программе MAC-адрес лучше хранить не в открытом виде как показано выше, а хэшем константы с солью, чтобы исключить атаку тупой подменой байтов в бинарнике с пересчётом контрольной суммы. Обход такой защиты уже может оказаться нетривиальным и оттого нецелесообразным.

Дальше исследовать способ предлагаю заинтересованным в защите лицам.