CTFするぞ

CTF以外のことも書くよ

SEC-T CTF 2018 - Writeup

It's been about two years since I last joined in a CTF. I participated in SEC-T CTF 2018 as a member of 'insecure.' I solved 7 challanges and got 357 point in total.

f:id:ptr-yudai:20180914231943p:plain:h256

Sanity check [Misc 51pts]

Flag is in the topic of #sect-ctf @ irc.freenode.net

The flag is written on the IRC.

Ez dos [Rev 51pts]

They told me you were old-school, great! Have a look at this license-server as a warm-up
Service: nc 142.93.38.98 7777 | nc rev.sect.ctf.rocks 7777
Download: ezdos.tar.gz

The file contains 'ezdos.com' and it's an executable for MS-DOS.

$ file ezdos.com
ezdos.com: COM executable for MS-DOS

Let's disassemble it.

$ objdump -D -b binary -M intel -mi386 -Maddr16,data16 ezdos.com > disasm

As I looked over the assembly, I found it reads a file named 'flag' and shows its contents when the license key is correct. The following part is where we enter the license key.

   c:   b9 00 00                mov    cx,0x0
   f:   bb 00 20                mov    bx,0x2000
  12:   ba 0d 00                mov    dx,0xd
  15:   b4 01                   mov    ah,0x1
  17:   cd 21                   int    0x21
  19:   3c 0a                   cmp    al,0xa
  1b:   74 08                   je     0x25
  1d:   88 07                   mov    BYTE PTR [bx],al
  1f:   43                      inc    bx
  20:   41                      inc    cx
  21:   39 d1                   cmp    cx,dx
  23:   75 f0                   jne    0x15

The license key we enter is stored at 0x2000.

  25:   b9 00 00                mov    cx,0x0
  28:   bb 00 20                mov    bx,0x2000
  2b:   b8 6b 02                mov    ax,0x26b
  2e:   ba 04 00                mov    dx,0x4
  31:   51                      push   cx
  32:   31 c9                   xor    cx,cx
  34:   8a 0f                   mov    cl,BYTE PTR [bx]
  36:   93                      xchg   bx,ax
  37:   8a 2f                   mov    ch,BYTE PTR [bx]
  39:   93                      xchg   bx,ax
  3a:   38 e9                   cmp    cl,ch
  3c:   0f 85 87 00             jne    0xc7
  40:   59                      pop    cx
  41:   41                      inc    cx
  42:   43                      inc    bx
  43:   40                      inc    ax
  44:   39 d1                   cmp    cx,dx
  46:   75 e9                   jne    0x31

The address of the license key is loaded into BX and the value 0x26b is stored into AX. AX(0x26b) points to the data '1337SHELL'. This part is a loop and it compares the first 4 characters of the license key with '1337', so the license key begins with '1337'. And then, it checks whether the next character is '-' as shown below.

  48:   31 d2                   xor    dx,dx
  4a:   8a 17                   mov    dl,BYTE PTR [bx]
  4c:   80 fa 2d                cmp    dl,0x2d
  4f:   75 76                   jne    0xc7

After checking '1337-', it checks the rest of the key character by character. The next character of the key and the data('S') is loaded into CL and CH respectively and compares CLCH with 0x66, which means the correct character is 'S'^0x66='5'.

  51:   43                      inc    bx
  52:   31 c9                   xor    cx,cx
  54:   8a 0f                   mov    cl,BYTE PTR [bx]
  56:   93                      xchg   bx,ax
  57:   8a 2f                   mov    ch,BYTE PTR [bx]
  59:   93                      xchg   bx,ax
  5a:   30 e9                   xor    cl,ch
  5c:   80 f9 66                cmp    cl,0x66
  5f:   75 66                   jne    0xc7

By restoring the rest of the key in the same way, I found the correct key is '1337-5115'. Connecting to the server with nc and entering the key, I got the flag.

Matry0ska1 [Crypto 51pts]

Discrete logarithms are hard...
nc 178.128.171.133 4444 | nc crypto.sect.ctf.rocks 4444

