เขียนโปรแกรมจำลองตัวเอง


11

เขียนโปรแกรมอย่างง่ายที่คัดลอกตัวเองเมื่อดำเนินการ

โปรแกรมของคุณควรเป็นไฟล์เรียกทำงานบางประเภทใน Windows, Linux และอื่น ๆ ควรสร้างไฟล์ปฏิบัติการใหม่ซึ่งเหมือนกับไฟล์ปฏิบัติการดั้งเดิมของคุณโดยใช้ชื่อแบบสุ่มและออกจากโปรแกรม

โปรแกรมของคุณไม่ควรเกี่ยวข้องกับการอ่านหรือคัดลอกไฟล์ อนุญาตให้เขียนไฟล์เพื่อสร้างไฟล์เรียกทำงานใหม่เท่านั้น

(PS. ฉันค่อนข้างอายเมื่ออยู่ที่ Wikipedia Self-replicating programเปลี่ยนเส้นทางไปยังComputer virusบทความ ... : / ... )

ขนาดไฟล์ปฏิบัติการที่เล็กที่สุดจะชนะ คำตอบของคุณอาจเป็นรหัสการเขียนโปรแกรมที่มีระบบปฏิบัติการ & คอมไพเลอร์, รหัสการประกอบหรือการถ่ายโอนข้อมูล HEX ของไฟล์ปฏิบัติการได้


6
สิ่งนี้ดูเหมือนจะเปลี่ยนแปลงเพียงเล็กน้อยจากความท้าทายที่มีอยู่ หรือฉันเข้าใจผิด?
dmckee --- ผู้ดูแลอดีตลูกแมว

1
@dmckee ผมเห็นภาษา Assembly ควินและตนเองจำลองโปรแกรม Hello Worldยอมรับคัดลอก แต่ฉันไม่สามารถหาโปรแกรมเขียนเองไม่ได้ของรหัส
JiminP

1
... แต่ฉันต้องการดูว่ามันใช้งานได้จริงจริง ๆ ! .. ฉันไม่รู้ว่าแนวคิดนี้สามารถขยายด้วยรหัสไบนารี่ได้อย่างไรแม้ว่าฉันจะอ่านบทความ Quine ที่ Wikipedia PS ไม่มีคอมไพเลอร์สำหรับการทำซ้ำและไม่อนุญาตให้ใช้ภาษาสคริปต์ ... : /
JiminP

4
ปัญหาใด ๆ สามารถทำได้ยากขึ้นและอัปลักษณ์เล็กน้อยโดยการเพิ่มข้อ จำกัด เพิ่มเติม ฉันพบว่าปัญหานี้เป็นปัญหาเล็กน้อยของปัญหาควินิน
Alexandru

1
หากขนาดที่ปฏิบัติการได้เล็กที่สุดชนะเราไม่ควรคำนึงถึงรหัสล่ามเป็นส่วนหนึ่งของขนาดที่สามารถใช้งานได้เพื่อให้ผู้ใช้ภาษาที่รวบรวมได้มีความยุติธรรม
Thomas Dignan

คำตอบ:


4

Bash, 236

นานกว่าที่จำเป็นอย่างเคร่งครัด แต่ฉันเกลียดสายยาว ขึ้นบรรทัดใหม่ต่อท้ายไม่ใช่ตัวเลือก

b=\\ q=\' r=\> d=\$
s='exec >$$; echo b=$b$b q=$b$q r=$b$r d=$b$d; echo s=$q$s$q'
t='echo t=$q$t$q; echo $s; echo $t; chmod 777 $$'
exec >$$; echo b=$b$b q=$b$q r=$b$r d=$b$d; echo s=$q$s$q
echo t=$q$t$q; echo $s; echo $t; chmod 777 $$

ที่จริงมันไม่ได้เป็นสิ่งที่ฉันต้องการ แต่เนื่องจากผมเขียน "ผิด" คำถามและคำตอบของคุณเป็นควินดี ...
JiminP

@JiminP: มันไม่ใช่สิ่งที่คุณต้องการได้อย่างไร? ฉันเพิ่งอ่านคำอธิบายปัญหาสองครั้งอีกครั้งและไม่เข้าใจ
JB

