MIT实验笔记冲刺2 实验部分

目录

实现trace调用(系统调用跟踪(中等))

攻击 xv6(中等)


下面就是实验的部分,Lab2中的实验有两个。一个是syscall implementations,另一个则是利用未抹除的内存内容来读取上一个内存留下的东西。

实现trace调用(系统调用跟踪(中等))

在此作业中,您将添加一个系统调用跟踪功能,该功能可能有助于您调试后续实验。您将创建一个新的跟踪系统调用来控制跟踪。它应该接受一个参数,即一个整数“掩码”,其位指定要跟踪哪些系统调用。例如,要跟踪 fork 系统调用,程序会调用 trace(1 << SYS_fork),其中 SYS_fork 是 kernel/syscall.h 中的系统调用号。如果系统调用的编号在掩码中设置,则必须修改 xv6 内核以在每个系统调用即将返回时打印一行。该行应包含进程 ID、系统调用的名称和返回值;您不需要打印系统调用参数。跟踪系统调用应该为调用它的进程以及它随后分叉的任何子进程启用跟踪,但不应影响其他进程。

我们提供了一个跟踪用户级程序,该程序运行另一个启用跟踪的程序(请参阅 user/trace.c)。完成后,您应该看到如下输出:

​
$ trace 32 grep hello README
3: syscall read -> 1023
3: syscall read -> 966
3: syscall read -> 70
3: syscall read -> 0
$
$ trace 2147483647 grep hello README
4: syscall trace -> 0
4: syscall exec -> 3
4: syscall open -> 3
4: syscall read -> 1023
4: syscall read -> 966
4: syscall read -> 70
4: syscall read -> 0
4: syscall close -> 0
$
$ grep hello README
$
$ trace 2 usertests forkforkfork
usertests Starting
test forkforkfork: 407: syscall fork -> 408
408: syscall fork -> 409
409: syscall fork -> 410
410: syscall fork -> 411
409: syscall fork -> 412
410: syscall fork -> 413
409: syscall fork -> 414
411: syscall fork -> 415
...
$

在上面的第一个例子中,trace 调用 grep 仅跟踪 read 系统调用。32 是 1<<SYS_read。在第二个例子中,trace 在跟踪所有系统调用时运行 grep;2147483647 的所有 31 个低位均已设置。在第三个例子中,程序未被跟踪,因此没有打印任何跟踪输出。在第四个示例中,正在跟踪 usertests 中 forkforkfork 测试的所有后代的 fork 系统调用。如果您的程序的行为如上所示(尽管进程 ID 可能不同),则您的解决方案是正确的。

一些提示:

  • 将 $U/_trace 添加到 Makefile 中的 UPROGS

  • 运行 make qemu,您将看到编译器无法编译 user/trace.c,因为跟踪系统调用的用户空间存根尚不存在:将 trace 的原型添加到 user/user.h,将存根添加到 user/usys.pl,并将系统调用号添加到 kernel/syscall.h。Makefile 调用 perl 脚本 user/usys.pl,该脚本生成 user/usys.S,即实际的系统调用存根,它使用 RISC-V ecall 指令转换到内核。修复编译问题后,运行 trace 32 grep hello README;它将失败,因为您尚未在内核中实现系统调用。

  • 在 kernel/sysproc.c 中添加一个 sys_trace() 函数,该函数通过在 proc 结构中的新变量中记住其参数来实现新的系统调用(请参阅 kernel/proc.h)。从用户空间检索系统调用参数的函数位于 kernel/syscall.c 中,您可以在 kernel/sysproc.c 中看到它们的使用示例。将您的新 sys_trace 添加到 kernel/syscall.c 中的 syscalls 数组中。

  • 修改 fork()(请参阅 kernel/proc.c)以将跟踪掩码从父进程复制到子进程。

  • 修改 kernel/syscall.c 中的 syscall() 函数以打印跟踪输出。您需要添加一个系统调用名称数组以进行索引。

本次实验的难度还好,只需要一步一步跟着走就好了。首先,我们需要做的就是在user.h加上原型:

user.h(提供一个接口跳转)

...
/* trace call */
int trace(int);

usys.pl 这个脚本生成riscv跳转汇编跳转道对应的systable上去

...
# trace call entry
entry("trace");

syscall.h

我们当然还需要系统调用号

// syscall of the trace
#define SYS_trace  22

然后辅助完成声明,以及我们需要trace实现的系统调用名称

