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?

IERAE CTF 2024 Writeup

Posted at

はじめに

IERAE CTF 2024に参加しました。6問解いて878ポイント66位でした。

環境

Fedora GNU/Linux

Welcome(122pt)

discordにjoinしてFLAGゲット。

IERAE{An_incredibly_interesting_flag}

OMG(123pt)

ブラウザの履歴を書き換えるウェブページ。

Let's press the browser back button 33 times. / 戻るボタンを33回押そう!

説明文のとおり33回戻るボタンをクリックしてFLAGゲット。
IERAE{Tr3ndy_4ds.LOL}

derangement(149pt)

deramgementしたものから15桁の文字列を推測する問題。
derangementの仕方を見ると、

def is_derangement(perm, original):
    return all(p != o for p, o in zip(perm, original))

とあり、オリジナルと一致しない組み合わせを返している。
桁ごとに、何度derangementしても出てこない文字がオリジナルの文字になりそう。

#include <stdio.h>

int main(void) {
	char str[16][16];
	char d[16];
	char list[16] = "!\"'()*<[15gOsSy"; //これが出てくる文字
	for (int i = 0; i < 15; i++) {
		for (int j = 0; j < 16; j++) {
			str[i][j] = list[j];
		}
	}
	for (; scanf("%s", &d) != -1; ) {
		for (int i = 0; i < 15; i++) {
			for (int j = 0; j < 16; j++) {
				if (str[i][j] == d[i])
					str[i][j]='\0';
			}
		}
	}
    // 候補を出力
	for (int i = 0; i < 15; i++) {
		for (int j = 0; j < 16; j++) {
			if (str[i][j])
				printf("%d:%c\n", i, str[i][j]);
		}
	}
}

出力は以下。