ดี ... สิ่งที่ฉันต้องการคือรหัสไบนารีที่ปฏิบัติการได้ ตามที่ฉันยอมรับข้างต้นเนื่องจากคำถามของฉันไม่ถูกต้องนัก ... ขอโทษสำหรับสิ่งนั้น
JiminP

3
@JiminP ใช่แล้วคำว่า "binary" ไม่ปรากฏในคำถามเลย ฉันเพิ่งพบมันในความคิดเห็น แต่สำหรับข้อ จำกัด ดังกล่าวมันก็ไม่ได้ตัด คุณสามารถเปิดคำถามใหม่ที่มีการป้อนข้อมูลรวมทั้งหมดจากความคิดเห็น ฉันแนะนำให้คุณใช้กล่องทรายเพื่อให้มั่นใจว่าพนักงานประจำช่วยรีดรายละเอียดเล็กน้อย แต่ระวังคำตอบไบนารีมักจะน่าเบื่อจริง
JB

10

ชุดประกอบสำหรับ x86 Linux, 106 ไบต์

BITS 32
                org     0x2E620000
                db      0x7F, "ELF", 1, 1, 1, 0 ; e_ident
                dd      0, 0
                dw      2                       ; e_type
                dw      3                       ; e_machine
                dd      1                       ; e_version
                dd      _start                  ; e_entry
                dd      phdr - $$               ; e_phoff
                dd      0                       ; e_shoff
                dd      0                       ; e_flags
                dw      0x34                    ; e_ehsize
                dw      0x20                    ; e_phentsize
phdr:           dd      1                       ; e_phnum       ; p_type
                                                ; e_shentsize
                dd      0                       ; e_shnum       ; p_offset
                                                ; e_shstrndx
                dd      $$                                      ; p_vaddr
fname           equ     $ - 2
                db      'out', 0                                ; p_paddr
                dd      filesize                                ; p_filesz
                dd      filesize                                ; p_memsz
                dd      5                                       ; p_flags
                dd      0x1000                                  ; p_align
_start:         mov     al, 5                   ; 5 = open syscall
                mov     ebx, fname
                mov     cl, 65                  ; 65 = O_WRONLY | O_CREAT
                mov     dx, 666q
                int     0x80
                lea     edx, [byte ecx + filesize - 65]
                xchg    eax, ebx
                xchg    eax, ecx
                mov     cl, 0
                mov     al, 4                   ; 4 = write syscall
                int     0x80
                mov     al, 1                   ; 1 = exit syscall
                int     0x80
filesize        equ     $ - $$

นี่คือสำหรับแอสเซมเบลอร์ nasm สร้างไบนารีด้วยบรรทัดคำสั่ง:nasm -f bin -o a.out selfrep.asm && chmod +x a.out

นี่คือไฟล์เดียวกับการถ่ายโอนข้อมูลฐานสิบหก: 7F 45 4C 46 01 01 01 00 00 00 00 00 00 00 00 00 02 00 03 00 01 00 00 00 4C 00 62 2E 2C 00 00 00 00 00 00 00 00 00 00 00 34 00 20 00 01 00 00 00 00 00 00 00 00 00 62 2E 6F 75 74 00 6A 00 00 00 6A 00 00 00 05 00 00 00 00 10 00 00 B0 05 BB 36 00 62 2E B1 41 66 BA B6 01 CD 80 8D 51 29 93 91 B1 00 B0 04 CD 80 B0 01 CD 80

ตามที่ร้องขอโปรแกรมคัดลอกตัวเองไปยังไฟล์แยกต่างหาก (โปรแกรมอาจสั้นลงอย่างเห็นได้ชัดหากได้รับอนุญาตให้เขียนไปยัง stdout และให้ผู้ใช้เปลี่ยนเส้นทางไปยังไฟล์)

ฉันหลีกเลี่ยงการใช้เทคนิคเส้นขอบเพื่อลดขนาด นี่ควรเป็นไบนารี ELF 32 บิตที่เป็นไปตามข้อกำหนด

