Rating:

# Machine Fix

>We ran a code on a machine a few years ago. It is still running however we forgot what it was meant for. It completed n=523693181734689806809285195318 iterations of the loop and broke down. We want the answer but cannot wait a few more years. Find the answer after n iterations to get the flag.
>
>The flag would be of the format csictf{answer_you_get_from_above}.

We are given the [code](code.py) of the program that takes years to compute.

```python
def convert (n):
if n == 0:
return '0'
nums = []
while n:
n, r = divmod(n, 3)
nums.append(str(r))
return ''.join(reversed(nums))

count=0
n=1
while(n<=523693181734689806809285195318):
str1=convert(n)
str2=convert(n-1)
str2='0'*(len(str1)-len(str2))+str2
for i in range(len(str1)):
if(str1[i]!=str2[i]):
count+=1
n+=1

print(count)
```

After some reversing, I found out that the `convert` function converts numbers to base 3.

The program goes through 1 to 523693181734689806809285195318 and increments the count variable every time there is a difference between the current number and the number before it in base 3. So basically whenever there is a carry in an addition. But it's more difficult than that. Take `100000000` in base 3 for example. The number before that is `022222222`. The count variable would be incremented 8 times! Not so simple, eh?

I played around with the code for a bit, trying to find if there is a shortcut for this big calculation.

```python
crack=32145#523693181734689806809285195318
while(n<=crack):
str1=convert(n)
str2=convert(n-1)
if (len(str1)!=len(str2)):
print(n)
print(count)
str2='0'*(len(str1)-len(str2))+str2
for i in range(len(str1)):
if(str1[i]!=str2[i]):
count+=1
hash = hashlib.md5()
hash.update(str1+str2)
print hash.hexdigest(), len(str1)-i, '!'#, str1[-5:], str2[-5:]
n+=1
```

I intentionally made the `crack` variable smaller, so my computer can actually execute the program in finite time. Whenever the count variable was incremented, I printed out the hex digest of both strings so all the data looks different, and which digit of the base3 number there is a difference. Again, I'm trying to find a pattern here.

I used `grep` to find each line where there is a certain digit that is changed and `wc` to count the number of lines. I was hoping to find a pattern that I can use in my algorithm.

```
jordan@notyourcomputer:~/CTF-writeups/csictf/machine-fix$ python code-edited.py | grep " 1 !" | wc -l
32145
jordan@notyourcomputer:~/CTF-writeups/csictf/machine-fix$ python code.py | grep " 2 !" | wc -l
10715
jordan@notyourcomputer:~/CTF-writeups/csictf/machine-fix$ python code.py | grep " 3 !" | wc -l
3571
jordan@notyourcomputer:~/CTF-writeups/csictf/machine-fix$ python code.py | grep " 4 !" | wc -l
1190
jordan@notyourcomputer:~/CTF-writeups/csictf/machine-fix$ python code.py | grep " 5 !" | wc -l
396
jordan@notyourcomputer:~/CTF-writeups/csictf/machine-fix$ python code.py | grep " 6 !" | wc -l
132
jordan@notyourcomputer:~/CTF-writeups/csictf/machine-fix$
```

It shocked me when I found out that they are all divisions of 3!

And the result:

```
48212
```

Is everything summed up!

```
jordan@notyourcomputer:~$ py
Python 3.7.3 (default, Dec 20 2019, 18:57:59)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 32145+10715+3571+1190+396+132
48149
>>> 132//3
44
>>> 32145+10715+3571+1190+396+132+44
48193
>>> 44//3
14
>>> 32145+10715+3571+1190+396+132+44+14
48207
>>> 32145+10715+3571+1190+396+132+44+15
48208
>>> 15//3
4
>>> 4//3
1
>>> 1//3
0
>>> 32145+10715+3571+1190+396+132+44+15+4+1
48212
>>>
```

I found out that it has to be floor division though, not just division.

So, all we have to do is floor divide n by 3 and add n to the count until n is zero!

```python
n = 523693181734689806809285195318
count = 0

while n != 0:
count += n
n = n // 3 ## use floor division

print(count)
```

Very fun challenge!

Flag: `csictf{785539772602034710213927792950}`

Original writeup (https://github.com/Jord4563/CTF-writeups/tree/master/csictf2020/machine-fix).