Linux/Linux_technic

제한시간 1초, 수학문제 프로그램 해킹?!

sosal 2010. 11. 6. 18:33
반응형


/*
 http://sosal.tistory.com/
 * made by so_Sal
 */



/*

 * 이 포스팅을 이해하기 위해선
 * c언어 srand(), time(), rand() 함수들
 * 리눅스 read write 파일 시스템콜 뿐만 아니라
 * fork(), execl(), pipe(), dup2() 프로세스 시스템콜을
 * 미리 아셔야 이해할 수 있습니다./
 */


예전에 숫자 맞추는 게임(?)이 널루트 가입문제로 나왔었던 기억이..있습니다 ㅎㅎ
아마 억대자리수 덧셈이었나?? 그럴텐데.. 기억이 잘 안나네요.
(동아리 선배분께서 열심히 풀고계신걸 잠깐 본적이 ㅎㅎㅎ)
여튼, 번뜩 생각나서 고걸 부셔버리는걸로.. 한번 포스팅 해보려고 합니다.
목적은 1초안에 1만자리수 덧셈문제를 풀기! 입니다.

srand()함수와 rand()함수는 다 아실거라 믿고...
srand()에 보통 time(0)를 넣죠?



#include <time.h>

    time_t time(time_t *t);
time - 초 단위로 시간을 얻는다.
    //man page 참조


초 단위로 시간을 얻는다는 말은, 즉 1초 간격으로 난수 테이블의 같은 시드값을 리턴한다는 말..


// gcc rand.c -o rand
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

int main(){
    srand(time(NULL));

    int a = rand()%10000
    printf("%d",a);
    return 0;
}



엄청 열심히, 빠르게!! 위 프로그램을 실행시켰습니다 -.-;;
역시 1초 단위로 rand()는 같은값을 리턴하네요..
덕분에 이 결과로 srand()시드값이 time(NULL)에 의해
1초간 같은 결과를 리턴한다는 사실을 확실하게 알 수 있었습니다.

그럼 이 원리를 통해.. 숫자 맞추기 게임을 풀 수 있겠습니다 ㅇ_ㅇ;


#include<stdio.h>
#include<time.h>

int main(){
    srand(time(0)); //1초 간격으로 같은 시드값 리턴

    printf("====== Speed math test!! ======\n");
    int operand1 = rand() / 100000; 
    int operand2 = rand() / 100000;
    int input;
    int result = operand1 + operand2;

    alarm(1); //제한시간 1초 -.-;

    printf("%d + %d = ?\n",operand1,operand2);
    scanf("%d",&input);

    if( result == input ) //정답확인
        printf("success!\n");
    else
        printf("fail..!\n");

    return 0;
}



실행해보았습니다.
1초만에 풀려고하니 alarm(1) , 1초 알람신호 때문에 왠만한 산수천재 아니고선..;;
그리고 찍짜하니..;; 답이없고 ㅠㅠ
하지만 우리는, 프로그래머 아닙니까? :-)
프로그래밍으로 풀어봅시다 +_+





/*
 * srand( time(0) )을 메인함수에서 일단 실행합니다.
 * 이로써, 곧 만들 프로그램은 math 문제와 같은 rand 시드를 가지고 시작합니다.
 * 2개의 pipe를 생성한 후, 자식 프로세스를 만듭니다.
 * dup2를 이용하여 자식프로세스의 표준입력을 input-pipe로,
 * dup2를 이용하여 자식프로세스의 표준출력을 output-pipe로 설정합니다.
 * execl 시스템콜을 이용하여 자식프로세스를 문제의 프로그램 math로 바꿔버립니다.
 * rand 시드가 똑같으니, 같은 결과값을 맞출 수 있습니다.
 * 그 답을 자식프로세스 (즉 math)에게 넘기면 문제 성공!
 */


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

int
main(){
    srand(time(0));
    int pid;
    int input[2];              // 부모에서 math 프로그램으로 입력할 파이프
    int output[2];            // math 프로그램이 출력하는 문자열을 건넬 파이프
    char buffer[BUFSIZ];

    if( pipe(input) !=0 ){
        perror("pipe error\n");
        exit(EXIT_FAILURE);
    }
    if( pipe(output) != 0){
        perror("pipe error\n");
        exit(EXIT_FAILURE);
    }                           // 입출력 파이프 2개 생성 완료

    pid = fork();
    if(pid == -1){
    }
    else if(pid == 0){
        //child process
        dup2(input[1],1); //input to STDIN
        dup2(output[0],0); // output to STDOUT
        execl("./math","math",0); 
        perror("execl error\n"); //execl 실패시 에러 출력
        exit(EXIT_FAILURE);
    }
    //parent process
    int count;
    int oper1,oper2;
    oper1 = rand() / 100000;
    oper2 = rand() / 100000;  
    sprintf(buffer,"%d",oper1+oper2); //문제의 프로그램의 답 알아내는 과정
    write(output[1],buffer,BUFSIZ);
    while(1){
        count = read(input[0],buffer,BUFSIZ);
        printf("%s\n",buffer); //답 전달
        break;
    }

    return 0;
}