# EASYCTF - Soupstitution Cipher
> description: We had a flag, but lost it in a mess of alphabet soup! Can you help us find it? Connect to the server via `nc c1.easyctf.com 12484`.
> hint: I love parsing characters!
> category: Reverse Engineering
Okay, There is the source code in `python`:
```#!/usr/bin/env python3
from binascii import unhexlify as sOupfrom operator import attrgetter as souP
ME_FLAGE = '<censored>'
SoUp = inputsoUP = hexsOUp = printsOuP = ordSOuP = open
def SoUP(sOUP):	soup = 0	while sOUP != 0:		soup = (soup * 10) + (sOUP % 10)		sOUP //= 10	return soup
def SOup(sOUP):	soup = 0	for soUp in sOUP:		soup *= 10		soup += sOuP(soUp) - sOuP('0')	return soup
def SOUP():	Soup = SoUp()[:7]	print(Soup)	if not souP('isdigit')(Soup)():		sOUp("that's not a number lol")		return
	soup = SoUP(SOup(Soup))	SouP = souP('zfill')(soUP(soup)[2:])(8)[-8:]	if sOup(SouP) == souP('encode')('s0up')():		sOUp("oh yay it's a flag!", ME_FLAGE)	else:		sOUp('oh noes rip u')
if __name__ == '__main__':	SOUP()```
Okay let's first `deobfuscate` this SoupCode:
```from binascii import unhexlify, hexlifyfrom operator import attrgetter
ME_FLAGE = '<censored>'
def third(param):	soup = 0	while param != 0:		soup = (soup * 10) + (param % 10)		param //= 10	return soup
def second(param):	soup = 0	for soUp in param:		soup *= 10		soup += ord(soUp) - ord('0')	return soup
def principal(a):	Soup = a[:7]	if not attrgetter('isdigit')(Soup)():		print("that's not a number lol")		return
	soup = third(second(Soup))
	SouP = attrgetter('zfill')(hex(soup)[2:])(8)[-8:]
	if unhexlify(SouP) == attrgetter('encode')('s0up')():		print("oh yay it's a flag!", ME_FLAGE)		exit(0)	else:		pass```
Alright so the principal method, will take the first `7 digits`. Then the method `second()` will convert it to an int and the method `third()` will invert all digits (123 -> 321).
The goal is to enter in the `if unhexlify(SouP) == attrgetter('encode')('s0up')()`:
We have:
`attrgetter('encode')('s0up')() = 'S0up'`
And we want:
`unhexlify(SouP) = 's0up'`
So, reversing it:
`SouP = hexlify('s0up') = 73307570`
Just before we have:
`SouP = attrgetter('zfill')(hex(soup)[2:])(8)[-8:]`
This is only a conversion to hexa, and we want it to be egal to 73307570:
`0x73307570 = 1932555632`
then soup = 1932555632
The program call `second()` and `third()` so all we have to do is to reverse this number:
`soup = third(second(Soup))`
We have Soup = 2365552391
The first line of the method limit our entry to 7 digits:
`Soup = a[:7]`
At this point you can try with the maximum 'legit' entry (`9999999`), u won't be able to reach 2365552391...
Okay first I commented the code with the values we would like to get:
```def principal(a):	Soup = a[:7]	#impossible	if not attrgetter('isdigit')(Soup)():		#print("that's not a number lol")		return	#Soup = "2365552391" # this to win	soup = third(second(Soup))	print(soup)	#soup = 1932555632 # this to win	SouP = attrgetter('zfill')(hex(soup)[2:])(8)[-8:]	#SouP = "73307570" # this to win	if unhexlify(SouP) == attrgetter('encode')('s0up')():	   # we want SouP = 73307570		print(Soup)		print("oh yay it's a flag!", ME_FLAGE)		exit(0)	else:		pass```
As u can see in the hint, there is characters that are interpreted as digit. let try to list some of them:
```def principal(a):	Soup = a[:7]	if not attrgetter('isdigit')(Soup)():		return	print(Soup, end=" ")
for i in range(2500):	principal(chr(i))```
The result is:
> 0 1 2 3 4 5 6 7 8 9 ² ³ ¹ ٠ ١ ٢ ٣ ٤ ٥ ٦ ٧ ٨ ٩ ۰ ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹ ߀ ߁ ߂ ߃ ߄ ߅ ߆ ߇ ߈ ߉ ० १ २ ३ ४ ५ ६ ७ ८ ९
Now let's see what is the value for one os this entry:
```def principal(a):	Soup = a[:7]	#impossible	if not attrgetter('isdigit')(Soup)():		return	soup = third(second(Soup))	print(soup)	#soup = 1932555632 # this to win
principal('߉')# ->  5491
principal('߉111')# -> 1115491
principal('߉789')# -> 9875491```
Alright, as we can see, all numbers added after the special char will be before it after the second() and third() methods.So we want something like (weird_char + 552391) in entry and that weird_char = 5632
Let's brute force those values and see if the weird_char = 5632 exists:
```def principal(a):	Soup = a[:7]	if not attrgetter('isdigit')(Soup)():		return	soup = third(second(Soup))	if soup == 5632:		print(a)		exit(0)
for i in range(10000):	principal(chr(i))
# -> ७```
Nice ! the `७` should make us win this challenge !Lets try it directly on the server =)
> nc c1.easyctf.com 12484
> ७552391
> oh yay it's a flag! easyctf{S0up_soup_soUP_sOuP_s0UP_S0up_s000000OOOOOOuuuuuuuuppPPppPPPp}
The flag is `easyctf{S0up_soup_soUP_sOuP_s0UP_S0up_s000000OOOOOOuuuuuuuuppPPppPPPp}` =)