write的奥秘.docx
- 文档编号:9115274
- 上传时间:2023-02-03
- 格式:DOCX
- 页数:15
- 大小:31.13KB
write的奥秘.docx
《write的奥秘.docx》由会员分享,可在线阅读,更多相关《write的奥秘.docx(15页珍藏版)》请在冰豆网上搜索。
write的奥秘
write的奥秘
在Linux下我们在使用设备的时候,都会用到write这个函数,通过这个函数我们可以象使用文件那样向设备传送数据。
可是为什么用户使用write函数就可以把数据写到设备里面
去,这个过程到底是怎么实现的呢?
这个奥秘就在于设备驱动程序的write实现中,这里我结合一些源代码来解释如何使得一个简简单单的write函数能够完成向设备里面写数据的复杂过程。
这里的源代码主要来自两个地方。
第一是oreilly出版的《Linuxdevicedriver》中的
实例,第二是LinuxKernel2.2.14核心源代码。
我只列出了其中相关部分的内容,如果
读者有兴趣,也可以查阅其它源代码。
不过我不是在讲解如何编写设备驱动程序,所以不
会对每一个细节都进行说明,再说有些地方我觉得自己还没有吃透。
由于《Linuxdevicedriver》一书中的例子对于我们还是复杂了一些,我将其中的一个
例程简化了一下。
这个驱动程序支持这样一个设备:
核心空间中的一个长度为10的数组
kbuf[10]。
我们可以通过用户程序open它,read它,write它,close它。
这个设备的名
字我称为short_t。
现在言归正传。
对于一个设备,它可以在/dev下面存在一个对应的逻辑设备节点,这个节点以文件的形式
存在,但它不是普通意义上的文件,它是设备文件,更确切的说,它是设备节点。
这个节
点是通过mknod命令建立的,其中指定了主设备号和次设备号。
主设备号表明了某一类设
备,一般对应着确定的驱动程序;次设备号一般是区分是标明不同属性,例如不同的使用
方法,不同的位置,不同的操作。
这个设备号是从/proc/devices文件中获得的,所以一
般是先有驱动程序在内核中,才有设备节点在目录中。
这个设备号(特指主设备号)的主
要作用,就是声明设备所使用的驱动程序。
驱动程序和设备号是一一对应的,当你打开一
个设备文件时,操作系统就已经知道这个设备所对应的驱动程序是哪一个了。
这个"知道"
的过程后面就讲。
我们再说说驱动程序的基本结构吧。
这里我只介绍动态模块型驱动程序(就是我们使用
insmod加载到核心中并使用rmmod卸载的那种),因为我只熟悉这种结构。
模块化的驱动程序由两个函数是固定的:
intinit_module(void);void
cleanup_module(void)。
前者在insmod的时候执行,后者在rmmod的时候执行。
init_nodule在执行的时候,进行一些驱动程序初始化的工作,其中最主要的工作有三
件:
注册设备;申请I/O端口地址范围;申请中断IRQ。
这里和我们想知道的事情相关的只
有注册设备。
下面是一个典型的init_module函数:
intinit_module(void){
intresult=check_region(short_base,1);/*察看端口地址*/
……
request_region(short_base,1,"short");/*申请端口地址*/
……
result=register_chrdev(short_major,"short",&short_fops);/*注册设备
*/
……
result=request_irq(short_irq,short_interrupt,SA_INTERRUPT,"short",
NULL);/*申请IRQ*/
……
return0;
}/*init_module*/
上面这个函数我只保留了最重要的部分,其中最重要的函数是
result=register_chrdev(short_major,"short",&short_fops);
这是一个驱动程序的精髓所在!
!
当你执行indmod命令时,这个函数可以完成三件大事:
第一,申请主设备号(short_major),或者指定,或者动态分配;第二,在内核中注册设
备的名字("short");第三,指定fops方法(&short_fops)。
其中所指定的fops方法就是
我们对设备进行操作的方法(例如read,write,seek,dir,open,release等),如何实现
这些方法,是编写设备驱动程序大部分工作量所在。
现在我们就要接触关键部分了--如何实现fops方法。
我们都知道,每一个文件都有一个file的结构,在这个结构中有一个file_operations的
结构体,这个结构体指明了能够对该文件进行的操作。
下面是一个典型的file_operations结构:
structfile_operations{
loff_t(*llseek)(structfile*,loff_t,int);
ssize_t(*read)(structfile*,char*,size_t,loff_t*);
ssize_t(*write)(structfile*,constchar*,size_t,loff_t*);
int(*readdir)(structfile*,void*,filldir_t);
unsignedint(*poll)(structfile*,structpoll_table_struct*);
int(*ioctl)(structinode*,structfile*,unsignedint,unsigned
long);
int(*mmap)(structfile*,structvm_area_struct*);
int(*open)(structinode*,structfile*);
int(*flush)(structfile*);
int(*release)(structinode*,structfile*);
int(*fsync)(structfile*,structdentry*);
int(*fasync)(int,structfile*,int);
int(*check_media_change)(kdev_tdev);
int(*revalidate)(kdev_tdev);
int(*lock)(structfile*,int,structfile_lock*);
};
我们可以看到它实际上就是许多文件操作的函数指针,其中就有write,其它的我们就不
去管它了。
这个write指针在实际的驱动程序中会以程序员所实现的函数名字出现,它指
向程序员实现的设备write操作函数。
下面就是一个实际的例子,这个write函数可以向核
心内存的一个数组里输入一个字符串。
intshort_write(structinode*inode,structfile*filp,constchar*buf,
intcount){
intretval=count;
externunsignedcharkbuf[10];
if(count>10)
count=10;
copy_from_user(kbuf,buf,count);
returnretval;
}/*short_write*/
设备short_t对应的fops方法是这样声明的:
structfile_operationsshort_fops={
NULL,/*short_lseek*/
short_read,
short_write,
NULL,/*short_readdir*/
NULL,/*short_poll*/
NULL,/*short_ioctl*/
NULL,/*short_mmap*/
short_open,
short_release,
NULL,/*short_fsync*/
NULL,/*short_fasync*/
/*nothingmore,fillwithNULLs*/
};
其中NULL的项目就是不提供这个功能。
所以我们可以看出short_t设备只提供了
read,write,open,release功能。
其中write功能我们在上面已经实现了,具体的实现函
数起名为short_write。
这些函数就是真正对设备进行操作的函数,这就是驱动程序的一
大好处:
不管你实现的时候是多么的复杂,但对用户来看,就是那些常用的文件操作函数。
但是我们可以看到,驱动程序里的write函数有四个参数,函数格式如下:
short_write(structinode*inode,structfile*filp,constchar*buf,intcount)
而用户程序中的write函数只有三个参数,函数格式如下:
write(inffd,char*buf,intcount)
那他们两个是怎么联系在一起的呢?
这就要靠操作系统核心中的函数sys_write了,下面
是LinuxKernel2.2.14中sys_write中的源代码:
asmlinkagessize_tsys_write(unsignedintfd,constchar*buf,size_tcount)
{
ssize_tret;
structfile*file;
structinode*inode;
ssize_t(*write)(structfile*,constchar*,size_t,loff_t*);/*指向
驱动程序中的wirte函数的指针*/
lock_kernel();
ret=-EBADF;
file=fget(fd);/*通过文件描述符得到文件指针*/
if(!
file)
gotobad_file;
if(!
(file->f_mode&FMODE_WRITE))
gotoout;
inode=file->f_dentry->d_inode;/*得到inode信息*/
ret=locks_verify_area(FLOCK_VERIFY_WRITE,inode,file,file->f_pos,
count);
if(ret)
gotoout;
ret=-EINVAL;
if(!
file->f_op||!
(write=file->f_op->write))/*将函数开始时声明的
write函数指针指向fops方法中对应的write函数*/
gotoout;
down(&inode->i_sem);
ret=write(file,buf,count,&file->f_pos);/*使用驱动程序中的write函数
将数据输入设备,注意看,这里就是四个参数了*/
up(&inode->i_sem);
out:
fput(file);
bad_file:
unlock_kernel();
returnret;
}
我写了一个简单的程序来测试这个驱动程序,该程序源代码节选如下(该省的我都省了):
main(){
intfd,count=0;
unsignedcharbuf[10];
fd=open("/dev/short_t",O_RDWR);
printf("inputstring:
");
scanf("%s",buf);
count=strlen(buf);
if(count>10)
count=10;
count=write(fd,buf,count);
close(fd);
return1;
}
现在我们就演示一下用户使用write函数将数据写到设备里面这个过程到底是怎么实现的:
1,insmod驱动程序。
驱动程序申请设备名和主设备号,这些可以在/proc/devIEces中获得。
2,从/proc/devices中获得主设备号,并使用mknod命令建立设备节点文件。
这是通过主
设备号将设备节点文件和设备驱动程序联系在一起。
设备节点文件中的file属性中指明了
驱动程序中fops方法实现的函数指针。
3,用户程序使用open打开设备节点文件,这时操作系统内核知道该驱动程序工作了,就
调用fops方法中的open函数进行相应的工作。
open方法一般返回的是文件标示符,实际
上并不是直接对它进行操作的,而是有操作系统的系统调用在背后工作。
4,当用户使用write函数操作设备文件时,操作系统调用sys_write函数,该函数首先通
过文件标示符得到设备节点文件对应的inode指针和flip指针。
inode指针中有设备号信
息,能够告诉操作系统应该使用哪一个设备驱动程序,flip指针中有fops信息,可以告诉
操作系统相应的fops方法函数在那里可以找到。
5,然后这时sys_write才会调用驱动程序中的write方法来对设备进行写的操作。
其中1-3都是在用户空间进行的,4-5是在核心空间进行的。
用户的write函数和操作系统
的write函数通过系统调用sys_write联系在了一起。
注意:
对于块设备来说,还存在写的模式的问题,这应该是由GNUC库来解决的,这里不予讨
论,因为我没有看过GNUC库的源代码。
另外,这是一个测试版的文章,请各位朋友们多提意见和建议,非常感谢!
KnowYourEnemy
ScriptKiddIE使用的工具和方法论
HoneynetProject
http:
//project.honeynet.org
http:
//www.xfocus.org
LastModified:
21July,2000
我的长官经常对我说:
在敌人面前好很好的保护自己,你必须先了解敌人先。
(孙子兵法:
知己知彼,百战百胜)。
这句军事用语现在也很好的应用于网络安全领域中了,就象作战一样,你要保护自己的资源,你需要知道谁是你最大的威胁和他们会怎样攻击。
在这个系列中的第一篇文章,就是讨论一种很流行很广泛的来自ScritpKiddie所使用的工具和方法,如果你或者你的组织有任何资源连接到Internet上,你就有此类的威胁。
KnowYourEnemy文章主要是涉及到blackhatck团体使用的工具,策略和动机。
而KnowYourEnemy:
II主要集中于你怎样能探测这些威胁,判断他们所使用的工具和他们在你系统上寻找什么样的漏洞。
KnowYourEnemy:
III集中讨论攻击者获得ROOT后在系统上怎样操作,特别是他们是如何掩盖他们的踪迹和他们下一步主要干什么。
KnowYourEnemy:
Forensics涉及了你怎样分析一种攻击。
KnowYourEnemy:
Motives通过捕获black-hat团体之间的通信和联系来分析他们的动机和心理状态。
KnowYourEnemy:
WormsatWar描述了WORM蠕虫是怎样自动攻击WINDOW系统的。
什么叫ScriptKiddie
Scriptkiddie是一些专门找寻一些容易下手资源的人,他们不专门针对某种特定信息或者目标特定公司,他们的目标是尽可能的用最简单的方法获得ROOT,他们通过搜集一些公开的exploit信息并搜索整个Internet来找寻有这种exploit漏洞的资源,这样,不管怎样,总有某些人会被他们操作。
其中一些高级点的家伙会开发他们自己的工具,并留下一些复杂的后门,另外一些根本就不知道他们做什么,就知道怎样在命令行打"go"的人。
忽略他们的技术水平不说,Scriptkiddie就是共享一些公共策略,随机搜索某个特殊漏洞并利用这个特殊漏洞的人。
他们形成的威胁在哪里?
由于Scriptkiddie是随机选择目标,所以存在的威胁是你的系统迟早会被扫描到,我知道管理员很惊讶他们的系统在设置以后没几天也没有告诉任何人的时候就被扫描到了,其实这一点也不值得惊讶,因为Scritpkiddie一般是扫描一段网络来操作的。
如果扫描只能限制在几个独立的资源,你可能会很安心,因为Internet上千千万万的机器,扫描到你的机器的几率少之又少。
但是,事实不是你想象的这样,目前多数工具能很方面的使用大范围扫描并广泛传播,任何人可以使用他们,使用这些工具的人数增长率呈现惊人的速率。
Internet是一个无国界的区域,这种威胁就很快转播到世界各个地方,有这么多人使用这些工具,你被探测就不是问题了。
试图以含糊其词来搪塞你的安全问题会害了你:
你或许会认为没有人知道你的系统,你就会安全,或者你认为你的系统没有价值,他们为何要探测你,其实这些系统正是scritpkiddies搜寻的目标--没有任何保护的系统,非常容易得手的系统。
具体方法讨论
Scritpkiddie的方法很简单,扫描Internet有特定缺陷的系统,一但查找到,便对它下手,他们用的许多工具会自动操作,不需要很多的交互。
你只要打开工具,然后过几天回来看看你的结果就可以了。
没有两个工具是相同的就象没有两个漏洞是一样的,但是虽然如此,许多工具的策略是一样的,第一,开发要扫描的IP段,然后扫描这些IP段中特定的漏洞。
例如:
我们假定一个用户有一个工具可以利用Linux系统上的imap漏洞,如imapd_exploit.c,开始,他们开发一IP数据库来扫描,一旦IP数据库构建好,用户会想判断系统是否运行LINUX系统。
目前许多扫描器可以通过发送不正常的信息包到目标系统并查看他们如果响应便可很方便的判断操作系统,如Fyodor的nmap,然后,工具会判断LINUX系统是否运行着imap服务,最后就是利用imapd_exploit.c程序来进入系统了。
你会想所以这些扫描会有很大的动静,很容易引起注意,但是,很多人没有很好的监视他们的系统,并不认识到他们正被扫描,而且,许多scriptkiddies在查看他们所要利用的系统时也会保持相当的安静,一旦他们利用这个漏洞进入系统,他们就会使用这个系统作为跳板,并不带任何包袱的扫描整个系统,因为如果这种扫描被抓获,责任是系统管理员而不是那些script-kiddie.
所有这些扫描的结果经常被用来归档或者在其他用户中共享,以便在以后的日子里使用,如用户在最初为了某个漏洞扫描出来的LINUX系统开了那些端口的数据库后,过一点时间,一个新的漏洞被发现以后,用户可以不用重新构建或者扫描新的IP段,他可以很方便的来查看以前归档的数据库并来利用这个新发现的漏洞。
其他变相的,用户可以交流或者买卖有漏洞系统的数据库。
你可以看KnowYourEnemy:
Motives文章中的例子,这样造成scritpkiddie可以不扫描系统而破坏你的资源。
有些Black-hats会采用木马或者后门来种植在破坏的系统中,后门允许方便的随时的让攻击者来访问你的系统,而木马使入侵者难于被发现,这些技术可以让他们的操作不显示在任何LOG记录,系统进程或者文件结构上,他可以构建一个舒适安全的环境来扫描Internet,跟详细的信息请看:
KnowYourEnemy:
III。
这些攻击没有限制在一天中的任何时间,许多管理员搜索他们的LOG记录来查询当晚发生了什么,并相信这是攻击者的攻击时间,其实scriptkiddies在任意时间进行攻击,他们一天24小时的进行扫描,你根本不能考虑到你什么时候会被探测到。
而且由于Internet的无边界性,时间也就不确定了,攻击者当地在午夜在攻击,而你这里可能是在当地时间下午一点种。
以上对系统漏洞的扫描可以用于多种用途,近来,一种新的拒绝服务攻击--分布式拒绝服务攻击DDos,就是攻击者一个人控制了很多台有漏洞的系统,他可以遥控这些控制的系统来共同对目标系统执行拒绝服务攻击。
由于多个系统被使用,所以防卫和判断源攻击地也变的非常困难。
要控制多个系统,Scriptkiddie的策略就变的很有用,有漏洞的系统随机被判断并用来作为DDOS的垫板,越多的系统被控制,DDOS攻击的强度就越大。
如stacheldraht,要了解关于更多的分布式拒绝服务攻击和怎样保护自己,请查看PaulFerguson站上的Denialinfo。
工具
这些工具一般使用起来很见大,许多工具一般只是几个选项来完成单个目标,开始工具用来构建IP数据库,这些工具很随机的扫描Internet,如一个工具有一个单一的选项,A,B和C,你可以选择一个字母来决定要扫描的网络大小,这工具然后就选择A,B,C相应的IP网络进行扫描。
另一个工具使用域名如z0ne,这个工具通过对域名和子域名的区域传输操作来构造IP数据库,用户通过扫描整个.com或者.edu域来获得2百万或者更多的IP数据库,一旦发现这些IP,它们就被会被工具用户判断版本名字,操作系统,所运行的服务,如果发现系统有漏洞,black-hat就会马上进行攻击。
要更好的理解这些工具,请看KnowYourEnemy:
Forensics。
怎样防止这类威胁
下面的一些步骤你可以比较好的保护你的系统,第一,scriptkiddie一般找寻容易下手的对象,如一些很公开很容易得手的漏洞系统,保证你的系统和网络不受这些漏洞的影响,www.cert.org和www.ciac.org是了解这些漏洞很好的资料库。
同样地,bugtraq(的一个邮件列表)也是获得这些漏洞信息很好的地方。
另一个保护你自己的方法是只运行你需要的服务,如果你不需要某个服务,关掉它,如果你确实要使用某个服务,确保你的服务版本是最新的。
要怎样操作,请看这些文章:
ArmoringSolaris,ArmoringLinux或者ArmoringNT.
上面知道,DNS服务器是经常被用来找寻IP数据库的对象之一,你必须在你的名字服务器上限制区域传送的操作,记录任何未认证的区域传输并跟踪他们。
我强烈建议升级BIND到最新的版本,你可以在下面的地址找到:
www.isc.org/bind.HTML.最后监视你被探测的系统,你可以跟踪这些探测操作获得更多对你网络有威胁的举动。
总结
Scritpkiddie会对所有系统有威胁,他们没有任何偏爱,任何系统他们都挑,不计较地点和价值。
不管怎样,你迟早会被扫描到。
通过了解他们的动机和方法,你可以很好的对付这些威胁而更好的保护你的系统。
KnowYourEnemy:
II
跟踪Blackhat的举动
HoneynetProject
http:
//project.honeynet.org
http:
//www.xfocus.org
LastModifIEd:
July7,2000
此文章是系列中的第二篇文章,在第一篇KnowYourEnemy,我们讲述了Scriptkiddie相关的工具和方法,特别是他们是怎样探测漏洞然后攻击的。
在第三篇KnowYourEnemyIII中我们将会描述Scriptkiddie在获得ROOT的时候将会做的事情,特别是他们是怎样覆盖踪迹和他们下一步做的是什么。
当前这文章,将涉及到有关则怎样跟踪他们的行为。
我们会讲述到
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- write 奥秘