プロジェクト

全般

プロフィール

ZeroWidthSpace » 履歴 » バージョン 3

kanata, 2025/04/13 14:03

1 1 kanata
# ZeroWidthSpace
2
3
{{toc}}
4
5
{{rawhtml(<iframe src="//www.slideshare.net/slideshow/embed_code/key/xsLdg6etgkh9K6" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/kanata1/unicode-104771309" title="Unicodeゼロ幅文字 難読化シェル芸" target="_blank">Unicodeゼロ幅文字 難読化シェル芸</a> </strong> from <strong><a href="https://www.slideshare.net/kanata1" target="_blank">kanata -</a></strong> </div>)}}
6
7
8
# 動機 : 先日こういう話題があった
9
10
{{rawhtml(<blockquote class="embedly-card"><h4><a href="http://developer.cybozu.co.jp/akky/2018/04/leaker-detection-by-zero-width-characters/">ゼロ幅文字にエンコードした隠し情報で、文書をリークしたメンバーを特定</a></h4><p>とある会員制掲示板からの文書の流出に困った運営者が、 ユニコードの見えない文字「ゼロ幅文字(Zero-Width characters)」を使って流出させたユーザーを特定した、という話 が出ていました。 ...</p></blockquote><script async src="//cdn.embedly.com/widgets/platform.js" charset="UTF-8"></script>)}}
11
12
* 要約
13
 * 競技ビデオゲームのチームが、プライベートの掲示板を利用
14
 * 外部の掲示板にコピペしているやつがいた
15
 * 見た目がわからない文字を仕込んで犯人を特定
16
17
# 原理 : Unicodeゼロ幅スペースを仕込んだ
18
19
## ゼロ幅スペース([Wikipedia](https://ja.wikipedia.org/wiki/%E3%82%BC%E3%83%AD%E5%B9%85%E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9))
20
21
コンピュータの組版に用いられる非表示文字で、文書処理システムに対して語の切れ目を示すのに用いる
22
23
[めっちゃ種類ある](http://anti.rosx.net/etc/memo/002_space.html)
24
25
U+034F , U+200B , U+200C , U+200D , U+200E , U+200F , U+2028 , U+2029 , U+202A , U+202B , U+202C , U+202D , U+202E , U+2061 , U+2062 , U+2063 , U+FEFF
26
27
# いろんな事に(難読化シェル芸)に使えるんじゃ・・・!
28
29
[元ネタ](https://github.com/umpox/zero-width-detection/blob/071dfd52aede7510952b05840ffec7f8a940e6cb/src/utils/usernameToZeroWidth.js)に習って4種類を使う ⇒ 4進数で表現できる!
30
31
| CodePoint | 名称       | デコード時 |
32
|-----------|-----------|------------|
33
| U+200B    | ゼロ幅空白                     | 0
34
| U+200C    | ゼロ幅非接合子(筆記体の時の制御) | 1
35
| U+200D    | ゼロ幅接合子(筆記体の時の制御)   | 2
36
| U+FEFF    | ゼロ幅のノーブレークスペース     | 3
37
38
## ゼロ幅スペースにエンコード
39
40
1. 文字を16進数に変換(xxd)
41
2. 16進数を4進数に変換(bc)
42
3. 0 1 2 3 をゼロ幅スペースに置換(sed)
43
44
```bash
45
ZWS1=$'\u200b'
46
ZWS2=$'\u200c'
47
ZWS3=$'\u200d'
48
ZWS4=$'\ufeff'
49
50
echo "unko" |xxd -p|tr a-z A-Z \
51
  |sed 's/^/obase=4; ibase=16; &/g'|bc \
52
  |sed s/0/$ZWS1/g |sed s/1/$ZWS2/g \
53
  |sed s/2/$ZWS3/g |sed s/3/$ZWS4/g 
54
```
55
56
## 仕込んだゼロ幅スペースのデコード
57
58
1. ゼロ幅スペースを 0 1 2 3 に置換(sed)
59
2. 16進数に変換(bc)
60
3. バイナリに変換(xxd)
61
62
```bash
63
ZWS1=$'\u200b'
64
ZWS2=$'\u200c'
65
ZWS3=$'\u200d'
66
ZWS4=$'\ufeff'
67
68
echo '‌‌‌‌‍‍‌‍‍‌‍​​‍‍' \
69
  |sed s/$ZWS1/0/g |sed s/$ZWS2/1/g \
70
  |sed s/$ZWS3/2/g |sed s/$ZWS4/3/g \
71
  |sed 's/^/obase=16; ibase=4; &/g'|bc|xxd -ps -r
72
```
73
74
※ echo '' の''にはゼロ幅スペース入ってる
75
76
# Twitter用 Unicodeゼロ幅スペースぶっ込みツール に作り直した
77
78
TwitterやSNSで使える種類が限られていることがわかった。
79
80
{{rawhtml(<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">こんどTwitter対応やってみます <a href="https://twitter.com/hashtag/%E3%82%B7%E3%82%A7%E3%83%AB%E8%8A%B8?src=hash&amp;ref_src=twsrc%5Etfw">#シェル芸</a> <a href="https://twitter.com/hashtag/%E3%81%99%E3%81%BF%E3%81%BE%E3%81%9B%E3%82%93%E5%8B%95%E3%81%8F%E3%81%A3%E3%81%A6%E8%A8%80%E3%81%A3%E3%81%A6%E5%8B%95%E3%81%8D%E3%81%BE%E3%81%9B%E3%82%93%E3%81%A7%E3%81%97%E3%81%9F%E8%A8%B1%E3%81%97%E3%81%A6%E3%81%8F%E3%81%A0%E3%81%95%E3%81%84%E3%81%AA%E3%82%93%E3%81%A7%E3%82%82%E3%81%97%E3%81%BE%E3%81%99%E3%81%8B%E3%82%89?src=hash&amp;ref_src=twsrc%5Etfw">#すみません動くって言って動きませんでした許してくださいなんでもしますから</a> <a href="https://t.co/gUjAI3x9wt">https://t.co/gUjAI3x9wt</a></p>&mdash; kanata (@kanata201612) <a href="https://twitter.com/kanata201612/status/1016273710846697472?ref_src=twsrc%5Etfw">2018年7月9日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>)}}
81
82
調査してTwitter用に良さそうな4種類のゼロ幅スペースを確認する
83
84
{{rawhtml(<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">結果、Twitterに仕込んでも大丈夫そうなゼロ幅スペース <a href="https://twitter.com/hashtag/%E3%82%B7%E3%82%A7%E3%83%AB%E8%8A%B8?src=hash&amp;ref_src=twsrc%5Etfw">#シェル芸</a><br><br>U+200B<br>U+200C<br>U+200D<br>U+2062<br><br>もうちょっと確認してみよう</p>&mdash; kanata (@kanata201612) <a href="https://twitter.com/kanata201612/status/1018409987654053889?ref_src=twsrc%5Etfw">2018年7月15日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> )}}
85
86
[シェル芸bot](https://twitter.com/minyoruminyon)氏のことも考慮して、割と真面目に作り直した
87
88
## Instration
89
90
ファイルダウンロードして実行権限をつけるだけ
91
92
```bash
93 3 kanata
$ wget https://raintrees.net/attachments/download/227/zws
94 1 kanata
$ chmod u+x ./zws
95
```
96
97
### 最新版について
98
99
現在、githubにて最新版を管理しています。インタフェースをbase64と全く同じに修正(してもらい)ました。
100
https://github.com/kanata2003/ZeroWidthSpace
101
102
### 動作環境
103
104
ただのシェルスクリプトなので、だいたいの環境(Linux,Mac,Unix)で動くのでは
105
106
以下で、動作確認しました。
107
108
* CentOS Linux release 7.2.1511 x86_64
109
110
## Usage
111
112
### エンコード
113
114
実行すると '' が出力されるが間にゼロ幅スペースが詰まっている
115
116
```bash
117
./zws unko
118
'‌⁢‌‌​​‍‍‌‍⁢‍​​‍‍‌‍‍⁢​​‍‍‌‍⁢⁢​​‍‍'
119
```
120
121
パイプ経由でもできる
122
123
```bash
124
echo "unko"|./zws
125
'‌⁢‌‌​​‍‍‌‍⁢‍​​‍‍‌‍‍⁢​​‍‍‌‍⁢⁢​​‍‍'
126
```
127
128
ちなみにTwitterでは、ゼロ幅スペースはアスキー文字と同等に数えられるらしく、140文字ではなく280文字までいけた
129
エンコードサイズが280文字を超えるとWARNINGを出すようにしている(エンコード自体はする)
130
131
```bash
132
./zws aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
133
[WARN] This encoded size over 280 characters. You can not tweet. Now 285 characters.
134
'‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌‌‍​‌​​‍‍'
135
```
136
137
[シェル芸bot](https://twitter.com/minyoruminyon)氏はゼロ幅スペースを普通にマルチバイト文字として数える(140文字制限)ので、bot氏に処理をお願いする時は140文字までの制限を意識する必要がございます
138
139
ゼロ幅スペースの文字数を数えるには wc -m コマンドで数えることができます
140
141
```bash
142
./zws 'I hava an apple'|wc -m
143
67
144
```
145
146
この短めの文で67文字も使うのでTwitterにはあまり長い文字列が仕込めません
147
148
### デコード
149
150
base64コマンドっぽいインタフェースにした
151
ゼロ幅スペース以外の文字があっても、そこは無視してデコードする
152
153
```bash
154
./zws -d 'this is a pen‌⁢‌‌​​‍‍‌‍⁢‍​​‍‍‌‍‍⁢​​‍‍‌‍⁢⁢​​‍‍'
155
unko
156
```
157
158
もちろんパイプ経由でもいける
159
160
```bash
161
echo '‌⁢‌‌​​‍‍‌‍⁢‍​​‍‍‌‍‍⁢​​‍‍‌‍⁢⁢​​‍‍'|./zws -d
162
unko
163
```
164
165
# 使えるシュチュエーション
166
## このシェル芸を実行したのは誰だ!
167
168
```bash
169
./zws -d 'echo unko⁢‍‌⁢‍‍‌⁢‍​​‌⁢‍​⁢‍​​‌‍‍‌⁢⁢‍​⁢‍​​‌‍‌‍‌​​‍‍'
170
私です
171
```
172
## 裏手順を隠しておく
173
174
```bash
175
./zws -d 'stop.sh #アプリを停止、yを入力‌⁢​​‌‍‍⁢‌‍‍‌‌‍⁢​‌‍⁢​​‍​​‌‍​‌‌⁢​​‌‍⁢​‌‍‍‌​​‍‍'
176
pkill apli
177
```
178
179
## 呪いを込めておく
180
181
```bash
182
./zws -d 'Start.sh #アプリ起動⁢‍‌‌‍⁢‍​‍⁢​​⁢‍​⁢‍​​‍‍​‍‍⁢‍​⁢‍​​‌‍‌⁢⁢⁢‍​⁢‍​​‌‍​‌​​​‍‍'
183
帰りたい
184
```
185
186
## 暗号的やり取り
187
188
実はTwitterはゼロ幅スペースが使えます
189
190
他のSNSでも使えそう(未確認)
191
192
```bash
193
./zws -d '草⁢‍‌⁢‍​‍‌‍⁢‍‌⁢‍‌‌‍‍​⁢‍⁢​‍⁢‍​⁢‍​​‌‍‍​​⁢‍​⁢‍​​‌‍‌⁢‍​​‍‍'
194
特売だぞ
195
```
196
197
## 難読化シェル芸
198
199
echoと見せかけたdateの実行
200
201
```bash
202
echo 'echo unko‌‍‌​‌‍​‌‌⁢‌​‌‍‌‌​​‍‍'|./zws -d|bash
203
2018年  7月 16日 月曜日 10:26:37 JST
204
```
205
206
# 他の実装
207
208
* ExcelのVBAで[風柳](https://twitter.com/furyutei)さんが実装しています
209
210
[Excel][VBA] ゼロ幅スペースを利用した情報隠蔽の試み
211
https://gist.github.com/furyutei/6bba0eaf5e0bcb4ae1ee30f916cfcb04
212
213
* 短縮URLのサービスで実装されています
214
215
Zero Width Shortener
216
https://zws.im/