Category: binary - Points: 75

Description: The flag is in the form of two words separated by an underscore.

The task comes with the file and_so_on.exe. As always we first check if the extension is correct:

$ file and_so_on.exe
and_so_on.exe: PE32 executable for MS Windows (console) Intel 80386 32-bit

Seems legit. So we fire up our Windows virtual machine and try to play with it:

C:\ctf>and_so_on.exe
LoadLibrary(pythondll) failed. The specified module could not be found. PYTHON27.DLL

Ok, it seems to be a python program. Let’s give it the dll so we can play:

C:\ctf>and_so_on.exe
Welcome, try your favorite number.
>>> 0
1
>>> 1
4
>>> 2
1
>>> 3
5
>>> 4
9
>>> 5
2
>>> 6
6
>>> 7
5

The numbers 14159265 are the first decimals of \(\pi\). We could fire IDA to check what’s going on, but since the program seems to use python, let’s check if we can get the python script out of there. We use strings at first and between lots of semi-interesting strings there are also things like:

PY2EXE_VERBOSE
PY2EXE_VERBOSE
C:\Python27\lib\site-packages\py2exe\boot_common.pyR

So it seems that py2exe was used in order to convert the python script into an exe. We can use unpy2exe in order to extract the pyc file from the exe.

$ python unpy2exe.py and_so_on.exe
Magic value: 78563412
Code bytes length: 4029
Archive name: library.zip
Extracting C:\Python27\lib\site-packages\py2exe\boot_common.py.pyc
Extracting pypy.py.pyc

Now we can use uncompyle2 to decompile the just extracted pypy.py.pyc into a py file.

$ uncompyle2 --py -o . pypy.py.pyc
+++ okay decompyling pypy.py.pyc
# decompiled 1 files: 1 okay, 0 failed, 0 verify failed

The decompiled pypy.py.py is:

def comp(list1):
    flag = 1
    list2 = [762, 763, 764, 765, 766, 767]
    for x in range(len(list1)):
        if list1[x] != list2[x]:
            flag = 0
    return flag


bigstring = '9891024612909591116678729100316608622171235087758187759157395787353288368265951137864557824094352895303741966771716024183802335785688257838731300010171881139162530586443352803225246203809643554954420595813690618237137950159940879273899999943112707815069903177477926318951814430468069120921211659910245329852986972297050173585945641034359422109044864127871736371906987757243177587728065362541721865000231504966764818476483257671392671712935077207349068971207091737422593649493120680346656044263376338921949110381839722198427257588153765947269973264470845811501397116239183711681290359195957563072750334906115149159641483125664028845035033110063095298763463517190452928269029025188471885513606600785427372141942062706393312846623454016843064329665846541909102172561387687332846574821644339566579018824469183039459849226446955501125839107201482054711184821804953527132285055906448390746603282315680841289760711243528430826899802682604618703295449479028501573993961791488205972383346264832397985356295141'[::-1]

sixinputs = []
print 'Welcome, try your favourite number.'
while True:
    print '>>> ',
    givemethis = input()
    sixinputs.append(givemethis)
    if len(sixinputs) > 6:
        del sixinputs[0]
    print bigstring[givemethis % 1000]
    if len(sixinputs) == 6:
        flag = comp(sixinputs)
        if flag == 1:
            print "You've done well, what you've reached is the answer."
            break

First we note that bigstring reversed (because of [::-1]) are actually the decimals of \(\pi\).

The function comp(list1) returns 1 if list1 is exactly composed by:

[762, 763, 764, 765, 766, 767]

The main loop asks the user to insert numbers which are used to retrieve and print the corresponding indexes in bigstring (restarting from the beginning if the number is greater than 1000). The last six numbers inserted by the user are kept in a list which is passed to comp1. So if the last 6 numbers from the user are [762, 763, 764, 765, 766, 767] the following string is printed and the program exits:

You've done well, what you've reached is the answer.

Let’s try it:

C:\ctf>and_so_on.exe
Welcome, try your favorite number.
>>> 762
9
>>> 763
9
>>> 764
9
>>> 765
9
>>> 766
9
>>> 767
8
You've done well, what you've reached is the answer.

After some time investing on the result, we thought that’s it’s quite interesting that in the first 1000 digits of \(\pi\) there are five 9’s in a row. Actually this is a famous sequence known as Feynman Point:

Pi digits distribution

Remembering that the description of the task was: The flag is in the form of two words separated by an underscore, the flag is:

feynman_point