Tags: rev 

Rating:

lonk

I found a script that prints the flag! Unfortunately it's a bit slow...

Attachments:

  • flag.py
  • lib.py

TLDR

lib.py implements simple arithmetic operations on numbers represented on linked lists. However, this means large numbers take a huge amount of memory, which makes it impossible to print the flag from flag.py using the current implementation.

Solution: Reverse each function and replace it with a usual implementation on integers.

%s/我/Node/g
%s/非/from_int/g
%s/常/to_int/g
%s/需/copy/g
%s/要/add/g
%s/放/sub/g
%s/屁/mul/g
%s/然/mod/g
%s/後/power/g
%s/睡/pow/g
%s/覺/print_char/g

Solution

Running flag.py gives

$ python3 flag.py
CCC{m4Th

It takes about 3 seconds for it to print T and 50 seconds to print h on my laptop.

Looking at the code, flag.py seems to be filled with nonsense:

from lib import *

覺(非(67))
覺(要(非(34), 非(33)))
覺(要(放(非(105), 非(58)), 非(20)))
覺(屁(非(3), 非(41)))
覺(然(非(811), 非(234)))
覺(睡(非(3), 非(5), 非(191)))

# ...

The actual logic seems to be in lib.py. We can see this function

def(n):
    print(chr(常(n)), end="", flush=True)

prints out a single character, and every line of code in flag.py calls this function once.

Starting from the top, the first line of code in flag.py is:

print_char(非(67))

Here's the relevant function in lib.py

class 我:
    def __init__(self, n=None):
        self.n = n

def(a):
    h = 我()
    c = h
    while a > 0:
        c.n = 我()
        c = c.n
        a -= 1
    return h.n

The class looks like a linked list Node without the usual self.data attribute. Knowing this, we can see that 非() create a linked list of length a.

So this linked list gets passed to the print_char() function, which then calls print(chr(常(n)), end="", flush=True). Here's the source for the 常() function:

def(a):
    i = 0
    while a:
        i += 1
        a = a.n
    return i

We can see that it just calculates the length of the of the linked list.

In summary, 覺(非(67)) translates to print_char(make_list(67)), which prints C, whose ASCII code is 67.


The next line of code in flag.py is

覺(要(非(34), 非(33)))

Here's the code for 要()

def(a, b):
    h = 需(a)
    c = h
    while c.n:
        c = c.n
    c.n = 需(b)
    return h

First it calls 需()

def(a):
    h = Node()
    b = h
    while a:
        b.n = Node()
        b = b.n
        a = a.n
    return h.n

We can see that it just makes a copy of a linked list. Going back to 要(), we can see that it returns a new list whose length is the sum of the lengths of its parameters.

def(a, b):
    h = copy(a)

    # Walk to tail of `a`
    c = h
    while c.next:
        c = c.next

    # Connect tail to a copy of `b`
    c.next = copy(b)

    # Return head
    return h

So the line 覺(要(非(34), 非(33))) prints ASCII code 34 + 33, which ends up being C again.


Working in a similar manner, we can see that 放(a, b) computes a - b, so 覺(要(放(非(105), 非(58)), 非(20))) prints 105 - 58 + 20 which prints C.

The next function is 屁().

def(a, b):
    h = Node()
    c = a
    while c:
        h = add(h, b)
        c = c.next
    return h.next

This computes a * b, so 覺(屁(非(3), 非(41))) prints 3 * 41, which is {.

The next function 然() is more interesting, and I have annotated it below:

def mod(a, b):
    b_copy = copy(b)

    # Walk to the end of b's copy
    c = b_copy
    while c.next:
        c = c.next

    # Connect b_copy's tail to its head, making it a ring.
    c.next = b_copy

    # Iterate `a` using `c`, but also increment `b_copy_c` around its ring.
    b_copy_c = b_copy
    c = a
    while c.next:
        b_copy_c = b_copy_c.next
        c = c.next

    # Cut the ring where `b_copy_c` is currently at and return the starting
    # point of the ring.
    if id(b_copy_c.next) == id(b_copy):
        # Special case when we end up at the start again
        b_copy = None
    else:
        b_copy_c.next = None

    return b_copy

The implementation is pretty confusing, but it actually just computes a % b (if you visualize modular arithmetic using clocks, it might make more sense).

Knowing this, 覺(然(非(811), 非(234))) prints 811 % 234 which is m.

The last two functions left these:

def(a, b):
    h = Node()
    c = b
    while c:
        h = mul(h, a)
        c = c.n
    return h


def(a, b, m):
    return mod(後(a, b), m)

We can see that computes a ** b and computes (a ** b) % m. However that's not an efficient way to compute modular powers. Instead we should use Python's built-in pow function pow(a, b, m).


Now we can just replace the functions in lib.py with the simpler functions we've derived, and running flag.py will print the flag.

def from_int(a):
    return a


def to_int(a):
    return a


def add(a, b):
    return a + b


def sub(a, b):
    return a - b


def mul(a, b):
    return a * b


def mod(a, b):
    return a % b


def power(a, b):
    return a ** b


def powermod(a, b, m):
    return pow(a, b, m)


def pc(n):
    print(chr(to_int(n)), end="", flush=True)

pc(from_int(67))
pc(add(from_int(34), from_int(33)))
pc(add(sub(from_int(105), from_int(58)), from_int(20)))
pc(mul(from_int(3), from_int(41)))
pc(mod(from_int(811), from_int(234)))
pc(powermod(from_int(3), from_int(5), from_int(191)))

pc(
    sub(
        mod(
            mul(
                mul(
                    mul(
                        mul(
                            mul(
                                mul(
                                    mul(
                                        mul(
                                            mul(
                                                mul(
                                                    mul(from_int(2), from_int(2)),
                                                    from_int(2),
                                                ),
                                                from_int(2),
                                            ),
                                            from_int(2),
                                        ),
                                        from_int(2),
                                    ),
                                    from_int(2),
                                ),
                                from_int(2),
                            ),
                            from_int(2),
                        ),
                        from_int(2),
                    ),
                    from_int(2),
                ),
                from_int(2),
            ),
            from_int(1337),
        ),
        from_int(1),
    )
)

pc(
    mul(
        sub(
            mul(mod(power(from_int(3), from_int(9)), from_int(555)), from_int(2)),
            from_int(464),
        ),
        from_int(2),
    )
)

pc(powermod(from_int(2020), from_int(451813409), from_int(2350755551)))

pc(
    powermod(
        from_int(1234567890),
        from_int(9431297343284265593),
        add(from_int(119), from_int(17017780892086357584)),
    )
)

pc(
    mul(
        powermod(from_int(3), sub(from_int(60437), from_int(1024)), from_int(151553)),
        powermod(
            from_int(3),
            add(
                mul(
                    from_int(5),
                    mod(
                        mul(
                            mul(
                                mul(mul(from_int(10), from_int(10)), from_int(10)),
                                from_int(10),
                            ),
                            from_int(10),
                        ),
                        from_int(1337),
                    ),
                ),
                from_int(54103),
            ),
            from_int(151553),
        ),
    )
)

pc(
    add(
        powermod(
            from_int(111111111111111111111111111111111111),
            from_int(222222222222222222222222222222222222),
            from_int(333333333333333333333333333333333333),
        ),
        mul(mul(from_int(2), from_int(2)), from_int(29)),
    )
)

pc(
    mul(
        sub(
            power(
                mul(add(from_int(1), from_int(1)), add(from_int(1), from_int(1))),
                from_int(2),
            ),
            from_int(8),
        ),
        powermod(from_int(2), from_int(7262490), from_int(98444699)),
    )
)

pc(
    sub(
        mul(mul(mul(from_int(1337), from_int(1337)), from_int(1337)), from_int(1337)),
        from_int(3195402929666),
    )
)

pc(
    sub(
        mod(
            sub(
                from_int(
                    1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
                ),
                from_int(1),
            ),
            from_int(100),
        ),
        from_int(23),
    )
)

pc(
    sub(
        mod(sub(power(from_int(100), from_int(100)), from_int(1)), from_int(100)),
        from_int(50),
    )
)

pc(
    mod(
        add(
            add(
                add(
                    add(
                        add(
                            add(
                                add(
                                    add(
                                        add(
                                            add(
                                                add(
                                                    add(
                                                        add(
                                                            add(
                                                                add(
                                                                    add(
                                                                        add(
                                                                            add(
                                                                                add(
                                                                                    from_int(
                                                                                        1
                                                                                    ),
                                                                                    from_int(
                                                                                        2
                                                                                    ),
                                                                                ),
                                                                                from_int(
                                                                                    3
                                                                                ),
                                                                            ),
                                                                            from_int(4),
                                                                        ),
                                                                        from_int(5),
                                                                    ),
                                                                    from_int(6),
                                                                ),
                                                                from_int(7),
                                                            ),
                                                            from_int(8),
                                                        ),
                                                        from_int(9),
                                                    ),
                                                    from_int(10),
                                                ),
                                                from_int(11),
                                            ),
                                            from_int(12),
                                        ),
                                        from_int(13),
                                    ),
                                    from_int(14),
                                ),
                                from_int(15),
                            ),
                            from_int(16),
                        ),
                        from_int(17),
                    ),
                    from_int(18),
                ),
                from_int(19),
            ),
            from_int(20),
        ),
        from_int(132),
    )
)

pc(
    add(
        sub(
            powermod(from_int(1337), from_int(1337), add(from_int(1337), from_int(1337))),
            from_int(1336),
        ),
        from_int(106),
    )
)

pc(add(from_int(50), from_int(1)))

pc(
    add(
        mod(
            sub(
                power(
                    power(power(from_int(10), from_int(10)), from_int(10)), from_int(10)
                ),
                from_int(1),
            ),
            from_int(100),
        ),
        from_int(1),
    )
)

pc(
    add(
        sub(
            mod(
                sub(
                    power(from_int(55555), from_int(5)),
                    mul(
                        mul(
                            mul(
                                mul(
                                    mul(
                                        mul(
                                            mul(
                                                mul(
                                                    mul(
                                                        mul(
                                                            mul(
                                                                mul(
                                                                    mul(
                                                                        mul(
                                                                            mul(
                                                                                mul(
                                                                                    mul(
                                                                                        mul(
                                                                                            mul(
                                                                                                mul(
                                                                                                    mul(
                                                                                                        mul(
                                                                                                            from_int(
                                                                                                                1
                                                                                                            ),
                                                                                                            from_int(
                                                                                                                2
                                                                                                            ),
                                                                                                        ),
                                                                                                        from_int(
                                                                                                            3
                                                                                                        ),
                                                                                                    ),
                                                                                                    from_int(
                                                                                                        4
                                                                                                    ),
                                                                                                ),
                                                                                                from_int(
                                                                                                    5
                                                                                                ),
                                                                                            ),
                                                                                            from_int(
                                                                                                6
                                                                                            ),
                                                                                        ),
                                                                                        from_int(
                                                                                            7
                                                                                        ),
                                                                                    ),
                                                                                    from_int(
                                                                                        8
                                                                                    ),
                                                                                ),
                                                                                from_int(
                                                                                    9
                                                                                ),
                                                                            ),
                                                                            from_int(
                                                                                10
                                                                            ),
                                                                        ),
                                                                        from_int(11),
                                                                    ),
                                                                    from_int(12),
                                                                ),
                                                                from_int(13),
                                                            ),
                                                            from_int(14),
                                                        ),
                                                        from_int(15),
                                                    ),
                                                    from_int(16),
                                                ),
                                                from_int(17),
                                            ),
                                            from_int(18),
                                        ),
                                        from_int(19),
                                    ),
                                    from_int(20),
                                ),
                                from_int(21),
                            ),
                            from_int(22),
                        ),
                        from_int(23),
                    ),
                ),
                from_int(1337),
            ),
            from_int(200),
        ),
        from_int(45),
    )
)

pc(powermod(from_int(6), from_int(11333), from_int(29959)))

pc(
    sub(
        mul(
            mul(
                mul(
                    mul(
                        from_int(4),
                        from_int(4),
                    ),
                    from_int(4),
                ),
                from_int(4),
            ),
            from_int(4),
        ),
        from_int(975),
    )
)

pc(
    mul(
        sub(
            add(sub(add(from_int(3), from_int(3)), from_int(1)), from_int(4)),
            from_int(3),
        ),
        sub(
            add(sub(add(from_int(3), from_int(3)), from_int(1)), from_int(4)),
            from_int(3),
        ),
    )
)

pc(
    sub(
        powermod(
            powermod(from_int(12345), from_int(12345), from_int(54321)),
            from_int(12345),
            from_int(54321),
        ),
        from_int(3037),
    )
)

pc(add(from_int(50), from_int(3)))
pc(from_int(125))

print()

Output:

CCC{m4Th_w1tH_L1Nk3d_l1$t5}
Original writeup (https://github.com/qxxxb/ctf_challenges/blob/master/2021/ccc/rev/lonk/solve).