แก้ไขเพื่อเพิ่ม : ในเวอร์ชันด้านบนไฟล์ที่สร้างขึ้นเป็นเพียงไฟล์ธรรมดา แต่มันเกิดขึ้นกับฉันว่าสองสามไบต์ (และกฎเล็ก ๆ ) คุณสามารถสร้างบางสิ่งที่น่าสนใจยิ่งขึ้น รุ่นนี้มีความยาวเพียงสองไบต์ที่ 108 ไบต์:

BITS 32
                org     0x00010000
                db      0x7F, "ELF", 1, 1, 1, 0 ; e_ident
                dd      0, 0
                dw      2                       ; e_type
                dw      3                       ; e_machine
                dd      1                       ; e_version
                dd      _start                  ; e_entry
                dd      phdr - $$               ; e_phoff
                dd      0                       ; e_shoff
                dd      0                       ; e_flags
                dw      0x34                    ; e_ehsize
                dw      0x20                    ; e_phentsize
phdr:           dd      1                       ; e_phnum       ; p_type
                                                ; e_shentsize
                dd      0                       ; e_shnum       ; p_offset
                                                ; e_shstrndx
                dd      $$                                      ; p_vaddr
fname:          db      'asr', 0                                ; p_paddr
                dd      filesize                                ; p_filesz
                dd      filesize                                ; p_memsz
                dd      7                                       ; p_flags
                dd      0x1000                                  ; p_align
_start:         mov     al, 5                   ; 5 = open syscall
                mov     ebx, fname
                inc     byte [ebx]
                mov     cl, 65                  ; 65 = O_WRONLY | O_CREAT
                mov     dx, 777q
                int     0x80
                lea     edx, [byte ecx + filesize - 65]
                xchg    eax, ebx
                xchg    eax, ecx
                mov     cl, 0
                mov     al, 4                   ; 4 = write syscall
                int     0x80
                mov     al, 1                   ; 1 = exit syscall
                int     0x80
filesize        equ     $ - $$

ตั้งชื่อรุ่นนี้asrสำหรับ "ตัวจำลองข้อมูลตนเอง":nasm -f bin -o asr asr.asm && chmod +x asr

เลขฐานสิบหกสำหรับรุ่นที่ผิดปกติ: 7F 45 4C 46 01 01 01 00 00 00 00 00 00 00 00 00 02 00 03 00 01 00 00 00 4C 00 01 00 2C 00 00 00 00 00 00 00 00 00 00 00 34 00 20 00 01 00 00 00 00 00 00 00 00 00 01 00 61 73 72 00 6C 00 00 00 6C 00 00 00 07 00 00 00 00 10 00 00 B0 05 BB 38 00 01 00 FE 03 B1 41 66 BA FF 01 CD 80 8D 51 2B 93 91 B1 00 B0 04 CD 80 B0 01 CD 80

เมื่อคุณเรียกใช้มันจะสร้างไฟล์ที่เกือบจะเหมือนกันbsrแต่ไฟล์นั้นจะสามารถเรียกใช้งานได้ csrเล่นมันจะสร้างอีกแฟ้มไบนารีชื่อ และอื่น ๆ

(โปรดทราบว่าสิ่งที่น่ารำคาญเริ่มเกิดขึ้นหลังจากzsrนั้นฉันคิดว่าการสร้างเวอร์ชันที่จะทำให้การเปลี่ยนชื่อเป็นไปเรื่อย ๆatrแต่ฉันคิดว่าคนส่วนใหญ่จะเบื่อกันก่อนดังนั้นจึงอาจไม่คุ้มค่าไบต์พิเศษทั้งหมด )


+1 สำหรับคำตอบการชุมนุม! คุณเคยเห็นความท้าทายในการชุมนุมหรือไม่?
MD XF

2

ต่อไปนี้เป็นแนวคิดการพิสูจน์ (ungolfed) ที่แสดงให้เห็นว่าบริการการรวบรวมใน. NET อาจถูกใช้เพื่อรวบรวมซอร์สโค้ดแบบทันทีเพื่อสร้างเอาต์พุตที่เหมือนกัน สำเนาแรกไม่เหมือนต้นฉบับ แต่สำเนาที่ตามมาจากการเรียกใช้ครั้งต่อไปจะเหมือนกันทุกประการกับชื่อไฟล์แบบสุ่ม:

