WriteFile
从R3 ,到磁盘
1:kernel32 WriteFile
1)
挺惊讶的,符号好使了,
前面大概4条判断,根据句柄判断要写到什么地方,一共有4个地方可能要去,
stdin stdout stderr 还有最后一个 控制台
2)然后就是一个异步的判断
如果是异步,那么整理信息,然后调用NtWriteFile,根据返回值判断情况成功了,返回1
否则返回0
这里不考虑,主要考虑同步的情况
3)同步的位置
倒是不拖拉,直接就走Nt函数准备进内核了
2:
1)内核里面,一个深情的问候,先获取有用的信息,ETHREAD,和FILE_OBJECT,还有设备对象
2)打了招呼,开始干活
Zw函数的标准玩法,先判断处于用户模式还是内核模式,其实我就很搞不懂,
驱动里面,Zw函数和Nt函数就那么点区别,一个判断内核模式,一个不判断内核模式,
判断了之后,简单地说,就是修改模式之后,Zw调用Nt,然后再走原有流程,
这里直接判断了,应该是优化了吧。
3)做完环境判断之后,
开始准备可能用到的结构了,
4)准备结构之后,还有一个步骤,
1.就是判断是否为同步操作,
如果是同步操作的话,那么后面直接走
2.并行的步骤还有个判断异步的
这里顺带判断了,如果传入字符个数是0个,并且又是非管道或者邮槽操作,
(这里要说一下,其实,管道等的操作,写入地址是NULL,写入字符个数0个,实际上是个常规操作,不算是违规操作)
5)这里先看同步操作吧
1。首先,设置当前状态,给文件系统,告诉它我现在在忙,我有同步的事情正在做
如果以前有人设置了,那么v17 = 0,否则减个引用计数,然后v17 = 1。
2。如果之前有人设置过了,那么这里自己获取一个文件对象锁
这里有个细节,其实挺奇怪的,这里加了锁,但是后面没有地方Release这个锁,所以是不是可以考虑,这个锁根本就不会加,
也就是说不会走到这里,也就是说当前文件不会有其他人在用,但是这不科学,这个理论说不通。
其实后面有地方SetEvnet了。是不是就为了这个锁而存在的。
3。
如果要写入的字符个数为0个,并且v35,没有修正,或者值有异常,
那么就把它修正为当前文件的偏移位置。
4。又是一个分水岭,这里,如果这个成员有值,则继续走内部流程,否则就走到外面去了,外面就是和异步流程相同的其它流程了
其实,这个成员是干嘛的,我就没搞清楚
An opaque member, set only by file systems, that points to handle-specific information and that is used for Cache Manager interaction.
MSDN上,只有这么一段话,说一个不透明的成员,只有文件系统可以操作它,类似于句柄,是和CM交互用的。
我是不是可以猜测成,这个东西的存在,就是说CM中,我要改写的这个文件已经进入缓存了,我直接修改缓存就可以了,所以才出现这个判断。
没有缓存的话,那就自然不是简单操作就能完成任务的。
5。这个判断,真的搞得我好郁闷,
首先判断 v35 的高位 < 0 ,就是说,它必须是 0xFFFF,
然后并且,v35 的值不为 -1 ,就是说,v35的值必须是 0xFFFF0000 ~ 0xFFFFFFFE
这是要判断什么呢,根据前面的经验,实际上这里出现这种值得可能性几乎没有,因为在前面已经通过各种设置,
设置了v35的值,不会变成这个样子,除非是文件位置的有意为之。
v35实际上是文件指针当前偏移,
6。终于到了同步最后一个位置了
这里的操作比较好理解,首先
- typedef
- BOOLEAN
- FAST_IO_WRITE (
- __in struct _FILE_OBJECT *FileObject,
- __in PLARGE_INTEGER FileOffset,
- __in ULONG Length,
- __in BOOLEAN Wait,
- __in ULONG LockKey,
- __in PVOID Buffer,
- __out PIO_STATUS_BLOCK IoStatus,
- __in struct _DEVICE_OBJECT *DeviceObject
- );
fastiowrite的原型是这样的,也就是说,调用的时候,函数包含了,哪个设备(文件所在设备),哪个文件(FILE_OBJECT 对应的文件),从哪写,写多少,甚至是否加锁是否等待都有了,
返回值是 BOOLEAN,符合要求,返回成功失败,如果函数调用成功了,判断 STATUS,是否执行也成功,执行也成功的话,
走进函数内部了。
第一个函数 IopUpdateWriteOperationCount ,具体做什么的网上没找到,自己看,发现它内部先更新了一个全局的写操作计数器,
然后又更新了一下ETHREAD里面的一个位置,很可能是解锁相关的
第二个函数 IopUpdateWriteTransferCount ,看名字,以及参数的用途,大概是提交修改字符的个数,
后续一系列的返回数据整理,然后设置Event,如果文件在忙,就给文件设置为空闲状态,如果文件在等待,那么就给它一个Event,
最后释放了句柄,就可以返回了。
6)异步操作部分
1。也是先判断偏移
不符合标准,直接就滚蛋了,这里不管
2。这里是我最喜欢的部分,创建IRP,然后整理IRP的初始化的部分
这部分操作结束之后
3。代码开始逐渐明朗了,把两块互斥的指针初始化
如果是 DO_BUFFERED_IO 的话,那么就是用 systembuffer
如果设置成功的话,标记IRP标志为48,也就是0x30,翻译成中文就是
这里使用的是 Buffered IO,用完之后,管理器需要把Buffer 释放
如果设置失败,那么就修改flags值为16,也就是0x10,和上面区别就是,你别删了,其实根本就用不了
4。代码第二块
也就是非 DO_BUFFERED_IO 的情况下,先判断是否为 MDL 方式,如果是的话,给IRP创建一个MDL,然后LOCK住,
如果不是MDL的情况,那么直接挂UserBuffer 为应用层传来的空间,这种方法非常危险,
标识位为0,鸡毛都没有
5。这块,主要是告诉下面处理的地方,这里都是什么操作
最后就是一个分发操作,开始让IRP干活去吧
至此,整个流程基本完成了,
实际上我们可以看出,
大体流程并不是很多,
大致流程就是
应用层的 WriteFile
然后进内核NtWriteFile
里面判断同步异步,
同步走磁盘设备的FastIoWrite
调用失败,或者异步的话,就自己创建IRP来实现,
整体流程就这么短。
剩下的就是FastIoWrite里面,或者文件系统驱动去对照IRP写磁盘了。
还有几处我不懂得地方,就是那个UserBuffer,为什么它在里面竟然写了东西,
IDA实际上没有识别出那个UserBuffer,是我自己根据偏移算出来的,
也不知道我算得是否正确
WriteFile的更多相关文章
- 转(Response.WriteFile 无法下载大文件解决方法)
以前用Response.WriteFile(filename),但当遇到大文件时无法完整下载. 该方法最大的问题,它不是直接将数据抛到客户端,而是在服务器端(IIS)上缓存.当下载文件比较大时,服务器 ...
- WriteFile实现下载
TransmitFile实现下载 protected void Button1_Click(object sender, EventArgs e) { /* ...
- lua 的 WriteFile 和 ReadFile
lua 的 ReadFile 和 WriteFile 注意: lua 代码中的 string 可以包含二进制数据 string.len(str) 不会被 '\0' 截断 从 lua 传入 c 时: 需 ...
- CreateFile,WriteFile,ReadFile
注意: CreateFile 跟 fopen 不同,打开文件时不区分 文本方式 或 二进制 方式 ReadFile 或 WriteFile 都是对二进制数据进行操作 HANDLE WINAPI Cre ...
- 用Windows API函数(CreateFile/ReadFile/WriteFile/CloseHandle)完成文件拷贝程序(初级版)
文件拷贝程序 程序类型:Console 参数:源文件名 目的文件名 要求:1.只能使用Windows API函数(CreateFile/ReadFile/WriteFile/CloseHandle ...
- page.Response.WriteFile(newpath);
page.Response.Clear(); page.Response.ClearHeaders(); page.Response.Buffer = fa ...
- Win32 WriteFile and ReadFile
HANDLE WINAPI CreateFile( __in LPCTSTR lpFileName, // 文件路径 __in DWORD dwDesiredAccess, // 访问权限,GENER ...
- 多种下载文件方式 Response.BinaryWrite(byte[] DocContent);Response.WriteFile(System.IO.FileInfo DownloadFile .FullName);Response.Write(string html2Excel);
通过html给xls赋值,并下载xls文件 一.this.Response.Write(sw.ToString());System.IO.StringWriter sw = new System.IO ...
- 串口通信中ReadFile和WriteFile的超时详解!
源:串口通信中ReadFile和WriteFile的超时详解! 在用ReadFile和WriteFile读写串行口时,需要考虑超时问题.如果在指定的时间内没有读出或写入指定数量的字符,那么ReadFi ...
- 使用CreateFile, ReadFile, WriteFile在Windows NT/2000/XP下读写绝对扇区的方法
也就是在CreateFile的时候打开文件名指定: "\\.\Device"就可以了. 因为代码比较短, 所以我不做注释, 相信大家看代码就能明白意思了. 另外这里读写的都是软盘A ...
随机推荐
- C++——函数及调用
1.函数调用:实参初始化形参:控制权交给被调函数 2.函数返回(return语句):返回return中的值:控制权交回主函数 3.参数传递 传值 传引用 传指针 初始值 不变,拷贝给形参 可变,形 ...
- C# WinfForm 控件之dev报表 XtraReport (八)动态生成报表
功能说明:生成一个报表文件DV1,保存到本地AA.rep,再重新加载这个文件到DV2 1.布局如下图: panel1 上有三个button panel2上有个documentView dv1 pane ...
- 「CSP-S 2019」树的重心
题目 考场上送\(75pts\)真实良心,正解不难:考虑直接对于每一个点算割掉多少条边能使得这个点成为重心,不难发现对于一个不是重心的点,我们要割掉的那条边一定在那个大于\(\lfloor \frac ...
- 第八篇 编写spider爬取jobbole的所有文章
通过scrapy的Request和parse,我们能很容易的爬取所有列表页的文章信息. PS:parse.urljoin(response.url,post_url)的方法有个好处,如果post_ur ...
- 远程服务器安装nginx
肯定有前端的小伙伴在腾讯云或者阿里云上购买了服务器,却不知道怎么访问使用它,那我们就一起来安装学习下? xshell 登录服务器,输入公网ip和密码登录 ls 查看目录,which nginx ,查看 ...
- .net core 下的跨域设置
1.CORS中间件处理跨源请求.以下代码为具有指定源的整个应用程序启用CORS: public void Configure(IApplicationBuilder app, IHostingEnvi ...
- wpf中datagrid绑定数据源发生改变
1.若datagrid绑定的数据源是同一个的话,即使里面的数据不同.页面也不会刷新,则需要重置数据源,再绑定.处理如下: datagrid1.ItemsSource=ListModule; 若List ...
- Mac OS X终端的常用操作命令(UNIX指令)
用了十多年windows,终于换了个高配Mac,俗话说 无论前端还是后端最终还是走向了linux,无论是换了多少台PC最终都会走向Mac.不学习命令行用什么Mac? 干就完了~ pwd 显示现在的文件 ...
- linux每日命令(3):which命令
这个命令我也神佑体会它的用处,在linux要查找某个文件,但不知道放在哪里了,可以使用下面的一些命令来搜索: which 查看可执行文件的位置. whereis 查看文件的位置. locate ...
- 结对编程-Core 第12组 [pb15061359+pb15061351]
一.项目要求 1.输入题目数量,生成操作数为3~5个的四则运算题目 2.输入上限值控制生成的操作数的最大值以及结果的最大值 3.输入支持的操作符类型:加.减.乘.除.乘方.括号 4.输入支持的操作数类 ...