Pwnablekr_Toddlers Bottle_blukat

보호 기법으로 카나리와 NX가 적용되어 있다. 64비트 프로그램이다.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
char flag[100];
char password[100];
char* key = "3\rG[S/%\x1c\x1d#0?\rIS\x0f\x1c\x1d\x18;,4\x1b\x00\x1bp;5\x0b\x1b\x08\x45+";
void calc_flag(char* s){
    int i;
    for(i=0; i<strlen(s); i++){
        flag[i] = s[i] ^ key[i];
    }
    printf("%s\n", flag);
}
int main(){
    FILE* fp = fopen("/home/blukat/password", "r");
    fgets(password, 100, fp);
    char buf[100];
    printf("guess the password!\n");
    fgets(buf, 128, stdin);
    if(!strcmp(password, buf)){
        printf("congrats! here is your flag: ");
        calc_flag(password);
    }
    else{
        printf("wrong guess!\n");
        exit(0);
    }
    return 0;
}

생각난 방법

  1. buf에 버퍼 오버플로우를 일으켜 글로벌 변수인 password 내용을 노출 시키기
  2. pintool을 이용한 사이드이펙트(strcmp에서 계산 수 차이가 있지 않을까?)

2번 방법은 문제를 풀어야 하는 서버에 pintool 라이브러리가 깔려있지 않아 안될 것 같다. 대신 시간을 측정하는 방법은 가능할지도 모르겠다 생각하여 실험해보았지만, 차이가 너무 미세하여 pintool 없이 사이드이펙트를 보기는 어려워보인다.

1번 방법은 스택 카나리를 처리해야 한다. 며칠 전에 읽은 책에서 카나리 check에서 실패하여 메시지를 출력할 때, 프로그램 이름(argv[0])을 출력한다는 것을 보았다.

하지만 여기서는 strcmp에 실패할 시 바로 exit을 하므로, 이 방법은 못 쓰겠다. (카나리 확인은 함수를 나가기 전에 하므로)

풀이

설정과 관련된 문제였다.

이 계정의 그룹은 blukat_pwn에 속한다. 그냥 password 파일을 읽을 수 있다.

cat: password: Permission denied는 오류 메시지가 아니라 바로 패스워드다.

flag는 congrats! here is your flag: Pl3as_DonT_Miss_youR_GrouP_Perm!! 이다.


tags: writeup, pwnable, elf file, linux, c lang, linux permission