using System;
using Microsoft.CSharp;
using System.CodeDom.Compiler;

namespace _2947
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello world!");

            var s = @"
using System;
using System.CodeDom.Compiler;
using Microsoft.CSharp;

namespace _2947
{{
    class Program
    {{
        static void Main(string[] args)
        {{
            Console.WriteLine({1}Hello world!{1});

            var s = @{1}{0}{1};
            s = string.Format(s, s, '{1}');

            string exeName = Environment.CurrentDirectory + @{1}\{1} + new Random().Next(1000, 9999) + {1}.exe{1};

            CompilerParameters cp = new CompilerParameters();
            cp.GenerateExecutable = true;
            cp.OutputAssembly = exeName;
            cp.GenerateInMemory = false;
            cp.TreatWarningsAsErrors = false;
            cp.ReferencedAssemblies.Add({1}System.dll{1});

            var c = CSharpCodeProvider.CreateProvider({1}cs{1});
            var cr = c.CompileAssemblyFromSource(cp, s);
        }}
    }}
}}
";
            s = string.Format(s, s, '"');

            string exeName = Environment.CurrentDirectory + @"\" + new Random().Next(1000, 9999) + ".exe";

            CompilerParameters cp = new CompilerParameters();
            cp.GenerateExecutable = true;
            cp.OutputAssembly = exeName;
            cp.GenerateInMemory = false;
            cp.TreatWarningsAsErrors = false;
            cp.ReferencedAssemblies.Add("System.dll");

            var c = CSharpCodeProvider.CreateProvider("cs");
            var cr = c.CompileAssemblyFromSource(cp, s);
        }
    }
}

เอาต์พุตการสาธิตบนบรรทัดคำสั่ง:

C:\projects\codegolf\2947\2947\bin\Debug>2947
Hello world!

C:\projects\codegolf\2947\2947\bin\Debug>dir
 Volume in drive C has no label.
 Volume Serial Number is 361D-4479

 Directory of C:\projects\codegolf\2947\2947\bin\Debug

09/27/2011  02:17 PM    <DIR>          .
09/27/2011  02:17 PM    <DIR>          ..
09/27/2011  02:17 PM             7,680 2947.exe
09/27/2011  02:17 PM            13,824 2947.pdb
09/27/2011  01:33 PM            11,600 2947.vshost.exe
09/27/2011  02:17 PM             6,656 8425.exe
               4 File(s)         39,760 bytes
               2 Dir(s)   6,486,368,256 bytes free

C:\projects\codegolf\2947\2947\bin\Debug>8425
Hello world!

C:\projects\codegolf\2947\2947\bin\Debug>dir
 Volume in drive C has no label.
 Volume Serial Number is 361D-4479

 Directory of C:\projects\codegolf\2947\2947\bin\Debug

09/27/2011  02:17 PM    <DIR>          .
09/27/2011  02:17 PM    <DIR>          ..
09/27/2011  02:17 PM             7,680 2947.exe
09/27/2011  02:17 PM            13,824 2947.pdb
09/27/2011  01:33 PM            11,600 2947.vshost.exe
09/27/2011  02:17 PM             6,656 7538.exe
09/27/2011  02:17 PM             6,656 8425.exe
               5 File(s)         46,416 bytes
               2 Dir(s)   6,486,360,064 bytes free

C:\projects\codegolf\2947\2947\bin\Debug>7538
Hello world!

C:\projects\codegolf\2947\2947\bin\Debug>dir
 Volume in drive C has no label.
 Volume Serial Number is 361D-4479

 Directory of C:\projects\codegolf\2947\2947\bin\Debug

09/27/2011  02:17 PM    <DIR>          .
09/27/2011  02:17 PM    <DIR>          ..
09/27/2011  02:17 PM             7,680 2947.exe
09/27/2011  02:17 PM            13,824 2947.pdb
09/27/2011  01:33 PM            11,600 2947.vshost.exe
09/27/2011  02:17 PM             6,656 4127.exe
09/27/2011  02:17 PM             6,656 7538.exe
09/27/2011  02:17 PM             6,656 8425.exe
               6 File(s)         53,072 bytes
               2 Dir(s)   6,486,351,872 bytes free

