대략적인 구성이 이렇게 되어있고 a.out 이라는 실행파일이 있다.

a.out 를 열어보면 'Can you read the flag?' 라는 문구를 출력하고

Falg value address 주소 값을 반환하는데 이건 여러번 실행해도 같은 주소값을 반환한다.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>

#define FLAG_PATH "./flag"
#define FLAG_SIZE 0x40

void alarm_handler() { exit(-1); }

void initialize()
{
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);
    signal(SIGALRM, alarm_handler);
    alarm(60);
}

char flag_buf[FLAG_SIZE];

void read_flag() {
    int fd = open(FLAG_PATH, O_RDONLY);
    if (fd < 0) {
        perror("open");
        exit(1);
    }

    ssize_t r = read(fd, flag_buf, FLAG_SIZE - 1);
    if (r < 0) {
        perror("read");
        close(fd);
        exit(1);
    }

    flag_buf[r] = '\0';
    close(fd);
}

int main() {
    initialize();

    char buf[1024];
    memset(buf,0x0,1024);

    read_flag();

    printf("Can you read the flag?\n");
    printf("Flag value address : %p\n",flag_buf);
    printf("Please answer this question (YES/NO) : ");

    read(0, buf, 1024);

    printf("Your opinion: ");
    printf(buf);

    
    return 0;
}

 

같은 메모리 주소값을 반환한다는 것은 어떤 의미를 가질까?

 

바로 전역변수라는 것이다. 지역변수의 경우 각 함수 내에서 변수값을 가져오기 때문에 함수가 실행되는 시점에 따라 변소 주소값이 변환된다.

그에 반해 전역변수는 어느 함수든 같은 위치에 있는 값을 가져와야 데이터 혼선이 없기 때문에 실행 시 항상 동일한 위치에 정해지게 된다.

 

그 전역 변수 선언이 바로 char flag_buf[FLAG_SIZE]; 이곳이다.

 

그럼 이제 메모리 주소값을 알기 때문에 큰 문제없이 접근이 가능하다.

 

필자는 gdb를 이용하여 해당 변수에 접근하겠다.

# main 우선 브레이크 포인트 걸기
(gdb) b main
# 프로그램 실행 시 main 첫 부분에 브레이크
(gdb) r
# main 내 read_flag()함수가 있기 때문에 해당 부분까지 실행해야 로딩
(gdb) n
# flag_buf의 메모리 주소 확인
(gdb) p &flag_buf
# 메모리 내 값 확인
(gdb) x/s &flag_buf

 

 

그 결과 FLAG{fIrst_M3Mory_re4D1}라는 값을 추출에 성공함

+ Recent posts