Author: pattu_sai
Same as last time, but but but but but but but but but but but but
We were given the ELF binary main.
Extracting the Source#
I couldn’t really understand much from the static analysis to I tried running it
❯ file main
main: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=91f195f677bd49f09bf72523558d34197cff5dd9, for GNU/Linux 2.6.32, stripped
❯ ./main
Enter row 0 : 123
Enter row 1 : 123
Enter row 2 : 123
Enter row 3 : 123
Enter row 4 : 123
Enter row 5 : 123
Enter row 6 : 123
Enter row 7 : 123
Enter row 8 : 123
YWRkaXRpb25hbF9lbmNyeXB0aW9ueG9y
Traceback (most recent call last):
File "main.py", line 27, in <module>
7,
ValueError: chr() arg not in range(0x110000)
[8564] Failed to execute script 'main' due to unhandled exception!file main.py 💀, interesting, i thought this was an ELF?
a little searching took me to this writeup that mentioned something called PyInstaller used to bundle python projects into a single executable
We can extract the original python source with PyInstXtractor to get individual compiled python files one of which is main.pyc and probably the only one of interest
We can then decompile the compiled python bytecode with any of decompyle3, uncompyle6, or pycdc I followed the writeup and used pycdc giving me main.py
| |
for a long time the given sudoku was just unsolvable 💀, the handout was fixed later
Analysis#
Looking at the parts that actually run, first we can understand what input is expected. Each row expects a 9-digit number that it will then split into 3 3-digit numbers and populate the array n with them
Then it decrypts the encrypted flag by XORing each number in the enc array with numbers in n
But the numbers in enc are way larger than 3-digits! There’s no way XORing them with n is going to give you a printable character!
Let’s look at the other included functions
def YWRkaXRpb25hbF9lbmNyeXB0aW9u(suduko_solution):
a = (lambda .0: [ str(i) for i in .0 ])(suduko_solution)
sc = [''] * 9
for i in range(len(suduko_solution)):
for j in range(len(a)):
sc[i] += a[j][i]
sc[i] = int(sc[i])
print(sc)the function name translates to additional_encryption in b64, and looking carefully we can note that it creates an array of 9 integers that represent the transpose of the input sudoku matrix
def pmitonsicnufsihtknihtuoyod(suduko, n):
m = []
for i in range(len(suduko)):
m.append([
n[i],
suduko[i].count(0)]
)
m.sort((lambda x: x[1]), **('key',))
print(m)the function name is the reversed string doyouthinkthisfuncisnotimp and what it seems to do is sort an array based on the number of zeroes in the rows of the incomplete sudoku
Working Towards A Solution#
Eventually the author released an open hint
@everyone Open hint for sudo_u2.0 compare encrypted data with solved_sudoku, columnwise
My teammate had solved the sudoku already

So i tried out the suggested xor in the hint
❯ python solve.py
495237299 ^ 495237618 = 321
217684511 ^ 217684953 = 454
386590850 ^ 386591742 = 892
528415946 ^ 528416379 = 689
731927833 ^ 731928564 = 749
964744145 ^ 964753821 = 10828
679842775 ^ 679842135 = 640
152369177 ^ 152369487 = 342
843175228 ^ 843175296 = 188and these numbers are a lot more workable with than earlier, also they can now be XORed with our n matrix of 3-digit numbers! (except that weird 10828 but nvm that for now)
I know n is 3-digits at a time row-wise of the solved sudoku, but the first row doesn’t give me printable characters :(
321 ^ 423 = 230 = æ
454 ^ 579 = 901 = ΅
892 ^ 618 = 278 = ĖSo I tried another row till I got something printable, in this case namely the 4th row
321 ^ 265 = 72 = H
454 ^ 497 = 55 = 7
892 ^ 831 = 67 = Cand wow, that’s starting to look like the flag format H7CTF
Continuing in this way I got to my final row order
mod_sudo = [
[ 2, 6, 5, 4, 9, 7, 8, 3, 1],
[ 7, 4, 1, 6, 8, 3, 2, 9, 5],
[ 6, 9, 7, 3, 5, 8, 1, 4, 2],
[ 9, 1, 8, 2, 3, 6, 7, 5, 4],
[ 5, 7, 6, 8, 1, 4, 9, 2, 3],
[ 3, 8, 9, 1, 2, 5, 4, 6, 7],
[ 1, 5, 4, 7, 6, 2, 3, 8, 9],
[ 4, 2, 3, 5, 7, 9, 6, 1, 8],
[ 8, 3, 2, 9, 4, 1, 5, 7, 6],
]Giving me the string
H7CTF⭫9022b983⬨e13d74ce⬧a7fe7625⭳32eec874⬡12f8f7fa⬨609438e6⬨f7231daf⬤3|Cleaning this up and submitting did not in fact give me the flag so I raised a ticket and was told there was still another step related to the doyouthinkthisfuncisnotimp function. I tried rearranging the chunks based on the number of zeroes in their original row
For example 9022b983 came from XORing enc with rows 7 and 2 in the original sudoku which both had 6 zeroes in them originally.
Similarily e13d74c3 came from XORing enc with rows 3 and 5 which both had 5 zeroes initially
So I would rearrange my flag to something like H7CTF{e13d74c39022b983...
I am straight up ignoring the unprintable characters and assuming they are just delimiters because idk what else to do with them
I tried the flag that I got in this manner but that wasn’t correct either so I went back to the tickets to cry about it.
10 minutes later the challenge author told me try the cleaned up original flag I had gotten again and that was the flag, I’m guessing something went wrong with the intended 3rd stage of the challenge, 🤷
H7CTF{9022b983e13d74cea7fe762532eec87412f8f7fa609438e6f7231daf3} | |

