Play with Balsn this time and got 12th place, teamates are really amazing.
I just slept late at the weekend…, there was only a reverse challenge left …
Though, they release the sixology on the last day, we almost solve that, but I did not notice that the compare operation in the bubble sort is lexicographically….
The binary expects us to input a string , and pick some characters from the flag string, then the binary would perform sorting on these characters. At the end of the binary, it prints out the record of it’s code coverage. Which means that we may recover the control flow of binary from these information which sounds difficult. And the key point is what kind of sorting was implemented in the binary.
The below is the detail of the sorting implemented in the binary, take input as
123\n3\n1 2 5\n for example, which means that take the char at
flag, and sort these chars with string
123 together. (Newline would affect the code coverage)
The user input
123 would be processed first, then the characters from flag string.
And the phases of sorting can be summarize as follow :
- Build up a List
- Build a charObject which has
- Insert the charObject to the List base on the value of
sub_list_len,which should initialize as
0. If there were already some objects with 0
sub_list_len,the new object would be inserted at the tail of them (it’s actually not the length, just for convenience)
- Compare last two object at row of charObject with same
- The bigger one would be put into the sublist of the other one
- Go back to 2. if there are still chars remaining.
So, it look like
At this point, the last char, which is
flag would be compare with char
a, according to the result (> or <=), the binary would give us two different code coverage, but the problem here is we can only compare the last char,
flag here, with the other char ,
flag =='a' here , which was also from flag string.
If we change the order of the input slightly:
Now we can compare the unknown char from string with our input, but the new problem is the code coverage is implemented by a bunch of counter, the flow after this compare may cause them looks the same. So we have to construct a string which make the binary branch predictable. That is :
} respectively, this input make the path of sorting more predictable due to
} are almost bigeer than all ascii. The fun fact here is the last char of flag is
from pwn import *