picoCTF Practice Writeup 6

picoCTF Practice Writeup 6
[picoGym Practice Challenges page=6](https://play.picoctf.org/practice?page=6) の９問を勉強した記録


Compress and Attack は，python2 の import socket でブルートフォースに成功したので，チョーうれしい。(ソケット通信，フラグの総当たり攻撃)


このページの難問は，
442 solves の Play Nice （ジャンルはCryptographyだけど，ほぼpython力）
471 solves の Some Assembly Required 2
209 solves の gogo　（Ghidraを使用したReverse Engineering）
490 solves の Milkslap　（ステガノグラフィー）
182 solves の Compress and Attack　（圧縮比に着目したブルートフォース）
340 solves の Super Serial　（安全でないデシリアライゼーション）


Double DES と Scrambled: RSA はギブアップ。



# Disk, disk, sleuth!

Description:
Use `srch_strings` from the sleuthkit and some terminal-fu to find a flag in this disk image: dds1-alpine.flag.img.gz
Hints
1. Have you ever used `file` to determine what a file was?
2. Relevant terminal-fu in picoGym: https://play.picoctf.org/practice/challenge/85
3. Mastering this terminal-fu would enable you to find the flag in a single command: https://play.picoctf.org/practice/challenge/48
4. Using your own computer, you could use qemu to boot from this disk!

Solution:
fileコマンドで何ファイルか確認する。

```
$ file dds1-alpine.flag.img
dds1-alpine.flag.img: DOS/MBR boot sector; partition 1 : ID=0x83, active, start-CHS (0x0,32,33), end-CHS (0x10,81,1), startsector 2048, 260096 sectors
```

バイナリエディタで表層解析してみる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/da620831-c251-8666-42a9-f98ad1b83c82.png)
ビンゴ



# Play Nice
Category: Cryptography
Description
Not all ancient ciphers were so bad... The flag is not in standard format. nc mercury.picoctf.net 6057 playfair.py
Hints
(None)

```python:playfair.py
#!/usr/bin/python3 -u
import signal

SQUARE_SIZE = 6


def generate_square(alphabet):
	assert len(alphabet) == pow(SQUARE_SIZE, 2)
	matrix = []
	for i, letter in enumerate(alphabet):
		if i % SQUARE_SIZE == 0:
			row = []
		row.append(letter)
		if i % SQUARE_SIZE == (SQUARE_SIZE - 1):
			matrix.append(row)
	return matrix

def get_index(letter, matrix):
	for row in range(SQUARE_SIZE):
		for col in range(SQUARE_SIZE):
			if matrix[row][col] == letter:
				return (row, col)
	print("letter not found in matrix.")
	exit()

def encrypt_pair(pair, matrix):
	p1 = get_index(pair[0], matrix)
	p2 = get_index(pair[1], matrix)

	if p1[0] == p2[0]:
		return matrix[p1[0]][(p1[1] + 1)  % SQUARE_SIZE] + matrix[p2[0]][(p2[1] + 1)  % SQUARE_SIZE]
	elif p1[1] == p2[1]:
		return matrix[(p1[0] + 1)  % SQUARE_SIZE][p1[1]] + matrix[(p2[0] + 1)  % SQUARE_SIZE][p2[1]]
	else:
		return matrix[p1[0]][p2[1]] + matrix[p2[0]][p1[1]]

def encrypt_string(s, matrix):
	result = ""
	if len(s) % 2 == 0:
		plain = s
	else:
		plain = s + "meiktp6yh4wxruavj9no13fb8d027c5glzsq"[0]
	for i in range(0, len(plain), 2):
		result += encrypt_pair(plain[i:i + 2], matrix)
	return result

alphabet = open("key").read().rstrip()
m = generate_square(alphabet)
msg = open("msg").read().rstrip()
enc_msg = encrypt_string(msg, m)
print("Here is the alphabet: {}\nHere is the encrypted message: {}".format(alphabet, enc_msg))
signal.alarm(18)
resp = input("What is the plaintext message? ").rstrip()
if resp and resp == msg:
	print("Congratulations! Here's the flag: {}".format(open("flag").read()))

# https://en.wikipedia.org/wiki/Playfair_cipher
```

```:nc
$ nc mercury.picoctf.net 6057
Here is the alphabet: meiktp6yh4wxruavj9no13fb8d027c5glzsq
Here is the encrypted message: y7bcvefqecwfste224508y1ufb21ld
What is the plaintext message?
```

