Last active
March 15, 2023 02:54
-
-
Save LiveOverflow/bbdffe3777ce0f008b452e0a789cef65 to your computer and use it in GitHub Desktop.
GoogleCTF2018 - JS Safe 2
This file contains hidden or 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 random | |
import re | |
# python3 | |
# STAGE 1 | |
""" | |
stage1 = 'Ӈ#7ùª9¨M¤À.áÔ¥6¦¨¹.ÿÓÂ.Ö£JºÓ¹WþÊmãÖÚG¤ ¢dÈ9&òªћ#³1᧨' | |
out = "" | |
key = "\x82\x1e\x0a\x9a" | |
for i in range(0, len(stage1)): | |
out += (chr(ord(stage1[i])^ord(key[i%len(key)]))) | |
print(out) | |
х==c('¢×&Ê´cʯ¬$¶³´}ÍÈ´T©Ð8ͳÍ|Ô÷aÈÐÝ&¨þJ',h(х))//᧢ | |
""" | |
# STAGE 2 | |
stage2 = '¢×&Ê´cʯ¬$¶³´}ÍÈ´T©Ð8ͳÍ|Ô÷aÈÐÝ&¨þJ' | |
valid_re = re.compile(r'^[0-9a-zA-Z_@!?-]+$') | |
# return every 4th character of s, starting at the nth offset | |
def extract_nth(s, nth=0): | |
return "".join(list("{}".format(a) for a in s[nth::4])) | |
# xor the given cipher text with a repeating the key bytes | |
def xor(cipher, key): | |
out = "" | |
for i in range(0, len(cipher)): | |
out += (chr(ord(cipher[i])^(key[i%len(key)]))) | |
return (out) | |
# collect possible key candidates for each byte | |
key_canditates = {} | |
for offset in range(0,4): | |
for key_byte in range(0x00, 0xff+1): | |
tmp = extract_nth(stage2, offset) | |
plain = xor(tmp, [key_byte]) | |
if valid_re.match(plain): | |
# remember this possible key_byte in a dict | |
if offset not in key_canditates: | |
key_canditates[offset] = [] | |
key_canditates[offset].append(key_byte) | |
# print all possible decrypted flags | |
for a in key_canditates[0]: | |
for b in key_canditates[1]: | |
for c in key_canditates[2]: | |
for d in key_canditates[3]: | |
print(xor(stage2, [a, b, c, d])) | |
""" | |
_B3x7!v3R91ON!h45!AnTE-4NXi-abt1-H3bUk_ | |
_N3x7-v3R51ON-h45-AnTI-4NTi-ant1-D3bUg_ | |
""" |
This file contains hidden or 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
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>JS safe v2.0 - the leading localStorage based safe solution with military grade JS anti-debug technology</title> | |
<!-- | |
Advertisement: | |
Looking for a hand-crafted, browser based virtual safe to store your most | |
interesting secrets? Look no further, you have found it. You can order your own | |
by sending a mail to [email protected]. When ordering, please specify the | |
password you'd like to use to open and close the safe. We'll hand craft a | |
unique safe just for you, that only works with your password of choice. | |
--> | |
<style> | |
body { | |
text-align: center; | |
} | |
input { | |
font-size: 200%; | |
margin-top: 5em; | |
text-align: center; | |
width: 26em; | |
} | |
#result { | |
margin-top: 8em; | |
font-size: 300%; | |
font-family: monospace; | |
font-weight: bold; | |
} | |
body.granted>#result::before { | |
content: "Access Granted"; | |
color: green; | |
} | |
body.denied>#result::before { | |
content: "Access Denied"; | |
color: red; | |
} | |
#content { | |
display: none; | |
} | |
body.granted #content { | |
display: initial; | |
} | |
.wrap { | |
display: inline-block; | |
margin-top: 50px; | |
perspective: 800px; | |
perspective-origin: 50% 100px; | |
} | |
.cube { | |
position: relative; | |
width: 200px; | |
transform-style: preserve-3d; | |
} | |
.back { | |
transform: translateZ(-100px) rotateY(180deg); | |
} | |
.right { | |
transform: rotateY(-270deg) translateX(100px); | |
transform-origin: top right; | |
} | |
.left { | |
transform: rotateY(270deg) translateX(-100px); | |
transform-origin: center left; | |
} | |
.top { | |
transform: rotateX(-90deg) translateY(-100px); | |
transform-origin: top center; | |
} | |
.bottom { | |
transform: rotateX(90deg) translateY(100px); | |
transform-origin: bottom center; | |
} | |
.front { | |
transform: translateZ(100px); | |
} | |
@keyframes spin { | |
from { transform: rotateY(0); } | |
to { transform: rotateY(360deg); } | |
} | |
.cube { | |
animation: spin 20s infinite linear; | |
} | |
.cube div { | |
position: absolute; | |
width: 200px; | |
height: 200px; | |
background: rgba(0, 0, 0, 0.51); | |
box-shadow: inset 0 0 60px white; | |
font-size: 20px; | |
text-align: center; | |
line-height: 200px; | |
color: rgba(0,0,0,0.5); | |
font-family: sans-serif; | |
text-transform: uppercase; | |
} | |
</style> | |
<script> | |
function x(х) { | |
ord = Function.prototype.call.bind(''.charCodeAt); | |
chr = String.fromCharCode; | |
str = String; | |
function h(s) { | |
console.log("h('"+s+"')"); | |
for (i = 0; i != s.length; i++) { | |
a = ((typeof a == 'undefined' ? 1 : a) + ord(str(s[i]))) % 65521; | |
b = ((typeof b == 'undefined' ? 0 : b) + a) % 65521 | |
} | |
return chr(b >> 8) + chr(b & 0xFF) + chr(a >> 8) + chr(a & 0xFF) | |
} | |
function c(a, b, c) { | |
for (i = 0; i != a.length; i++) c = (c || '') + chr(ord(str(a[i])) ^ ord(str(b[i % b.length]))); | |
console.log("XOR decrypt result: "+c); | |
return c | |
} | |
for (a = 0; a != 1000; a++) {}; | |
foo = "function x(х){ord=Function.prototype.call.bind(''.charCodeAt);chr=String.fromCharCode;str=String;function h(s){for(i=0;i!=s.length;i++){a=((typeof a=='undefined'?1:a)+ord(str(s[i])))%65521;b=((typeof b=='undefined'?0:b)+a)%65521}return chr(b>>8)+chr(b&0xFF)+chr(a>>8)+chr(a&0xFF)}function c(a,b,c){for(i=0;i!=a.length;i++)c=(c||'')+chr(ord(str(a[i]))^ord(str(b[i%b.length])));return c}for(a=0;a!=1000;a++)debugger;x=h(str(x));source=/Ӈ#7ùª9¨M¤À.áÔ¥6¦¨¹.ÿÓÂ.Ö£JºÓ¹WþÊmãÖÚG¤ ¢dÈ9&òªћ#³1᧨/;source.toString=function(){return c(source,x)};try{console.log('debug',source);with(source)return eval('eval(c(source,x))')}catch(e){}}"; | |
x = h(str(foo)); | |
source = /Ӈ#7ùª9¨M¤À.áÔ¥6¦¨¹.ÿÓÂ.Ö£JºÓ¹WþÊmãÖÚG¤ ¢dÈ9&òªћ#³1᧨/; | |
source.toString = function() { | |
return c(source, x) | |
}; | |
try { | |
//console.log('debug', source); | |
// х==c('¢×&Ê´cʯ¬$¶³´}ÍÈ´T©Ð8ͳÍ|Ô÷aÈÐÝ&¨þJ',h(х))//᧢ | |
with(source) return eval('eval(c(source,x))') | |
} catch (e) {} | |
} | |
</script> | |
<script> | |
function open_safe() { | |
keyhole.disabled = true; | |
password = /^CTF{([0-9a-zA-Z_@!?-]+)}$/.exec(keyhole.value); | |
if (!password || !x(password[1])) return document.body.className = 'denied'; | |
document.body.className = 'granted'; | |
password = Array.from(password[1]).map(c => c.charCodeAt()); | |
encrypted = JSON.parse(localStorage.content || ''); | |
content.value = encrypted.map((c,i) => c ^ password[i % password.length]).map(String.fromCharCode).join('') | |
} | |
function save() { | |
plaintext = Array.from(content.value).map(c => c.charCodeAt()); | |
localStorage.content = JSON.stringify(plaintext.map((c,i) => c ^ password[i % password.length])); | |
} | |
</script> | |
</head> | |
<body> | |
<div> | |
<input id="keyhole" autofocus onchange="open_safe()" placeholder="🔑"> | |
</div> | |
<div class="wrap"> | |
<div class="cube"> | |
<div class="front"></div> | |
<div class="back"></div> | |
<div class="top"></div> | |
<div class="bottom"></div> | |
<div class="left"></div> | |
<div class="right"></div> | |
</div> | |
</div> | |
<div id="result"> | |
</div> | |
<div> | |
<input id="content" onchange="save()"> | |
</div> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment