0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

picoCTF Practice Writeup 6

Last updated at Posted at 2021-04-24

picoCTF Practice Writeup 6
picoGym Practice Challenges page=6 の9問を勉強した記録

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
ビンゴ

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)

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:
ソースの一番下にヒントがある。

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

平文2文字毎に暗号化(置換)する

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

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

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

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

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

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

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

XOR Brute Force かましてみる
image.png
ちょっと崩れてるけど =k を除去すればビンゴ

gogo

picoCTF gogo を Ghidra で静的解析しようとしたが。。。

Milkslap

Category: Forensics
Description:
🥛
Hints:
Look at the problem category
image.png
Solution:

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

<!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>
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
フィルムみたい
とにかく保存できたので,「青い空を見上げればいつもそこに白い猫」の出番
image.png
青色ビット0抽出に反応した
image.png
あとはビット抽出
image.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...

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

lsr

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

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

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

>>> hex((len(bin(2541039191))-2)*3)
'0x60'

picoCTF{00000060}
Sorry, that flag is incorrect!
なんでだろ?

Compress and Attack

picoCTF Practice Compress and Attack Writeup

Disk, disk, sleuth! II

Disk, disk, sleuth! II

Super Serial

フラグは異なりますが,解き方は同じです。
picoCTF 2021 Super Serial

So Meta

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

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?