Solution:
ソースの一番下にヒントがある。

https://en.wikipedia.org/wiki/Playfair_cipher

key を 5 * 5 の table に配置する

平文２文字毎に暗号化（置換）する

２文字とも table の同じ行にある場合，それぞれ右の文字を暗号文字として出力
２文字とも table の同じ列にある場合，それぞれ下の文字を暗号文字として出力
上記以外は，同じ行の文字と交換するが，列は対角とする。

key alphabet は table ではどうなっているか？
playfair.pyを改造していく

```python:solver_playfair.py（改造したとこだけ）
#alphabet = open("key").read().rstrip()
alphabet = "meiktp6yh4wxruavj9no13fb8d027c5glzsq"

m = generate_square(alphabet)
print(m)
```

実行結果

```
>python sol2_playfair.py
[['m', 'e', 'i', 'k', 't', 'p'], ['6', 'y', 'h', '4', 'w', 'x'], ['r', 'u', 'a', 'v', 'j', '9'], ['n', 'o', '1', '3', 'f', 'b'], ['8', 'd', '0', '2', '7', 'c'], ['5', 'g', 'l', 'z', 's', 'q']]
```

[['m', 'e', 'i', 'k', 't', 'p'],
 ['6', 'y', 'h', '4', 'w', 'x'],
 ['r', 'u', 'a', 'v', 'j', '9'],
 ['n', 'o', '1', '3', 'f', 'b'],
 ['8', 'd', '0', '2', '7', 'c'],
 ['5', 'g', 'l', 'z', 's', 'q']]

平文が 4wa1df とする
4w は同じ行にあるので wx に
aq は同じ列にあるので 10 に
df はそれ以外なので， 7o に（下図参照）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/1f6b111f-4efb-8e76-ca34-82e394ab2da7.png)


平文 4wa1d を暗号化すると wx107o になる。

暗号化の仕組みがわかったので，playfair.pyを改造したソルバーを完成させる

```python:solver_playfair.py
#!/usr/bin/python3 -u
import signal

SQUARE_SIZE = 6


def generate_square(alphabet):
	assert len(alphabet) == pow(SQUARE_SIZE, 2)
	matrix = []
	for i, letter in enumerate(alphabet):
		if i % SQUARE_SIZE == 0:
			row = []
		row.append(letter)
		if i % SQUARE_SIZE == (SQUARE_SIZE - 1):
			matrix.append(row)
	return matrix

def get_index(letter, matrix):
	for row in range(SQUARE_SIZE):
		for col in range(SQUARE_SIZE):
			if matrix[row][col] == letter:
				return (row, col)
	print("letter not found in matrix.")
	exit()

def encrypt_pair(pair, matrix):
	p1 = get_index(pair[0], matrix)
	p2 = get_index(pair[1], matrix)

	if p1[0] == p2[0]:
#		return matrix[p1[0]][(p1[1] + 1)  % SQUARE_SIZE] + matrix[p2[0]][(p2[1] + 1)  % SQUARE_SIZE]
		return matrix[p1[0]][(p1[1] - 1)  % SQUARE_SIZE] + matrix[p2[0]][(p2[1] - 1)  % SQUARE_SIZE]
	elif p1[1] == p2[1]:
#		return matrix[(p1[0] + 1)  % SQUARE_SIZE][p1[1]] + matrix[(p2[0] + 1)  % SQUARE_SIZE][p2[1]]
		return matrix[(p1[0] - 1)  % SQUARE_SIZE][p1[1]] + matrix[(p2[0] - 1)  % SQUARE_SIZE][p2[1]]
	else:
		return matrix[p1[0]][p2[1]] + matrix[p2[0]][p1[1]]

def encrypt_string(s, matrix):
	result = ""
	if len(s) % 2 == 0:
		plain = s
	else:
		plain = s + "meiktp6yh4wxruavj9no13fb8d027c5glzsq"[0]
	for i in range(0, len(plain), 2):
		result += encrypt_pair(plain[i:i + 2], matrix)
	return result

#alphabet = open("key").read().rstrip()
alphabet = "meiktp6yh4wxruavj9no13fb8d027c5glzsq"

m = generate_square(alphabet)
print(m)

#msg = open("msg").read().rstrip()
msg = "y7bcvefqecwfste224508y1ufb21ld"

enc_msg = encrypt_string(msg, m)

print("key: {}\nenc: {}\nmsg: {}".format(alphabet, msg, enc_msg))

#print("Here is the alphabet: {}\nHere is the encrypted message: {}".format(alphabet, enc_msg))
#signal.alarm(18)
#resp = input("What is the plaintext message? ").rstrip()
#if resp and resp == msg:
#	print("Congratulations! Here's the flag: {}".format(open("flag").read()))

# https://en.wikipedia.org/wiki/Playfair_cipher
```

