Hello Navi

Tech, Security & Personal Notes

1
2
3
4
5
6
7
8
9
10
11
# get help
# command /?

# Pagination
A:\> dir /p

# Wide List Format
A:\> dir /w

# Piping to more
A:\> dir | more

cat.exe (type)

1
2
3
4
5
6
7
8
9
10
11
12
13
DOS          <DIR>         12-15-25   5:07p
COMMAND COM 54,645 05-31-94 6:22a
WINA20 386 9,349 05-31-94 6:22a
CONFIG SYS 71 12-15-25 5:07p
AUTOEXEC BAT 78 12-15-25 5:07p
FLAG TXT 60 04-02-26 5:07a
6 file(s) 64,203 bytes
10,428,416 bytes free

C:\>type flag.txt
pwn.college{QMkbfHdYCkFD_y-FmBdS66_cyD2.******************}

C:\>

ls.exe (dir)

DOS filenames were case-insensitive

DOS assumed that every file had a name of 8 characters or less and an “extension” (after the one allowed . in the filename) of 3 characters or less.

there is no permission or ownership information

As a side note, extensions were critical in DOS for similar reasons that they remain important in Windows: figuring out the type of file. Specifically for DOS, programs needed to be named with extensions of EXE (normal DOS executable), COM (simple, older executables that were basically just raw binary code), and BAT (a batch script containing commands to run, analogous to a weird variant of a typical shell script).

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
Booting from Hard Disk...
Starting MS-DOS...


HIMEM is testing extended memory...done.
Batch file missing

C:\>dir

Volume in drive C is MS-DOS_6
Volume Serial Number is 5B8F-88E6
Directory of C:\

DOS <DIR> 12-15-25 5:07p
COMMAND COM 54,645 05-31-94 6:22a
WINA20 386 9,349 05-31-94 6:22a
CONFIG SYS 71 12-15-25 5:07p
FLG396 TXT 60 04-02-26 5:14a
5 file(s) 64,125 bytes
10,432,512 bytes free

C:\>type flg396.txt
pwn.college{c1dnzzEBipHvxFUOKeBsqnezrlb.******************}

C:\>

Changing Disks

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
Boot failed: could not read the boot disk

Booting from Hard Disk...
Starting MS-DOS...


HIMEM is testing extended memory...done.

C:\>C:\DOS\SMARTDRV.EXE /X
C:\>d:

D:\>dir

Volume in drive D has no label
Volume Serial Number is 409D-8F04
Directory of D:\

FLAG TXT 60 04-02-26 5:15a
1 file(s) 60 bytes
16,723,968 bytes free

D:\>type flag.txt
pwn.college{A_QSyVfCu23CuMIMATEp-popFEE.******************}

D:\>

Reading Floppies

floppy disks (软盘)

DOS assigned floppy drives the A: and B: drives, and “mounting” happened automatically on access (or, more specifically, there was no filesystem “mounting”; access just happened). The two letters were for computers that had both a 5.25” and a 3.5” floppy drive