// Prototypes for the functions that handle system calls.
...
extern uint64 sys_trace(void);
​
static const char* syscall_name_table[] = {
  "", /* blank syscall */
  "fork",
  "exit",
  "wait",
  "pipe",
  "read",
  "kill",
  "exec",
  "fstat",
  "chdir",
  "dup",
  "getpid",
  "sbrk",
  "sleep",
  "uptime",
  "open",
  "write",
  "mknod",
  "unlink",
  "link",
  "mkdir",
  "close",
  "trace",
};
​
​
// An array mapping syscall numbers from syscall.h
// to the function that handles the system call.
static uint64 (*syscalls[])(void) = {
...
// add this for the syscall callable
[SYS_trace]   sys_trace,
};

当然下一步就是要辅助记住我们设置的mask,这个需要在sys_trace中完成。第一步就是按照提示所说的,在proc上添加一个

struct proc{
...
    int proc_trace_mask; // using in sys_trace
};

在发起sys_trace的时候就为它赋值:

// trace the functions
uint64
sys_trace(void)
{
  /* fetch the params to gain the mask of trace */
  int mask = 0;
  /* browse the code of argint in syscall.c */
  argint(0, &mask);
  if(mask < 0){
    return -1;
  }
​
  myproc()->proc_trace_mask = mask;
  return 0;
}

以及fork的时候要拷贝我们的参数:

// Create a new process, copying the parent.
// Sets up child kernel stack to return as if from fork() system call.
int
fork(void)
{
    ...
    /* copy the mask */
  np->proc_trace_mask = p->proc_trace_mask;
​
  return pid;
}

最后一步,魔改我们的syscall:

void
syscall(void)
{
  int num;
  struct proc *p = myproc();
​
  num = p->trapframe->a7;
​
  if(num > 0 && num < NELEM(syscalls) && syscalls[num]) {
    // Use num to lookup the system call function for num, call it,
    // and store its return value in p->trapframe->a0
    p->trapframe->a0 = syscalls[num]();
​
    // now trace the system call if is required
    if((1 << num) & p->proc_trace_mask){
      printf("%d: syscall %s -> %ld\n", 
            p->pid,                   // pid 
            syscall_name_table[num],  // system call name
            p->trapframe->a0);        // the return value
    }
​
  } else {
    printf("%d %s: unknown sys call %d\n",
            p->pid, p->name, num);
    p->trapframe->a0 = -1;
  }
}

完事!

== Test trace 32 grep == trace 32 grep: OK (3.8s) 
== Test trace close grep == trace close grep: OK (1.0s) 
== Test trace exec + open grep == trace exec + open grep: OK (1.0s) 
== Test trace all grep == trace all grep: OK (1.0s) 
== Test trace nothing == trace nothing: OK (1.0s) 
== Test trace children == trace children: OK (15.1s) 

攻击 xv6(中等)

xv6 内核将用户程序彼此隔离,并将内核与用户程序隔离。正如您在上面的作业中看到的,应用程序不能直接调用内核或其他用户程序中的函数;相反,交互只能通过系统调用进行。但是,如果系统调用的实现中存在错误,攻击者可能能够利用该错误打破隔离边界。为了了解如何利用错误,我们在 xv6 中引入了一个错误,您的目标是利用该错误诱使 xv6 泄露另一个进程的秘密。

错误是,在编译此实验时,省略了对 kernel/vm.c 中第 272 行的 memset(mem, 0, sz) 的调用以清除新分配的页面。同样,在为本实验编译 kernel/kalloc.c 时,省略了使用 memset 将垃圾放入空闲页面的两行。省略这 3 行(全部由 ifndef LAB_SYSCALL 标记)的净效果是新分配的内存保留了其先前使用的内容。

user/secret.c 在其内存中写入一个 8 字节的秘密,然后退出(释放其内存)。您的目标是向 user/attack.c 添加几行代码以查找 secret.c 先前执行写入内存的秘密,并将 8 个秘密字节写入文件描述符 2。如果 attacktest 打印:“OK:secret is ebb.ebb”,您将获得全部积分。(注意:每次运行 attacktest 时秘密可能不同。)

您可以修改 user/attack.c,但不能进行任何其他更改:您不能修改 xv6 内核源代码、secret.c、attacktest.c 等。

一些提示:

在 xv6 shell 中运行 attacktest。它应该输出以下内容:

$ attacktest
FAIL:没有/不正确的秘密

请注意,尽管删除了 3 行,但 xv6 似乎可以正常工作:它启动了 shell 并运行了 attacktest。事实上,如果你运行 usertests,它们中的大多数都会通过!阅读 user/attacktest.c。它生成一个随机的 8 字节字符串,并将其传递给程序 secret,后者将其写入其内存中。secret 退出后,attacktest 生成攻击并等待攻击将秘密字符串写入文件描述符 2。 阅读 user/secret.c 并思考如何诱骗 xv6 向 attack.c 透露秘密。通过在 xv6 shell 中运行 attacktest 来测试你的漏洞。 user/secret.c 将秘密字节复制到地址为页面开始后 32 字节的内存中。将 32 更改为 0,你应该会看到你的攻击不再起作用;为什么不呢?一些小错误不会直接影响正确性,但仍可能被利用来破坏安全性(如上文所述),这让内核编程变得具有挑战性。xv6 很可能存在此类错误,尽管我们尽量避免。真正的内核比 xv6 的代码行多得多,这类错误由来已久。例如,请参阅公开的 Linux 漏洞和如何报告漏洞。

