angstromctf writeup [en]


## [angstromctf](https://2024.angstromctf.com/challenges) writeup



The result was 630th/923rd place out of 923, 80 pts.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3794748/a8c91216-fc5e-9ecb-64b2-8a0b51863bed.png)

Here are the four problems I was able to solve
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3794748/e6357634-13fe-f158-72de-9b59ecf7d56c.png)

## kcehC ytinaS[misc] 10pt, 550solvs
```
)csim# ni cipot lennahc eht s'ti( galf eht rof drocsiD ruo nioJ
```
At first I thought it was Caesar Encryption, but it was not.
The link was to discord, so I somehow read this word as discord.
After about 10 minutes of thinking, I realized that the letters could be read backwards.
```
joiin our Discord for the flag (it's the channel topic in #misc)
```
So I looked at the misc channel on Discord and found the following in the channel summary section.
```
}egassem_terces_ym_edoced_uoy_did_woh{ftca
```
This one was also flipped and the FLAG was removed.
```
actf{how_did_you_decode_my_secret_message}
```


## putnam[misc] 10pt, 637solves

```
Solve the putnam, get the flag. Easy right?

Connect to it at nc challs.actf.co 31337
```
Type the command as it is.
I did the addition and got the FLAG.
```
└─$ nc challs.actf.co 31337
514 + 97 = ?
611
You succeeded! The flag is actf{just_a_tad_easier_than_the_actual_putnam} :D
```

## erm what the enigma[crypto] 20pt, 530solves
```
In the dimly lit, smoke-filled war room, the Enigma M3 machine sat at the center of the table like a cryptographic sentinel.
Its reflector, UKW B, gleamed ominously in the low light. 
The three rotors, I, II, and III, stood proudly in their respective slots, each at position 1 with their rings set to 1. 
The plugboard, conspicuously vacant, indicated a reliance on the rotor settings alone to encode the day's crucial messages. 
As the operator's fingers hovered over the keys, the silence was heavy with anticipation. 
Each clack of the keys transformed plaintext into an unbreakable cipher, the resulting ciphertext, brht{d_imhw_cexhrmwyy_lbvkvqcf_ldcz}, a guardian of wartime secrets.
```
日本語訳
```
薄暗く、煙が充満した戦場では、エニグマM3マシンが暗号の歩哨のようにテーブルの中央に置かれていた。
その反射鏡UKW Bは暗い光の中で不吉に輝いていた。
I、II、IIIの3つのローターがそれぞれのスロットに誇らしげに立っており、それぞれのリングは1の位置にセットされていた。
オペレーターの指がキーの上に置かれると、期待に満ちた静寂が訪れた。
キーを叩くたびに、平文が解読不可能な暗号に変換され、その結果の暗号文、brht{d_imhw_cexhrmwyy_lbvkvqcf_ldcz}は、戦時中の秘密の守護者となった。
```
It turns out that it is an Enigma cryptographic problem.
I searched for "enigma m3" etc. and investigated various mechanisms.

