Rating:

# GroceryList

To begin with, we have a base 64 string:

```
UmV2ZXJzZSBHcm9jZXJ5UGxhY2UKCnZpY2h5c3NvaXNlICAgICAgICAgICAgIAptYW5nbyAgICAgICAgICAgICAgICAgICAKdmVybW91dGgKenVjb3R0bwpzYW5kd2ljaApsYW1iCnZlYWwKeW9ndXJ0CnZlcm1pY2VsbGkKenVjY2hpbmkKc2FsbW9uCmZlbm5lbCBzZWVkcwppY2UgY3JlYW0KY2Fycm90cwp1bmFnaQppbmNhIGJlcnJpZXMKY2FiYmFnZQp1cG1hCmdyYXBlcwpuYWFuCmFwcGxlcwpiYW5hbmFzCmFsbW9uZHMKYmFzaWwKZmVudWdyZWVrCnBvdGF0b2VzCnBpZQpzb3kgYmVhbnMKZWdncwp0dW5hZmlzaAoKRmluZCB0aGUgaW5wdXQgdG8gdGhlIGZvbGxvd2luZyBvdXRwdXQuCk9VVFBVVDogNGN1bTc3aXRRZEt5NHI3Y35ybTV1MDVwbE4=
```

Once decoded, we get:

```
Reverse GroceryPlace

vichyssoise
mango
vermouth
zucotto
sandwich
lamb
veal
yogurt
vermicelli
zucchini
salmon
fennel seeds
ice cream
carrots
unagi
inca berries
cabbage
upma
grapes
naan
apples
bananas
almonds
basil
fenugreek
potatoes
pie
soy beans
eggs
tunafish

Find the input to the following output.
OUTPUT: 4cum77itQdKy4r7c~rm5u05plN
```

I spent a LOT of time searching for any hint about what to do with the list. I eventually found this reading abot esoteric languages: [esolang](https://esolangs.org/wiki/Grocery_List) and [progopedia](http://progopedia.com/language/grocery-list). And BOTH SITES HAVE MISTAKES. The worst one being *progopedia* which does not event precise when to pop before an operation, and *esolang* having some typos but being much much more trustable.

As you may notice, this language has no online interpreter, so I decided to code one in Python.

```python
#!/usr/bin/env python3

import string

x = '''vichyssoise
mango
[...]
eggs
tunafish'''

s = x.split('\n')[:]

def debug(msg):
if d:
print(f'[*] {msg}')

def push(v):
L.insert(0, v)

def pop():
return L.pop(0)

def add():
a = pop()
b = pop()
push(a + b)
debug(f'add {a} + {b}')

def bring():
v = L.pop()
push(v)
debug(f'bring {v}')

def copy():
push(L[0])
debug(f'copy')

def endloop():
global j
j = save
debug(f'end loop -> returning to j={save}')

def flip():
L[0], L[1] = L[1], L[0]
debug(f'flip')

def gt():
s0 = pop()
s1 = pop()
if s0 > s1:
push(1)
else:
push(0)
debug(f'greater than')

def ipt():
global i
if i >= len(pld):
push(0)
debug(f'input: pushing 0 (end of input)')
else:
push(ord(pld[i]))
debug(f'input: pushing {pld[i]}')
i += 1

def loop():
global save
save = j
debug(f'loop starting')
if not L or L[0] == 0:
return True
return False

def number():
push(len(s[j]))
debug(f'number with {s[j]}')

def p():
global output
c = chr(pop())
if c not in charset:
return True
output += c
print(f'output = {c} -> {output}')
return False

def sub():
a = pop()
b = pop()
push(a - b)
debug(f'sub {a} - {b}')

def terminate():
return

def unbring():
L.append(pop())
debug(f'unbring')

def value():
global j
push(ord(prog[j + 1]))
j += 1
debug(f'value: pushing {prog[j]}')

def interpret(l):
ret = False
if l == 'a': add()
elif l == 'b': bring()
elif l == 'c': copy()
elif l == 'e': endloop()
elif l == 'f': flip()
elif l == 'g': gt()
elif l == 'i': ipt()
elif l == 'l': ret = loop()
elif l == 'n': number()
elif l == 'p': ret = p()
elif l == 's': sub()
elif l == 't': terminate()
elif l == 'u': unbring()
elif l == 'v': value()
elif l == 'w': push(100)
else:
print('critical error on letter {l}')
exit(1)
return ret

charset = string.ascii\_letters + string.punctuation + string.digits
prog = ''.join([w[0] for w in s])
L = [] # stack
i = 0
j = 0
save = 0
pld = 'c0mp73tedMyGr0c3ry5h0pp1Ng'
d = False
output = ''

while j < len(prog) and prog[j] != 't':
ret = interpret(prog[j])
j += 1
# print(f'i = {i}, j = {j}', prog[j:], L)
if ret:
break

out = '4cum77itQdKy4r7c~rm5u05plN'
print(f'prog = {prog}, len = {len(prog)}')
print(f'ipt = {pld}')
print(f'got = {output}')
print(f'exp = {out}')
```

Playing a bit with the input, we can easily notice that for each pair of character, we have

```
(x, y) => (y + 4, x)
```

Reversing the expected output gives us the flag:

```
shaktictf{c0mp73tedMyGr0c3ry5h0pp1Ng}
```

Original writeup (https://github.com/Ewael/CTFs/tree/master/2021/ShaktiCTF/Misc/GroceryList).