[c] 이 난독 화 된 C 코드는 main ()없이 실행된다고 주장하지만 실제로 어떤 역할을합니까?

#include <stdio.h>
#define decode(s,t,u,m,p,e,d) m##s##u##t
#define begin decode(a,n,i,m,a,t,e)

int begin()
{
    printf("Ha HA see how it is?? ");
}

이것은 간접적으로 호출 main합니까? 어떻게?



답변

C 언어는 독립형호스트 형의 두 가지 범주로 실행 환경을 정의합니다 . 두 실행 환경 모두에서 프로그램 시작을 위해 환경에 의해 함수가 호출됩니다.
A의 자립 환경 프로그램 기동 기능 구현 중에 정의 될 수 호스팅 환경이 있어야한다 main. 정의 된 환경에서 프로그램 시작 기능 없이는 C 프로그램을 실행할 수 없습니다.

귀하의 경우 main에는 전 처리기 정의에 의해 숨겨져 있습니다. begin()에 확장됩니다 decode(a,n,i,m,a,t,e)더 확장 될 것이다 main.

int begin() -> int decode(a,n,i,m,a,t,e)() -> int m##a##i##n() -> int main() 

decode(s,t,u,m,p,e,d)7 개의 매개 변수가있는 매개 변수화 된 매크로입니다. 이 매크로의 대체 목록은 m##s##u##t입니다. m, s, ut(4)이다 , 1 , 3 번째 및 2 교체리스트에 사용되는 파라미터.

s, t, u, m, p, e, d
1  2  3  4  5  6  7

나머지는 소용이 없습니다 ( 단지 난독 화하기 위해 ). 에 전달 인자 decode“이다 , N , I는 , m이 때문에, 식별자, A, t, E는” 과는 인수로 대체 하고 각각.m, s, utm, a, in

 m --> m
 s --> a
 u --> i
 t --> n


답변

사용 시도 gcc -E source.c와 함께, 출력단을 :

int main()
{
    printf("Ha HA see how it is?? ");
}

따라서 main()함수는 실제로 전처리기에 의해 생성됩니다.


답변

문제의 프로그램은 수행 전화를 main()인해 매크로 확장에, 그러나 당신의 가정은 결함이 – 그것은 하지 않습니다 호출 할 필요가 main()전혀!

엄밀히 말하면, C 프로그램을 가지고 main심볼 없이 컴파일 할 수 있습니다 . mainc library자체 초기화를 마친 후 점프 할 것으로 예상되는 것입니다 . 일반적으로 mainlibc 기호에서 _start. main없이 어셈블리를 실행하는 매우 유효한 프로그램을 항상 가질 수 있습니다. 이것 좀보세요 :

/* This must be compiled with the flag -nostdlib because otherwise the
 * linker will complain about multiple definitions of the symbol _start
 * (one here and one in glibc) and a missing reference to symbol main
 * (that the libc expects to be linked against).
 */

void
_start ()
{
    /* calling the write system call, with the arguments in this order:
     * 1. the stdout file descriptor
     * 2. the buffer we want to print (Here it's just a string literal).
     * 3. the amount of bytes we want to write.
     */
    asm ("int $0x80"::"a"(4), "b"(1), "c"("Hello world!\n"), "d"(13));
    asm ("int $0x80"::"a"(1), "b"(0)); /* calling exit syscall, with the argument to be 0 */
}

위를로 컴파일하고 인라인 어셈블리에서 시스템 호출 (인터럽트)을 실행하여 화면에 gcc -nostdlib without_main.c인쇄 Hello World!되는 것을 확인하십시오 .

이 특정 문제에 대한 자세한 내용은 ksplice 블로그를 확인하십시오.

또 다른 흥미로운 문제 main는 C 함수에 해당 하는 기호 없이 컴파일되는 프로그램을 가질 수도 있다는 것 입니다. 예를 들어 다음을 매우 유효한 C 프로그램으로 사용할 수 있으며 경고 수준이 올라갈 때만 컴파일러가 우는 소리를냅니다.

