首先提议:

  如果你是一个很容易遗忘的人,那么一定不要忘记在第一次设置密码的同时创建一张可以恢复Windows XP中的账户密码的启动盘,它可以让你免去格式化硬盘的烦恼。

  从“控制面板”中找到“用户账户”项,选中自己的账户进入如图所示的控制界面,我们可以看到左侧任务列表中有一项“阻止一个已忘记的密码”,点击后便可打开“忘记密码向导”,向导会提示插入一张格式化过的空白磁盘,操作过程中会让你输入该账户所使用的密码,很快便可以创建一张密码重设盘。

  以后,当我们忘记了账户密码的时候,在没有使用“欢迎屏幕”登录方式的情况下登录到Windows XP后,按下“Ctrl + Alt + Del”组合键,出现“Windows 安全”窗口,点击选项中“更改密码”按钮,出现更改密码窗口。这个窗口中,将当前用户的密码备份,点击左下角“备份”按钮,激活“忘记密码向导”,按照提示创建密码重设盘。

  如果在Windows XP的登录窗口输入了错误的密码,就会弹出“登录失败”窗口,如果你的确想不起来自己的密码是什么时,可点击“重设”按钮,启动密码重设向导,通过刚才所创建的密码重设盘,就可以用这张密码重设盘更改密码并启动系统。重新设定密码,登录Windows XP。

  “密码重设盘”的创建,含有一定的危险性,因为任何人都可以使用这一张“密码重设盘”来登录Windows XP,都可以以该用户的名义进入用户帐户,操作真正用户所能操作的一切,所以必须将“密码重设盘”保存在适当的地方,以防丢失或失泄密。

  方法1——利用“administrator”(此方法适用于管理员用户名不是“administrator”的情况)

  我们知道在安装Windows XP过程中,首先是以“administrator”默认登录,然后会要求创建一个新账户,以进入Windows XP时使用此新建账户登录,而且在Windows XP的登录界面中也只会出现创建的这个用户账号,不会出现“administrator”,但实际上该“administrator”账号还是存在的,并且密码为空。

  当我们了解了这一点以后,假如忘记了登录密码的话,在登录界面上,按住Ctrl+Alt键,再按住Del键二次,即可出现经典的登录画面,此时在用户名处键入“administrator”,密码为空进入,然后再修改“zhangbp”的口令即可。

  方法2——删除SAM文件(注意,此法只适用于WIN2000)

  Windows NT/2000/XP中对用户帐户的安全管理使用了安全帐号管理器(Security Account Manager , SAM)的机制,安全帐号管理器对帐号的管理是通过安全标识进行的,安全标识在帐号创建时就同时创建,一旦帐号被删除,安全标识也同时被删。安全标识是唯一的,即使是相同的用户名,在每次创建时获得的安全标识完全不同。因此,一旦某个帐号被用户名重建帐号,也会被赋予不同的安全标识,不会保留原来的权限。安全帐号管理器的具体表现就是%SystemRoot%system32configsam文件。SAM文件是Windows NT/2000/XP的用户帐户数据库,所有用户的登录名以及口令等相关信息都会保存在这个文件中。

  知道了这些,我们的解决办法也产生了:删除SAM文件,启动系统,它会重建一个干净清白的SAM,里面自然没有密码了。

  不过,这么简单的方法在XP是不适用的,可能微软以此为BUG,做了限制……所以现在在XP系统下,即使你删除了SAM,还是不能删除密码,反而会使系统启动初始化出错,从而进入死循环而不能进系统!!

  方法3——从SAM文件中找密码(前提……会使用DOS基本命令就行)

  在系统启动前,插入启动盘,进入:C:WINNTSystem3Config 用COPY命令将SAM文件复制到软盘上。拿到另一台机子读取。这里需要的工具是LC4,运行LC4,打开并新建一个任务,然后依次击“IMPORT→Import from SAM file”,打开已待破解的SAM文件,此时LC4会自动分析此文件,并显示出文件中的用户名;之后点击“Session→Begin Audit”,即可开始破解密码。如果密码不是很复杂的话,很短的时间内就会得到结果。

  不过,如果密码比较复杂的话,需要时间会很长,这时我们就需要用下面的方法了。

  方法4——用其他SAM文件覆盖(前提是你可以得到另外一台电脑的SAM文件和它的密码……个人觉得是最为可行的办法)

  1——如上所说,SAM文件保存着登录名以及口令,那么我们只要替换SAM文件就是替换登录名以及口令了。不过,这个替换用的SAM文件的“产地”硬盘分区格式要和你的系统一样(看是FAT32还是NTFS,你自己确认)。最好这个“产地”的系统没有设密码,安全方面设置没动过(实际上很大部分的个人电脑都是这样),当然,比较保险的方式是把XP的[Win NTSystem 32Config]下的所有文件覆盖到[C:Win NTSystem 32Config]目录中(假设你的XP安装在默认分区C:),

  2——如果得不到别人的帮助(我是说“万一”),你可以在别的分区上在安装一个XP系统,硬盘分区格式要和原来的一样,并且请你注意一定不要和原来的XP安装在同一分区!在开始之前,一定要事先备份引导区MBR,备份MBR的方法有很多,使用工具软件,如杀毒软件KV3000等。装完后用Administrator登陆,现在你对原来的XP就有绝对的写权限了,你可以把原来的SAM考下来,用10PHTCRACK得到原来的密码。也可以把新安装的XP的Win NTSystem 32Config下的所有文件覆盖到C:Win NTSystem 32Config目录中(架设原来的XP安装在这里),然后用KV3000恢复以前悲愤的主引导区MBR,现在你就可以用Administrator身份登陆XP了。

  [2号方案我自己都觉得麻烦,还是1号:叫别人帮忙比较好……]

  【另外,据说C:windows epair 目录下的SAM是原始版本的,可以用它来覆盖 system32下的这个 SAM,这样就可以删除现在的密码,而恢复到刚开始安装系统时的密码了。如果这个密码为空,岂不是…… 】

  方法5——使用Win 2000安装光盘引导修复系统(前提……很明显吧?就是你要有一张Win 2000安装光盘)

  使用Win 2000安装光盘启动电脑,在Wndows2000安装选择界面选择修复Windows 2000(按R键);,然后选择使用故障控制台修复(按C键),系统会扫描现有的Window2000/XP版本。一般只有一个操作系统,所以只列出了一个登录选择(l:C:Windows)。从键盘上按l,然后回车,这个时候,Window XP并没有要求输人管理员密码,而是直接登录进入了故障恢复控制台模式(如果使用的是Windows XP安装光盘启动的,那是要求输人管理员密码的。这里指的管理员是指系统内建的Administraor账户)熟悉Windows的朋友都知道,故障恢复控制台里面可以进行任何系统级别的操作,例如:复制、移动、删除文件,启动、停止服务,甚至格式化、重新分区等破坏性操作。

  测试使用光盘:集成SP3的Windows 2000 Proessional 简体中文版。

  测试通过的系统:Windows XP Proessional,打SPI补丁的Windows XP (FAT32和NTFS文件系统都一样)

  [需要注意的是,由于各种原因,市面上的一些Windows 2000安装光盘不能够显现故障控制台登录选项,所以也无法利用这个漏洞。同时,由于故障控制台模式本身的限制,也无法从网络上利用这个漏洞,换句话说,这个漏洞仅限于单机。]

  方法6——利用NET命令(有两个必要前提才行:按装WINDOWS XP的分区必须采用FAT 32文件小系统,用户名中没有汉字。)

  我们知道在Windows XP中提供了“net user”命令,该命令可以添加、修改用户账户信息,其语法格式为:

  net user [UserName [Password   *] [options]] [/domain]

  net user [UserName {Password   *} /add [options] [/domain]

  net user [UserName [/delete] [/domain]]

  每个参数的具体含义在Windows XP帮助中已做了详细的说明,在此笔者就不多阐述了。好了,我们现在以恢复本地用户“zhangbq”口令为例,来说明解决忘记登录密码的步骤:

  1、重新启动计算机,在启动画面出现后马上按下F8键,选择“带命令行的安全模式”。

  2、运行过程结束时,系统列出了系统超级用户“administrator”和本地用户“zhangbq”的选择菜单,鼠标单击“administrator”,进入命令行模式。

  3、键入命令:“net user zhangbq 123456 /add”,强制将“zhangbq”用户的口令更改为“123456”。若想在此添加一新用户(如:用户名为abcdef,口令为123456)的话,请键入“net user abcdef 123456 /add”,添加后可用“net localgroup administrators abcdef /add”命令将用户提升为系统管理组“administrators”的用户,并使其具有超级权限。

  4、重新启动计算机,选择正常模式下运行,就可以用更改后的口令“123456”登录“zhangbq”用户了。另外,zhangbq 进入 登入後在〔控制台〕→〔使用者帐户〕→选忘记密码的用户,然後选〔移除密码〕後〔等出〕 在登入画面中选原来的用户便可不需密码情况下等入 (因已移除了) 删除刚才新增的用户,在〔控制台〕→〔使用者帐户〕→选〔alanhkg888〕,然後选〔移除帐户〕便可

  [但是有人提出:在实验后得知——在安全模式命令符下新建的用户不能进入正常模式(此结论暂不确认)]

  方法7——用破解密码软件(前提是你要有标准的系统安装光盘——不是那种“集成”多个系统的D版盘)

  1——使用PASSWARE KIT 5.0中的Windows KEY 5.0,用于恢复系统管理员的密码,运行后生成3个文件:TXTSETUP.OEM、WINKEY.SYS和WINKEY.INF,3个文件共50KB。把这3个文件放在任何软盘中,然后使用XP安装光盘启动电脑,启动过程中按F6键让系统采用第三方驱动程序。此时,正是我们切入的最好时机,放入该软盘就会自动跳到Windows KEY的界面。他会强行把ADMINISTRATOR的密码换成12345,如此一来何愁大事不成?嗬嗬!当你重新启动以后,你会被要求再次修改你的密码。

  2——使用OFFICE NT PASSWORD & REGISTRY EDITOR.用该软件可以制作LINUX启动盘,这个启动盘可以访问NTFS文件系统,因此可以很好地支持Windows 2000/XP。使用该软盘中的一个运行在LINUX下的工具NTPASSWD就可以解决问题,并且可以读取注册表并重写账号。使用方法很简单,只需根据其启动后的提示一步一步做就可以了。在此,建议你使用快速模式,这样会列出用户供你选择修改那个用户密码。默认选择ADMIN组用户,自动找到把ADMINISTRATOR的名字换掉的用户,十分方便。

  3——ERD.Commander2003为Windows的管理员和最终用户,面对随时可能崩溃的系统,可能每人都会有自己的一套工具,用来挽救数据和修复系统。ERD Commander这可以算是Winternals Administrators Pak工具中最强大的组件了,其中一个引人注目的功能就是修改密码,Windows NT/2000/XP/2003 系统中任何一个用户的密码都可以在不知道原先密码的情况下被ERD修改掉。

  方法8——修改屏幕保护程序(前提是你有设置屏保)

  使用NTFSDOS这个可以从DOS下写NTFS分区的工具。用该软件制作一个DOS启动盘,然后到C:Win NTSystem 32下将屏幕保护程序Logon.Scr改名,接着拷贝Command.com到C:Win NTSystem 32下(WIN2000下可以用CMD.EXE),并将该文件改名为Logon.Scr。这样启动机器15分钟以后,本该出现的屏幕保护现在变成了命令行模式,而且是具有ADMINISTRATOR权限的,通过他就可以修改密码或者添加新的管理员账号了。改完以后不要忘了把屏幕保护程序的名字改回去。

  方法9——使用启动脚本(前提……会使用DOS基本命令就行)

  Windows XP启动脚本(startup scripts)是计算机在登录屏幕出现之前运行的批处理文件,它的功能类似于Windows 9×和DOS中的自动执行批处理文件autoexec.bat。利用这个特性,可以编写一个批处理文件重新设置用户密码,并将它加入启动脚本中,这样就达到了目的。以下是具体步骤(假设系统目录为C:Windows)。

  1.使用Windows98启动盘启动电脑。在DOS下新建一个文件叫a.bat,内容只需要一条“net user”命令即可:“Net user rwd 12345678”。这条命令的意思是将用户rwd的密码设置为“12345678”(有关Net命令的用法,可参考Windows帮助)。然后将文件a.bat保存到“C:windowssystem32GroupPolicyMachineScriptsStartup”下。

  2.编写一个启动/关机脚本配置文件scripts.ini,这个文件名是固定的,不能改变。内容如下:

  [Startup]

  0CmdLine=a.bat

  0Parameters=

  3.将文件scripts.ini保存到“C:winntsystem32GroupPolicyMachineScripts”下。scripts.ini保存着计算机启动/关机脚本的设置数据,文件内容通常包含两个数据段:[Startup]和[Shutdown]。[Startup]数据段下是启动脚本配置,[Shutdown]数据段下是关机脚本配置。每个脚本条目被分成脚本名和脚本参数两部分存储,脚本名保存在XCmdLine关键字下,参数保存在XParameters关键字下,这里的X表示从0开始的脚本序号,以区别多个脚本条目和标志各脚本条目的运行顺序。

  4.取出Windows 98启动盘,重新启动电脑,等待启动脚本运行。启动脚本运行结束后用户rwd的密码就被恢复为“12345678”。

  5.登录成功后删除上述步骤建立的两个文件。

  [实际上你可以借用另一台电脑用“记事本”编写a.bat和scripts.ini,再用软盘通过DOS复制到自己的电脑上]

  说明:

  以上脚本使用的是FAT32文件系统,如果使用NTFS文件系统,可以将这块硬盘以从盘模式挂接到其它能识别NTFS文件系统(如Windows 2000或Windows XP)的计算机上进行上述操作。本方法可以恢复管理员(Administrator)的密码。对Windows2000系统中本地计算机用户和域用户的密码恢复同样有效。

  数据库命令执行时使用Command对象。Command类有三种:SqlCommand、OleDbCommand与OdbcCommand。

  Command对象主要用来运行SELECT、INSERT、UPDATE或DELETE之类的SQL语句。Command对象还可以调用存储过程或从特定表中取得记录。

  DataReader对象主要是用来读取数据结果,使用它读取记录时通常比从DataSet更快。DataReader类有三种:SqlDataReader、OleDbDataReader和OdbcDataReader。DataReader对象用Commmand对象从数据库中读取记录,并且DataReader对象只能向前的读取记录,用于在某些情况下替代DataSet对象(DataSet对象可以存储数据库中的行拷贝,可以在切断数据库的连接时处理这个拷贝,我们将在以后的章节中详细介绍该对象)。

  注意:不能用DataReader修改数据库中的记录,它是采用向前的,只读的方式读取数据库。

  SqlCommand类

  SqlCommand对象用于对Sql Server数据库执行命令。OleDbCommand对象用于对支持OleDb的数据库执行命令,如Oracle与Access。OdbcCommand对象用于对支持Odbc的数据库执行命令。尽管SqlCommand类是针对Sql Server的,但是这个类的许多属性、方法与事件和OleDbCommand及OdbcCommand等类相似。本章将重点讲解SqlCommand特定的属性与方法,其他的Command类你可以参考相应的帮助文档。

  注意:使用不同的Command对象需要导入不同的命名空间。OleDbCommand的命名空间为System.Data.OleDb。SqlCommand的命名空间为System.Data.SqlClient。OdbcCommand的命名空间为System.Data.Odbc。

  SqlCommand属性:

属性 说明
CommandText 其返回类型为string, 获取或设置要对数据源执行的 SQL 语句、存储过程或表。
CommandTimeOut 其返回类型为int,获取或设置在终止执行命令的尝试并生成错误之前的等待时间。
CommandType 其返回类型为CommandType,读取或设置表示CommandText属性将如何被解释的值,其有效的值可以为CommandType.Text、CommandType.StoredProcedur与CommandType.TableDirect,分别表示SQL语句、存储过程调用或要读取的表,默认为Text。
Connection 其返回类型为string, 获取或设置 SqlCommand 的此实例使用的 SqlConnection。
Parameters 其返回类型为SqlParameterCollection,取得提供给命令的参数(如有)。

  SqlCommand方法:

方法 说明
Cancle() 其返回类型为void,取消命令的执行
CreateParameter() 其返回类型为SqlParameter, 用于创建 SqlParameter 对象的新实例。
ExecuteNonQuery() 其返回类型为int,执行不返回结果集的Sql语句,包括INSERT、UPDATE与DELETE语句、DDL语句和不返回结果集的存储过程调用。返回的int值是命令影响的数据库行数。
ExecuteReader() 其返回类型为SqlDataReader, 执行SELECT语句、TableDirect命令或返回结果集的存储过程调用。在SqlDataReader对象中返回结果集。
ExecuteScalar() 其返回类型为object,执行返回单个值的SELECT语句(任何其他的值将被忽略)。这个命令结果作为对象被返回。
ExecuteXmlReader() 其返回类型为XmlReader,执行返回XML数据的SELECT语句,用XmlReader对象返回结果集,只适用于SqlCommand类

 

      生成SqlCommand对象

  我们可以用构造函数生成SqlCommand对象,也可以调用SqlConnection对象的CreateCommand()方法生成SqlCommand对象,下面分别介绍这两种方法。

  用构造函数生成SqlCommand对象

  SqlCommand对象的构造函数如下所示:

SqlCommand()
SqlCommand(string commandText)
SqlCommand(string commandText,SqlConnection mySqlConnection)

  程序代码说明:在上述语法范例的程序代码中,commandText包含SQL语句、存储过程调用或要读取的表。mySqlConnection是对应的SqlConnection对象。

  在使用SqlCommand对象之前,首先要确定一个SqlConnection对象,用于和SQL Server数据库进行数据传递。

mySqlConnection.ConnectionString="server=localhost;database=Northwind;
integrated security=SSPI";

  然后可以用下列语句生成新的SqlCommand对象:

SqlCommand mySqlCommand=new SqlCommand();

  再将mySqlCommand对象的Connection属性设置为mySqlConnection:

mySqlCommand.Connection= mySqlConnection;

  这样mySqlCommand对象就可以使用mySqlConnection与数据库进行数据传递。现在,Command对象的CommandType属性确定要执行的命令类型。可以用System.Data.CommandType枚举值指定CommandType属性。
CommandType的枚举值如下表所示:

数值 说明
Text 表示命令是SQL语句,默认值是Text
StoredProcedure 表示命令是储存过程调用
TableDirect 表示被读取的行和列的表名。注意:SqlCommand对象不支持TableDirect,要使用其他的Command类的对象。

  例如你可以采用如下的形式执行一个SQL查询:

SqlCommand mySqlCommand=new SqlCommand();
mySqlCommand.Connection=mySqlConnection;
mySqlCommand.CommandText=”SELECT * FROM Employees”;
//mySqlCommand.CommandType=CommandType.Text;

  程序代码说明:在上述语法范例的程序代码中,我们设置了mySqlCommand对象的commandText为一个SELECT查询语句,并且指定了mySqlCommand对象的CommandType属性为CommandType.Text,表示命令是SQL语句。由于CommandType.Text是默认的CommandType值,所以我们可以将其注译掉。

  还有一个更具效率的形式,那就是使用SqlCommand对象的其中一种构造函数:

SqlCommand mySqlCommand=new SqlCommand(”SELECT * FROM Employees”,myConnection);

  程序代码说明:在上述语法范例的程序代码中,我们可以直接利用SqlCommand(string commandText,SqlConnection mySqlConnection) 构造函数,从而使得程序代码更加的简练和直观。

  还可以使用储存过程来查询所需要的数据,我们可以采用如下的代码形式:

SqlCommand mySqlCommand=new SqlCommand(”GetEmpolyees”,myConnection);
mySqlCommand.CommandType=CommandType.StoredProcedure;

  程序代码说明:在上述语法范例的程序代码中,GetEmpolyees为一个储存过程名,用来实现所有的雇员信息查询。并且将CommandType值指定为StoredProcedure,表示命令是储存过程调用。

  使用CreateCommand()方法生成SqlCommand对象

  如果不用构造函数,也可以使用SqlConnection对象的CreateCommand()方法生成SqlCommand对象。这个方法返回新的SqlCommand对象。例如:

SqlCommand mySqlCommand=mySqlConnection.CreateCommand();

SqlDataReader类

  可以用SqlDataReader类对象从SQL Server数据库中读取行;用OleDbDataReader类对象从支持OLE DB的数据库中读行,如Oracle与Access;用OdbcDataReader类对象从支持ODBC的数据库中读取行。

  DataReader对象允许你以向前的,只读的方式读取数据,有时候DataReader对象也称为消软管游标。DataReader对象采用了一种简化的数据读取方式,但是提高了性能的同时也牺牲了很多特性。例如在DataSet中支持的排序,分页等功能。这些功能将在以后的章节进行详细的介绍。

  SqlDataReader的属性

属性 说明
Depth 其返回类型为int,取得表示当前行嵌入深度的值
FieldCount 其返回类型为int,取得当前行的列数
IsColsed 其返回类型为bool,取得一个布尔值,表示是否关闭数据读取
RecordsAffected 其返回类型为int, 取得执行SQL语句增加、修改或删除的行数。

  SqlDataReader的方法

方法 说明
Reader() 其返回类型为bool,将数据阅读器移到结果集的下一行并读取该行。这个方法返回的布尔值表示结果集中是否有多行
GetValue() 其返回类型为object, 返回指定列的值
GetValues() 其返回类型为int,将当前行中所有列的值复制到指定对象数组。这个方法返回的int是数组元素的个数
NextResult() 其返回类型为bool,将数据阅读器移到结果集的下一行。这个方法返回的布尔值表示结果集中是否有多行
Close() 关闭 SqlDataReader 对象
GetInt32(),GetChar(),
GateDataTime(),Get×××()
返回指定列的值,并且返回的类型为相应的数据类型。例如GetInt32()返回整型的数值。注意,如果你将返回值赋予一个类型不匹配的变量时,将会抛出一个InvalidCastException异常

   用ExecuteReader()方法执行查询

  下面是一个用ExecuteReader()方法执行SELECT语句的范例。这个方法用DataReader对象返回结果集,然后可以用此对象读取数据库返回的行。

  范例程序代码如下:

01 public partial class _Default : System.Web.UI.Page
02 {
03  protected void Page_Load(object sender, EventArgs e)
04  {
05   string connectionString =
06 ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString;
07   SqlConnection con = new SqlConnection(connectionString);
08   string sql = "SELECT top 5 CustomerID,CompanyName,ContactName,Address
09          FROM Customers";
10   SqlCommand cmd = new SqlCommand(sql, con);
11   con.Open();
12   SqlDataReader reader = cmd.ExecuteReader();
13   StringBuilder htmlStr = new StringBuilder("");
14   while (reader.Read())
15   {
16    htmlStr.Append("CustomerID:" + reader["CustomerID"] + "<br>");
17    htmlStr.Append("CompanyName:" + reader["CompanyName"] + "<br>");
18    htmlStr.Append("ContactName:" + reader.GetString(2) + "<br>");
19    htmlStr.Append("Address:" + reader.GetString(3) + "<br>");
20    htmlStr.Append("<hr>");
21   }
22   reader.Close();
23   con.Close();
24   HtmlContent.Text = htmlStr.ToString();
25  }
26 }

  程序代码说明:在上述语法范例的程序代码中,第5到12行代码生成所要的对象并执行SELECT语句,从Customers表中读取前5条记录。cmd返回的结果集存放在reader对象中,然后你可以用Reader()方法读取reader对象的记录。这个方法在有另一个可读的行时返回布尔真值,否则返回布尔假值。可以从reader对象中读取一个记录的各个列值,只要在方括号中传入列名即可。如第16和17行所示,我们用reader[“CustomerID”]读取CustomerID列的各项内容。你也可以直接在方括号中传入数字值指定想要列的索引。如第18和19行代码所显示,由于我们在用SELECT进行数据查询的时,ContactName和Address分别位于第3和第4列,而相应的索引值则为2和3,所以我们可以用reader.GetString(2)和reader.GetString(3)读取ContactName和Address列的数据。如第14行代码所示,我们可以在While循环中用Reader()方法一一读取每条记录。

  执行结果:

附件:wrx298kd8j.png(11780 Byte)

      每次程序执行命令时,都要将相应的命令通过网络传递到数据库中,并在数据库进行执行,然后将结果返回到程序中,从而产生大量的网络通信流。我们可以使用ExecuteReader()方法同时执行多条SELECT语句查询减少重复的数据传递。

  下面的实例是使用ExecuteReader()方法同时查询三个表中的数据,并将返回的三个结果集显示在页面上。

  范例程序代码如下:

01 public partial class _Default : System.Web.UI.Page
02 {
03  protected void Page_Load(object sender, EventArgs e)
04  {
05   string connectionString =
06 ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString;
07   SqlConnection con = new SqlConnection(connectionString);
08   SqlCommand cmd = con.CreateCommand();
09   cmd.CommandText = "SELECT TOP 3 ProductID,ProductName
10   FROM Products ORDER BY ProductID;" +
11    "SELECT TOP 3 CustomerID,CompanyName
12    FROM Customers ORDER BY CustomerID;" +
13     "SELECT TOP 3 OrderID,CustomerID
14     FROM Orders ORDER BY OrderID;";
15   con.Open();
16   SqlDataReader reader = cmd.ExecuteReader();
17   StringBuilder htmStr=new StringBuilder("");
18   int i = 0;
19   do
20   {
21    htmStr.Append("结果集");
22    htmStr.Append(i.ToString());
23    htmStr.Append("<br>");
24    while (reader.Read())
25    {
26     htmStr.Append("reader[0]=" + reader[0]);
27     htmStr.Append("<br>");
28     htmStr.Append("reader[1]=" + reader[1]);
29     htmStr.Append("<br><br>");
30    }
31    htmStr.Append("<hr>");
32    i++;
33   } while (reader.NextResult());
34   reader.Close();
35   con.Close();
36   HtmlContent.Text = htmStr.ToString();
37  }
38 }

  程序代码说明:在上述语法范例的程序代码中,第9行到第14中定义了3个查询语句,各语句之间用分号进行间隔。第16行调用ExecuteReader()方法,并返回SqlDataReader对象,并且对三条不同的SELECT语句各返回一个结果集。要读取第一个结果集的话,可以用SqlDataReader对象的Reader()方法。Reader()方法在没有其他的可读行时将返回一个false值。当一个结果集的所有记录都读取完毕后,可以调用SqlDataReader对象的NextResult()方法,然后在读取下一个结果集,在没有其他的结果集时,也返回一个false值。

  提示:外循环do…while测试结尾的reader. NextResult()的返回值。由于do…while循环末尾检测这个条件,这样就保证了do…while循环至少执行一次。之所以在末尾才调用NextResult()方法,是因为这样可以首先把SqlDataReader对象移到下一个结果集,然后才返回表示是否还有下一个结果集的布尔结果。如果使用while循环中,则有可能直接跳过第一个结果集,从而产生错误。

81d4kg6g51.png

    用ExecuteScalar()方法执行SELECT语句

  用ExecuteScalar()方法执行SELECT语句,返回单个值,并且忽略其他的任何读取的结果。ExecuteScalar()方法返回的结果是一个object对象。ExecuteScalar()主要是用来执行SELECT语句,或者执行包括聚合函数的SQL语句。

  下面我们将使用如下的程序读取Products表中的记录条数,并且在相应的查询语句中使用COUNT()聚合函数。

  范例程序代码如下:

01 public partial class _Default : System.Web.UI.Page
02 {
03  protected void Page_Load(object sender, EventArgs e)
04  {
05   string connectionString =
06    ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString;
07   SqlConnection con = new SqlConnection(connectionString);
08   SqlCommand cmd = con.CreateCommand();
09   cmd.CommandText = "SELECT COUNT(*) FROM Products";
10   con.Open();
11   int returnValue = (int)cmd.ExecuteScalar();
12   HtmlContent.Text = "Products表中共有" + returnValue.ToString()+"条记录";
13  }
14 }

  程序代码说明:在上述语法范例的程序代码中,第9行即为查询Products表中的记录条数的SQL语句。第11行代码用ExecuteScalar()方法执行SELECT语句。注意,由于ExecuteScalar()方法的结果为object对象,因此我们要将其进行强制类型转换,再赋予相应的变量。

  执行结果:

3iw32u28xs.png

  我们经常会遇到批量上传的问题,也会遇到将某个目录下所有文件都上传到服务器上的问题。那么,如何解决此类问题呢?以前的技术一般采用ActiveX等方式,这里笔者采用SharpZlib来实现,听说VS2005已有压缩和解压缩的解决方案,笔者还没有时间用VS2005,所以就只好使用VS2003 + SharpZlib来解决问题了。

  1、首先从这里下载0.84版本的SharpZlib源码及示例码。
  2、下载下来之后你发现它没有VS2003的解决方案文件,没有关系。你可以自己建立,首先新建一个ZipUnzip的解决方案,然后,将上面经过解压缩之后的所有文件及目录COPY到你的解决方案所在的目录下。
  3、在VS2003解决方案资源管理器(一般是在右上方中部点的位置)中点击显示所有文件按钮,然后可以见到很多“虚”的图标、文件及文件夹等,可以一次选择它们,然后包含进项目中。
  4、编译,最好使用Release选项,编译完成之后你可以在inRelease看到ZipUnzip.dll的类了。如果你编译时报错,说什么AssemblyKeyFile之类的,你可以使用强命名工具新建一个,也可以将AssemblyInfo.cs中[assembly: AssemblyKeyFile("。。。。。")]改成:[assembly: AssemblyKeyFile("")] (不推荐这样做)。
  5、新建一个WEBFORM项目,添加ZipUnzip.dll类的引用,然后添加如下文件及内容:

// ——————————————
// 1. AttachmentUnZip.cs
// ——————————————
using System;
using System.IO;
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode.SharpZipLib.BZip2;
using ICSharpCode.SharpZipLib.Checksums;
using ICSharpCode.SharpZipLib.Zip.Compression;
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;

namespace WebZipUnzip
{
public class AttachmentUnZip
{
public AttachmentUnZip()
{
}
public static void UpZip(string zipFile)
{
string []FileProperties=new string[2];
FileProperties[0]=zipFile;//待解压的文件
FileProperties[1]=zipFile.Substring(0,zipFile.LastIndexOf("\")+1);//解压后放置的目标目录
UnZipClass UnZc=new UnZipClass();
UnZc.UnZip(FileProperties);
}
}
}

// ———————————————
// 2. UnZipClass.cs
// ———————————————

using System;
using System.IO;
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode.SharpZipLib.BZip2;
using ICSharpCode.SharpZipLib.Checksums;
using ICSharpCode.SharpZipLib.Zip.Compression;
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;

namespace WebZipUnzip
{
public class UnZipClass
{
///
/// 解压文件
///
/// 包含要解压的文件名和要解压到的目录名数组
public void UnZip(string[] args)
{
ZipInputStream s = new ZipInputStream(File.OpenRead(args[0]));
try
{
ZipEntry theEntry;
while ((theEntry = s.GetNextEntry()) != null)
{
string directoryName = Path.GetDirectoryName(args[1]);
string fileName = Path.GetFileName(theEntry.Name);

//生成解压目录
Directory.CreateDirectory(directoryName);

if (fileName != String.Empty)
{
//解压文件到指定的目录
FileStream streamWriter = File.Create(args[1]+fileName);

int size = 2048;
byte[] data = new byte[2048];
while (true)
{
size = s.Read(data, 0, data.Length);
if (size > 0)
{
streamWriter.Write(data, 0, size);
}
else
{
break;
}
}

streamWriter.Close();
}
}
s.Close();
}
catch(Exception eu)
{
throw eu;
}
finally
{
s.Close();
}

}//end UnZip
public static bool UnZipFile(string file, string dir)
{
try
{
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
string fileFullName = Path.Combine(dir,file);
ZipInputStream s = new ZipInputStream(File.OpenRead( fileFullName ));

ZipEntry theEntry;
while ((theEntry = s.GetNextEntry()) != null)
{
string directoryName = Path.GetDirectoryName(theEntry.Name);
string fileName = Path.GetFileName(theEntry.Name);

if (directoryName != String.Empty)
Directory.CreateDirectory( Path.Combine(dir, directoryName));

if (fileName != String.Empty)
{
FileStream streamWriter = File.Create( Path.Combine(dir,theEntry.Name) );
int size = 2048;
byte[] data = new byte[2048];
while (true)
{
size = s.Read(data, 0, data.Length);
if (size > 0)
{
streamWriter.Write(data, 0, size);
}
else
{
break;
}
}

streamWriter.Close();
}
}
s.Close();
return true;
}
catch (Exception)
{
throw;
}
}

}//end UnZipClass
}
// ———————————————-
// 3. ZipClass.cs
// ———————————————-
using System;
using System.IO;
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode.SharpZipLib.BZip2;
using ICSharpCode.SharpZipLib.Checksums;
using ICSharpCode.SharpZipLib.Zip.Compression;
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;

namespace WebZipUnzip
{
///
/// 压缩文件
///
public class ZipClass
{
public void ZipFile(string FileToZip, string ZipedFile ,int CompressionLevel, int BlockSize,string password)
{
//如果文件没有找到,则报错
if (! System.IO.File.Exists(FileToZip))
{
throw new System.IO.FileNotFoundException("The specified file " + FileToZip + " could not be found. Zipping aborderd");
}

System.IO.FileStream StreamToZip = new System.IO.FileStream(FileToZip,System.IO.FileMode.Open , System.IO.FileAccess.Read);
System.IO.FileStream ZipFile = System.IO.File.Create(ZipedFile);
ZipOutputStream ZipStream = new ZipOutputStream(ZipFile);
ZipEntry ZipEntry = new ZipEntry("ZippedFile");
ZipStream.PutNextEntry(ZipEntry);
ZipStream.SetLevel(CompressionLevel);
byte[] buffer = new byte[BlockSize];
System.Int32 size =StreamToZip.Read(buffer,0,buffer.Length);
ZipStream.Write(buffer,0,size);
try
{
while (size < StreamToZip.Length)
{
int sizeRead =StreamToZip.Read(buffer,0,buffer.Length);
ZipStream.Write(buffer,0,sizeRead);
size += sizeRead;
}
}
catch(System.Exception ex)
{
throw ex;
}
ZipStream.Finish();
ZipStream.Close();
StreamToZip.Close();
}
public void ZipFileMain(string[] args)
{
//string[] filenames = Directory.GetFiles(args[0]);
string[] filenames = new string[]{args[0]};

Crc32 crc = new Crc32();
ZipOutputStream s = new ZipOutputStream(File.Create(args[1]));

s.SetLevel(6); // 0 – store only to 9 – means best compression

foreach (string file in filenames)
{
//打开压缩文件
FileStream fs = File.OpenRead(file);
byte[] buffer = new byte[fs.Length];
fs.Read(buffer, 0, buffer.Length);
ZipEntry entry = new ZipEntry(file);

entry.DateTime = DateTime.Now;

// set Size and the crc, because the information
// about the size and crc should be stored in the header
// if it is not set it is automatically written in the footer.
// (in this case size == crc == -1 in the header)
// Some ZIP programs have problems with zip files that don‘t store
// the size and crc in the header.
entry.Size = fs.Length;
fs.Close();

crc.Reset();
crc.Update(buffer);

entry.Crc = crc.Value;

s.PutNextEntry(entry);

s.Write(buffer, 0, buffer.Length);

}
s.Finish();
s.Close();
}
}
}
// ———————————————
// 4. WebForm1.aspx
// ———————————————
<%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="WebZipUnzip.WebForm1" %>&nbsp;
<META content="Microsoft Visual Studio .NET 7.1" name=GENERATOR>
<META content=C# name=CODE_LANGUAGE>
<META content=JavaScript name=vs_defaultClientScript>
<META content=http://schemas.microsoft.com/intellisense/ie5 name=vs_targetSchema>
<FORM id=Form1 method=post runat="server"><?xml:namespace prefix = asp /><asp:Button id=Button1 style="Z-INDEX: 101; LEFT: 56px; POSITION: absolute; TOP: 64px" runat="server" Text="压缩"></asp:Button><asp:Button id=Button2 style="Z-INDEX: 102; LEFT: 112px; POSITION: absolute; TOP: 64px" runat="server" Text="解压"></asp:Button><INPUT id=File1 style="Z-INDEX: 103; LEFT: 32px; POSITION: absolute; TOP: 24px" type=file name=File1 runat="server"> </FORM></BODY></HTML>
//——————————————-
// 5.WebForm1.aspx.cs
//——————————————-

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace WebZipUnzip
{
///
/// Summary description for WebForm1.
///
public class WebForm1 : System.Web.UI.Page
{
protected System.Web.UI.WebControls.Button Button1;
protected System.Web.UI.HtmlControls.HtmlInputFile File1;
protected System.Web.UI.WebControls.Button Button2;

private void Page_Load(object sender, System.EventArgs e)
{
// Put user code to initialize the page here
}

#region Web Form Designer generated code
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: This call is required by the ASP.NET Web Form Designer.
//
InitializeComponent();
base.OnInit(e);
}

///
/// Required method for Designer support – do not modify
/// the contents of this method with the code editor.
///
private void InitializeComponent()
{
this.Button1.Click += new System.EventHandler(this.Button1_Click);
this.Button2.Click += new System.EventHandler(this.Button2_Click);
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion

#region 压缩
private void Button1_Click(object sender, System.EventArgs e)
{
string []FileProperties=new string[2];
string fullName=this.File1.PostedFile.FileName;//C: esta.txt
string destPath=System.IO.Path.GetDirectoryName(fullName);//C: est
//待压缩文件
FileProperties[0]=fullName;

//压缩后的目标文件
FileProperties[1]= destPath +"\"+ System.IO.Path.GetFileNameWithoutExtension(fullName) + ".zip";
ZipClass Zc=new ZipClass();
Zc.ZipFileMain(FileProperties);

//删除压缩前的文件
System.IO.File.Delete(fullName);
}

#endregion

#region 解压
private void Button2_Click(object sender, System.EventArgs e)
{
string fullName=this.File1.PostedFile.FileName;//C: esta.zip
//解压文件
//AttachmentUnZip.UpZip(fullName);

// string[] FileProperties = new string[2];
// FileProperties[0] = fullName;//待解压的文件
// FileProperties[1] = System.IO.Path.GetDirectoryName(fullName);//解压后放置的目标目录
// UnZipClass UnZc=new UnZipClass();
// UnZc.UnZip(FileProperties);
string dir = System.IO.Path.GetDirectoryName(fullName);
string fileName = System.IO.Path.GetFileName(fullName);
UnZipClass.UnZipFile(fileName, dir);
}
#endregion
}
}
  OK! 试试看。

  此方案解决了文件名中文字的问题,目录解压缩问题。
  至于整个文件夹批量上传并压缩成一个WINZIP压缩包的问题,没有时间解决了,各位如有解决方案,不妨共享一下。

  为什么使用Google扫描安全漏洞

  如果你正在执行信息安全评估――渗入测试、漏洞评估,或者范围更广的黑客测试――你就不能没有一个相应的测试工具。虽然对于一个网站来说,此类工具很难找,但Google(是的,www.google.com)还是一个你可以使用的,能够测试Windows系统安全漏洞的最热工具中的其中之一。假设它的功能和力量能够被用来攻击你,那么在对你的恶意攻击之前,这是一个让你知道自己系统漏洞,并采取相应保护措施的好工具。

  除了能够用Google做你能做的事情之外,它的最大优势之一就是不存在价格上的问题。Google被认为是穷人的安全评估工具,或者是为那些很少,甚至没有IT预算的安全管理员(即几乎所有的人)提供的工具。我个人是商业安全评估工具的大力提倡者,它们有助于提供更加详尽的测试项目、优良的报告能力和其它可以使你的评估工作更加容易的工具。然而,“花多少钱办多少事”,有时和它们并不相符。Google能够提供像黑客一样的眼睛,做你想像不到的事情,或者能够做任何安全测试工具(包括商业软件、免费软件或开源软件)能够做的事情,而这一切都是免费的!

  和许多外部测试工具一样,Google能够看到当前你为网络世界提供的服务。并且,它能够搜集、缓存、寻找和挖掘那些对你来说并不是很新的信息,或者在你不知道的情况下放上互联网的内容。在执行安全评估查询方面,你可以有几个选择,在Google的首页,高级搜索页面,甚至使用Google API写一个你自己的Web应用程序。

  当在你的系统上执行信息安全测试时,你最想做的就使像黑客一样进行查看,这也是Google最为擅长的。这里是一些进行黑客测试时Google能够找到的信息的例子:

  1.信用卡信息(credit card information)、社会安全号(social security number)和其它公众可以通过Web应用程序和数据库访问的机密信息。

  2.网络摄像头。

  3.文字处理文档、电子表格和演示文稿文件。

  4.Outlook Web Access相关的文件。

  5.默认的(通常是不安全的)IIS文件和自定义的ISS错误信息。

  6.本想隐藏的Web登录页面。

  7.进行不属于你的网络的主机欺诈。

  8.包含敏感信息的新闻组帖子。

  以上述的最后一个为例,当在Google Groups中执行一个基本的查询时,我看到了一个我认识的电信供应商的支持组信息,它是由供应商的网络管理员发表的。那个帖子泄漏了供应商内部网络的详细配置,包括网络布局、内网IP地址和主机名。它显露出的这么多信息给我的第一感觉是,我不应该信息那个公司,并将自己企业的敏感信息交给他们。我使用公司的名称和几个关键词,执行简单的搜索就找到了这些信息,若是使用Google的高级搜索,还不知道能够找到多少信息呢!

  在今天高价漏洞评估工具的世界里,Google是一阵清新的空气,它的安全测试查询是无敌的!作为一个安全漏洞检测的顶级人士,你不仅需要像黑客一样进行工作,还需要有创新的测试方法,Google无疑就是这样一款工具,他允许你进行这样的工作。

  在不久的将来,我将向你讲述使用真实的Google查询测试你的Windows系统的安全,这将帮助你确定自己的Windows系统是否足够健壮。

  用Google工具自动执行黑客测试

  已经有多种Google工具能够自动执行黑客测试,或者增强Google黑客测试的能力,它们包括:

  ·Johnny Long的Google Hacking Database (GHDB):http://johnny.ihackstuff.com/index.php?module=prodreviews,提供许多查询样例,你可以调节这些样例,将其用于你自己的站点或域名上。

  ·Foundstone公司的SiteDigger(http://www.foundstone.com/resources/proddesc/sitedigger.htm),它利用Foundstone自己个性化的Google查询,像Johnny Long的Google Hacking Database (GHDB)一样执行自动搜索。

  注意:Google每天最多只允许运行1,000条查询,这看起来挺多,但对于此类工具来说,很快就能够执行完毕。

  ·Johnny Long的Gooscan for Linux(http://johnny.ihackstuff.com/modules.php?op=modload&name=Downloads&file=indexreq=viewdownload&cid=5),它能够用来在Linux下执行命令行方式的Google查询。

  ·Google Toolbar for Internet Explorer允许你不进入Google的首页www.google.com就能够在IE浏览器中直接输入关键词进行简单的查询。如果你是IE的反对者,还可以使用能够在Netscape或者Mozilla Firefox下执行的开放源码的Googlebar(http://googlebar.mozdev.org/)。

  ·GooDelete(http://www.dirfile.com/goodelete_history.htm)能够清理那些你不想留下的,使用Google Toolbar查询留下的,可能包含敏感信息的缓存。

  另外,如果你非常热心于Google黑客行为,你的书橱中就不能少了Johnny Long撰写的,具有很高评价的《Google Hacking for Penetration Testers.》(_ihackstuff-20/102-5005443-2664941?v=glance&s=books">http://www.amazon.com/exec/obidos/tg/detail/-/1931836361/ref=ase_ihackstuff-20/102-5005443-2664941?v=glance&s=books)这本书。

  用Google查询人工执行黑客测试

  在上一个技巧列出的自动查询工具之外,你可能还想执行自主的人工Google查询,这里是一些我在服务器上运行过的测试,它们可以作为你的开始。

  注意:事实上,你能够使用Google进行的这些查询是非常非常少的一部分,你只需将你的想像力与前述的工具结合即可,它们对你要进行的查询的数量没有限制。

  ·site:你的主机或者域名 需要找的关键字

  这将测试搜索一个特定Internet主机或域名下的任意关键字,你可以使用如SSN、 confidential、finance、student等众多关键字。

  ·filetype:想要找的文件扩展名 site:你的主机或者域名

  这个测试将搜索你系统中的特定文件,你可以输入任意文件扩展名,比如doc、pdf、ppt、db、dbf等,只要是你能够想像到的就行。

  除非你能够确定你的信息已经泄漏到了其它网站,否则就一直使用“site:”操作符来限定你的搜索结果。使用“link:”操作符则能够搜索连接到个页面上的超链接。

  如果Google返回了查询结果,但其中的链接已经成为死链,你可以点击搜索结果下面的“快照”链接进行搜索和查找。这将搜索Google的缓存,你的信息可能有存在那里的机会。同样,确定在Google Groups(网上论坛)搜索敏感信息,我曾经利用这种方法,在这里搜索到很多有用的信息。你还可以查看Interesting Google Queries(http://artkast.yak.net/81)这个网页,找到针对Microsoft的特殊Google搜索技巧。

  四个步骤保护Windows数据远离Google黑客

  使用适当的对策,可以帮助你将高度机密信息远离Google,不能够被Google黑客搜索到。这里有四个步骤,你可以尝试做一下:

  1.巩固你的服务器,并将其与外部环境隔离

  有一个很不幸的事实是,许多关键服务器仍然完全暴露在Internet上,现在请收紧你服务器的存取控制,并将其放在防火墙之后。

  2.设置robots.txt文件,禁止Google索引你的网页

  你能够通过设置“googlebot”的“User-agent:”参数的方法保护网络服务器的文件和目录免受Google索引,方法是在“Disallow:”部分列出你想保密的信息。

  或者,如果你想所有的Web机器人都不访问你的网站和网页,就请将“User-agent:”参数设置为“*”,不过记住,怀有恶意的在网上到处闲逛的人能够从你的Web Server上得到此文件,并且看到你不想被别人看到的是哪些信息。如果这看起来像互联网的弱点,那么它就是。你可以不用robots.txt文件,但你应该允许机器人只能索引那些具体的公开页面,或者通过输入“Disallow /”禁止它们索引任何以根目录开始的信息。

  请访问The Web Robots Pages(http://www.robotstxt.org/wc/robots.html)获取如何配置你的robots.txt文件和如何执行更多反机器人欺骗的信息。Google同样有一个FAQ on Googlebot’s operation(http://www.google.com/bot.html)。

  3.将高度机密的信息从公众服务器上去除

  制定一项组织策略用来保护高度机密的信息(例如密码、机密文件等)远离公众可以访问的服务器。否则,使用任何可能的存取控制措施来保护它们,并且确保这些策略能够被强制执行,并且管理那些违规者。

  4.保证你的服务器是安全的

  为了维护服务器安全,请使用我在这一系列技巧中讨论过的Google测试工具和Google查询对其进行黑客测试。

  我高度推荐使用自动化测试工具,譬如SiteDigger和Gooscan进行黑客测试,手工执行多个查询的方式不仅缓慢枯燥,还不易于管理。

  记住,这些测试只是通过Google进行的挖掘测试,它们并不能代表所有的黑客和Internet安全,这些也不是测试所有系统漏洞的最好工具。作为替代,你必须使用“多层”测试手段:同时使用Google和其它免费的、开源的,以及――据我看来,最具有综合性和可靠性的――商业性的工具进行测试,这些商业性的工具我推荐的有SPI Dynamics公司的WebInspect(应用于Web应用程序,http://www.spidynamics.com/)、Application Security公司的AppDetective(用于Web数据库,http://www.appsecinc.com/)和Qualys公司的QualysGuard(用于操作系统和网络漏洞,http://www.qualys.com/)。

  如果模拟黑客、渗入测试和普通的网络安全审计是你工作职责的一部分,这些Google黑客技术和相应的工具将成为你需要的安全工具箱中的一部分。为了安全的缘故,请现在就开始执行它,并且以后也经常执行。

  关于作者:Kevin Beaver是一位独立的信息安全顾问、作者,也是位于亚特兰大的Principle Logic, LLC公司的发言人,他专门为那些需要严格安全保护,或者突发安全事件寻求解决方法的公司提供信息安全研究服务。他是四本有关信息安全的书的作者或共同作者,其中包含获得巨大成功的《Hacking for Dummies》(_1_2/002-6195114-4480811?v=glance&s=books">http://www.amazon.com/exec/obidos/tg/detail/-/076455784X/qid=1086746862/sr=1-2/ref=sr_1_2/002-6195114-4480811?v=glance&s=books)和即将出版的《Hacking Wireless Networks for Dummies》(http://www.wiley.com/WileyCDA/WileyTitle/productCd-0764597302.html)。这些书都由Wiley Publishing出版集团策划发行。你可以通过[email protected]联系Kevin Beaver,这是他的个人邮箱。也可以通过http://searchwindowssecurity.techtarget.com/ateAnswers/0,289620,sid45_tax297883,00.html,直接向他提问有关黑客方面的问题

    大家一定使用过 phpmyadmin 里面的数据库导入,导出功能,非常方便。但是在实际应用中,我发现如下几个问题:

  1 数据库超过一定尺寸,比如6M 这时使用导出一般没问题,可以正确的保存到本机硬盘上面,但是导入则不行!原因是:一般的 PHP.INI 里面设置临时文件/上传文件的大小限制为2M,而phpmyadmin使用了上传的方式,造成失败。

  2 导出到硬盘的 .SQL 文件在导回时,经常出现由于某些单引号的问题引起失败,造成导入失败,只能用 mysql等应用程序导入了。 我的数据库已经超过10M,所以必须解决这个问题。我的思路:

  导出: 用phpmyadmin 保存数据库/表格结构,用脚本读取数据库内容并保存到文件里面!
  导入: 用phpmyadmin 恢复数据库/表格结构,用脚本读取文件,然后保存到库里面!

  导出程序如下:调用方法为 ****.php?table=tablename
  这个简单的程序目前一次保存一个表格!!每行为一个字段的数据!!

以下为引用的内容:
< ?
if($table=="")exit();
mysql_connect("localhost","name","password");
mysql_select_db("database");
$result = mysql_query("select * from $table");
if(mysql_num_rows($result) < = 0) exit();
echo "开始转换数据到文本…
";
$handle = fopen("$table.txt","w");
$numfields = mysql_num_fields($result);
fputs($handle,$numfields."
");
for($k=0;$k< mysql_num_rows($result);$k++)
{
$msg = mysql_fetch_row($result);
for($i=0;$i< $numfields;$i++)
{
$msg[$i] = str_replace("
","&&php2000mysqlreturn&&",$msg[$i]);
$msg[$i] = str_replace("
" ,"&&php2000mysqlreturn&&",$msg[$i]);
fputs($handle,$msg[$i]."
");
}
fputs($handle,"——- php2000 dump data program V1.0 for MySQL ——–
");
}
fclose($handle);
echo "ok";
?>

  导入的程序如下:用法同上面!

以下为引用的内容:
< ?
if($table=="")exit();
mysql_connect("localhost","name","password");
mysql_select_db("database");
$message = file("$table.txt");
echo $numfields = chop($message[0]);
for($k=1;$k< count($message);$k+=($numfields+1))
{
$value="";
for ($i=$k;$i< ($k+$numfields-1);$i++)
{
$tmp = str_replace("&&php2000mysqlreturn&&","
",chop($message[$i]));
$value .= "‘".addslashes($tmp)."‘,";
}
$tmp = str_replace("&&php2000mysqlreturn&&","
",chop($message[$k+$numfields-1]));
$value .= "‘".$tmp."‘";
$query = "insert into $table values (".$value.")";
echo mysql_error();
mysql_query($query);
echo $k." ";
}
echo "ok";
?>

  使用方法和可能的问题!
  1 导入时 file()函数可能会有问题(我的10M的数据没出现问题),可以改为 fopen()然后没次读一行!!
  2 导入,导出都需要用 ftp 操作,也就是导出后,用 ftp 把数据转到本机,导入时先用ftp转移数据到服务器!

转自:http://www.weste.net/2006/7-14/16243358863.html

查询手机是正品还是水货,方法很简单,需要进行“手机IMEI号验证”和“标志验证”,方法如下:

登录电信设备进网管理网站,网址是 http://www.tenaa.com.cn/

第一步:手机IMEI号验证
地址:http://www.tenaa.com.cn/WSFW/FlagValidateImei.aspx

按照网页中的提示进行选择,在手机上按“*#06#”获得手机的IMEI码。

第二步:标志验证
鉴于手机IMEI号可以被伪造,此种验证方式仅供参考,如需准确查询请使用“标志验证”进行验证。
地址:http://www.tenaa.com.cn/WSFW/FlagValidate.aspx

两个验证都无误说明您的手机是正品。

其他验证方式:

短消息验证进网许可标志方式:

方法介绍:

1.进入手机写信息界面;

2.按以下格式输入信息:

1).查询进网许可证信息:RW#许可证编号;
2).查询进网许可证标志真伪:RW#许可证编号#扰码;
3).查询手机设备真伪:RW#许可证编号#扰码#手机串号;

说明:
A、“RW”为固定代码,可以不分大小写;
B、“#”为间隔符,可以用空格代替;
C、许可证编号为进网标志上第1行,如“02-0010-994631”,其中“-”可以用字母“A”(不分大小写)代替;
D、扰码为进网标志上第3行,如“3N48PT7C17XP3X1”;
E、在手机上输入“*#06#”可以获得手机串号。只需输入数字,不需输入“/”或“-”
F、若需获得帮助信息,只需输入“RW”;

输入完毕,发送至9500,即可等待回复结论。

适用范围:手机短信查验进网许可标志的适用范围:目前适用于中国移动的全部用户和中国联通的全部用户。

服务时间:24小时开通

收费标准:每条一元

如果你想把二进制的数据,比如说图片文件和HTML文件,直接保存在你的MySQL数据库,那么这篇文章就是为你而写的!我将告诉你怎样通过HTML表单来储存这些文件,怎样访问和使用这些文件。
  本文概述: 
  在mysql中建立一个新的数据库 
  一个怎样储存文件的例子程序 
  一个怎样访问文件的例子程序 
  在mysql中建立一个新的database
   首先,你必须在你的mysql中建立一个新的数据库,我们将会把那些二进制文件储存在这个数据库里。在例子中我会使用下列结构,为了建立数据库,你必须做下列步骤: 
  进入MySql控制器 
  输入命令"create database binary_data;" 
  输入命令"use binary_data;" 
  输入命令"CREATE TABLE binary_data ( id INT  (4) NOT NULL AUTO_INCREMENT PRIMARY KEY,
description CHAR(50), bin_data LONGBLOB, filename CHAR(50), filesize CHAR  (50), filetype CHAR(50));" (不能断行) 
  如果没有意外,数据库 和 表 应该建立好了。 
  一个怎样储存文件的例子程序 用这个例子你可以通过Html表单将文件传输到数据库中。.

store.php3

以下为引用的内容:

// store.php3 – by Florian Dittmer 
?>

// 如果提交了表单,代码将被执行:

if ($submit) {

     // 连接到数据库
     // (你可能需要调整主机名,用户名和密码)

    MYSQL_CONNECT( "localhost", "root", "password");
    mysql_select_db( "binary_data");

    $data = addslashes(fread(fopen($form_data,  "r"), filesize($form_data)));

    $result=MYSQL_QUERY( "INSERT INTO binary_data (description,bin_data,filename,filesize,filetype) ".
         "VALUES (’$form_description’,’$data’,’$form_data_name’,’$form_data_size’,’$form_data_type’)");

    $id= mysql_insert_id();
    print  "

This file has the following Database ID: $id";

    MYSQL_CLOSE();

} else {

     // 否则显示储存新数据的表单
?> 
}

?>

  如果你执行了这个程序,你将会看见一个简单的Html表单,单击“浏览”选择一个文件,然后单击提交。
  当文件上传至web服务器之后,程序将会告诉你刚刚上传的文件的ID,记住这个ID,待会要用的。
  一个怎样访问文件的例子程序
  你可以通过这个程序访问你刚才储存的文件

以下为引用的内容:

// getdata.php3 – by Florian Dittmer 
// 调用方法: getdata.php3?id=

if($id) {

     // 你可能需要调整主机名,用户名和密码:
    @MYSQL_CONNECT( "localhost", "root", "password");

    @mysql_select_db( "binary_data");

    $query =  "select bin_data,filetype from binary_data where id=$id";
    $result = @MYSQL_QUERY($query);

    $data = @MYSQL_RESULT($result,0, "bin_data");
    $type = @MYSQL_RESULT($result,0, "filetype");

    Header(  "Content-type: $type");
    echo $data;

};
?>

  程序必须知道要访问那个文件, 你必须将ID作为一个参数。
  例如: 一个文件在数据库中的ID为2. 你可以这样调用它:
                    getdata.php3?id=2如果你将图片储存在数据库里, 你可以向调用图片一样调用它。
  Example: 一个图片文件在数据库中的ID为3. 你可以这样调用它:
                    
  怎样储存大于1MB的文件:
  如果你想储存大于1MB的文件,你必须对你的程序、PHP设置、SQL设置进行许多修改,。
  下面几条也许可以帮助你储存小于24MB的文件:
  修改 store.php3 ,将 MAX_FILE_SIZE 的值改成 24000000。 
  修改你的PHP设置,在一般情况下,PHP只允许小于2MB的文件,你必须将max_filesize(在php.ini中)的值改成24000000

  去掉MYSQL的数据包大小限制,在一般情况下 MYSQL 小于1 MB的数据包. 
  你必须用以下参数重启你的MYSQL
  /usr/local/bin/safe_mysqld -O key_buffer=16M -O table_cache=128 -O sort_buffer=4M -O record_buffer=1M -O max_allowed_packet=24M 

    一、修改硬盘分区表信息

    硬盘分区表信息对硬盘的启动至关重要,如果找不到有效的分区表,将不能从硬盘启动或即使从软盘启动也找不到硬盘。 通常,第一个分区表项的第0子节为80H,表示C盘为活动DOS分区,硬盘能否自举就依靠它。

    若将该字节改为00H,则不能从硬盘启动,但从软盘启动后,硬盘仍然可以访问。分区表的第4字节是分区类型标志,第一分区的此处通常为06H,表示C盘为活动DOS分区,若对第一分区的此处进行修改可对硬盘起到一定加密作用。

    具体表现在:

    1.若将该字节改为0,则表示该分区未使用,当然不能再从C盘启动了。从软盘启动后,原来的C盘不见了,你看到的C盘是原来的D盘,D盘是原来的E盘,依此类推。

    2.若将此处字节改为05H,则不但不能从硬盘启动,即使从软盘启动,硬盘的每个逻辑盘都不可访问,这样等于整个硬盘被加密了。另外,硬盘主引导记录的有效标志是该扇区的最后两字节为55AAH。若将这两字节变为0,也可以实现对整个硬盘加锁而不能被访问。硬盘分区表在物理0柱面0磁头1扇区,可以用Norton for Win95中的Diskedit直接将该扇区调出并修改后存盘。或者在Debug下用INT 13H的02H子功能将0柱面0磁头1扇区读到内存,在相应位置进行修改,再用INT 13H的03H子功能写入0柱面0磁头1扇区就可以了。

    上面的加密处理,对一般用户来讲已足够了。但对有经验的用户,即使硬盘不可访问,也可以用INT 13H的02H子功能将0柱面0磁头1扇区读出,根据经验将相应位置数据进行修改,可以实现对硬盘解锁,因为这些位置的数据通常是固定的或有限的几种情形。

    另外一种保险但显得笨拙的方法是将硬盘的分区表项备份起来,然后将其全部变为0,这样别人由于不知道分区信息,就无法对硬盘解锁和访问硬盘了。

    二、对硬盘启动加口令

    我们知道,在CMOS中可以设置系统口令,使非法用户无法启动计算机,当然也就无法使用硬盘了。但这并未真正锁住硬盘,因为只要将硬盘挂在别的计算机上,硬盘上的数据和软件仍可使用。要对硬盘启动加口令,可以首先将硬盘0柱面0磁头1扇区的主引导记录和分区信息都储存在硬盘并不使用的隐含扇区,比如0柱面0磁头3扇区。

    然后用Debug重写一个不超过512字节的程序(实际上100多字节足矣)装载到硬盘0柱面0磁头1扇区。该程序的功能是执行它时首先需要输入口令,若口令不对则进入死循环;若口令正确则读取硬盘上存有主引导记录和分区信息的隐含扇区(0柱面0磁头3扇区),并转去执行主引导记录。

    由于硬盘启动时首先是BIOS调用自举程序INT 19H将主硬盘的0柱面0磁头1扇区的主引导记录读入内存0000:7C00H处执行,而我们已经偷梁换柱,将0柱面0磁头1扇区变为我们自己设计的程序。这样从硬盘启动时,首先执行的不是主引导程序,而是我们设计的程序。

    在执行我们设计的程序时,口令若不对则无法继续执行,也就无法启动了。即使从软盘启动,由于0柱面0磁头1扇区不再有分区信息,硬盘也不能被访问了。当然还可以将我们设计的程序像病毒一样,将其中一部分驻留在高端内存,监视INT 13H的使用,防止0柱面0磁头1扇区被改写。

    三、对硬盘实现用户加密管理

    UNIX操作系统可以实现多用户管理,在DOS系统下,将硬盘管理系统进行改进,也可实现类似功能的多用户管理。该管理系统可以满足这样一些要求:

    1.将硬盘分为公用分区C和若干专用分区D。其中“超级用户”来管理C区,可以对C区进行读写和更新系统;“特别用户”(如机房内部人员)通过口令使用自己的分区,以保护自己的文件和数据;“一般用户”(如到机房上机的普通人员)任意使用划定的公用分区。后两种用户都不能对C盘进行写操作,这样如果把操作系统和大量应用软件装在C盘,就能防止在公共机房中其他人有意或无意地对系统和软件的破坏,保证了系统的安全性和稳定性。

    2.在系统启动时,需要使用软盘钥匙盘才能启动系统,否则硬盘被锁住,不能被使用。 此方法的实现可通过利用硬盘分区表中各逻辑盘的分区链表结构,采用汇编编程来实现。

    四、对某个逻辑盘实现写保护

    我们知道,软盘上有写保护缺口,在对软盘进行写操作前,BIOS要检查软盘状态,如果写保护缺口被封住,则不能进行写操作。而写保护功能对硬盘而言,在硬件上无法进行,但可通过软件来实现。

    在DOS系统下,磁盘的写操作包括几种情况:

    ①在COMMAND.COM支持下的写操作,如MD、RD、COPY等;

    ②在DOS功能调用中的一些子功能如功能号为10H、13H、3EH、5BH等可以对硬盘进行写操作;

    ③通过INT 26H将逻辑扇区转换为绝对扇区进行写;

    ④通过INT 13H的子功能号03H、05H等对磁盘进行写操作。 但每一种写操作最后都要调用INT 13H的子功能去实现。

    因此,如果对INT 13H进行拦截,可以实现禁止对硬盘特定逻辑盘的写操作。由于磁盘上文件的写操作是通过INT 13H的03H子功能进行写,调用此子功能时,寄存器CL表示起始扇区号(实际上只用到低6位);CH表示磁道号,在硬盘即为柱面号,该柱面号用10位表示,其最高两位放在CL的最高两位。

    对硬盘进行分区时可以将硬盘分为多个逻辑驱动器,而每个逻辑驱动器都是从某一个完整的柱面开始。如笔者的硬盘为2.5GB,分为C、D、E、F、G五个盘。其中C盘起始柱面号为00H,D盘起始柱面号为66H,E盘起始柱面号为E5H,F盘起始柱面号为164H,G盘起始柱面号为26BH。如果对INT 13H进行拦截,当AH=03H,并且由CL高两位和CH共同表示的柱面号大于E4H并小于164H,就什么也不做就返回,这样就可以实现对E盘禁止写。

    SQL Server连接中的常见错误:

  一、"SQL Server 不存在或访问被拒绝"

  这个是最复杂的,错误发生的原因比较多,需要检查的方面也比较多。

  一般说来,有以下几种可能性:

  1、SQL Server名称或IP地址拼写有误

  2、服务器端网络配置有误

  3、客户端网络配置有误

  要解决这个问题,我们一般要遵循以下的步骤来一步步找出导致错误的原因。

  首先,检查网络物理连接

  ping <服务器IP地址/服务器名称>

  如果 ping <服务器IP地址> 不成功,说明物理连接有问题,这时候要检查硬件设备,如网卡,HUB,路由器等。

  还有一种可能是由于客户端和服务器之间安装有防火墙软件造成的,比如 ISA Server。防火墙软件可能会屏蔽对 ping,telnet 等的响应

  因此在检查连接问题的时候,我们要先把防火墙软件暂时关闭,或者打开所有被封闭的端口。

  如果ping <服务器IP地址> 成功而,ping <服务器名称> 失败

  则说明名字解析有问题,这时候要检查 DNS 服务是否正常。

  有时候客户端和服务器不在同一个局域网里面,这时候很可能无法直接使用服务器名称来标识该服务器,这时候我们可以使用HOSTS文件来进行名字解析,

  具体的方法是:

  1、使用记事本打开HOSTS文件(一般情况下位于C:WINNTsystem32driversetc)。

  添加一条IP地址与服务器名称的对应记录,如:

  172.168.10.24 myserver

  2、或在 SQL Server 的客户端网络实用工具里面进行配置,后面会有详细说明。

   其次,使用 telnet 命令检查SQL Server服务器工作状态

  telnet <服务器IP地址> 1433

  如果命令执行成功,可以看到屏幕一闪之后光标在左上角不停闪动,这说明 SQL Server 服务器工作正常,并且正在监听1433端口的 TCP/IP 连接

  如果命令返回"无法打开连接"的错误信息,则说明服务器端没有启动 SQL Server 服务,

  也可能服务器端没启用 TCP/IP 协议,或者服务器端没有在 SQL Server 默认的端口1433上监听。

  接着,我们要到服务器上检查服务器端的网络配置,检查是否启用了命名管道。是否启用了 TCP/IP 协议等等

  可以利用 SQL Server 自带的服务器网络使用工具来进行检查。

  点击:程序 — Microsoft SQL Server — 服务器网络使用工具

  打开该工具后,在"常规"中可以看到服务器启用了哪些协议。

  一般而言,我们启用命名管道以及 TCP/IP 协议。

  点中 TCP/IP 协议,选择"属性",我们可以来检查 SQK Server 服务默认端口的设置

  一般而言,我们使用 SQL Server 默认的1433端口。如果选中"隐藏服务器",则意味着客户端无法通过枚举服务器来看到这台服务器,起到了保护的作用,但不影响连接。

   接下来我们要到客户端检查客户端的网络配置

  我们同样可以利用 SQL Server 自带的客户端网络使用工具来进行检查,

  所不同的是这次是在客户端来运行这个工具。

  点击:程序 — Microsoft SQL Server — 客户端网络使用工具

打开该工具后,在"常规"项中,可以看到客户端启用了哪些协议。

  一般而言,我们同样需要启用命名管道以及 TCP/IP 协议。

  点击 TCP/IP 协议,选择"属性",可以检查客户端默认连接端口的设置,该端口必须与服务器一致。

  单击"别名"选项卡,还可以为服务器配置别名。服务器的别名是用来连接的名称,

  连接参数中的服务器是真正的服务器名称,两者可以相同或不同。别名的设置与使用HOSTS文件有相似之处。

  通过以上几个方面的检查,基本上可以排除第一种错误。  

    二、"无法连接到服务器,用户xxx登陆失败"

  该错误产生的原因是由于SQL Server使用了"仅 Windows"的身份验证方式,

  因此用户无法使用SQL Server的登录帐户(如 sa )进行连接。解决方法如下所示:

  1、在服务器端使用企业管理器,并且选择"使用 Windows 身份验证"连接上 SQL Server

  2、展开"SQL Server组",鼠标右键点击SQL Server服务器的名称,选择"属性",再选择"安全性"选项卡

  3、在"身份验证"下,选择"SQL Server和 Windows "。

  4、重新启动SQL Server服务。

  在以上解决方法中,如果在第 1 步中使用"使用 Windows 身份验证"连接 SQL Server 失败,

  那就通过修改注册表来解决此问题:

  1、点击"开始"-"运行",输入regedit,回车进入注册表编辑器

  2、依次展开注册表项,浏览到以下注册表键:

  [HKEY_LOCAL_MACHINESOFTWAREMicrosoftMSSQLServerMSSQLServer]

  3、在屏幕右方找到名称"LoginMode",双击编辑双字节值

  4、将原值从1改为2,点击"确定"

  5、关闭注册表编辑器

  6、重新启动SQL Server服务。

  此时,用户可以成功地使用sa在企业管理器中新建SQL Server注册,

  但是仍然无法使用Windows身份验证模式来连接SQL Server。

  这是因为在 SQL Server 中有两个缺省的登录帐户:

  BUILTINAdministrators

  <机器名>Administrator 被删除。

  要恢复这两个帐户,可以使用以下的方法:

  1、打开企业管理器,展开服务器组,然后展开服务器

  2、展开"安全性",右击"登录",然后单击"新建登录"

  3、在"名称"框中,输入 BUILTINAdministrators

  4、在"服务器角色"选项卡中,选择"System Administrators"

  5、点击"确定"退出

  6、使用同样方法添加 <机器名>Administrator 登录。

  说明:

  以下注册表键:
  HKEY_LOCAL_MACHINESOFTWAREMicrosoftMSSQLServerMSSQLServerLoginMode

  的值决定了SQL Server将采取何种身份验证模式。

  1、表示使用"Windows 身份验证"模式

  2、表示使用混合模式(Windows 身份验证和 SQL Server 身份验证)。

    三、提示连接超时

  如果遇到第三个错误,一般而言表示客户端已经找到了这台服务器,并且可以进行连接,

  不过是由于连接的时间大于允许的时间而导致出错。

  这种情况一般会发生在当用户在Internet上运行企业管理器来注册另外一台同样在Internet上的服务器,并且是慢速连接时,有可能会导致以上的超时错误。有些情况下,由于局域网的网络问题,也会导致这样的错误。

  要解决这样的错误,可以修改客户端的连接超时设置。

  默认情况下,通过企业管理器注册另外一台SQL Server的超时设置是 4 秒,而查询分析器是 15 秒(这也是为什么在企业管理器里发生错误的可能性比较大的原因)。

  具体步骤为:

  企业管理器中的设置:

  1、在企业管理器中,选择菜单上的"工具",再选择"选项"

  2、在弹出的"SQL Server企业管理器属性"窗口中,点击"高级"选项卡

  3、在"连接设置"下的"登录超时(秒)"右边的框中输入一个比较大的数字,如 20。

  查询分析器中的设置:

  工具 — 选项 — 连接 — 将登录超时设置为一个较大的数字

  连接超时改为0

  1、先保证ping通

  2、在dos下写入telnet ip 1433不会报错

  3、用ip连如企业管理器:

  企业管理器–>右键SQlserver组–>新建sqlserver注册–>下一步–>写入远程实例名 (IP,机器名)–>下一步–>选Sqlserver登陆–>下一步–>写入登陆名与密码(sa,pass)– >下一步–>下一步–>完成

  4、如果还不行:

  sqlserver服务器–>开始菜单–>SQLserver–>服务器网络实用工具–>启用 WinSock代理–>代理地址:(sqlserver服务器IP)–>代理端口–>1433–>OK了

  5、如果还不行:

  sqlserver客户端–>开始菜单–>SQLserver–>客户端网络实用工具–>别名–>添加–>写入别名如"大力"–>"网络库"选tcp/ip–>服务器名称写入远程ip或实例名–>OK了