笔者这里因为没有熟悉过risc-v架构的页表分配等,实际上参考的是这位大佬:

xv6-lab-2024 lab2 Attack最详细解答_xv6 attack lab-CSDN博客

的解答,看官可以自行前往了解原理,笔者的实现放在这里:

#include "kernel/types.h"
#include "kernel/fcntl.h"
#include "user/user.h"
#include "kernel/riscv.h"
​
int
main(int argc, char *argv[])
{
  if(argc != 1){
    printf("usage: attack");
    exit(0);
  }
  char *end = sbrk(PGSIZE*32);
  end = end + 16 * PGSIZE;          /* 为什么是第十七页参考推介的博客 */
  printf("secret: %s\n", end + 32);
  write(2, end+32, 8);
  exit(1);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/943521.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

随身 WiFi 连接 X-Wrt 共享网络与 IPv6 中继配置

本文首发于只抄博客&#xff0c;欢迎点击原文链接了解更多内容。 前言 之前分享的《随身 WiFi 通过 USB 连接路由器共享网络 扩展网络覆盖范围》介绍了随身 WiFi 通过 USB 连接到路由器共享网络&#xff0c;其中留下两个小问题没有解决&#xff1a; OpenWrt 无法识别中兴微的…

3.银河麒麟V10 离线安装Nginx

1. 下载nginx离线安装包 前往官网下载离线压缩包 2. 下载3个依赖 openssl依赖&#xff0c;前往 官网下载 pcre2依赖下载&#xff0c;前往Git下载 zlib依赖下载&#xff0c;前往Git下载 下载完成后完整的包如下&#xff1a; 如果网速下载不到请使用网盘下载 通过网盘分享的文件…

家用无线路由器的 2.4GHz 和 5GHz

家中的无线路由器 WiFi 名称有两个&#xff0c;一个后面带有 “5G” 的标记&#xff0c;这让人产生疑问&#xff1a;“连接带‘5G’的 WiFi 是不是速度更快&#xff1f;” 实际上&#xff0c;这里的 “5G” 并不是移动通信中的 5G 网络&#xff0c;而是指路由器的工作频率为 5G…

【HarmonyOS NEXT】鸿蒙原生应用“上述”

鸿蒙原生应用“上述”已上架华为应用市场&#xff0c;欢迎升级了鸿蒙NEXT系统的用户下载体验&#xff0c;用原生更流畅。 个人CSDN鸿蒙专栏欢迎订阅&#xff1a;https://blog.csdn.net/weixin_44640245/category_12536933.html?fromshareblogcolumn&sharetypeblogcolumn&a…

AI开发:使用支持向量机(SVM)进行文本情感分析训练 - Python

支持向量机是AI开发中最常见的一种算法。之前我们已经一起初步了解了它的概念和应用&#xff0c;今天我们用它来进行一次文本情感分析训练。 一、概念温习 支持向量机&#xff08;SVM&#xff09;是一种监督学习算法&#xff0c;广泛用于分类和回归问题。 它的核心思想是通过…

Linux部署spring项目基础教程

目录 一、安装jdk(yum安装) 1.查看是否有jdk ​编辑 2.查找你想安装的jdk版本 3.安装你需要的版本 4.重复第一步查看版本号,看到版本号说明安装成本 二、部署服务 1.上传jar包 2.启动服务 3.脚本启动 自己搞了个服务器,部署了一个demo项目,把部署流程记录下 一、…

JS中的原型与原型链

1. 基本概念 原型&#xff08;Prototype&#xff09;&#xff1a;每个对象都有一个内部属性 [[Prototype]]&#xff0c;通常通过 __proto__ 访问&#xff08;非标准&#xff0c;但广泛支持&#xff09;。 原型链&#xff08;Prototype Chain&#xff09;&#xff1a;对象通过原…

如何从 0 到 1 ,打造全新一代分布式数据架构

导读&#xff1a;本文从 DIKW&#xff08;数据、信息、知识、智慧&#xff09; 模型视角出发&#xff0c;探讨数字世界中数据的重要性问题。接着站在业务视角&#xff0c;讨论了在不断满足业务诉求&#xff08;特别是 AI 需求&#xff09;的过程中&#xff0c;数据系统是如何一…

Docker完整技术汇总

Docker 背景引入 在实际开发过程中有三个环境&#xff0c;分别是&#xff1a;开发环境、测试环境以及生产环境&#xff0c;假设开发环境中开发人员用的是jdk8&#xff0c;而在测试环境中测试人员用的时jdk7&#xff0c;这就导致程序员开发完系统后将其打成jar包发给测试人员后…

华为 AI Agent:企业内部管理的智能变革引擎(11/30)

一、华为 AI Agent 引领企业管理新潮流 在当今数字化飞速发展的时代&#xff0c;企业内部管理的高效性与智能化成为了决定企业竞争力的关键因素。华为&#xff0c;作为全球领先的科技巨头&#xff0c;其 AI Agent 技术在企业内部管理中的应用正掀起一场全新的变革浪潮。 AI Ag…

Idea使用阿里云创建springboot项目

文章目录 创建springboot项目选择Spring Initializr配置Server URL 创建springboot项目 选择Spring Initializr 配置Server URL https://start.aliyun.com

安全教育培训小程序系统开发制作方案

安全教育培训小程序系统是为了提高公众的安全意识&#xff0c;普及安全知识&#xff0c;通过微信小程序的方式提供安全教育培训服务&#xff0c;帮助用户了解并掌握必要的安全防范措施。 一、目标用户 企业员工&#xff1a;各岗位员工&#xff0c;特别是IT部门、财务、行政等对…

MySQL 数据”丢失”事件之 binlog 解析应用

事件背景 客户反馈在晚间数据跑批后,查询相关表的数据时,发现该表的部分数据在数据库中不存在 从应用跑批的日志来看,跑批未报错,且可查到日志中明确显示当时那批数据已插入到数据库中 需要帮忙分析这批数据丢失的原因。 备注:考虑信息敏感性,以下分析场景测试环境模拟,相关数据…

2024年11月HarmonyOS应用开发者高级认证 最新题库

新增单选 1.下述代码片段中的renderGroup属性&#xff0c;对性能的影响是什么&#xff1a;A A.劣化 B.不一定 C.没有变化 D.优化 2.在刷新Image组件内容时&#xff0c;如果观察到画面会闪一下白块&#xff0c;要怎样优化才能避免白块儿出现&#xff0c;同时又不会卡住画面…

《Opencv》基础操作详解(1)

目录 一、Opencv简介 OpenCV 的主要特点 二、Opencv库安装 1、opencv-python库安装 2、opencv-contrib-python库安装 三、Opencv 基础操作 1、opencv库的导入 2、读取、展示图片 3、查看图片信息 4、控制图片显示时间、关闭窗口 5、读取灰度图 6、彩色图片转灰度图 …

springboot3版本结合knife4j生成接口文档

1.概述 knife4j官网为&#xff1a;介绍 | Knife4j (xiaominfo.com)https://doc.xiaominfo.com/docs/introduction 初步了解的码友可以初步了解一下官网的如下几个模块&#xff1a; 其中在快速开始模块中&#xff0c;不同的springboot版本都有一个使用的案例demo如下图位置&am…

Android笔记(四十一):TabLayout内的tab不滚动问题

背景 假设二级页面是上面图片的布局&#xff0c;当进来时TabLayout和ViewPager2绑定完就马上调setCustomItem&#xff0c;跳转到最后一个tab页面时&#xff0c;会发现tab不滚动&#xff0c;手动滑一下ViewPager2时才会滚动tab到正确的位置 原因分析 调用TabLayoutMediator.at…

Oracle中间件 SOA之 OSB 12C服务器环境搭建

环境信息 服务器基本信息 如下表&#xff0c;本次安装总共使用1台服务器&#xff0c;具体信息如下&#xff1a; App1服务器 归类 APP服务器 Ip Address 172.xx.30.xx HostName appdev01. xxxxx.com Alias appdev01 OSB1服务器 归类 OSB服务器 Ip Address 172.xx3…

【HENU】河南大学计院2024 计算机网络 期末复习知识点

和光同尘_我的个人主页 一直游到海水变蓝。 计网复习 第一章互联网组成类别交换方式分组交换的要点&#xff1a;分组交换的优点&#xff1a; 网络性能指标体系结构网络协议五层协议 第二章&#xff1a;物理层物理层的主要任务&#xff08;四大特性&#xff09;通信的三种方式…

深入探讨 Go 中的高级表单验证与翻译:Gin 与 Validator 的实践之道20241223

深入探讨 Go 中的高级表单验证与翻译&#xff1a;Gin 与 Validator 的实践之道 在现代后端开发中&#xff0c;表单验证是保证数据完整性和服务稳定性的核心环节。如何优雅、高效地实现表单验证&#xff0c;同时提供人性化的错误提示&#xff0c;是每位开发者的必修课。在本文中…