C:\projects\codegolf\2947\2947\bin\Debug>

2

ชุด

รุ่น 1 (30 ไบต์)

type%0>%random%.bat&type%0>con

ผมชนะ! :)


การอ้างอิง% 0 ทำให้เกิดการอ่านจากไฟล์ซึ่งละเมิดกฎ นอกจากนี้เวอร์ชั่นไบนารีของฉันยังสั้นกว่า :-)
peter ferrie

1

ไฟล์ DOS COM - 50 ไบต์

สร้างไฟล์X.COMที่Xถูกแทนที่ด้วยตัวเลขหลักของเวลาปัจจุบัน ไฟล์ COM จะถูกโหลดลงในหน่วยความจำเพียงส่วนตรงข้าม100hของส่วนข้อมูล (CS และ DS ถูกตั้งค่าให้เหมือนกัน) ดังนั้นเราจึงสามารถเขียนหน่วยความจำนี้ลงในไฟล์ได้

0000000: b402 cd1a 80e6 0f80 ce30 8836 2c01 31c9  .........0.6,.1.
0000010: ba2c 01b4 3ccd 21c6 062c 0178 89c3 b440  .,..<.!..,.x...@
0000020: ba00 01b9 3200 cd21 b44c cd21 782e 636f  ....2..!.L.!x.co
0000030: 6d00                                     m.

แหล่ง nasm

org 100h ; this is a COM file
mov ah,02h ; fn=get time
int 1ah ; rtc interrupt
; convert to ascii - dh gets ones digit of seconds
and dh,0fh
or dh,30h
mov [fname],dh ; move time into filename
xor cx,cx ; clear attributes
mov dx,fname ; load filename
mov ah,3ch ; fn=create file
int 21h ; dos interrupt
mov byte [fname],'x' ; reset filename
mov bx,ax ; set filehandle
mov ah,40h ; fn=write to file
mov dx,100h ; offset is the loaded binary
mov cx,len ; length of write
int 21h ; dos iterrupt
mov ah,4ch ; fn=exit
int 21h ; dos interrupt
fname: db 'x.com',0
len equ $-$$

1

ไฟล์ DOS .COM ขนาด 29 ไบต์

'@' ถูกแทนที่โดยการสุ่มตัวอักษรแปลก ๆ ในครึ่งแรก + ส่วนหนึ่งของตัวอักษร (A, C, E, G, ฯลฯ ) ไฟล์ที่ส่งออกเป็น 255 หรือ 256 ไบต์ การลงทะเบียนครั้งแรกใน DOS จริง (เมื่อเทียบกับดีบักเกอร์) คือ AX = 0000, CX = 00FF, SI = 0100

40       INC  AX         ;"@"
2E       CS:             ;"."
43       INC  BX         ;"C"
4F       DEC  DI         ;"O"
4D       DEC  BP         ;"M"
00 20    ADD  [BX+SI],AH ;"\0" and dummy parm
E4 40    IN   AL,40
24 0F    AND  AL,0F
0C 41    OR   AL,41
88 04    MOV  [SI],AL
B4 3C    MOV  AH,3C
41       INC  CX
89 F2    MOV  DX,SI
CD 21    INT  21
93       XCHG BX,AX
B4 40    MOV  AH,40
49       DEC  CX
CD 21    INT  21
C3       RET

0

ไฟล์ DOS COM - 36 ไบต์

56 BE 80 00 AD FE C8 A2 10 01 7E 17 89 F2 88 74
02 B4 3C 33 C9 CD 21 72 0A 8B D8 B4 40 5A B9 24
00 CD 21 C3 

ชื่อไฟล์ที่ส่งออกมีการระบุไว้ในบรรทัดคำสั่งตัดให้เป็นรูปแบบ 8.3 ช่องว่างตกลง (ช่องว่างในชื่อไฟล์ DOS ถูกกฎหมาย) ทดสอบโดยใช้พรอมต์คำสั่ง WinXP

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.