Blog

内存与调试-window内核调试WinDbg、KD环境搭建

为什么会去学内核调试,因为之前学内存管理的时候,介绍过内核调试可以查看进程的物理地址,亲自动手实验,加深理解。

最初看到KD命令行(kernel debug),感觉很神奇,可以查找内存物理地址,查询后发现是内核调试,需要安装软件,然后建立调试环境。

一、安装WinDbg软件

注意:WinDbg软件是安装在主机上的,用于调试测试机。

微软官网下载,Debugging Tools for Windows (WinDbg, KD, CDB, NTSD)

3 ways to get Debugging Tools for Windows

  • As part of the WDKDebugging Tools for Windows is included in the WDK. You can get the WDK here.
  • As a standalone tool set 【感觉独立模式不错,但是没有xp版本的】If you want to download only Debugging Tools for Windows, install the Windows SDK, and, during the installation, select the Debugging Tools for Windows box and clear all the other boxes.
  • As part of the Windows SDKInstall the complete Windows Software Development Kit (SDK). Debugging Tools for Windows is included in the Windows SDK. You can get the Windows SDK here.

记得我下载的是XP版WDK文件GRMWDK_EN_7600_1.ISO,好像不是选择独立模式,将下载好的ISO文件(也叫镜像文件)进行解压。解压出来后,选择Debugging Tools 文件夹就行了。这里已经提取了xp版的Windbg软件,可以直接下载安装。

如果安装出错,可能是缺少类似  Microsoft Visual C++ 2010 Redistributable 等软件

二、配置双机连接

需要两台电脑,一台作为主机,另一台作为被测试机。主机连接到测试机才能进行内核调试。   那没有两台电脑怎么办?

方案一:一台主机,一台虚拟机,虚拟机作为测试机。

方案二:两台虚拟机,一台作为主机,一台作为测试机。

1、开启测试机的debug模式

无论方案一还是方案二,都要开启测试机的debug模式。

对于 Windows XP,直接编辑 C:\\boot.ini 文件。添加新的启动项:

multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional -Debug" /fastdetect /debug /debugport=com1 /baudrate=115200

其中/baudrate=115200,表示串行通信的速率 bps,115200 是串行通信的最大速率,因此使用串行通信进行内核调试时,如果进行频繁的单步跟踪和要传递较大的文件(如 .kdfiles 和 .dump 命令),那么会感觉到速度有些慢。com1是连接端口号。

最终编辑好的boot.ini文件效果如下所示,

