Створення програм, що самодифікуються

Швидше за все моя ідея не нова, але все ж таки я хотів би її озвучити. Я намагався розглянути її крізь призму коду і метапрограмування, що самодифікується, але саме такої реалізації знайти я так і не зумів.

Коротко ідея звучить так: ми створюємо програму, яка у своїх ресурсах містить компілятор та власний код. Через деякий вплив ззовні або необхідність змінити саму себе, програма намагається поліпшити свою нову копію або пристосувати її до нових умов середовища. Для цього вона дістає з ресурсів компілятор (він вже може бути в операційній системі, тоді цей пункт можна згаяти) і власний вихідний код. Після цього вихідний код модифікується відповідно до нових умов і компілюється (при цьому ресурси потрапляє новий вихідний код і той же компілятор). Після вдалої компіляції батьківська програма завантажує на згадку машини свою нову версію і завершується сама. Таким чином програма-нащадок починає функціонувати замість батьківської програми і, у разі потреби, цикл самодифікації повторюється, тобто програма-нащадок стає батьківською програмою для нового нащадка.

Навіщо це все потрібно?

1) Циклічне вдосконалення програми чи її алгоритма. Програма модифікує себе, вирішує деяке еталонне завдання та оцінює результат. На основі результату приймається рішення про новий цикл модифікації. 2) У разі вірусної програми такий підхід може використовуватися для модифікації свого коду при переході на нову машину та обходу таким чином антивірусів. При цьому можна змінювати вже існуючий код, так і додавати новий, який не несе смислового навантаження. 3) Програма може запам'ятовувати конкретного користувача та підлаштовуватися під нього. Наприклад, можна експериментувати з квітамиі формою вікна і запитувати користувача про прийнятний для нього варіант або аналізувати функції програми, що найчастіше використовуються користувачем. У випадку оператора типу switch() може мати сенс найбільш часто використовувані варіанти вибору пересувати вгору для того, щоб намагатися уникнути перевірок тих варіантів вибору, які практично не використовуються. 4) Програма може спробувати знайти в мережі Інтернет вихідний код нового рішення якоїсь із своїх функцій, завантажити його, відповідним чином змінити свій код з урахуванням нової реалізації цієї функції та спробувати відкомпілювати та перевірити роботу нової копії. Таким чином можна створити програму, яка згодом сама знаходитиме найкращі рішення проблем і використовуватиме їх у своїй роботі. Така програма йтиме в ногу з часом без постійної участі свого розробника (це поки що область фантастики, на жаль =( ).

Приклад технічної реалізації цього підходу на C#

У разі наявності платформи .NET на машині користувача додавати компілятор у ресурси не обов'язково, оскільки він поставляється із самим .NET.

Код програми має такий вигляд:

using System; using System.Windows.Forms; using System.Resources; namespace SMC static class Program [STAThread] static void Main() // Дістаємо з ресурсів власний код ResourceManager rm = new ResourceManager("my", System. Reflection.Assembly.GetExecutingAssembly()); string code = rm.GetString("Program"); // Перевіряємо версію програми if (code.Substring(0, 7) != "//mark0") MessageBox.Show("I am the first program"); // Якщо працює батьківська програма - додаємо мітку на початок коду code = @"//mark0" + Environment.NewLine + code; // Створюємо файл ресурсів ResXResourceWriter rw = New ResXResourceWriter(@"c:\my.resx"); rw.AddResource("Program", code); rw.Close(); // Створюємо файл з вихідним кодом System.IO.File.WriteAllText(@"c:\Program.cs", code); // Перетворюємо файл ресурсів з .resx на .resources System.Diagnostics.Process proc1 = new System.Diagnostics.Process(); proc1.StartInfo.FileName = "cmd"; proc1.StartInfo.Arguments = @"/C " + "\"C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\\ResGen.exe\" c:\\ my.resx c:\\my.resources"; proc1.StartInfo.UseShellExecute = false; proc1.StartInfo.RedirectStandardOutput = true; proc1.StartInfo.CreateNoWindow = true; proc1.Start(); proc1.WaitForExit(); // Компілюємо нову версію програми System.Diagnostics.Process proc = new System.Diagnostics.Process(); proc.StartInfo.FileName = "cmd"; proc.StartInfo.Arguments = @"/C " + @"C:\Windows\Microsoft.NET\Framework\v2.0.50727\csc.exe /target:winexe /resource:c:\my.resources /nologo /warn:0 /out:c:\myprog.exe c:\Program.cs"; proc.StartInfo.UseShellExecute = false; proc.StartInfo.RedirectStandardOutput = true; proc.StartInfo.CreateNoWindow = true; proc.Start(); proc.WaitForExit(); > else MessageBox.Show("I am the second program"); > > > >

Хотілося б почути конструктивну критику та посилання на джерела, де такий підхід застосовується, якщо такі є. Всім дякую за увагу.