load floppy in control panel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
iPXE (http://ipxe.org) 00:03.0 CA00 PCI2.10 PnP PMM+00F91FB0+00EF1FB0 CA00



Booting from Floppy...
Boot failed: could not read the boot disk

Booting from Hard Disk...
Starting MS-DOS...


HIMEM is testing extended memory...done.

C:\>C:\DOS\SMARTDRV.EXE /X
C:\>a:

A:\>cat flag.txt
Bad command or file name

A:\>type flag.txt
pwn.college{USkPRtXd3nCSZPKf6MUGwdJLU8J.******************}

A:\>

Installing MS-DOS

use the provided floppies to install MS-DOS 6.22

since each floppy only holds 1.44mb, it was necessary to ship software in multiple floppies. MS-DOS 6.22 used three disks

load floppy in control panel from 0 to 2 and follow the wizard

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
SeaBIOS (version rel-1.17.0-0-gb52ca86e094d-prebuilt.qemu.org)


iPXE (http://ipxe.org) 00:03.0 CA00 PCI2.10 PnP PMM+00F91FB0+00EF1FB0 CA00



Booting from Floppy...
Boot failed: could not read the boot disk

Booting from Hard Disk...
Starting MS-DOS...


HIMEM is testing extended memory...done.

C:\>C:\DOS\SMARTDRV.EXE /X
C:\>a:

A:\>type flag.txt
pwn.college{gF-MZnE1WGsp7qf0RwDh0DJDe2c.******************}

A:\>

autoexec.bat

Any boot process includes not just the loading of the OS itself, but its initialization. In DOS, this was elegantly handled by autoexec.bat, a script that specified what commands would run when the system booted.

you can access the various menu items using your Alt key (e.g., Alt-F to open the File menu).

modify the file from del to type

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
SeaBIOS (version rel-1.17.0-0-gb52ca86e094d-prebuilt.qemu.org)


iPXE (http://ipxe.org) 00:03.0 CA00 PCI2.10 PnP PMM+00F91FB0+00EF1FB0 CA00



Booting from Floppy...
Boot failed: could not read the boot disk

Booting from Hard Disk...
Starting MS-DOS...


HIMEM is testing extended memory...done.

C:\>type c:\flag.txt
pwn.college{UBwCBfcUDi1W3W0o4QuVdHGB6rH.******************}

C:\>

doskey

Once doskey is loaded, you gain access to command history with up/down arrows and command line editing

上下箭头 :浏览命令历史记录 左右箭头 :在行内移动光标 F7 :在弹出窗口中显示命令历史记录 F9 :按编号选择命令

FUN FACT: doskey was introduced in MS-DOS 5.0 (1991) and was a game-changer for productivity. Before doskey, if you made a typo in a long command, you’d have to retype the whole thing!

edit and add doskey at top of autoexec.bat and quit relaunch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
C:\>
C:\>echo pwn.college{
pwn.college{

C:\>echo 011NPLaz5mkZ
011NPLaz5mkZ

C:\>echo PSINV-xsu6g7
PSINV-xsu6g7

C:\>echo 7JI.********
7JI.********

C:\>echo **********}
**********}

C:\>

pwn.college{011NPLaz5mkZPSINV-xsu6g77JI.******************}

DOS Networking

install the packet drivers (make sure to specify the interrupt!) install and configure mtcp netcat to 192.168.13.37 port 1337 for the flag!

load pcnet floppy

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
PKTCHK   COM           856 01-28-92   9:58p
PKTMODE COM 1,728 01-28-92 9:58p
PKTMULTI COM 1,822 01-28-92 9:59p
PKTRING COM 2,420 01-28-92 9:59p
PKTSEND COM 2,346 01-28-92 9:59p
PKTSTAT COM 1,693 01-28-92 9:59p
PKTTRAF COM 6,019 01-28-92 9:59p
TERMIN COM 1,419 01-28-92 9:58p
TRACE COM 2,124 01-28-92 9:58p
WINPKT COM 3,617 01-28-92 9:59p
18 file(s) 116,641 bytes
192,512 bytes free

A:\PKTDRVR>pcntpk int=0x60
Packet driver for an PCNTPK, version 03.10
Packet driver skeleton copyright 1988-92, Crynwr Software.
This program is free software; see the file COPYING for details.
NO WARRANTY; see the file COPYING for details.

Packet driver is at segment 0BC8
Interrupt number 0xB (11)
I/O port 0xC000 (49152)
My Ethernet address is 52:54:00:12:34:56

A:\PKTDRVR>

load mtcp floppy

netcat to 192.168.13.37 port 1337 for the flag!

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
set mtcpcfg=ftp.cfg

# need edit yourself
A:\>type ftp.cfg
PACKETINT 0x60
IPADDR 192.168.13.100
NETMASK 255.255.255.0
GATEWAY 192.168.13.1
NAMESERVER 192.168.13.1
MTU 1500

A:\>set mtcpcfg=ftp.cfg

A:\>nc -target 192.168.13.37 1337
mTCP Netcat by M Brutman (mbbrutman@gmail.com) (C)opyright 2007-2025
Version: Jan 10 2025

Resolving server address - press Ctrl-Break to abort

Server resolved to 192.168.13.37 - connecting

Connected!

pwn.college{sig-JqvzdYNSstfBBdU6WAW8lln.******************}

Elapsed time: 0.00 Bytes sent: 0 Received: 60

A:\>

We sent the same announcement to three servers for redundancy. Each server has its own RSA key. Intercept all three — maybe you can piece something together.

Initial Analysis

The challenge provides an output.txt containing an exponent e = 3, three moduli (n1, n2, n3), and three ciphertexts (c1, c2, c3). By examining the data, we notice:

  1. Low Exponent: e = 3 is very small.
  2. Identical Ciphertexts: c1 = c2 = c3. This means the raw message M was not padded differently for each server.
  3. Magnitude of c: The ciphertext c is significantly smaller than any of the moduli n.

In RSA, the encryption process is c = Me (mod  n). Usually, Me is much larger than n. However, if Me < n, then the modulo operation has no effect, and c = Me.

Solution

Since c < ni and e = 3, the message M can be recovered simply by calculating the integer cube root of c: $$M = \sqrt[3]{c}$$

Implementation

Using Python and the gmpy2 library, we can solve for M:

1
2
3
4
5
6
7
8
9
10
11
12
13
import gmpy2
from binascii import unhexlify

# Intercepted ciphertext
c = 475436441896018898725156479190091126537849994697426945980826369000641892902004477923335055269088235139492237640527487698088281484953901383579636883543216552932099156009006828723690550706326538736801225046068870773990108130474408522838234755277972911893744937243892927414355347438993698991261629557719442242861719577879055371620865465785392597257968132649494474946507819896785671106833645551504301840437212737125

# Calculate the cubic root
m, exact = gmpy2.iroot(c, 3)

if exact:
# Convert integer to hex, then to ASCII
flag = unhexlify(hex(m)[2:]).decode()
print(f"Flag: {flag}")

Note: This challenge is a simplified version of Håstad’s Broadcast Attack. While Håstad’s attack typically uses the Chinese Remainder Theorem (CRT) to solve for Me when Me > ni, the small size of the message relative to the key size here allowed for a direct cubic root calculation.

Flag

kashiCTF{h4st4d_s4ys_sm4ll_3xp0n3nts_k1ll_RSA_br04dc4sts}

Join the RITSEC CTF Discord server to get the most up-to-date information about the competition. The flag can be found in the topic of the #announcements channel, or in the CTF kickoff announcement.

Initial Analysis

The challenge points to the RITSEC CTF Discord server as a source for competition updates and a hidden flag.

Solution

By checking the topic of the #announcements channel, the flag is readily available.

Flag

RS{p1r4t3_d1sc0rd}

A secret message has been passed down through generations since the time of the great Mahabharata war. Legend says that every 64 years, the keepers of this secret would encode the message once more to protect it from those who might seek to misuse its power. The message has traveled through 3136 years of history, from the ancient battlefields of Kurukshetra in 3136 BCE to the dawn of the Common Era.

Initial Analysis

The challenge provides two main clues:

  1. Mathematical Clue: The message has existed for 3136 years and was re-encoded every 64 years. $$\frac{3136}{64} = 49$$ This suggests the message has been recursively encoded 49 times.
  2. File Inspection: The provided file secret_message.txt is large (~59MB) and starts with the characters Vm0wd2Qy..., which is a classic signature for multiple layers of Base64 encoding.

Extraction & Decoding

We can use a Python script to iteratively decode the file 49 times. Each layer of decoding reduces the file size until the final plaintext flag is revealed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import base64

def solve():
# Read the initial encoded data
with open('secret_message.txt', 'r') as f:
data = f.read().strip()

# Iteratively decode 49 times
print("[*] Starting iterative Base64 decoding...")
for i in range(49):
try:
data = base64.b64decode(data).decode('utf-8')
except Exception as e:
print(f"[-] Error at iteration {i+1}: {e}")
break

print(f"[+] Final Decoded Message: {data}")

if __name__ == "__main__":
solve()

Flag

kashiCTF{th3_s3cr3t_0f_mah4bh4r4t4_fr0m_3136_BCE}

I like to save my files as pdfs. Kashi kings hate 184.

Initial Analysis

The file is named flag.pdf, but standard PDF analysis tools fail to recognize it:

1
2
pdfid flag.pdf
# Output: Not a PDF document

Using the file command reveals its true identity:

1
2
file flag.pdf
# Output: flag.pdf: Netpbm image data, size = 284 x 150, rawbits, pixmap

The challenge hint “Kashi kings hate 184” suggests that the height of the image (currently 150) has been tampered with and should likely be 184.

Extraction & Decoding

Netpbm (PPM) files use a plain-text header. We can repair the height by editing the file header. Opening the file in a hex editor or a text editor like vim (using :set binary or simply editing the ASCII header) reveals:

1
2
3
4
P6
284 150
255
[Binary Data...]

Change the height value from 150 to 184:

1
2
3
4
P6
284 184
255
[Binary Data...]

After saving the change, the image can be opened with a standard image viewer to reveal the flag.

Flag

kashiCTF{iLOVEkashi}

Generating primes is expensive. I optimized my key generation to be twice as fast. The modulus is 4096 bits — perfectly secure.

Initial Analysis

The hint “optimized my key generation to be twice as fast” suggests that instead of generating two distinct large primes, the author might have reused the same prime (n = p2) or chosen two primes that are extremely close to each other. This makes the modulus vulnerable to Fermat’s Factorization Method or simply taking the square root.

Extraction & Decoding

Given a 4096-bit modulus n, we can check if it’s a perfect square or if its factors are close to $\sqrt{n}$ by starting from $\lfloor\sqrt{n}\rfloor$ and searching downwards. Once factored, we calculate ϕ(n), derive the private key d, and decrypt the AES key which was used to encrypt the flag.

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
29
30
31
32
33
34
35
36
import math
import base64
from Crypto.Util.number import long_to_bytes, bytes_to_long
from Crypto.Util.Padding import unpad
from Crypto.Cipher import AES

# Modulus and public exponent
n = 0x752a94a112ba0ce096f47934dac094d3d07b8c036613938142c0d4c15fc82692eee38d2457dd8d16472c4ddbe8cb5e2a6331e0ca0351094fc9516559768ebfe44509154d64116fa1fe1daf698413d37c9fe3406555f3190e29d99bee0cdd663d531c8e818f2686c7ad24338b4e93c6bfbd1b5a6dc5161316b2cb9ac1ae05a4ac43fdeb3b024b2e00dfcd87069ea1645996d9ad16ac3a9697414c17279112303a1d21136a99dc47628e15a3d6e18779de7aec310331dff1a81871b03e214de09f56c0f3de02f9f399be4ebc094f34b578d311a8b48e9c6cf2fa2f4e321f1dab0a99e5b9d99464c19452d9cc21544ac8e32fb9f13d1b2990758de0876de465cbd3632f846ef49fd7b97abee2ce529cfbc75a0d0792df6cc8091198134e9f646cf7d33c85c4ddd2c4b9a248c2c470d7369ebc7245bcec049455da2ceb742b26058514418398149d03cd1ad74a997375d0462a43e73aa62fc1f7e0dcc67e8f1559073074b9b8d3c37edfcfce67fd1822227933c5a14425d76119fc0a25da4c059761c86bc3077c4d096d9b9f6ae2faf728dbf24d48fa74d99c8c0d8780d2963ca9eccef0dd847ce22fc5b13793981257a9d4dd1af965e9baa5bd9fc4e3321cf8c6fd9871e342e5ae0dff19ab6e9fd8e14b5cc766b92df3306ef63af248b019528928644007c17e31918f9fdf10daeadc1eb8abeb6297bdc8f8e9b27c591f12159479
e = 65537

# Factor n
p = math.isqrt(n)
while n % p != 0:
p -= 1
q = n // p

# Calculate phi
if p == q:
phi = p * (p - 1)
else:
phi = (p - 1) * (q - 1)

# Decrypt AES Key
d = pow(e, -1, phi)
ct_b64 = "MVoAMG4KRlXdSxEtVL/GpwXWyelWmAsJJhMnPaTzF2Hhjm/h/vkHJKQIyHSld2XuB6Q0sWq/TN1dkSePEB1oq6ugzMcgp5VQ9Xn0mOCn1GZ7fP3bKUVD6mG1bt3dkHxzlAT7v6c6xKaTtJJKTV3JXnB2u3duW4dCrFyassEjHM1PEML3CWqJBrgxnlTIYI4i9ydwg1MF1fTOBTm2KLlQ6rIGnBWcGwg4k+8I7e0mIbhod53w3FzIPXePv0ONVp+HBn4XsICwEHhJLXixmHcEz0jxwCgRdz9qr+Ur1pOaVuKN/26cwpYdVTlY5Fk7KapoV3Ews69353gCa+QYiJtzuwr1uFTBe74GfZZ8xzxFK51TnMbqB1M5cpzBK8/TK+ES/+yy1R4jsGkQ4i7Qz0oAsqBoNExSaLsNgwzZe4dYRE2BwDy2tW2QAYFUeU+SVjUb2BI67QtQYl2g+GB0kAMzbcRFr/kykIHqqb2N05BxgRrtsFjq2zWvpJJ71OFCrWVg8IzO7N+WUXFFyFv7ZfdnKOhC/iPNNmLbJXa3Gul89Fa6VyvCJw6lA/t7QCsjtcVG7ox51JAvoHhw5FLIpT+wmfq969iUujkXzLpjyXBVrfnEdjRt61zGEd3tmWIYst721GcKnbxKBehxwpseDBYR0hJRy+CIf5SnrP6/Blq55cQ="
ct_int = bytes_to_long(base64.b64decode(ct_b64))
aes_key = long_to_bytes(pow(ct_int, d, n))

# Decrypt Flag
iv = base64.b64decode("XSCnpZLyN1Oin7F67hOKWQ==")
flag_ct = base64.b64decode("n+H1n3ezKEm0ulyLMcp/ShxLZAddKX7y848o/Lf/56qDev/DPBz+IRcJ14yHWGOuodMaMwyLZi9er7slNa+QMw==")

cipher = AES.new(aes_key, AES.MODE_CBC, iv)
flag = unpad(bytes(cipher.decrypt(flag_ct)), AES.block_size).decode()

print(f"\n[+] FLAG: {flag}")

Flag

kashiCTF{wh3n_0n3_pr1m3_1s_n0t_3n0ugh_p_squared_1s_w0rs3}

Wait, you forgot to give me the Advent calendar!?!?! And what is that supposed to mean, I should have opened the doors up until today?? Ugh, okay, then I’ll start: Door 1

Investigation

The hint suggests that we need to visit the “doors” of the Advent calendar. The URL structure was identified as:

1
GET https://hack.arrrg.de/adventskalender/$$ HTTP/1.1

Where $$ represents the door number. To find the flag, we need to check all possible doors (1 to 30).

Solution

Using Zaproxy (OWASP ZAP) or a similar fuzzer, we can automate the process:

  1. Intercept/Send Request: Create a base request to https://hack.arrrg.de/adventskalender/1.
  2. Set Payload: In Zaproxy’s fuzzer, set the payload for the door number position.
  3. Configure Generator: Use a Numberzz generator:
    • From: 1
    • To: 30
    • Step: 1
  4. Execute Fuzz: Start the fuzzer and monitor the responses.
  5. Analyze Results: Look for a response that differs in content.

After fuzzing, collecting the responses and looking for a secret message was revealed the hidden message.

THE ANSWER: FELIZNAVIDAD

I like to have my poems saved on CTFd instances like this. But the admin does like it, so I hid the secret in my poem.

Solution

The provided poem contains a significant amount of trailing tabs and spaces at the end of each line. This is a classic indication of SNOW (Steganographic Nature Of Whitespace) steganography.

By using a SNOW decoder (such as the web-based snow.js decoder), we can extract the hidden message from the poem text:

1
2
3
4
5
6
7
8
9
10
11
12
13
The way a crow	      	  	   	   		     	   	      
Shook down on me
The dust of snow
From a hemlock tree

Has given my heart
A change of mood
And saved some part
Of a day I had rued.




The decoded message reveals the flag.

Flag

kashiCTF{1_like_poems_but_1_lik3_u_more<3}

Its Time to be sane. I wish I could give the flag, but I can’t. Try searching this site. xd :>

Solution

The flag was split into two parts found in different locations on the platform:

  1. robots.txt: Navigating to https://kashictf.iitbhucybersec.in/robots.txt revealed the first part of the flag:

    1
    2
    3
    User-agent: *
    Disallow: /admin
    kashiCTF{50_you_did

  2. Home Page Source: Inspecting the HTML source code of the main landing page https://kashictf.iitbhucybersec.in/ revealed the second part hidden inside a comment:

    1
    <!--- _endup_ge77ing_the_flag_hehe} --->

Combining both parts yields the full flag.

Flag

kashiCTF{50_you_did_endup_ge77ing_the_flag_hehe}

The flag was hidden in the #rules channel of the kashiCTF Discord server.

Solution

The following encoded string was found:

1
Tk5RWEcyREpJTktFTTYzVU5CVVhHWDNYTUZaVjYzVFBPUlBXUVlMU01SNlFVPT09Cg==
  1. Base64 Decoding: Decoding the string once results in a Base32-encoded string.
    1
    NNQXG2DJINKEM63UNBUXGX3XMFZV63TPORPWQYLSMR6QU===
  2. Base32 Decoding: Decoding the resulting string

Flag

kashiCTF{this_was_not_hard}