Rating: 5.0

When we look at the open_safe() function we can see that it requires our input to be in form `CTF{[0-9a-zA-Z_@!?-]+}` and only the middle part is checked.
We can't just skip password verification, because it is used as encryption key and we'll got wrong result.
Now, let's proceed to x() function which checks if our input is valid.
I copied this function to scratchpad in Firefox, so I can easily modify it and immediately see the results.
First, let's add the following code
```js
if(/g/.test(code.substr(i,4)))
{
console.log(i);
console.log(env[fn]);
console.log(env);
console.log(code.substr(i,4));
break;
}
```
`env[g]` contains our input, so probably nothing very important happens before it is used.
W we have to notice is that this code can not only do some calculations on numbers, but it also can create strings and functions.
The other thing is that if object property doesn't exist and we try to write something to it, JS will just add the property.

When we dump `env` object (i==876) we can see something interesting.
There is SubtleCrypto in one property and we have also digest function and `sha-256` parameter. Let's see what happens next.
```js
if(i==880)
```
In the last property we have an array of `sha-256` string and Uint8Array with our password.
It will be probably passed as an argument to digest() function.
I added some pseudo disassembly to see what's going on later.
```js
if(i>=872)
{
console.log(i);
console.log(lhs+"="+fn+"("+arg1+","+arg2+")")
console.log(lhs+"="+env[fn]+"("+env[arg1]+","+env[arg2]+")")
}
if(i==980)
{
console.log(env);
break;
}
```
For i=940 they move hash of our input to `env[Ѿ]` and for i=960 they move first byte of it to `env[ѿ]`. Then they xor the result with 230 and `or` it to `env[h]` which is used to check if the password was correct. (`env[h]` must be zero, so all xors need to be zero too)
`xor a,b` gives 0 only if `a=b`, so we know that first byte of our hash must equal 230.
Replace our disassembler with
```js
var hash =[];
for (var i = 0; i < code.length; i += 4) {
var [lhs, fn, arg1, arg2] = code.substr(i, 4);
if(fn=='ѡ')
{
hash.push(env[arg1][1]);
}
```
Now we know the required hash of our password ` 230,104,96,84,111,24,205,187,205,134,179,94,24,181,37,191,252,103,247,114,198,80,206,223,227,255,122,0,38,250,29,238` -> `e66860546f18cdbbcd86b35e18b525bffc67f772c650cedfe3ff7a0026fa1dee`
As they mentioned in the comment we can google for this hash and we get the password `Passw0rd!`

Flag: `CTF{Passw0rd!}`

Original writeup (https://github.com/BOAKGP/CTF-Writeups/tree/master/Google%20CTF%202018%20Quals%20Beginners%20Quest/JS%20safe).