이번 문제는 바이너리가 아닌 무슨 소스코드를 다운받는거 같다. 한번 코드를 다운 받아 보면,
요런 C언어 소스코드가 다운 받아짐을 확인 할 수 있다. C 소스코드는 다음과 같이 생겼당
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <ctype.h>
void get_flag(){
system("cat flag");
}
int rps(){
int computer=rand()%3,len,player=-1,i=0;
char input[10]={0,};
switch(computer){
case 0:
puts("My choice >Rock");
break;
case 1:
puts("My choice >Paper");
break;
case 2:
puts("My choice >Scissors");
break;
}
printf("Your input(Rock, Scissors, Paper) >");
len = read(STDIN_FILENO,input,10);
if(input[len-1]=='\n') input[len-1]='\0';
while(input[i]){
input[i]=toupper(input[i]);
i++;
}
if(!strcmp(input,"ROCK")) player=2;
if(!strcmp(input,"SCISSORS")) player=1;
if(!strcmp(input,"PAPER")) player=0;
if(player==-1)return 0;
if(player==computer){
return 1;
}
else{
puts("Seriously??");
return 0;
}
}
void intro(){
puts("===== Play a game with me! =====");
puts("Do you know rock paper scissors?");
puts("It's a simple game.. Rock beats scissors,");
puts("And scissors beat paper.");
puts("Finally, paper beats rock.");
puts("So simple rule.. if you win 100times, I'll just give you flag");
}
int main(){
setvbuf(stdin,0,2,0);
setvbuf(stdout,0,2,0);
srand(time(NULL));
int cnt=0;
intro();
while(1){
printf("\nYou have won %d times.\n",cnt);
if(cnt >= 100){
get_flag();
exit(0);
}
cnt += rps();
}
exit(0);
return 0;
}
|
코드를 해석해보면 "Rock", "Scissors", "Paper" 중 무작위로 하나를 보여주고 프로그램이 "Rock"이면, "Paper",
"Siccors"면 "Rock", "Paper"면 " Siccors"를 입력해서 즉, 가위바위보에서 이기면 1점을 얻는다. 그리고 총 100번을 이기면
flag를 얻게 되는 방식인데 물론 100번 손수 다 입력해서 flag를 얻을 수도 있겠지만, pwntools를 활용하면,
아~~주 쉽게 flag를 쓱싹 할 수 있당.
우선 저 프로그램 컴파일후 실행 시켜보면,
"My choice >(프로그램이 낸 값)"이라는 문자열과 밑에 줄에는 우리가 입력을 할 수가 있당 예시로 위와 같이 프로그램이
"Scissors"를 냈고 내가 "Rock"을 입력으로 넣으면 밑에 내가 한번 이겼다는 문자열과 함께 또 다시 프로그램이 낸 값과 내가 입력을 할 수
있게 된당 이제 내가 짠 익스코드를 보면,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
from pwn import *
i=0
while i<100:
p.recvuntil("My choice >")
data=p.recvuntil("\n")[:-1]
p.recvuntil("Your input(Rock, Scissors, Paper) >")
if data=="Rock":
p.sendline("Paper")
elif data=="Scissors":
p.sendline("Rock")
elif data=="Paper":
p.sendline("Scissors")
i=i+1
p.interactive()
|
remote로 nc 서버랑 연결한 다음 while문을 100번 돌리면서 recvuntil함수로 "My choice"까지 받아서 저장하지 않고 버린당 그럼 그줄에 남는 문자열은 프로그램이 낸 값만 남게될 거고, 다음 한번더 recvuntil함수를 통해 개행문자"\n"전까지인 데이터를 담는다. 즉 프로그램이 낸 값만 문자열로 data라는 변수에 저장이 된당 이후 한번더 recvuntil함수로 "Your input(Rock, Scissors, Paper) >" 까지 걸러낸 다음,
프로그램이 낸 값에 따라 sendline함수로 데이터를 보낸당 이렇게 100돌리고 나면 위과 같이 flag가 잘 나옴을 확인 할 수 있다.
FLAG : flag{Y0u_kn0w_'bout_s0ck3t_pro9ramm1n9!!}
'WARGAME > smch ctf' 카테고리의 다른 글
SMCH CTF - BOF_ret (0) | 2019.11.09 |
---|---|
SMCH CTF - Calc (0) | 2019.11.09 |
SMCH CTF - BOF4 (0) | 2019.11.08 |
SHCH CTF - BOF3 (0) | 2019.11.03 |
SMCH CTF - BOF2 (EZ) (0) | 2019.11.03 |