2009-10-03 5 views
0

그래서 누군가가 "어떻게"숨길 수 있는지 질문했습니다. 그것을 할 수인라인 어셈블리 및 함수가 세그 폴트로 인해 덮어 쓰기

 
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 

내 첫 번째 질문은 왜 인라인 어셈블리는 실패한다 ... 어떤 것이 올바른 방법은 : 문제가있다,

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

하지만이 내 대답했다? 다른 것 - "ret"또는 "retn"에 대한 코드는 0x00입니다. 바로 ... 내 코드 xor의 물건이 반환 될 때까지 ... 그렇다면 왜 SEGFAULTing입니까?

답변

1

높은 수준의 요점으로, 인라인 어셈블리를 사용하여 printf로 간단한 호출을하는 이유는 확실하지 않습니다. 모든 작업을 수행하면 잘못된 버전의 함수 호출이 생성됩니다. 인라인은 스택에 뭔가를 푸시하지만 결코 튕겨 나오지 않아서 문제를 야기 할 수 있습니다. GCC는 함수의 중간에서 스택 포인터를 수정했다는 것을 인식하지 못합니다. 더 복잡한 기능이 아닌 명백한 오류)

여기에 귀하의 상위 기능의 올바른 구현의 : 당신의 라에 관해서는

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

st 질문, RET에 대한 일반적인 opcode는 "C3"이지만 많은 유사 콘텐츠가 있습니다. http://pdos.csail.mit.edu/6.828/2009/readings/i386/RET.htm RET 검색에 대한 아이디어는 임의의 집합에서 0xC3 바이트를 볼 때 지시 사항이 있으시면, 귀하가 응급 처치를 당했다는 것을 의미하지는 않습니다. 0xC3은 단순히 다른 명령어의 데이터/속성 일 수 있기 때문에 (사이드 노트로, x86은 1-16 바이트 사이의 명령어 길이를 가진 CISC 아키텍처이기 때문에 x86 명령어를 시도하고 분석하는 것이 특히 어렵다.)

다른 메모로서 모든 OS가 텍스트/코드 세그먼트 (실행 가능한 명령어가 저장되는 곳)에 대한 수정을 허용하지는 않으므로 메인에있는 코드는 상관없이 작동하지 않을 수 있습니다.

1

GCC 인라인 asm은 AT & T 문법을 사용합니다 (인텔의 경우 특정 옵션을 선택하지 않은 경우).

다음은 예입니다 :

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

따라서, 문제는 "텍스트"전화에서 식별되지 않는 것입니다 (그리고 다음과 같은 명령도).

참조를 위해 here을 참조하십시오.

또한 코드는 32 비트와 64 비트 환경 사이에서 이식 가능하지 않습니다. 적절한 분석을 위해 -m32 플래그로 컴파일하십시오 (오류가 발생할 경우 GCC가 불평 할 것입니다).

문제에 대한 완벽한 해결책은 GCC 메일 링리스트의 this 게시물에 있습니다. 여기에 코드 조각의 : Windows 시스템에서

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 */); 

도 할 수있는 추가 asm ("addl %0, %%esp" : /* No outputs */ : "g" (method->args_size * 4));있다. 더 자세한 내용은 Google을 참조하십시오.

0

인쇄되지 않지만 _printf