0:g
1:1
2:y
3:"
4:(
5:s
6:O
7:<
8:5
9:)
10:[
11:*
12:!
13:'
14:S

15桁の文字列は以下と分かった。※実行時ごとに異なる
g1y"(sO<5)[*!'S

プログラムに入力してFLAGゲット。
IERAE{th3r35_n0_5uch_th!ng_45_p3rf3ct_3ncrypt!0n}

Assignment

バイナリが渡された。
とりあえずobjdump -dしてみる。
0x1cの位置に0x33を代入、0x1の位置に0x45を代入、・・・としてフラグ文字列を作っていそう。

$ objdump -d chal
...省略...
0000000000001149 <main>:
    1149:	55                   	push   %rbp
    114a:	48 89 e5             	mov    %rsp,%rbp
    114d:	48 83 ec 10          	sub    $0x10,%rsp
    1151:	89 7d fc             	mov    %edi,-0x4(%rbp)
    1154:	48 89 75 f0          	mov    %rsi,-0x10(%rbp)
    1158:	c6 05 fd 2e 00 00 33 	movb   $0x33,0x2efd(%rip)        # 405c <flag+0x1c>
    115f:	c6 05 db 2e 00 00 45 	movb   $0x45,0x2edb(%rip)        # 4041 <flag+0x1>
    1166:	c6 05 d5 2e 00 00 52 	movb   $0x52,0x2ed5(%rip)        # 4042 <flag+0x2>
    116d:	c6 05 e0 2e 00 00 72 	movb   $0x72,0x2ee0(%rip)        # 4054 <flag+0x14>
    1174:	c6 05 df 2e 00 00 61 	movb   $0x61,0x2edf(%rip)        # 405a <flag+0x1a>
    117b:	c6 05 c8 2e 00 00 5f 	movb   $0x5f,0x2ec8(%rip)        # 404a <flag+0xa>
    1182:	c6 05 d7 2e 00 00 7d 	movb   $0x7d,0x2ed7(%rip)        # 4060 <flag+0x20>
    1189:	c6 05 b9 2e 00 00 65 	movb   $0x65,0x2eb9(%rip)        # 4049 <flag+0x9>
    1190:	c6 05 bf 2e 00 00 6e 	movb   $0x6e,0x2ebf(%rip)        # 4056 <flag+0x16>
    1197:	c6 05 b3 2e 00 00 5f 	movb   $0x5f,0x2eb3(%rip)        # 4051 <flag+0x11>
    119e:	c6 05 a1 2e 00 00 73 	movb   $0x73,0x2ea1(%rip)        # 4046 <flag+0x6>
    11a5:	c6 05 9b 2e 00 00 30 	movb   $0x30,0x2e9b(%rip)        # 4047 <flag+0x7>
    11ac:	c6 05 9c 2e 00 00 30 	movb   $0x30,0x2e9c(%rip)        # 404f <flag+0xf>
    11b3:	c6 05 96 2e 00 00 6d 	movb   $0x6d,0x2e96(%rip)        # 4050 <flag+0x10>
    11ba:	c6 05 94 2e 00 00 31 	movb   $0x31,0x2e94(%rip)        # 4055 <flag+0x15>
    11c1:	c6 05 90 2e 00 00 5f 	movb   $0x5f,0x2e90(%rip)        # 4058 <flag+0x18>
    11c8:	c6 05 7d 2e 00 00 34 	movb   $0x34,0x2e7d(%rip)        # 404c <flag+0xc>
    11cf:	c6 05 83 2e 00 00 35 	movb   $0x35,0x2e83(%rip)        # 4059 <flag+0x19>
    11d6:	c6 05 82 2e 00 00 63 	movb   $0x63,0x2e82(%rip)        # 405f <flag+0x1f>
    11dd:	c6 05 5f 2e 00 00 41 	movb   $0x41,0x2e5f(%rip)        # 4043 <flag+0x3>
    11e4:	c6 05 55 2e 00 00 49 	movb   $0x49,0x2e55(%rip)        # 4040 <flag>
    11eb:	c6 05 6b 2e 00 00 35 	movb   $0x35,0x2e6b(%rip)        # 405d <flag+0x1d>
    11f2:	c6 05 59 2e 00 00 73 	movb   $0x73,0x2e59(%rip)        # 4052 <flag+0x12>
    11f9:	c6 05 53 2e 00 00 74 	movb   $0x74,0x2e53(%rip)        # 4053 <flag+0x13>
    1200:	c6 05 44 2e 00 00 72 	movb   $0x72,0x2e44(%rip)        # 404b <flag+0xb>
    1207:	c6 05 3a 2e 00 00 6d 	movb   $0x6d,0x2e3a(%rip)        # 4048 <flag+0x8>
    120e:	c6 05 30 2e 00 00 7b 	movb   $0x7b,0x2e30(%rip)        # 4045 <flag+0x5>
    1215:	c6 05 28 2e 00 00 45 	movb   $0x45,0x2e28(%rip)        # 4044 <flag+0x4>
    121c:	c6 05 38 2e 00 00 39 	movb   $0x39,0x2e38(%rip)        # 405b <flag+0x1b>
    1223:	c6 05 34 2e 00 00 34 	movb   $0x34,0x2e34(%rip)        # 405e <flag+0x1e>
    122a:	c6 05 26 2e 00 00 67 	movb   $0x67,0x2e26(%rip)        # 4057 <flag+0x17>
    1231:	c6 05 15 2e 00 00 6e 	movb   $0x6e,0x2e15(%rip)        # 404d <flag+0xd>
    1238:	c6 05 0f 2e 00 00 64 	movb   $0x64,0x2e0f(%rip)        # 404e <flag+0xe>
    123f:	83 7d fc 01          	cmpl   $0x1,-0x4(%rbp)
    1243:	7e 30                	jle    1275 <main+0x12c>
    1245:	48 8b 45 f0          	mov    -0x10(%rbp),%rax
    1249:	48 83 c0 08          	add    $0x8,%rax
    124d:	48 8b 00             	mov    (%rax),%rax
    1250:	48 89 c6             	mov    %rax,%rsi
    1253:	48 8d 05 e6 2d 00 00 	lea    0x2de6(%rip),%rax        # 4040 <flag>
    125a:	48 89 c7             	mov    %rax,%rdi
    125d:	e8 de fd ff ff       	call   1040 <strcmp@plt>

FLAG文字列を作成するプログラムを作成した。

#include <stdio.h>

int main(void) {
	int str[100] = {0};
	int c, offset;
	for (; scanf("%x %x", &c, &offset) != -1; ) {
		str[offset] = c;
	}
	for (int i = 0; i < 100; i++) {
		printf("%c", str[i]);
	}
}

入力は以下。ディスアセンブル結果から値とoffsetを抽出した。

33 1c
45 1
52 2
...

FLAGゲット。
IERAE{s0me_r4nd0m_str1ng_5a9354c}

Weak PRNG

メルセンヌ・ツイスタで作った数字を、それ以降の出力から予測する問題。
以下記事を参考に作成。

xs1 = [ # プログラムの出力を624個並べた
1053714421,
2234018411,
2819543536,
254786992,
...
500837242,
56794293,
3564297824,
]
mt_state = [untemper(x) for x in xs1]
prev_mt_state = get_prev_state(mt_state)
random.setstate((3, tuple(prev_mt_state + [0]), None))

predicted = [random.getrandbits(32) for _ in range(N)]
print(predicted[-1]) # これが欲しい数字

数字を入力してFLAGゲット。

Luz Da Lua

luacファイルが渡された。unluacでデコンパイルしてみた。

$ java -jar unluac_2023_12_24.jar LuzDaLua.luac 

luaでは~=は否定の条件式なので、条件式が成り立たない文字を探していけばよさそう。

io.write("Input > ")
input = io.read("*l")
if 28 ~= string.len(input) then
elseif string.byte(input, 1) ~ 232 ~= 161 then
elseif 43 ~= string.byte(input, 2) ~ 110 then
elseif string.byte(input, 3) ~ 178 ~= 224 then
elseif string.byte(input, 4) ~ 172 ~= 237 then
elseif string.byte(input, 5) ~ 212 ~= 145 then
elseif 98 ~= string.byte(input, 6) ~ 25 then
elseif 121 ~= string.byte(input, 7) ~ 53 then
elseif 74 ~= string.byte(input, 8) ~ 63 then
elseif string.byte(input, 9) ~ 135 ~= 230 then
elseif 3 ~= string.byte(input, 10) ~ 92 then
elseif 23 ~= string.byte(input, 11) ~ 38 then
elseif string.byte(input, 12) ~ 250 ~= 137 then
elseif 135 ~= string.byte(input, 13) ~ 216 then
elseif 86 ~= string.byte(input, 14) ~ 5 then
elseif 117 ~= string.byte(input, 15) ~ 69 then
elseif string.byte(input, 16) ~ 226 ~= 189 then
elseif string.byte(input, 17) ~ 137 ~= 186 then
elseif string.byte(input, 18) ~ 148 ~= 240 then
elseif 53 ~= string.byte(input, 19) ~ 64 then
elseif string.byte(input, 20) ~ 130 ~= 225 then
elseif string.byte(input, 21) ~ 241 ~= 197 then
elseif string.byte(input, 22) ~ 151 ~= 227 then
elseif 250 ~= string.byte(input, 23) ~ 203 then
elseif string.byte(input, 24) ~ 179 ~= 220 then
elseif string.byte(input, 25) ~ 216 ~= 182 then
elseif 4 ~= string.byte(input, 26) ~ 101 then
elseif 130 ~= string.byte(input, 27) ~ 238 then
elseif 64 ~= string.byte(input, 28) ~ 61 then
else
  print("Correct")
  goto lbl_305
end
print("Wrong")
::lbl_305::

luaでプログラムを作成。io.write()だと改行なしで出力できる。

io.write(string.char(232 ~ 161))
io.write(string.char(43 ~ 110))
io.write(string.char(178 ~ 224))
io.write(string.char(172 ~ 237))
io.write(string.char(212 ~ 145))
io.write(string.char(98 ~ 25))
io.write(string.char(121 ~ 53))
io.write(string.char(74 ~ 63))
io.write(string.char(135 ~ 230))
io.write(string.char(3 ~ 92))
io.write(string.char(23 ~ 38))
io.write(string.char(250 ~ 137))
io.write(string.char(135 ~ 216))
io.write(string.char(86 ~ 5))
io.write(string.char(117 ~ 69))
io.write(string.char(226 ~ 189))
io.write(string.char(137 ~ 186))
io.write(string.char(148 ~ 240))
io.write(string.char(53 ~ 64))
io.write(string.char(130 ~ 225))
io.write(string.char(241 ~ 197))
io.write(string.char(151 ~ 227))
io.write(string.char(250 ~ 203))
io.write(string.char(179 ~ 220))
io.write(string.char(216 ~ 182))
io.write(string.char(4 ~ 101))
io.write(string.char(130 ~ 238))
io.write(string.char(64 ~ 61))

FLAGゲット。
IERAE{Lua_1s_S0_3duc4t1onal}

感想

楽しかったです。
web系とpwn系の問題をもっと解けるようになりたいと思いました。

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?