[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS
[operating systems]
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional" /fastdetect
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional -Debug" /fastdetect /debug /debugport=com1 /baudrate=115200

从 Windows Vista 开始,考虑到 boot.ini 文件很容易被恶意软件所修改,因此不再使用 boot.ini 文件,而是使用 Boot Configuration Data—BCD。修改 BCD,需要启动一个管理员权限(Run As Administrator)的命令行窗口。然后使用 bcdedit 命令来编辑 BCD(建议首先将当前启动入口复制一份):

c:\Windows\system32>bcdedit /copy {current} /d "Win7 Debug with Serial port"
The entry was successfully copied to {new_uuid}

c:\Windows\system32>bcdedit /debug {new_uuid} on
The operation completed successfully.

BCD 中有一套全局的调试设置,使用 bcdedit /dbgsettings 可以观察和修改这套全局设置:

c:\Windows\system32>bcdedit /dbgsettings
debugtype Serial
debugport 1
baudrate 115200
The operation completed successfully.

可以看到默认的全局调试设置中,调试类型为 Serial,调试端口为 1,波特率为 115200,这已经是我们需要的设置了。当然也可以通过如下命令再次设置为串口调试:

c:\Windows\system32>bcdedit /dbgsettings serial DEBUGPORT:1 BAUDRATE:115200
The operation completed successfully.

如果希望为某个自启动项设置单独的调试选项,那么可以使用 bcdedit /set:

bcdedit /set {new_uuid} debugtype serial
bcdedit /set {new_uuid} debugport 1
bcdedit /set {new_uuid} baudrate 115200

2、配置虚拟机的连接环境

这个地方是一个大坑,需要特别注意一下。其中方案一的配置和方案二的配置是不一样的,需要特别注意。

方案一的操作:

虚拟机设置方面:

主机操作windbg软件,连接时的配置:

特别提醒:

这种方案里主机肯定是Windows系统,所以pipe管道文件的路径的写法是   \\.\pipe\debugpipe   不像linux系统中的 / xx/xx/  路径写法。

还有虚拟机实际输出文件是pipe,所以主机的WinDbg配置连接时,需要勾选pipe。

方案二的操作:
虚拟测试机的设置:
虚拟主机的设置:
虚拟主机操作WinDbg软件,连接虚拟测试机的配置:
特别提醒:
1、“Port  Path/Address”  的路径是:/tmp/debugpipe  因为我实际电脑主机是mac系统,所以用 “/” 。如果实际电脑主机是Windows的话,那么 “Port  Path/Address”  的路径类似 \\.\pipe\debugpipe
2、虚拟主机和虚拟测试机中,只要有一个创建pipe文件就行了,另一个直接连上已经存在的pipe文件。[大白话就是两台主机的设置界面的connect to existing pipe/socket 只要有一个勾选上就行了]
3、虚拟主机用WinDbg连接虚拟测试机时,不要勾选pipe。因为之前两台虚拟机都已经配置过外部信息采用pipe形式,所以虚拟主机的外部已经自动变成pipe形式和虚拟测试机进行信息交互了,不用多此一举。所以虚拟主机连接虚拟测试机时,不需要勾选pipe形式。

三、添加符号(Symbols)文件

1、什么是符号文件

https://docs.microsoft.com/zh-cn/windows-hardware/drivers/debugger/symbols-and-symbol-files

大白话:符号symbol文件,包含全局变量,局部变量,行号,函数入口地址等等,所有的这些东西都叫符号。符号是方便显示调试信息的。

When applications, libraries, drivers, or operating systems are linked, the linker that creates the .exe and .dll files also creates a number of additional files known as symbol files.
Symbol files hold a variety of data which are not actually needed when running the binaries, but which could be very useful in the debugging process.
Typically, symbol files might contain:
Global variables
Local variables
Function names and the addresses of their entry points
Frame pointer omission (FPO) records
Source-line numbers
Each of these items is called, individually, a symbol. For example, a single symbol file Myprogram.pdb might contain several hundred symbols, including global variables and function names and hundreds of local variables. Often, software companies release two versions of each symbol file: a full symbol file containing both public symbols and private symbols, and a reduced (stripped) file containing only public symbols. For details, see Public and Private Symbols.
When debugging, you must make sure that the debugger can access the symbol files that are associated with the target you are debugging. Both live debugging and debugging crash dump files require symbols. You must obtain the proper symbols for the code that you wish to debug, and load these symbols into the debugger.
Windows Symbols

Windows keeps its symbols in files with the extension .pdb.

2、设置符号文件夹路径

https://docs.microsoft.com/zh-cn/windows-hardware/drivers/debugger/using-a-symbol-server

原理就是:我们设置一个存放符号文件的本地文件夹,WinDbg 会自动从 微软的符号服务器中下载符号文件,然后存放到刚刚指定的本地文件夹。WinDbg具体调试时,就会利用本地文件夹的符号文件。

具体操作:打开WindDbg,选择File菜单,找到Symbol File Path说明:C:\SysCache 是本地下载symbol的文件夹,http://msdl.microsoft.com/download/symbols 是微软符号服务器。

SRV*C:\SysCache*http://msdl.microsoft.com/download/symbols

四、常见问题和简单操作

1、启动顺序问题

方案2中,因为是两台虚拟机,启动时首先要启动创建pipe的那台虚拟机,然后再启动不创建pipe,只连接pipe的虚拟机。

方案1中,因为主机本身就启动了,所以只要启动虚拟测试机就行了。

注意无论是方案一还是方案二,启动虚拟测试机时,都需要选择debug模式启动项,不要选择正常模式启动项啊。

2、debugee not connected

当在主机或虚拟主机上,打开 WInDbg 软件–>file菜单–>kernel debug 选项时,会出现 debug not connetced  。这个是正常现象。因为第一次需要下载symbol 符号文件,然后呢,要进行内核 debug 的话,还要选择debug菜单,执行break操作,这样子才能 完成 两台机器间的通讯连接。

3、常见KD命令

r cr4
读取控制寄存器cr4的内容

!process 0 0 
命令查看当前系统所有进程信息

!process 0 0 notepad.exe
查看文本编辑器的进程信息  ,举例如下,其中 Dirbase 是内存页目录表的基地址

kd> !process 0 0 notepad.exe PROCESS 81dbd5a8 SessionId: 0 Cid: 0754 Peb: 7ffd7000 ParentCid: 05e0 DirBase: 0f255000 ObjectTable: e14c47d0 HandleCount: 50. Image: notepad.exe


!dd db9e000
查看 db9e000 物理地址的内存 显示二进制内容 (32位格式显示内存信息)

!dq db9e000
查看 db9e000 物理地址的内存 显示二进制内容 (64位格式显示内存信息)

!db db9e000
查看 db9e000 物理地址的内存  显示ascii编码后的内容

 

五、VirtualKD

在这里还可以使用VirtualKD自动设置调试。除了自动化之外,VirtualKD的另一个重要特性是性能提升。VirtualKD承诺将Windows内核调试速度提高45倍,这值得花时间进行投资。

由于我不运行Windows主机,我实际上不会这样做; VirtualKD只能在Windows主机上完成,不支持Linux。但是,您可以在此处找到非常好的步骤:http://virtualkd.sysprogs.org/tutorials/install/

参考链接:

https://resources.infosecinstitute.com/introduction-to-kernel-debugging-with-windbg/#gref

https://reverseengineering.stackexchange.com/questions/11367/kernel-debugging-between-two-virtual-machines-not-working

http://neilscomputerblog.blogspot.com/2011/05/vitualbox-kernel-debugging.html

https://www.cnblogs.com/exclm/p/4097576.html

https://www.tenforums.com/tutorials/5558-windbg-basics-debugging-crash-dumps-windows-10-a.html

https://www.tenforums.com/tutorials/5560-configure-windows-10-create-minidump-bsod.html

坑爹生活反思-博客系统待优化点

1、文章标题支持  自定义 生成。

2、目录与标签的问题,如何利用 自定义标签 生成 自定义目录分类。

3、文章主题问题,生活类文章 和  技术类文章,应该是两种不同的风格和样式,相当于两个网站的风格。

4、关于短文章 和长文章  交织在一起的 布局优化

5、关于 图片 和文章 关联问题,删除文章 自动删除图片

6、博客和电子书阅读体验还是不一样的,如何改进。

7、实模式和保护模式,分段与分页管理。两篇文章即有联系又有区别,分开写,还是合在一起写,有没有一种更好的 内容组织模式。既能体现联系,又能反应区别。

字符编码-用Cheat Engine查看内存线性地址及系统内部编码

Windows操作系统,使用的编码是不是UTF-16

答案:应该是utf-16编码。

实验验证:

  • 新建一个txt文本文档,然后写一段英文字符 比如 helloword,默认保存方式是ANSI也就是常见的ASCII编码。
  • 保存完再重新打开该文档。接着打开Cheat Engine ,选择注入文本编辑器的进程,然后搜索hellword字符串,记得勾选utf-16,找到内存地址后,选择查看内存空间,记住该文本内容存放在内存中的地址是虚拟地址(也叫线性地址),且内存上存放文本内容采用的是utf-16 编码,不再是ANSI编码了。

 

字符编码-windows内部编码探讨用notepad++  查看十六进制代码如下:

字符编码-windows内部编码探讨

字符编码-windows内部编码探讨

字符编码-windows内部编码探讨

这里我们可以看到 hellword 字符串在内存中的虚拟地址(即线性地址)是000B386A


参考文章链接:https://social.microsoft.com/Forums/zh-TW/dc75573f-85c3-47a1-b761-97dda06ee847/windows2580520316319953247965292203512999230340325343072126159199?forum=windowsxpzhchs


windows操作系统区别于大多数其他操作系统的特点之一是,它的大多数内部文本串是以16位宽的Unicode字符来存储和处理的。Unicode(统一的字符编码标准)是一个国际字符集标准,它为世界上绝大多数一直的字符集定义了唯一的16位值(有关Unicode的更多信息,请参考www.unicode.org以及MSDN Library中有关的程序车技文档)
因为许多应用程序只处理8位(单字节)ANSI字符串,所以,接受字符串参数的windows的函数都有两个入口点:一个Unicode(宽字符,16位)和一个ANSI(窄字符,8位)。windows的以下几个版本,即windows95、windows98、windowsME,并没有为所有的windows函数实现Unicode的接口,所有如果所设计的应用程序要考虑到运行在这些操作系统之上,则往往使用窄字符版本。如果你调用一个windows函数的窄字符版本,则输入的字符串参数在被系统处理之前,先转成Unicode,而输出的参数则在被返回给应用程序之前,从Unicode转成ANSI字符串。因此,如果你有一个老的服务程序或者一段代码需要运行在windows上,而这份代码是按照ANSI字符串来编写的,那么windows将把ANSI字符转成Unicode,以便于内部使用。然而,windows永远不会转换文件内部的数据——由应用程序来决定是否要存储为Unicode或者ANIS。
在windows的以前版本中,亚洲和中东版本是美国和欧洲核心版本的一个超集,其中也包含了额外的windows函数,它可以满足处理更加复杂的文本输入和排版需求(比如从右至左的文本输入)。到了windows2000,所有语种的版本都包含同样的windows函数。windows不再使用单独的语言版本,而是有一份全球统一的二进制代码,因此,同一份安装可以支持多种语言(只需求加入各种语言包即可)。应用程序也可以利用这一套windows函数,做到同一份应用程序二进制代码可以支持多种语言!

互联网入门-KB / KiB,MB / MiB,GB / GiB区别

1KiB = 1,024Byte
1MiB = 1,024KiB
1GiB = 1,024MiB = 1,048,576 KiB
1TiB = 1,024GiB = 1,073,741,824 KiB

1KB = 1,000 Byte
1MB = 1,000 KB
1GB = 1,000,000 KB
1TB = 1,000,000,000 KB

  • 其中,KiB是kilo binary byte的缩写,指的是千位二进制字节
  • 而KB是kilobyte的缩写,指的是千字节
  • 说白了就是二进制与十进制的区别,也就是两种标准问题:国际单位制 SI 制定的十进制标准和 国际电工委员会 制定的二进制标准,也就是通常所说的SI和IEC标准。

众 所周知,在计算机中是采用二进制,在电脑世界里,以2的次方数为“批量”处理Byte会方便一些,整齐一些。每1024Byte为1KB,每1024KB为1MB,每1024MB为1GB,每1024GB为1TB。

而在国际单位制中TB、GB、MB、KB是“1000进制”的数,为此国际电工协会(IEC)拟定了”KiB”、“MiB”、“GiB”的二进制单位,专用来标示“1024进位”的数据大小;而硬盘厂商在计算容量方面是以每1000为一进制的,每1000字节为1KB,每1000KB为1MB,每1000MB为1GB,每1000GB为1TB,在操作系统中对容量的计算是以1024为进位的,并且并未改为”KiB”、“MiB”、“GiB”的二进制单位,这差异造成了硬盘容量“缩水”。买硬碟回家的时候是不是常常发现怎么买回去的容量,与真实可用的容量相差了一点点呢?

这是因为厂商、电脑使用的单位不同的缘故,500G硬碟厂商是使用1KB = 1,000 Byte 计算,但是到了电脑会变成 1KiB = 1,024Byte 计算。因此使用厂商的算法500GB = 500,000 MB,而到了电脑500,000 MB / 1024 MiB = 488.28125 GB。

来自:https://www.twblogs.net/a/5b8d73a02b717718833e15b6/zh-cn

内存与调试-Cheat Engine 介绍与教程通关

Cheat Engine 简称 CE ,这是一款开源的内存查看和修改软件。作用如下:

  • 1、可以查看和修改别的软件的内存数据。
  • 2、可以修改别的软件的运行逻辑和过程。(也就是注入汇编代码)

官网:https://www.cheatengine.org/

CE 是英文版的,里面自带了一个新手通关教程,不过是英文的,可能看不懂。嗯,没关系,网上有人翻译了带中文教程的中文版CE。点击此处下载CE免安装中文版

感觉通关教程,难道不是很大。

1、下面两个是教程1-8 的图文解说,这里就不具体写了。
  • https://www.52pojie.cn/thread-833773-1-1.html
  • https://blog.csdn.net/cgs_______/article/details/77799091

但是有一个巨坑要讲一下:就是关卡8(即step8),多级指针的问题:

最后一个基址指针,需要设置多次偏移,才能使得指针能够指向最终的目标地址。内存与调试-Cheat Engine 介绍与教程通关

等最后,操作完成,点击改变指针就能进入第九关了。如果最后一个基址指针不设置多次偏移(offset)的话,就永远过了第8关了。

2、第九关教程,有点难度,可以看这里:

经过实际测试,这个版本的CE关卡9教程,和下面的攻略有稍许不匹配,但基本思路是一样的。教程来自  https://zhuanlan.zhihu.com/p/33702835 。

游戏讲的是,你需要调整游戏内部数据,来使得玩家控制的Dave和Eric打败500血的电脑。正常情况自动执行,玩家的血量会很快归0,so just hack it!

1 找到四个血量的地址

首先,用精确数值扫描的方法,找到Dave的血量地址,注意这个地方血量是单浮点型。

如上图,我找到了两个玩家的血量地址,并设置了描述。

接着,以Dave为例,右击,选择“是什么改写了这个地址”,打开debug窗口,并再次攻击Dave,找到相应的代码,如图

打开:“显示反汇编程序”

右击moves [rbx+08],xmm0,选择,找出指令访问的地址。出现一个新的空白对话框,再次对每个角色攻击一次,结果如图。

可以发现,前两个地址正是Dave和Eric的地址,并且如果你之前用类似的方法找到了两个电脑的地址,正是下面两个。故猜测,运行“攻击”时,程序是依次获得该角色的指针位置,放到rbx寄存器中,然后在offset为08的位置,就是该角色的血量,修改这个血量,即角色受到了攻击。那么,要让Dave和Eric胜出,我们就要让他们血量不减少的同时,找到电脑的血量,并使其减少。

2 分析数据

选中四个地址,右击选中“打开选中的地址分析数据”(control+D)。如图

可以发现,每个角色,除了在基址的前几个地址有数据,别的都是0,仔细贯彻这些数据可以发现,在offset为14的位置,玩家的值为1,电脑的值为2。并且多次攻击发现,这个值为定值。故,我们可以采用这一点来区分玩家与电脑,达成目标。

回到汇编代码的窗口,分析命令moves [rbx+08],xmm0,并结合上面的代码,我们发现下图这样的代码:

显然,这是一个简单的改变[rbx+08]位置值的指令。先将[rbx+08](血量)存储的值放到xmm1中,再减掉一个xmm0,然后在放回去。

故在subss xmm1,xmm0处代码注入。

3 注入代码

打开-内存浏览器-工具-自动汇编

再打开模板-代码注入

如图

代码会注入在原代码的上方,并且原来的代码也会保留。其中newmem,originalcode等,是汇编中的位置标志,可以直接用来跳转。

故在newmem下添加代码如下:

cmp [rbx+14],1 //判断是否是玩家
jne originalcode //不是玩家,直接跳转到原代码执行
addss xmm1,xmm0 //是玩家,将相减改为相加。也可以去掉这一句,即不对玩家血量进行修改
jmp exit //调到exit处

然后点击执行。回到tutorial程序,重启游戏并自动执行,结果如图

至此,解决了CE的最后一个问题,成功通关。

总的来说,CE是一个相当强劲的修改器,用完之后也深深感到制作者设计之精妙,Cheat Engine :: Index 官方论坛里还有更多的奇技淫巧,有兴趣的朋友可以去看看。


3、CE有什么用,答用于内存分析:

1、可以看到Windows 内存中 字符串编码是utf-16 形式。字符编码-用Cheat Engine查看内存线性地址及系统内部编码

2、可以研究内存分页机制 (下面的文章大体OK,但有部分错误)

https://blog.csdn.net/tutucoo/article/details/84729919

https://www.twblogs.net/a/5b83db5d2b71777cb15c6302/zh-cn

互联网入门-shtml,html,xhtml,dtd,xsd,htm的含义与解析

一、Html与Xhtml 的区别与联系

XHTML1.0是“3种HTML 4文件根据XML 1.0标准重组”而成的,W3C推荐标准。

XHTML 1.0 Strict(严格版)是参照“HTML 4.01 Strict”改编,但不包括被弃用的元素。其文件类型描述为:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

XHTML 1.0 Transitional(过渡版)是参照“HTML 4.01 Transitional”改编,包括已于Strict版本被弃用的呈现性元素(例如<center><font>等)。其文件类型描述为:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

XHTML 1.0 Frameset(框架版)是参照“HTML 4.01 Frameset”改编,并允许于网页中定义框架元素。其文件类型描述为:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">

xhtml1.0与html4.01的区别 https://www.w3.org/TR/2002/REC-xhtml1-20020801/#diffs

XHTML是XML的一种应用。基于这一事实,那些在以SGML为基础的HTML 4中,不完全合法的用法,应被改写。

文档应该是结构良好的

良好结构(Well-formed)[3]是由XML[4]引入的一个新概念。也就是说所有的元素都必须有结束标签或者以特殊的方式书写(如下所述),而且所有的标签必须合理地嵌套。

尽管如此,交叉使用在SGML中仍然是合法的,而且在现有的浏览器中也能够被广泛接受。

正确:元素嵌套

<p><em>这是一个要强调的段落。</em></p>
错误:元素交叉

<em><p>这是一个要强调的段落。</em></p>

元素名称和属性必须小写

XHTML文件要求所有的HTML元素名称和属性名称都要小写。因为XML本身大小写意义不同,因此必须区分开来。比如,<li><LI>是完全不同的。

要有结束标签

基于SGML的HTML 4里面,允许特定的标签省略结束标签;这些元素暗含有结束标记。XHTML不允许省略结束标记。所有元素(包括在DTD中声明为空的标签),都必须有结束标签。在DTD中声明为空的元素可以用结束标签或者使用空元素速记法(参见空元素)。

正确的:结束的元素

<p>這是一個段落。</p><p>這是另一個段落。</p>
錯誤的:没有结束的元素

<p>這是一個段落。<p>這是另一個段落。
等等等。。。直接看原文
HTML 4.01和XHTML 1.0之间的相似性导致许多网站和内容管理系统采用最初的W3C XHTML 1.0建议书。为了帮助作者过渡,W3C提供了有关如何以HTML兼容的方式发布XHTML 1.0文档的指导,并将它们提供给非XHTML设计的浏览器。

这种“HTML兼容”内容使用HTML媒体类型(text/html)而不是XHTML(application/xhtml+xml)的官方Internet媒体类型发送。

二、html与htm的区别

没有区别,但因DOS、Windows 95等早期系统采用的8.3命名规则只支持最长3字符的扩展名,为了兼容采用了htm,而linux或者ios都是支持多位扩展名的。

同理还有 jpg与jpeg 的区别。

三、shtml 与html的区别

本质上都属于静态网页一种,html属于纯静态,客户端浏览器读取html文件是什么就呈现给浏览者什么内容。而shtml则可以使用SSI。

SSI是为WEB服务器提供的一套命令,这些命令只要直接嵌入到HTML文档的注释内容之中即可。如:
<!–#include file=”info.htm”–>
就是一条SSI指令,其作用是将”info.htm”的内容拷贝到当前的页面中,当访问者来浏览时,会看到其它HTML文档一样显示info.htm其中的内容。

假如我们A页面是shtml的静态网页,而A页面里我们使用了include包含嵌入B静态html页面,如果你的服务器空间支持Shtml SSI这个时候我们,浏览器打开A页面时候,就会在A页面显示A原本内容以及B页面内容,我们查看网页源代码,不会发现B页面引入痕迹,而是看到B页面内容完全在A页面里。

假如:
1、A shtml页面里内容是:
我包含页面B:<!–#include file=”b.html”–>

2、B html网页内容:
我是B页面内容

3、这个时候浏览器查看A页面HTML源代码:
A shtml页面里内容是:我是B页面内容

这个就是shtml ssi 包含include魅力之处。

其它的SSI指令使用形式基本同刚才的举例差不多,可见SSI使用只是插入一点代码而已,使用形式非常简单。

当然,如果WEB服务器不支持SSI,它就会只不过将它当作注释信息,直接跳过其中的内容;浏览器也会忽略被包含信息,我们可以查看源代码看到include引入注解信息。

四、dtd的含义

经常能够看到dtd,那到底是什么意思呢?(ps,提前剧透一下,现在dtd已经被xsd取代了)

这首先要从xml,说起:下面举例的是早期2.3版本的web.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app id="WebApp_ID">
	<display-name>q</display-name>
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
		<welcome-file>index.htm</welcome-file>
		<welcome-file>index.jsp</welcome-file>
		<welcome-file>default.html</welcome-file>
		<welcome-file>default.htm</welcome-file>
		<welcome-file>default.jsp</welcome-file>
	</welcome-file-list>
</web-app>

第一行是 XML 声明。它定义 XML 的版本 (1.0) 和所使用的编码 (UTF-8)。

下面的是DOCTYPE声明。DOCTYPE是document type(文档类型)的简写,它规定了文档类型,文档类型遵循的协议名,以及文档类型协议的具体定义(也就是DTD,Document Type Definition)

在html中,我们也能看DOCTYPE,比如:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

说白了,dtd就是定义了文件中可以使用哪些标签,以及标签的用法。

所有的 XML 文档(以及 HTML 文档)均由以下简单的构建模块构成:

  • 元素
  • 属性
  • 实体
  • PCDATA
  • CDATA

(DTD就是用来定义这些模块的),dtd教程参考http://www.w3school.com.cn/dtd/index.asp

五、xsd的含义

XML Schema 是基于 XML 的 DTD 替代者。
XML Schema 描述 XML 文档的结构。
XML Schema 语言也称作 XML Schema 定义(XML Schema Definition,XSD)。
参考教程http://www.w3school.com.cn/schema/index.asp

举个例子:3.1新版的web.xml 文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>o2o</display-name>

</web-app>

第一行,没有变化,第二行不再是DOCTYPE了。

先讲xmlns,这个是xml namespace 的含义,也就是 xml 命名空间。
我重新将web.xml的代码编排一下,便于理解。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" 
id="WebApp_ID" version="3.1">
  <display-name>o2o</display-name>

</web-app>xmlns="http://xmlns.jcp.org/xml/ns/javaee"

首先xmlns="http://xmlns.jcp.org/xml/ns/javaee" 代表了整个web.xml的默认命名空间。
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  表示如果标签遇到xsi:xxx的,就以这个http://www.w3.org/2001/XMLSchema-instance命名空间为准。
xsi:schemaLocation 后面跟的是一些列键值对,记录的是 <命名空间,命名空间的定义>

下面是springmvc.xml的配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
		http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">

。。。
</beans>

说明:上述例子中的命名空间xsi调用方法  xsi:schemaLocation或xsi:noNamespaceSchemaLocation 其实就是xsd中对命名空间调用方法进行设置。

这显然是逻辑自恰的,我们在xsd文件中,对命名空间调用一些方法进行设置。那么在xml文件中,自然就可以在命名空间中识别这些设置了。至于xml头中的xsi:schemaLocation,其实也是对命名空间xsi的设置。设置的目的就是将相应的命名空间和xsd文件进行键值对关联。至于xsi的命名空间,因为在本xml文件中,没有用到该命名空间,所以xsi是炮灰,纯粹就是为了让别的命名空间和xsd进行关联。

参考

https://www.w3.org/TR/xmlschema-1/#Instance_Document_Constructions

https://stackoverflow.com/questions/34202967/xmlns-xmlnsxsi-xsischemalocation-and-targetnamespace

 

 

java踩坑-找不到或无法加载主类(Error: Could not find or load main class)

在spring mvc的单元测试中,就是src/test目录下,我写了一个main方法类。这个代码没有任何错误。但是运行时,就报错了。

1、我试着将代码中,添加一行,然后删除一行,保存后,还是报错。

2、我将这个类放到了别的包目录下,单独运行,发现是OK的。

3、我最后将报错的类,改了名字,保存后,发现可以正常运行,没有报错。

4、我将名字又改了回来,这次发现可以正常运行了。

记录一下,奇怪的坑爹。

建站通用-开源富文本编辑器所见即所得wysiwyg-editor

开发博客时,可以集成的 文章编辑器

https://github.com/quilljs/quill

https://github.com/tinymce/

https://github.com/ckeditor/ckeditor5

https://github.com/froala/wysiwyg-editor

其他富文本编辑器:https://segmentfault.com/q/1010000002897384

上面已经回答了,http://simditor.tower.im/,或者kindeditor,ueditor

uEditer 之前用的感觉不是很好。现需要更换,求推荐好用,且兼容性好
比如本站中的富文本编辑器。
主要需求为:能上传图片,排版方便,添加附件。

ckeditor,可以通过js调用他们的API来完成对编辑器的自定义,提供插件也比较丰富。比如可以自定义段落是用p、div或者是br标签来分割?也可以定义内容过滤器指定源码中可以用哪些标签,每个标签允许出现什么属性以及是否允许出现style样式。

官方文档里讲的很详细http://docs.ckeditor.com/ 我最近一直在用,功能很强大,建议下载完整包然后再根据自己的情况定制自己需要的功能。

https://github.com/sofish/pen

SpringMVC-Boot校园商铺-1-搭建maven-web工程并修改动态web版本

一、搭建maven-web工程

1、maven 建项目的时候选择 webapp。然后对话框选择 groupID:就是公司名。artifactID:就是项目名。

2、添加依赖项,比如build path 中 add library –> server runtime

3、在pom.xml中配置jdk编译版本

<build>
<finalName>o2o</finalName>
<plugins>
	<plugin>
		<!-- 指定maven编译的jdk版本,如果不指定,maven3默认用jdk 1.5 maven2默认用jdk1.3 -->
		<groupId>org.apache.maven.plugins</groupId>
		<artifactId>maven-compiler-plugin</artifactId>
		<version>3.6.1</version>
		<configuration>
		   <!-- 一般而言,target与source是保持一致的,但是,有时候为了让程序能在其他版本的jdk中运行(对于低版本目标jdk,源代码中不能使用低版本jdk中不支持的语法),会存在target不同于source的情况 -->                    
			<souce>1.8</souce> <!-- 源代码使用的JDK版本 --> 
			<target>1.8</target><!-- 需要生成的目标class文件的编译版本 -->  
			<encoding>UTF8</encoding><!-- 字符集编码 -->
		</configuration>
	</plugin>
</plugins>
</build>

4、补全工程文件夹和输出位置。maven工程有四个文件夹:

main/resources main/java 编译输出目录:target/classes
test/resources test/java 编译输出目录:target/test-classes
(新创建的test/resources目录,记得要修改一下输出目录)

5、在maven项目中,选中项目右键属性,有个project facets,里面有一个Dynamic web module,将动态网站版本改成3.1。这里eclipse有一个bug,无法修改。需要修改项目文件夹目录,找到.setting隐藏文件夹,编辑文件org.eclipse.wst.common.project.facet.core.xml

<?xml version="1.0" encoding="UTF-8"?>
 <faceted-project> 
<fixed facet="wst.jsdt.web"/> 
<installed facet="java" version="1.7"/> 
<installed facet="jst.web" version="3.1"/> 
<installed facet="wst.jsdt.web" version="1.0"/>
 </faceted-project>

facet=”jst.web” version=”3.1″ 这个2.3值改成3.1后,还需要将web.xml的2.3版本改一下:

<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app> 
<display-name>Archetype Created Web Application</display-name> 
</web-app>

修改成下面这个3.1动态网站版本:

<?xml version="1.0" encoding="UTF-8"?>
 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
 <display-name>Archetype Created Web Application</display-name> 
</web-app>