Pregunta

Alguien más en SO registró una pregunta sobre la forma en que pudo "ocultar" una función. Esta fue mi respuesta:

#include <stdio.h>
#include <stdlib.h>

int encrypt(void)
{
  char *text="Hello World";
  asm("push text");
  asm("call printf");
  return 0;
}

int main(int argc, char *argv[])
{
  volatile unsigned char *i=encrypt;
  while(*i!=0x00)
    *i++^=0xBE;
  return EXIT_SUCCESS;
}

Sin embargo, hay problemas:

encode.c: In function `main':
encode.c:13: warning: initialization from incompatible pointer type
C:\DOCUME~1\Aviral\LOCALS~1\Temp/ccYaOZhn.o:encode.c:(.text+0xf): undefined reference to `text'
C:\DOCUME~1\Aviral\LOCALS~1\Temp/ccYaOZhn.o:encode.c:(.text+0x14): undefined reference to `printf'
collect2: ld returned 1 exit status

Mi primera pregunta es ¿por qué el ensamblador en línea fallando ... ¿cuál sería la forma correcta de hacerlo? Otra cosa - el código para "ret" o "RETN" es 0x00, a la derecha ... cosas mi código de xor hasta que alcanza un rendimiento ... ¿por qué es violación de segmento

¿Fue útil?

Solución

Como punto de alto nivel, no estoy seguro de por qué usted está tratando de utilizar ensamblador en línea para hacer una simple llamada a printf, como todo lo que ha hecho es crear una versión incorrecta de una llamada de función (su línea empuja algo en la pila, pero nunca pop si fuera poco, los problemas que causa más probable causa del CCG no es consciente de que ha modificado el puntero de pila en el medio de la función. Esto está bien en un ejemplo trivial, pero podría conducir a la no errores -obvious en una función más complicado)

Aquí hay una aplicación correcta de la función de la parte superior:

int encrypt(void)
{
  char *text="Hello World";
  char *formatString = "%s\n";
  // volatile really isn't necessary but I just use it by habit
  asm volatile("pushl %0;\n\t"
               "pushl %1;\n\t"
            "call printf;\n\t"
               "addl $0x8, %%esp\n\t"          
               : 
               : "r"(text), "r"(formatString)
               );

  return 0;
}

En cuanto a su última pregunta, el código de operación habitual para RET es "C3", pero hay muchas variaciones, echar un vistazo a http://pdos.csail.mit.edu/6.828/2009/readings/i386/RET.htm Su idea de la búsqueda de RET también es defectuosa ya que debido al hecho de que cuando vea el 0xC3 byte en un conjunto aleatorio de instrucciones, esto no significa que usted ha encontrado un ret. A medida que el 0xC3 puede ser simplemente los datos / atributos de otra instrucción (Como nota al margen, es particularmente difícil de tratar y analizar las instrucciones x86 como usted está haciendo debido al hecho de x86 es una arquitectura CISC con la instrucción longitudes de entre 1-16 bytes )

Como otra nota, no todos los OS de permitir la modificación al segmento de texto / código (cuando se almacenan instrucciones ejecutables), por lo que el código que tiene en principal no pueden trabajar independientemente.

Otros consejos

asm GCC en línea utiliza la sintaxis de AT & T (si no se seleccionan opciones específicas para el uso de Intel uno).

Este es un ejemplo:

 int a=10, b;
 asm ("movl %1, %%eax; 
       movl %%eax, %0;"
      :"=r"(b)        /* output */
      :"r"(a)         /* input */
      :"%eax"         /* clobbered register */
      );       

Por lo tanto, el problema es que el "texto" no es identificable de su llamada (y siguiendo instrucciones también).

aquí de referencia.

Además su código no es portable entre 32 y 64 entornos bits. Compilarlo con la bandera -m32 para garantizar un análisis adecuado (GCC se quejará de todos modos si usted se cae en el error).

Una solución completa a su problema está en este poner en la lista de correo GCC. He aquí un fragmento:

for ( i = method->args_size - 1; i >= 0; i-- ) {
    asm( "pushl %0": /* no outputs */: \
         "g" (stack_frame->op_stack[i]) );
}

asm( "call *%0" : /* no outputs */ : "g" (fp) :
     "%eax", "%ecx", "%edx", "%cc", "memory" );

asm ( "movl %%eax, %0" : "=g" (ret_value) : /* No inputs */ );

En los sistemas Windows también hay un asm ( "addl %0, %%esp" : /* No outputs */ : "g" (method->args_size * 4) ); adicional para hacerlo. Google para más detalles.

No es printf pero _printf

scroll top