実行結果

```
>python sol2_playfair.py
[['m', 'e', 'i', 'k', 't', 'p'], ['6', 'y', 'h', '4', 'w', 'x'], ['r', 'u', 'a', 'v', 'j', '9'], ['n', 'o', '1', '3', 'f', 'b'], ['8', 'd', '0', '2', '7', 'c'], ['5', 'g', 'l', 'z', 's', 'q']]
key: meiktp6yh4wxruavj9no13fb8d027c5glzsq
enc: y7bcvefqecwfste224508y1ufb21ld
msg: wd9bukbspdtj7skd3kl8d6oa3f03g0
```
nc すると

```
$ nc mercury.picoctf.net 6057
Here is the alphabet: meiktp6yh4wxruavj9no13fb8d027c5glzsq
Here is the encrypted message: y7bcvefqecwfste224508y1ufb21ld
What is the plaintext message? wd9bukbspdtj7skd3kl8d6oa3f03g0
Congratulations! Here's the flag: 消しました
```


# Some Assembly Required 2
Category: Web Exploitation
Description:
http://mercury.picoctf.net:53929/index.html
Hints:
(None)

Solution:
Some Assembly Required 1と同じやり方で進める

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/fa6e25d7-e21f-5c53-d971-2263e56600a9.png)

```
xakgK\5cNs>n;jl90;9:mjn9m<0n9::0::881<00?>u\00\00
```

XOR Brute Force かましてみる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/93fd0362-663a-2717-c52b-c3569c2b6636.png)
ちょっと崩れてるけど =k を除去すればビンゴ