/* These values are extracted from the decimal representation of the instructions
 * of a hello world program written in asm, that gdb provides.
 */
const int main[] = {
    -443987883, 440, 113408, -1922629632,
    4149, 899584, 84869120, 15544,
    266023168, 1818576901, 1461743468, 1684828783,
    -1017312735
};

배열의 값은 Hello World를 화면에 인쇄하는 데 필요한 지침에 해당하는 바이트입니다. 이 특정 프로그램의 작동 방식에 대한 자세한 설명은이 블로그 게시물을 참조 하십시오.

이 프로그램에 대해 마지막으로 알려 드리고 싶습니다. C 언어 사양에 따라 유효한 C 프로그램으로 등록되어 있는지는 모르겠지만, 사양 자체를 위반하더라도 컴파일하고 실행하는 것은 확실히 가능합니다.


답변

누군가 마술사처럼 행동하려고합니다. 그는 우리를 속일 수 있다고 생각합니다. 그러나 우리 모두는 c 프로그램 실행이 main().

int begin()대체 될 decode(a,n,i,m,a,t,e)전처리 단계 중 하나 개를 통과하여. 그런 다음 다시 decode(a,n,i,m,a,t,e)m ## a ## i ## n으로 대체됩니다. 매크로 호출의 위치 연관과 마찬가지로 swill의 값은 character a입니다. 마찬가지로 u‘i’ t로 대체되고 ‘n’으로 대체됩니다. 그리고 그렇게 m##s##u##t될 것입니다.main

관한 ##매크로 팽창 기호는 전처리 연산자이며 토큰 붙여 넣기를 행한다. 매크로가 확장되면 각 ‘##’연산자의 양쪽에있는 두 개의 토큰이 단일 토큰으로 결합 된 다음 매크로 확장에서 ‘##’및 두 개의 원래 토큰을 대체합니다.

나를 믿지 않는다면 -E플래그로 코드를 컴파일 할 수 있습니다 . 전처리 후 컴파일 과정이 중단되고 토큰 붙여 넣기 결과를 볼 수 있습니다.

gcc -E FILENAME.c


답변

decode(a,b,c,d,[...])처음 4 개의 인수를 섞고 결합하여 순서대로 새 식별자를 얻습니다 dacb. (나머지 세 개의 인수는 무시됩니다.) 예를 들어, decode(a,n,i,m,[...])식별자를 제공합니다 main. 이것이 begin매크로가 정의 된 것입니다.

따라서 begin매크로는 간단히 main.


답변

귀하의 예제에서는 컴파일러가 매크로로 대체하고 차례로 m ## s ## u ## t 표현식으로 대체되는 매크로 main()이므로 함수가 실제로 존재 begin합니다 decode. 매크로 확장을 사용하면 from ##이라는 단어에 도달하게 main됩니다 decode. 이것은 추적입니다.

begin --> decode(a,n,i,m,a,t,e) --> m##parameter1##parameter3##parameter2 ---> main

를 갖는 것은 단지 속임수 main()이지만 main()C 프로그래밍 언어에서는 프로그램의 입력 함수에 이름 을 사용할 필요가 없습니다. 운영 체제와 해당 도구 중 하나 인 링커에 따라 다릅니다.

Windows에서 항상 사용하지 않는 main()하지만, 오히려 WinMainwWinMain 있지만, 사용할 수있는 main(), 심지어 마이크로 소프트의 툴 체인과 함께 . Linux에서는 _start.

언어 자체가 아니라 진입 점을 설정하는 운영 체제 도구로서의 링커에 달려 있습니다. 당신도 할 수 있습니다 우리 자신의 진입 점을 설정하고, 또한 실행 가능한 라이브러리를 만들 수 있습니다 !


답변