The server tells a message like this:

    _
  (("))  --- Gimme exponent pl0x
  /   \
 ( (@) )
 \__(__/


p = 122488473105892538559311426995019720049507640328167439356838797108079051563759027212419257414247
g = 2
g^x = 49865908605708412727604941701889315223850522668539772014048529597300749129536778697051808702829
:

What we have to do is find x such that 2^{x}=y \mod p when y and p are given. The number [tex:gx] is variable but p is fixed. p can be factorized by using wolfram alpha. This means the discrete logarithm problem can be solved by applying the Pollard's rho algorithm for logarithms and the Pohlig-Hellman algorithm. However, I used the following service which solves the discrete logarithm problem.

www.alpertron.com.ar

It took a few tens of seconds to solve the problem. Sending the answer returned the flag.

Section6 [Misc 51pts]

This file was recovered from a scavenger.
Download: section6.tar.gz

The given file contains a zip file. I guessed it's a word document since it has some directories such as Documents or _rels. Though I tried to open it with Libre Office, the document seemed broken. The contents of a word document basically exist in the Document directory. I found a file Documents/6/Pages/6.fpage which contains the text data. Since the text goes for several lines, I wrote a simple Python code which formats the text data.

import re

out = ""
with open("6.fpage", "r") as f:
    for line in f:
        found = re.findall("UnicodeString\=\"(.+)\"", line)
        if found:
            text = found[0]
            print text

This program gave me the flag in ASCII art.

Puppetmatryoshka [Misc 51pts]

Greetings Kusanagi, your mission is to find Puppet Master.
Download: puppetmatryoshka.tar.gz

The given archive has a pcap file named matryoshka.

$ file matryoshka 
matryoshka: tcpdump capture file (little-endian) - version 2.4 (Ethernet, capture length 262144)

I found TCP packets in which contains a file compressed by bzip2. I extracted and decompressed it, which created a disk dump.

$ file extracted
extracted: Linux rev 1.0 ext4 filesystem data, UUID=b72f5197-d45b-4079-b6e8-b9d1be583d67 (extents) (huge files)

There are some empty files and a 7-zip archive. I decompressed the archive and got an ASCII text file that seemed base64-encoded. Exhausting. Decoding the text made an Open Document file. Here is what is written in it:

Kusanagi, well done so far.

Try not to get compromized, we know he sometimes change metadata to cover his traces. Look for sign.

No flag here? It indicates the metadata, especially the signature is the key. I looked into META-INF/documentsignatures.xml and found the flag finally.

Shredder [Misc 51pts]

We intercepted this floppy we believe belonged to the laughing man. We haven't found anything other than this shredder tool though.
Download: floppy.gz

The file floppy is a disk dump of FAT filesystem.

$ file floppy
floppy: DOS/MBR boot sector, code offset 0x3c+2, OEM-ID "mkfs.fat", root entries 112, sectors 2880 (volumes <=32 MB), sectors/FAT 9, sectors/track 18, serial number 0xb4d31337, unlabeled, FAT (12 bit), followed by FAT

I mounted the disk and found a 64-bit ELF named shredder. Analysing the binary with using IDA reveals how it works.

  1. Open and read a file
  2. Generate a random byte as a key
  3. XOR the whole file byte by byte with the key
  4. Repeat step 2 and 3 for several times (It depends on the argument)

No matter how many times it XORs the file, it's easy to recover the original one because we just have to try 255 keys. However, the problem is we don't have the XORed file because it deletes the file before exiting. Deleting a file on FAT filesystem means just changing some bits on the disk so the file itself is not deleted. The given disk image is so small that we can easily find the deleted file. (The deleted file is located at 0x8800.) I wrote a Python code which tries to recover the file.

with open("floppy", "rb") as f:
    buf = f.read()[0x8800:]
buf = buf[:buf.index("\x00\x00\x00\x00")]
print repr(buf)

for key in range(0x100):
    out = ""
    for c in buf:
        out += chr(ord(c) ^ key)
    print out

As I looked over the output, I found the flag when the XOR key is 108.

Batou [Misc 51pts]

We manage to collect a dump from Batou's computer. Try to find info/notes that can help us
Download: batou.tar.gz

The file batou is a vmss image because the file begins with "d2 be d2 be 08." Let's use volatility to analyse this memory dump. At first, we have to determine the profile. imageinfo tells us the profile.

$ vol.py -f batou imageinfo
INFO    : volatility.debug    : Determining profile based on KDBG search...
          Suggested Profile(s) : Win7SP1x64, Win7SP0x64, Win2008R2SP0x64, Win2008R2SP1x64_24000, Win2008R2SP1x64_23418, Win2008R2SP1x64, Win7SP1x64_24000, Win7SP1x64_23418
                     AS Layer1 : WindowsAMD64PagedMemory (Kernel AS)
                     AS Layer2 : VMWareAddressSpace (Unnamed AS)
                     AS Layer3 : FileAddressSpace (/home/ptr/workspace/ctf/sect/batou/batou)
                      PAE type : No PAE
                           DTB : 0x187000L
                          KDBG : 0xf800028480a0L
          Number of Processors : 2
     Image Type (Service Pack) : 1
                KPCR for CPU 0 : 0xfffff80002849d00L
                KPCR for CPU 1 : 0xfffff880009ea000L
             KUSER_SHARED_DATA : 0xfffff78000000000L
           Image date and time : 2018-09-11 04:17:17 UTC+0000
     Image local date and time : 2018-09-10 21:17:17 -0700

The process list can be obtained by psscan.

$ vol.py -f batou --profile=Win7SP1x64 psscan
Offset(P)          Name                PID   PPID PDB                Time created                   Time exited                   
------------------ ---------------- ------ ------ ------------------ ------------------------------ ------------------------------
0x000000003de683c0 dwm.exe            1660    792 0x0000000014479000 2018-09-11 04:16:05 UTC+0000                                 
0x000000003de72b30 explorer.exe       1720   1652 0x00000000154e2000 2018-09-11 04:16:05 UTC+0000                                 
0x000000003df57b30 SearchProtocol     1040   1988 0x000000000d026000 2018-09-11 04:16:13 UTC+0000                                 
0x000000003df77b30 SearchFilterHo     1140   1988 0x000000000d92f000 2018-09-11 04:16:13 UTC+0000                                 
0x000000003df9f100 SearchProtocol     1340   1988 0x00000000106ca000 2018-09-11 04:16:13 UTC+0000                                 
0x000000003dfaf4a0 iexplore.exe       1536   1720 0x000000000c130000 2018-09-11 04:16:15 UTC+0000                                 
0x000000003dfe54f0 iexplore.exe       1636   1536 0x000000000be44000 2018-09-11 04:16:17 UTC+0000                                 
0x000000003dfef570 StikyNot.exe       1872   1720 0x0000000006f04000 2018-09-11 04:16:20 UTC+0000                                 
0x000000003e08d3a0 taskhost.exe       1728    460 0x0000000014187000 2018-09-11 04:16:05 UTC+0000                                 
0x000000003e1da210 notepad.exe         204   1720 0x0000000028c02000 2018-09-11 04:16:31 UTC+0000                                 
0x000000003e22bb30 svchost.exe         748    460 0x000000001ba0c000 2018-09-11 04:15:34 UTC+0000                                 
0x000000003e23eb30 svchost.exe         792    460 0x000000001b619000 2018-09-11 04:15:34 UTC+0000                                 
0x000000003e264890 svchost.exe         820    460 0x000000001b31f000 2018-09-11 04:15:34 UTC+0000                                 
0x000000003e2b32a0 svchost.exe         944    460 0x000000001bf2a000 2018-09-11 04:15:35 UTC+0000                                 
0x000000003e2eb890 svchost.exe         212    460 0x000000001bb38000 2018-09-11 04:15:35 UTC+0000                                 
0x000000003e367b30 spoolsv.exe         300    460 0x000000001b064000 2018-09-11 04:15:35 UTC+0000                                 
0x000000003e379b30 svchost.exe         968    460 0x000000001b8c6000 2018-09-11 04:15:36 UTC+0000                                 
0x000000003e4de060 csrss.exe           316    308 0x000000002004a000 2018-09-11 04:15:32 UTC+0000                                 
0x000000003e4f0b30 lsass.exe           468    372 0x000000001ea74000 2018-09-11 04:15:33 UTC+0000                                 
0x000000003e5062b0 wininit.exe         372    308 0x000000001fc50000 2018-09-11 04:15:33 UTC+0000                                 
0x000000003e510a00 winlogon.exe        400    356 0x000000001f19d000 2018-09-11 04:15:33 UTC+0000                                 
0x000000003e551060 services.exe        460    372 0x000000001eb54000 2018-09-11 04:15:33 UTC+0000                                 
0x000000003e55bb30 lsm.exe             476    372 0x000000001f47c000 2018-09-11 04:15:33 UTC+0000                                 
0x000000003e5b7b30 svchost.exe         584    460 0x000000001e7c5000 2018-09-11 04:15:34 UTC+0000                                 
0x000000003e612b30 svchost.exe         664    460 0x000000001b903000 2018-09-11 04:15:34 UTC+0000                                 
0x000000003edbe2d0 SearchIndexer.     1988    460 0x000000000fe67000 2018-09-11 04:16:12 UTC+0000                                 
0x000000003f41c750 smss.exe            232      4 0x0000000025ac0000 2018-09-11 04:15:30 UTC+0000                                 
0x000000003febdb30 notepad++.exe      1568   1720 0x0000000005f4c000 2018-09-11 04:16:39 UTC+0000   2018-09-11 04:16:48 UTC+0000  
0x000000003ffbdae0 System                4      0 0x0000000000187000 2018-09-11 04:15:30 UTC+0000                                 
0x000000003ffc65f0 csrss.exe           364    356 0x000000001fb97000 2018-09-11 04:15:33 UTC+0000                                 

As you can see from the list, notepad++ had terminated. I tried to dump the process but it didn't work. Maybe the flag is written to the disk by notepad++. filescan is useful when we want to survey the files.

$ vol.py -f batou --profile=Win7SP1x64 filescan > filelist

I looked over the list and found curious lines in which notepad++ makes some backup files.

...
0x000000003fe9c930     16      0 R--rw- \Device\HarddiskVolume2\Users\Batou\AppData\Roaming\Notepad++\backup\new 2@2018-09-10_203737
0x000000003feacbc0      3      0 R--r-d \Device\HarddiskVolume2\Windows\SysWOW64\WindowsCodecs.dll
0x000000003fead410     16      0 R--rw- \Device\HarddiskVolume2\Users\Batou\AppData\Roaming\Notepad++\backup\new 1@2018-09-10_202915
...

Those files can be dumped by dumpfile. The extracted file has the flag in hex :-)

$ vol.py -f batou --profile=Win7SP1x64 dumpfiles --dump-dir="./" -Q 0x000000003fe9c930
$ cat file.None.0xfffffa8000da35c0.dat

53 45
43 54 7b 
34 6c 6c 5f 79 6f 75 72 5f 4e 30 74 33 73 5f 34 72 33 5f 62 33 6c 30 6e 67 5f 74 30 5f 75 35