# gogo
[picoCTF gogo を Ghidra で静的解析しようとしたが。。。](https://qiita.com/housu_jp/items/6521093d18546c356c0c)




# Milkslap
Category: Forensics
Description:
[🥛](http://mercury.picoctf.net:16940/)
Hints:
Look at the problem category
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/e4e85c6c-be3a-7712-0131-c12f6519ae16.png)
Solution:

右クリックでは画像の保存が出来ない。
どんな仕掛け？
ソース見てみる

```html
<!doctype html>

<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=400" />
  <title>🥛</title>
  <link rel="stylesheet" href="style.css" />

</head>
<body>
  <div id="image" class="center"></div>
  <div id="foot" class="center">
    <h1>MilkSlap!</h1>
    Inspired by <a href="http://eelslap.com">http://eelslap.com</a> <br>
    Credit to: <a href="https://github.com/boxmein">boxmein</a> for code inspiration.
  </div>
  <script src="script.js">


</script>
</body>
</html>
```

```html:style.css
/* source: milkslap-milkslap.scss */
body {
  margin: 0;
  padding: 0;
  overflow: hidden; }

a {
  color: inherit; }

.center {
  width: 1080px;
  height: 720px;
  margin: 0 auto; }

#image {
  height: 720px;
  margin-top: 5%;
  margin-bottom: 20px;
  background-image: url(concat_v.png);
  background-position: 0 0; }

#foot {
  margin-bottom: 5px;
  color: #999999; }
  #foot h1 {
    font-family: serif;
    font-weight: normal;
    font-size: 1rem;
    text-align: center; }
```

これか。

```
background-image: url(concat_v.png);
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/e5125105-c722-520a-0fc4-f996c573108b.png)
フィルムみたい
とにかく保存できたので，「青い空を見上げればいつもそこに白い猫」の出番
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/e7559ed3-af77-db55-3d53-28be00927389.png)
青色ビット０抽出に反応した
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/d5cbfe64-98b0-f6d1-fcfd-7ae66d35b82d.png)
あとはビット抽出
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/a22b7d81-2d36-178a-7739-0ee3db61feb0.png)



# ARMssembly 3
Category: Reverse Engineering
Description:
What integer does this program print with argument 2541039191? File: chall_3.S Flag format: picoCTF{XXXXXXXX} -> (hex, lowercase, no 0x, and 32 bits. ex. 5614267 would be picoCTF{0055aabb})
Hints:
beep boop beep boop...

```armasm:chall_3.S
	.arch armv8-a
	.file	"chall_3.c"
	.text
	.align	2
	.global	func1
	.type	func1, %function
func1:
	stp	x29, x30, [sp, -48]!
	add	x29, sp, 0
	str	w0, [x29, 28]
	str	wzr, [x29, 44]	
	b	.L2
.L4:
	ldr	w0, [x29, 28]				
	and	w0, w0, 1
	cmp	w0, 0
	beq	.L3
	ldr	w0, [x29, 44]
	bl	func2
	str	w0, [x29, 44]
.L3:
	ldr	w0, [x29, 28]
	lsr	w0, w0, 1
	str	w0, [x29, 28]
.L2:
	ldr	w0, [x29, 28]				
	cmp	w0, 0
	bne	.L4
	ldr	w0, [x29, 44]
	ldp	x29, x30, [sp], 48
	ret
	.size	func1, .-func1
	.align	2
	.global	func2
	.type	func2, %function
func2:
	sub	sp, sp, #16
	str	w0, [sp, 12]
	ldr	w0, [sp, 12]
	add	w0, w0, 3
	add	sp, sp, 16
	ret
	.size	func2, .-func2
	.section	.rodata
	.align	3
.LC0:
	.string	"Result: %ld\n"
	.text
	.align	2
	.global	main
	.type	main, %function
main:
	stp	x29, x30, [sp, -48]!
	add	x29, sp, 0
	str	w0, [x29, 28]
	str	x1, [x29, 16]
	ldr	x0, [x29, 16]
	add	x0, x0, 8
	ldr	x0, [x0]
	bl	atoi
	bl	func1
	str	w0, [x29, 44]
	adrp	x0, .LC0
	add	x0, x0, :lo12:.LC0
	ldr	w1, [x29, 44]
	bl	printf
	nop
	ldp	x29, x30, [sp], 48
	ret
	.size	main, .-main
	.ident	"GCC: (Ubuntu/Linaro 7.5.0-3ubuntu1~18.04) 7.5.0"
	.section	.note.GNU-stack,"",@progbits
```

Solution:

beq bne

https://www.mztn.org/dragon/arm6408cond.html

lsr

https://www.mztn.org/dragon/arm6407shift.html

簡単に説明する // を見て

```armasm
func1:
	stp	x29, x30, [sp, -48]!
	add	x29, sp, 0
	str	w0, [x29, 28]          // [x29, 28]は引数
	str	wzr, [x29, 44]	       // [x29, 44]は戻り値（初期値0）
	b	.L2
.L4:
	ldr	w0, [x29, 28]				
	and	w0, w0, 1              // 1 と and して
	cmp	w0, 0                  // 0になったら終了方向 
	beq	.L3
	ldr	w0, [x29, 44]
	bl	func2                  // func2 内で +3
	str	w0, [x29, 44]
.L3:
	ldr	w0, [x29, 28]
	lsr	w0, w0, 1              // 入力値を右シフト
	str	w0, [x29, 28]
.L2:
	ldr	w0, [x29, 28]				
	cmp	w0, 0
	bne	.L4
	ldr	w0, [x29, 44]           // 戻り値
	ldp	x29, x30, [sp], 48
	ret
	.size	func1, .-func1
	.align	2
	.global	func2
	.type	func2, %function
func2:
	sub	sp, sp, #16
	str	w0, [sp, 12]
	ldr	w0, [sp, 12]
	add	w0, w0, 3               // +3
	add	sp, sp, 16
	ret
	.size	func2, .-func2
	.section	.rodata
	.align	3
```

ゼロになるまで右シフトするループの中で，戻り値を＋３し続けている。
つまり，入力値を２進数にしてビット数　を　３倍してることになる。

```
>>> hex((len(bin(2541039191))-2)*3)
'0x60'
```
picoCTF{00000060}
Sorry, that flag is incorrect!
なんでだろ？

# Compress and Attack
[picoCTF Practice Compress and Attack Writeup](https://qiita.com/housu_jp/items/e003bc5dace6189bd554)




# Disk, disk, sleuth! II
[Disk, disk, sleuth! II](https://qiita.com/housu_jp/items/26ce2e5cf6122ff1744b)



# Super Serial

フラグは異なりますが，解き方は同じです。
[picoCTF 2021 Super Serial](https://qiita.com/housu_jp/items/7a9741e799aec6c0becf)



# So Meta
なんで６ページ目にこんな簡単な問題があるのか意味不明だ。