Escribe un programa autorreplicante.

11

Escriba un programa simple que se copie solo cuando se ejecute.

Su programa debe ser algún tipo de archivo ejecutable en Windows, Linux, etc., debe generar un nuevo archivo ejecutable, que es idéntico a su archivo ejecutable original, con un nombre aleatorio y se cierra.

Su programa no debe involucrar ningún tipo de lectura o copia de archivos. Solo se permite la escritura de archivos para generar un nuevo archivo ejecutable.

(PD. Estaba bastante avergonzado cuando en Wikipedia, Self-replicating programredirige al Computer virusartículo ...: / ...)

El tamaño de archivo ejecutable más pequeño gana. Su respuesta puede ser un código de programación con sistema operativo y compilador adecuados, código de ensamblaje o volcado HEX de un archivo ejecutable.

JiminP
fuente
66
Esto parece variar solo trivialmente de los desafíos [quine] existentes. ¿O he entendido mal?
dmckee --- ex-gatito moderador
1
@dmckee Vi que el lenguaje ensamblador Quine y el programa Hello World autorreplicante aceptaban copias, pero no pude encontrar el programa se escribe solo , no su código .
JiminP
1
... pero quiero ver cómo funciona realmente ... No sé cómo se puede ampliar la idea con códigos binarios ... aunque leí el artículo de Quine en Wikipedia. PD. no hay compiladores para replicar y no se permiten lenguajes de script ...: /
JiminP
44
Cualquier problema puede hacerse un poco más difícil y feo agregando más restricciones. Este problema me parece una extensión trivial del problema quine.
Alexandru
1
Si gana el tamaño ejecutable más pequeño, ¿no deberíamos incluir también el código del intérprete como parte del tamaño ejecutable para que esto sea justo para los usuarios de lenguajes compilados?
Thomas Dignan

Respuestas:

4

Bash, 236

Más de lo estrictamente necesario, pero odio las largas colas. La nueva línea final no es opcional.

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 $$
JB
fuente
En realidad, no es lo que quería, sin embargo, ya que escribí una pregunta "incorrecta" y su respuesta es una gran pregunta ...
JiminP
@ Jimim: ¿Cómo no es lo que querías? Acabo de leer la descripción del problema dos veces más y no lo entiendo.
JB
Bueno ... lo que quería era un código binario ejecutable. Como admití anteriormente, ya que mi pregunta no era del todo "correcta" ... lo siento.
JiminP
3
@JiminP Bueno, sí, la palabra "binario" no aparece en absoluto en la pregunta. Lo acabo de encontrar en los comentarios, pero para tal restricción, simplemente no es suficiente. Puede abrir una nueva pregunta con toda la información consolidada de los comentarios. Le sugiero que use el sandbox para asegurarse de que los clientes habituales lo ayuden a resolver los pequeños detalles. Pero cuidado, las respuestas binarias tienden a ser realmente aburridas.
JB
10

Ensamblado para x86 Linux, 106 bytes

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     $ - $$

Esto es para el ensamblador nasm. Construya el binario con la línea de comando:nasm -f bin -o a.out selfrep.asm && chmod +x a.out

Aquí está el mismo archivo que un volcado hexadecimal: 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

Según lo solicitado, el programa se copia en un archivo separado. (El programa podría haber sido significativamente más corto si se le hubiera permitido escribir en stdout y permitir al usuario redirigir a un archivo).

Evité usar cualquier truco límite para reducir el tamaño. Este debería ser un binario ELF de 32 bits totalmente conforme.

Editado para agregar : en la versión anterior, el archivo creado es solo un archivo simple, pero se me ocurre que por un par de bytes (y una pequeña curva de las reglas), puede crear algo un poco más interesante. Esta versión es solo dos bytes más larga, a 108 bytes:

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     $ - $$

Nombre esta versión asr, para "un autorreplicador":nasm -f bin -o asr asr.asm && chmod +x asr

Versión de volcado hexadecimal para personas con problemas nasm: 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

Cuando lo ejecuta, crea un archivo casi idéntico llamado bsr, pero uno que es ejecutable. Ejecutarlo creará otro archivo binario llamado csr. Y así.

(Tenga en cuenta que las cosas molestas comienzan a suceder después zsr. Pensé en hacer una versión que cambiara el nombre en cascada atry así sucesivamente, pero creo que la mayoría de la gente se aburrirá mucho antes de eso, por lo que probablemente no valga la pena todos los bytes adicionales. )

caja de pan
fuente
+1 para la respuesta de la asamblea! ¿Has visto el desafío quine de la asamblea ?
MD XF
2

Aquí hay una prueba de concepto (sin golf) que muestra cómo los servicios de compilación en .NET podrían usarse para compilar el código fuente sobre la marcha para generar una salida idéntica. La primera copia no es idéntica al original, pero las copias posteriores de ejecuciones posteriores son exactamente idénticas con nombres de archivos aleatorios:

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);
        }
    }
}

Salida de demostración en línea de comando:

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>
mellamokb
fuente
2

Lote

Versión 1 (30 bytes)

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

¡Yo gano! :)

st0le
fuente
la referencia% 0 provoca una lectura del archivo, lo que viola las reglas. Además, mi versión binaria es aún más corta. :-)
Peter Ferrie
1

Archivo COM de DOS: 50 bytes

Crea un archivo X.COMdonde Xse reemplaza con los dígitos de la hora actual. Los archivos COM simplemente se cargan en la memoria en el desplazamiento 100hdel segmento de datos (CS y DS están configurados para ser los mismos) para que simplemente podamos escribir esta memoria en un archivo.

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.

fuente 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 $-$$
Geoff Reedy
fuente
1

Archivo DOS .COM, 29 bytes

La '@' se reemplaza aleatoriamente por una letra impar en la primera mitad + parte del alfabeto (A, C, E, G, etc.). Los archivos de salida son 255 o 256 bytes. Los registros iniciales en DOS real (a diferencia de un depurador) son que 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
Peter Ferrie
fuente
0

Archivo COM DOS - 36 bytes

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 

El nombre del archivo de salida se especifica en la línea de comando, truncado al formato 8.3, espacios OK (los espacios en los nombres de archivo DOS son legales). Probado con el símbolo del sistema WinXP.

Skizz
fuente