First, I tried [this site](https://cryptii.com/pipes/enigma-machine), but it did not work.

Next, I searched for enigma ctf and found [this site](https://www.dcode.fr/enigma-machine-cipher).

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3794748/b3510627-d5b0-2e38-7beb-c136717b26a8.png)

Decryptoed and was able to get flag.

```
actf{i_love_enigmatic_machines_mwah}
```

## philosophy[crypto] 40pt, 338solves
```
Clam decided to start studying philosophy, and what is the difference between plus one and minus one anyway...

challenge
```

Given a file named "call.py", let's look at its contents with the cat command
```
cat chall.py
```
chell.py
```
from Crypto.Util.number import getPrime
from secret import flag

p = getPrime(512)
q = getPrime(512)

m = int.from_bytes(flag.encode(), "big")

n = p * q
e = 65537
c = pow(m, e, n)

phi = (p + 1) * (q + 1)

print(f"n: {n}")
print(f"e: {e}")
print(f"c: {c}")
print(f"\"phi\": {phi}")

"""
n: 86088719452932625928188797700212036385645851492281481088289877829109110203124545852827976798704364393182426900932380436551569867036871171400190786913084554536903236375579771401257801115918586590639686117179685431627540567894983403579070366895343181435791515535593260495162656111028487919107927692512155290673
e: 65537
c: 64457111821105649174362298452450091137161142479679349324820456191542295609033025036769398863050668733308827861582321665479620448998471034645792165920115009947792955402994892700435507896792829140545387740663865218579313148804819896796193817727423074201660305082597780007494535370991899386707740199516316196758
"phi": 86088719452932625928188797700212036385645851492281481088289877829109110203124545852827976798704364393182426900932380436551569867036871171400190786913084573410416063246853198167436938724585247461433706053188624379514833802770205501907568228388536548010385588837258085711058519777393945044905741975952241886308
```
I thought pow might be a clue, so I used Google.
```
ctf crypto writeup pow
```
I looked into this.
```
https://trap.jp/post/1582/
```
I referred to this site.

Current.
```math
c = m^e(mod\;n)\\
```
The following equation is used to obtain the plaintext m.
The following equation can be calculated to obtain the plaintext m

```math
\displaylines{ 
\begin{align}
φ & = (p-1)(q-1)\\
d & = e^{-1}(mod\;φ)\\
m & = c^d(mod \;n)\\
\end{align}
} 
```

First, we obtain φ.
```math
φ =pq-(p+q)+1・・・①
```

Here from the problem statement,
```math
\displaylines{ 
\begin{align}
n & = pq\\
phi & = pq + (p+q) + 1\\
\end{align}
}
```
So, we can transform the formula to
```math

p+q = phi-n-1・・・②


```
We can see that
Substituting (2) into (1), we get

```math
\displaylines{ 
\begin{align}
φ & =n-(phi-n-1)+1\\
  & = 2n -phi +2
\end{align}
} 
```
Then find d
```math
\displaylines{ 
\begin{align}
d & = e^{-1}(mod\;φ)\\
  & = pow(e, -1, φ)
\end{align}
} 
```
Finally, substitute the previous ones to get m
```math
\displaylines{ 
\begin{align}
m & = c^d(mod \;n)\\
  & = pow(c, d, n) 
\end{align}
} 
```
The code for these is as follows.
```
from Crypto.Util.number import long_to_bytes

n = 86088719452932625928188797700212036385645851492281481088289877829109110203124545852827976798704364393182426900932380436551569867036871171400190786913084554536903236375579771401257801115918586590639686117179685431627540567894983403579070366895343181435791515535593260495162656111028487919107927692512155290673

e = 65537

c = 64457111821105649174362298452450091137161142479679349324820456191542295609033025036769398863050668733308827861582321665479620448998471034645792165920115009947792955402994892700435507896792829140545387740663865218579313148804819896796193817727423074201660305082597780007494535370991899386707740199516316196758

phi = 86088719452932625928188797700212036385645851492281481088289877829109110203124545852827976798704364393182426900932380436551569867036871171400190786913084573410416063246853198167436938724585247461433706053188624379514833802770205501907568228388536548010385588837258085711058519777393945044905741975952241886308

f = 2*n - phi + 2 
d = pow(e, -1, f)
#d = (e ** -1) % f
m = pow(c, d, n)
#k = (c ** d) % n


print(m)
print("----------------")
#print(k)
print(long_to_bytes(m))
```

```
d = pow(e, -1, f)
#d = (e ** -1) % f
```

I was initially writing below and was stuck on the error.
I guess I still don't have a good understanding of these areas.
```
From GPT
pow(e, -1, f) computes the modulo inverse of an integer. It is intended to solve certain number-theoretic problems.
e ** -1 % f computes the inverse of a floating-point number and divides the result by f to get the remainder, which is not the same as computing the number-theoretic modulo inverse.
To calculate the exact modulo inverse, always use pow(e, -1, f).
```


```
actf{its_okay_i_figured_out_phi_anyway}
```

## Problems I couldn't solve but tried below
## trip 30pt,484solves
```
What road was this this photo taken on?

For example, if the road was "Colesville Road" the flag would be actf{colesville}.
```
A question where you are given a photo and you have to answer where it was taken.
I referred to [Summary of tools, sites, and techniques I personally use for [CTF] OSINT questions](https://qiita.com/xryuseix/items/e35b8c946e5dfe96f848) and tried various methods such as google lens and image search, but no matches I gave up because I could not find any images that matched.


## aw man 50pt, 290solves
```
Man? Is that you?
```
This was another problem where a picture was given.
```
CTF Images
```
I tried to solve it with reference to the following site, but I could not find the FLAG and gave up.

[Forensics入門（CTF）](https://qiita.com/knqyf263/items/6ebf06e27be7c48aab2e)
[4-Girls Petit CTF WriteUp（in SECCON 2023 電脳会議）](https://tech.dentsusoken.com/entry/2024/01/17/4-Girls_Petit_CTF_WriteUp)


```
$ file guess_the_flag
guess_the_flag: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=5872c12702d2954fef870af77944910ef66b5d69, for GNU/Linux 3.2.0, not stripped
```
```
$ strings guess_the_flag           
/lib64/ld-linux-x86-64.so.2
mgUa
__cxa_finalize
fgets
__libc_start_main
strcmp
puts
strlen
stdin
__stack_chk_fail
libc.so.6
GLIBC_2.4
GLIBC_2.2.5
GLIBC_2.34
_ITM_deregisterTMCloneTable
__gmon_start__
_ITM_registerTMCloneTable
D$H1
D$HdH+
PTE1
u+UH
Go ahead, guess the flag: 
Correct! It was kinda obvious tbh.
Wrong. Not sure why you'd think it'd be that.
:*3$"
`bugzbnllhuude^un^uid^md`ru^rhfohghb`ou^chu|
GCC: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
Scrt1.o
__abi_tag
guess_the_flag.c
crtstuff.c
deregister_tm_clones
__do_global_dtors_aux
completed.0
__do_global_dtors_aux_fini_array_entry
frame_dummy
__frame_dummy_init_array_entry
__FRAME_END__
_DYNAMIC
__GNU_EH_FRAME_HDR
_GLOBAL_OFFSET_TABLE_
__libc_start_main@GLIBC_2.34
_ITM_deregisterTMCloneTable
puts@GLIBC_2.2.5
stdin@GLIBC_2.2.5
secretcode
_edata
_fini
strlen@GLIBC_2.2.5
__stack_chk_fail@GLIBC_2.4
fgets@GLIBC_2.2.5
__data_start
strcmp@GLIBC_2.2.5
__gmon_start__
__dso_handle
_IO_stdin_used
_end
__bss_start
main
__TMC_END__
_ITM_registerTMCloneTable
__cxa_finalize@GLIBC_2.2.5
_init
.symtab
.strtab
.shstrtab
.interp
.note.gnu.property
.note.gnu.build-id
.note.ABI-tag
.gnu.hash
.dynsym
.dynstr
.gnu.version
.gnu.version_r
.rela.dyn
.rela.plt
.init
.plt.got
.plt.sec
.text
.fini
.rodata
.eh_frame_hdr
.eh_frame
.init_array
.fini_array
.dynamic
.data
.bss
.comment
```

```
$ sudo chmod 777 guess_the_flag.exe   
```
```
$ ./guess_the_flag                  
Go ahead, guess the flag: 
a
Wrong. Not sure why you'd think it'd be that.
```
```
$ readelf guess_the_flag 
Usage: readelf <option(s)> elf-file(s)
 Display information about the contents of ELF format files
 Options are:
  -a --all               Equivalent to: -h -l -S -s -r -d -V -A -I
  -h --file-header       Display the ELF file header
  -l --program-headers   Display the program headers
     --segments          An alias for --program-headers
  -S --section-headers   Display the sections' header
     --sections          An alias for --section-headers
  -g --section-groups    Display the section groups
  -t --section-details   Display the section details
  -e --headers           Equivalent to: -h -l -S
  -s --syms              Display the symbol table
     --symbols           An alias for --syms
     --dyn-syms          Display the dynamic symbol table
     --lto-syms          Display LTO symbol tables
     --sym-base=[0|8|10|16] 
                         Force base for symbol sizes.  The options are 
                         mixed (the default), octal, decimal, hexadecimal.
  -C --demangle[=STYLE]  Decode mangled/processed symbol names
                           STYLE can be "none", "auto", "gnu-v3", "java",
                           "gnat", "dlang", "rust"
     --no-demangle       Do not demangle low-level symbol names.  (default)
     --recurse-limit     Enable a demangling recursion limit.  (default)
     --no-recurse-limit  Disable a demangling recursion limit
     -U[dlexhi] --unicode=[default|locale|escape|hex|highlight|invalid]
                         Display unicode characters as determined by the current locale
                          (default), escape sequences, "<hex sequences>", highlighted
                          escape sequences, or treat them as invalid and display as
                          "{hex sequences}"
     -X --extra-sym-info Display extra information when showing symbols
     --no-extra-sym-info Do not display extra information when showing symbols (default)
  -n --notes             Display the contents of note sections (if present)
  -r --relocs            Display the relocations (if present)
  -u --unwind            Display the unwind info (if present)
  -d --dynamic           Display the dynamic section (if present)
  -V --version-info      Display the version sections (if present)
  -A --arch-specific     Display architecture specific information (if any)
  -c --archive-index     Display the symbol/file index in an archive
  -D --use-dynamic       Use the dynamic section info when displaying symbols
  -L --lint|--enable-checks
                         Display warning messages for possible problems
  -x --hex-dump=<number|name>
                         Dump the contents of section <number|name> as bytes
  -p --string-dump=<number|name>
                         Dump the contents of section <number|name> as strings
  -R --relocated-dump=<number|name>
                         Dump the relocated contents of section <number|name>
  -z --decompress        Decompress section before dumping it
  -w --debug-dump[a/=abbrev, A/=addr, r/=aranges, c/=cu_index, L/=decodedline,
                  f/=frames, F/=frames-interp, g/=gdb_index, i/=info, o/=loc,
                  m/=macro, p/=pubnames, t/=pubtypes, R/=Ranges, l/=rawline,
                  s/=str, O/=str-offsets, u/=trace_abbrev, T/=trace_aranges,
                  U/=trace_info]
                         Display the contents of DWARF debug sections
  -wk --debug-dump=links Display the contents of sections that link to separate
                          debuginfo files
  -P --process-links     Display the contents of non-debug sections in separate
                          debuginfo files.  (Implies -wK)
  -wK --debug-dump=follow-links
                         Follow links to separate debug info files (default)
  -wN --debug-dump=no-follow-links
                         Do not follow links to separate debug info files
  --dwarf-depth=N        Do not display DIEs at depth N or greater
  --dwarf-start=N        Display DIEs starting at offset N
  --ctf=<number|name>    Display CTF info from section <number|name>
  --ctf-parent=<name>    Use CTF archive member <name> as the CTF parent
  --ctf-symbols=<number|name>
                         Use section <number|name> as the CTF external symtab
  --ctf-strings=<number|name>
                         Use section <number|name> as the CTF external strtab
  --sframe[=NAME]        Display SFrame info from section NAME, (default '.sframe')
  -I --histogram         Display histogram of bucket list lengths
  -W --wide              Allow output width to exceed 80 characters
  -T --silent-truncation If a symbol name is truncated, do not add [...] suffix
  @<file>                Read options from <file>
  -H --help              Display this information
  -v --version           Display the version number of readelf

```


## layers 50pt, 530solves
```
nc challs.actf.co 31398‎

challenge.py
```
When I hit the nc command as described in the problem statement, I got the following.
```
└─$ nc challs.actf.co 31398
Welcome to my encryption service!
Surely encrypting multiple times will make it more secure.
1. Encrypt message.
2. Encrypt (hex) message.
3. See encrypted flag!
Pick 1, 2, or 3 > 
```
If you select 1, you will be able to type a message, and if you type it properly, you will be told that it is different.
```
Pick 1, 2, or 3 > 1
Your message > actf
fb7fdbf9
Not sure what that means.
```
Here is challenge.py
```
   1   │ import hashlib
   2   │ import itertools
   3   │ import os
   4   │ 
   5   │ def xor(key, data):
   6   │     return bytes([k ^ d for k, d in zip(itertools.cycle(key), data)]
       │ )
   7   │ 
   8   │ def encrypt(phrase, message, iters=1000):
   9   │     key = phrase.encode()
  10   │     for _ in range(iters):
  11   │         key = hashlib.md5(key).digest()
  12   │         message = xor(key, message)
  13   │     return message
  14   │ 
  15   │ print('Welcome to my encryption service!')
  16   │ print('Surely encrypting multiple times will make it more secure.')
  17   │ print('1. Encrypt message.')
  18   │ print('2. Encrypt (hex) message.')
  19   │ print('3. See encrypted flag!')
  20   │ 
  21   │ phrase = os.environ.get('FLAG', 'missing')
  22   │ 
  23   │ choice = input('Pick 1, 2, or 3 > ')
  24   │ if choice == '1':
  25   │     message = input('Your message > ').encode()
  26   │     encrypted = encrypt(phrase, message)
  27   │     print(encrypted.hex())
  28   │ if choice == '2':
  29   │     message = bytes.fromhex(input('Your message > '))
  30   │     encrypted = encrypt(phrase, message)
  31   │     print(encrypted.hex())
  32   │ elif choice == '3':
  33   │     print(encrypt(phrase, phrase.encode()).hex())
  34   │ else:
  35   │     print('Not sure what that means.')


```

```
nc challs.actf.co 31398
```

and select 3, does it output the exclusive or of the flag and the flag's encoded number?
If I could figure out which of these two it should be possible to get the flag, but I couldn't figure it out.