[문제링크](https://dreamhack.io/wargame/challenges/3021)
문제를 다운로드하여보면 구성은 다음과 같다.

문제를 보니 일반 pwnable이랑 구성이 비슷하다. chall 파일이 있고, flag.txt가 있다.
chall.enc를 읽어보면

와.... 이거 쉽지 않다.
hint.txt를 보면 다음과 같이 쓰여있다.
"X or going_to_home"
이게 뭘까... 곰곰이 생각해 보니
X or going_to_home
Xor going_to_home
xor "going_to_home"
이 된다.
일단 chall.enc를 going_to_home으로 xor 해보겠다.
data = open("chall.enc", "rb").read()
key = b"going_to_home"
key = (key * (len(data) // len(key) + 1))[:len(data)]
print(bytes(a ^ b for a, b in zip(data, key)).decode())

오 뭔가 cpp 같은 코드가 나온다.
이를 cpp파일로 옮긴 후 분석을 해보겠다.
void read_flag(){
ifstream itzfile("flag.txt");
string flag;
if(itzfile.is_open()){
getline(itzfile,flag);
}
cout<<flag;
}
flag를 보여주는 것은 여기 있다.
이를 호출하는 함수는
void going_out(int n){
if(n!=1){
cout<<"hack detected! terminating...";
return;
}
cout<<"i checked who you are. you need to pass the test\n";
int a;
random_device rd;
mt19937 gen(rd());
uniform_int_distribution<int> distrib(10000,100000);
int door=distrib(gen);
cout<<"type "<<door<<"\n";
cin>>a;
if(a==door){
cout<<"bye! i'll give you a key~\n";
read_flag();
return;
}
cout<<"say the number!";
//breaking bad reference
return;
}
여기 있고, 이를 호출하는 함수는
int main(){
signal(SIGALRM,yaza_end);
alarm(5);
string a;
random_device rd;
mt19937 gen(rd());
uniform_int_distribution<int> distrib(1,10);
cout<<"어서 자신의 집가고시픔을 어필해 주세요!\n\n";//zip gagohipheum
int auth=0;
while(1){
getline(cin,a);
int luck=distrib(gen);
if(luck==1)cout<<"응 안돼 돌아가\n";//return 0
else if(luck==2)cout<<"되겠냐?\n";//yey!
else if(luck==3)cout<<"집중 공부 실시\n";//shihumgigan
else if(luck==4)cout<<"아따 이러고 자빠졌네잉~\n";//i fall down
else if(luck==5)cout<<"얼마 줄건데~~~\n";//u-chi
else if(luck==6){
if(a.compare(0,3,"key")==0){
cout<<"it's a ";//noice grammer~
auth++;
}
cout<<"random text6\n";
}
else if(luck==7)cout<<"6번과 10번에서 내가 바로 대답하지 않은 이유는 당연해서가 아니다\n";
else if(luck==8)cout<<"참고로 이거 java로 썼다\n";//hutsori
else if(luck==9)cout<<"헛소리 집어치워!\n";//hutsori2
else if(luck==10){
if(a.compare(0,10,"secretcode")==0 && auth==1){
going_out(auth);
return 0;
}else{
cout<<"나갈 기회는 충분하다!\n";//or not?
}
}
}
}
여기 있다.
going_out함수를 보면, 10000~100000이 uniform 분포로 door에 설정되고 door를 타이핑하면 된다.
going_out함수를 실행하는 부분을 보면, 입력이 secretcode여야 하며, auth는 1이어야 한다.
auth를 1로 하는 부분은 luck이 6일 때 입력이 key여야 한다.
즉, 정리하면
luck이 6일 때, 입력이 "key"
luck이 10일 때, 입력이 "secretcode"
type {n}이 출력되면, 입력이 "{n}"
하면 flag가 나온다.
이를 python 코드로 작성하면
from pwn import *
p = remote("host3.dreamhack.games", 23162)
p.recvuntil("어서 자신의 집가고시픔을 어필해 주세요!\n\n")
# luck이 랜덤이기에 6이 나올 때까지 반복
six_detected = False
while(not six_detected):
p.sendline(b"key")
response = p.recvline().decode()
# luck이 6일때 나오는 텍스트
if(response == "it's a random text6\n"):
six_detected = True
# 마찬가지로 luck이 랜덤이기에 10이 나올 때까지 반복
ten_detected = False
while(not ten_detected):
p.sendline(b"secretcode")
response = p.recvline().decode()
# luck이 10일때 나오는 텍스트
if(response == "i checked who you are. you need to pass the test\n"):
ten_detected = True
# 형식이 "type {n}"임
typeNumber = p.recvline().decode().split("type ")[1]
p.send(f"{typeNumber}".encode())
p.interactive()
다음과 같고, 이를 실행하면

flag를 얻을 수 있다.