Selected Writeups from NISC CTF 2019

Summary0x00 Game. Inspecting the source reveals a suspicious JavaScript file. Sending a POST request with score=15 returns the data. 0x01 Who are you? The source suggests XML injection, and testing confirms an XXE vulnerability. Because the flag path is unknown, use php://filter…

CTFNISC

0x00 Game

Procedure: inspecting the source reveals a suspicious JavaScript file:

1.png

Reading it reveals:

image

Send a POST request with score=15 to read the data.

3.png

0x01 who are you?

Inspect the source file:

4.png

An XML injection vulnerability seems likely, and testing confirms XML external entity injection.

5.png

Because the flag's path is unknown, it cannot be read directly with file. Use php://filter/read=convert.base64-encode/resource= to read index.php:

6.png

After decoding:

7.png

0x02 Sign-In Challenge

A DNS lookup reveals:

8.png

0x03 Seventh Hokage

The file header is disguised as PNG, but the file is actually a GIF.

9.png

The animation contains 66 frames. Searching for the original Seventh Hokage GIF reveals a 65-frame version; comparison shows that frame seven was duplicated.

10.png

StegSolve reveals the answer.

11.png

0x04 Yasashii

12.png

The password is loli. After extracting the image, open it in WinHex and inspect the suspicious data:

13.png

After extraction:

14.png

Decode the Brainfuck program:

15.jpeg
16.png

0x05 24word

17.png

Following the hint in the first image, decode it with the Chinese Core Socialist Values cipher:

18.jpeg

The resulting image is:

19.jpeg

Scanning produces the correct answer:

20.png

0x06 dp

Given N and dq, solve the factorization problem with the following script:

TEXT
import gmpy2
import libnum
e=65537
n=9637571466652899741848142654451413405801976834328667418509217149503238513830870985353918314633160277580591819016181785300521866901536670666234046521697590230079161867282389124998093526637796571100147052430445089605759722456767679930869250538932528092292071024877213105462554819256136145385237821098127348787416199401770954567019811050508888349297579329222552491826770225583983899834347983888473219771888063393354348613119521862989609112706536794212028369088219375364362615622092005578099889045473175051574207130932430162265994221914833343534531743589037146933738549770365029230545884239551015472122598634133661853901
dp=81339405704902517676022188908547543689627829453799865550091494842725439570571310071337729038516525539158092247771184675844795891671744082925462138427070614848951224652874430072917346702280925974595608822751382808802457160317381440319175601623719969138918927272712366710634393379149593082774688540571485214097
c=5971372776574706905158546698157178098706187597204981662036310534369575915776950962893790809274833462545672702278129839887482283641996814437707885716134279091994238891294614019371247451378504745748882207694219990495603397913371579808848136183106703158532870472345648247817132700604598385677497138485776569096958910782582696229046024695529762572289705021673895852985396416704278321332667281973074372362761992335826576550161390158761314769544548809326036026461123102509831887999493584436939086255411387879202594399181211724444617225689922628790388129032022982596393215038044861544602046137258904612792518629229736324827
for i in range(1,65538):
    if (dp*e-1)%i == 0:
        if n%(((dp*e-1)/i)+1)==0:
            p=((dp*e-1)/i)+1
            q=n/(((dp*e-1)/i)+1)
            phi = (p-1)*(q-1)
            d = gmpy2.invert(e,phi)%phi
            print libnum.n2s(pow(c,d,n))

0x07 sflat

The challenge applies control-flow flattening, but its validation logic is simple. The solution script follows:

TEXT
data="J2261C63-3I2I-EGE4-IBCC-IE41A5I5F4HB"
flag='flag{'
for i in data:
if i=='-':
flag += '-'
elif i >= '0'and i <= '9':
flag += chr(ord(i) + 48)
elif i>='A':
flag += chr(ord(i) - 17)
flag+='}'
print flag

0X08 src_leak

func1:

21.png

Analyze _func1 and convert it to a standard function for automated calculation. Split the IfElse block into ordinary if/else branches, then convert the relevant code from func1 into a conditional loop using while.

22.png

func2: func2 is relatively simple. Its recursion can be converted into a while loop without much difficulty.

image

func3: func3 is even simpler and can be readily converted into a standard function.

24.png

Func4:

25.png

Func4 is more complex. First convert NEXT_N and NEXT_M, then convert TEST. TEST has two fixed return values that require attention. Finally coordinate func4's two fixed conditional returns and call TEST to complete the reconstruction.

26.png

Main function: define the max array from the output hint. A value satisfies the condition when func3(func2(j)) equals 1, so this nested loop automatically generates five valid numbers, x1 through x5.

27.png

Following the hint, count how many numbers make func4 return 1. That total is x6, so I wrote the following code to calculate it.

28.png

This ultimately yields the flag.

29.png

0x09 sm4

This is standard SM4 encryption. Running a C implementation directly produces the flag.

30.png