教你SQLSERVER扩展存储过程XPCMDSHELL的简单应用

时间:2022年12月11日

/

来源:理水

/

编辑:本站小编

收藏本文

下载本文

这次小编给大家整理了教你SQLSERVER扩展存储过程XPCMDSHELL的简单应用,本文共6篇,供大家阅读参考。本文原稿由网友“理水”提供。

篇1:教你SQLSERVER扩展存储过程XPCMDSHELL的简单应用

XP_CMDSHELL存储过程是执行本机的CMD命令,要求系统登陆有SA权限,也就是说如果获得SQLSERVER的SA命令,那就可以在目标机为所欲为了,知名软件“流光”使用的应该也是这个存储过程来实现在目标机上的操作,下面是我写的一个简单的应用页面(ASP),代码如下。

XP_CMDSHELL存储过程是执行本机的CMD命令,要求系统登陆有SA权限,也就是说如果获得SQLSERVER的SA命令,那就可以在目标机为所欲为了,知名软件“流光”使用的应该也是这个存储过程来实现在目标机上的操作。

下面是我写的一个简单的应用页面(ASP),代码如下。

CMD.ASP

<%@LANGUAGE=“VBSCRIPT” CODEPAGE=“936”%>

SQLSERVER_XP_CMDSHELL实例_魔术师·刘

<%if request(“cmd”)“” then%>

XP_CMDSHELL请求结果

<%dim connstr,conn,rs,i

ConnStr=“Provider=sqloledb.1;persist security info=false;server=”&request(“server”)&“;uid=sa;pwd=”&request(“pwd”)&“;database=master”

'ConnStr=“Provider=sqloledb.1;persist security info=false;server=(local);uid=sa;pwd=www.zhi.net;database=master”

set conn=Server.CreateObject(“ADODB.Connection”)

conn.open Connstr

set rs=server.CreateObject(“ADODB.Recordset”)

set rs=conn.execute(“xp_cmdshell '”&replace(replace(request(“cmd”),“'”,“''”),chr(34),“''”)&“'”)

i=0

while not rs.eof

if not isnull(rs(0)) then

if i mod 2 =0 then

response.Write “”&rs(0)&“”

else

response.Write “”&rs(0)&“”

end if

i=i 1

end if

rs.movenext

wend

rs.close

set rs=nothing

conn.close

set conn=nothing

%>

<%end if%>

XP_CMDSHELL实例

服务器

<%=request(“Server”)%>“>

SA密码

<%=request(”PWD“)%>”>

CMD命令

<%=request(“CMD”)%>“>

篇2:编写安全的扩展存储过程存储过程

近日在写一个扩展存储过程时,发现再写这类动态库时,还是有一些需要特别注意的地方,之所以会特别注意,是因为DLL运行于SQL Server的地址空间,而SQL Server到底是怎么进行线程调度的,却不是我们能了解的,即便了解也无法控制。

我们写动态库一般是自己用,即便给别人用,也很少像SQL Server这样,一个动态库很有可能加载多次,并且都是加载到一个进程的地址空间中。我们知道,当一个动态库加载到进程的地址空间时,DLL所有全局与局部变量初始化且仅初始化一次,以后再次调用 LoadLibrary函数时,仅仅增加其引用计数而已,那么很显然,假如有一全局 int,初始化为0,调用一个函数另其自加,此时其值为1,然后再调用LoadLibray,并利用返回的句柄调用输出函数输出该值,虽然调用者觉得自己加载后立即输出,然后该值确实1而不是0。windows是进程独立的,而在线程方面,假如不注意,上面的情况很可能会程序员带来麻烦。

介绍一下我的扩展存储过程,该动态库导出了三个函数:Init,work,Final,Init读文件,存储信息于内存,work简单的只是向该内存检索信息,Final回收内存。如上所说,假如不考虑同一进程空间多次加载问题,两次调用Init将造成无谓的浪费,因为我第一次已经读进了内存,要是通过堆分配内存,还会造成内存泄露。

我使用的引用计数解决的该问题,代码很短,直接贴上来:

#include ”stdafx.h“

#include

using namespace std;

extern ”C“ {

RETCODE __declspec(dllexport) xp_part_init(SRV_PROC *srvproc);

RETCODE __declspec(dllexport) xp_part_process(SRV_PROC *srvproc);

RETCODE __declspec(dllexport) xp_part_finalize(SRV_PROC *srvproc);

}

#define XP_NOERROR 0

#define XP_ERROR 1

HINSTANCE hInst = NULL;

int nRef = 0;

void printError (SRV_PROC *pSrvProc, CHAR* szErrorMsg);

ULONG __GetXpVersion{ return ODS_VERSION;}

SRVRETCODE xp_part_init(SRV_PROC* pSrvProc){

typedef bool (*Func)();

if(nRef == 0){

hInst = ::LoadLibrary(”part.dll“);

if(hInst == NULL){

printError(pSrvProc,”不能加载part.dll“);

return XP_ERROR;

}

Func theFunc = (Func)::GetProcAddress(hInst,”Init“);

if(!theFunc()){

::FreeLibrary(hInst);

printError(pSrvProc,”不能获得分类号与专辑的对应表“);

return XP_ERROR;

}

}

++ nRef;

return (XP_NOERROR);

}

SRVRETCODE xp_part_process(SRV_PROC* pSrvProc){

typedef bool (*Func)(char*);

if(nRef == 0){

printError(pSrvProc,”函数尚未初始化,请首先调用xp_part_init“);

return XP_ERROR;

}

Func theFunc = (Func)::GetProcAddress(hInst,”Get“);

BYTE bType;

关 键 字:MYSQL

篇3:编写安全的扩展存储过程

近日在写一个扩展存储过程时,发现再写这类动态库时,还是有一些需要特别注意的地方,之所以会特别注意,是因为DLL运行于SQL Server的地址空间,而SQL Server到底是怎么进行线程调度的,却不是我们能了解的,即便了解也无法控制。

我们写动态库一般是自己用,即便给别人用,也很少像SQL Server这样,一个动态库很有可能加载多次,并且都是加载到一个进程的地址空间中。我们知道,当一个动态库加载到进程的地址空间时,DLL所有全局与局部变量初始化且仅初始化一次,以后再次调用 LoadLibrary函数时,仅仅增加其引用计数而已,那么很显然,假如有一全局 int,初始化为0,调用一个函数另其自加,此时其值为1,然后再调用LoadLibray,并利用返回的句柄调用输出函数输出该值,虽然调用者觉得自己加载后立即输出,然后该值确实1而不是0。windows是进程独立的,而在线程方面,假如不注意,上面的情况很可能会程序员带来麻烦。

介绍一下我的扩展存储过程,该动态库导出了三个函数:Init,work,Final,Init读文件,存储信息于内存,work简单的只是向该内存检索信息,Final回收内存。如上所说,假如不考虑同一进程空间多次加载问题,两次调用Init将造成无谓的浪费,因为我第一次已经读进了内存,要是通过堆分配内存,还会造成内存泄露。

我使用的引用计数解决的该问题,代码很短,直接贴上来:

#include ”stdafx.h“

#include

using namespace std;

extern ”C“ {

RETCODE __declspec(dllexport) xp_part_init(SRV_PROC *srvproc);

RETCODE __declspec(dllexport) xp_part_process(SRV_PROC *srvproc);

RETCODE __declspec(dllexport) xp_part_finalize(SRV_PROC *srvproc);

}

#define XP_NOERROR 0

#define XP_ERROR 1

HINSTANCE hInst = NULL;

int nRef = 0;

void printError (SRV_PROC *pSrvProc, CHAR* szErrorMsg);

ULONG __GetXpVersion(){ return ODS_VERSION;}

SRVRETCODE xp_part_init(SRV_PROC* pSrvProc){

typedef bool (*Func)();

if(nRef == 0){

hInst = ::LoadLibrary(”part.dll“);

if(hInst == NULL){

printError(pSrvProc,”不能加载part.dll“);

return XP_ERROR;

}

Func theFunc = (Func)::GetProcAddress(hInst,”Init“);

if(!theFunc()){

::FreeLibrary(hInst);

printError(pSrvProc,”不能获得分类号与专辑的对应表“);

return XP_ERROR;

}

}

++ nRef;

return (XP_NOERROR);

}

SRVRETCODE xp_part_process(SRV_PROC* pSrvProc){

typedef bool (*Func)(char*);

if(nRef == 0){

printError(pSrvProc,”函数尚未初始化,请首先调用xp_part_init“);

return XP_ERROR;

}

Func theFunc = (Func)::GetProcAddress(hInst,”Get“);

BYTE bType;

ULONG cbMaxLen,cbActualLen;

BOOL fNull;

char szInput[256] = {0};

if (srv_paraminfo(pSrvProc, 1, &bType, (ULONG*)&cbMaxLen, (ULONG*)&cbActualLen,

(BYTE*)szInput, &fNull) == FAIL){

printError(pSrvProc,”srv_paraminfo 返回 FAIL“);

return XP_ERROR;

}

szInput[cbActualLen] = 0;

string strInput = szInput;

string strOutput = ”;“;

int cur,old = 0;

while(string::npos != (cur = strInput.find(’;’,old)) ){

strncpy(szInput,strInput.c_str() + old,cur - old);

szInput[cur - old] = 0;

old = cur + 1;

theFunc(szInput);

if(string::npos ==strOutput.find((string)”;“ + szInput))

strOutput += szInput;

}

strcpy(szInput,strOutput.c_str());

if (FAIL == srv_paramsetoutput(pSrvProc, 1, (BYTE*)(szInput + 1),

strlen(szInput) - 1,FALSE)){

printError (pSrvProc, ”srv_paramsetoutput 调用失败“);

return XP_ERROR;

}

srv_senddone(pSrvProc, (SRV_DONE_COUNT | SRV_DONE_MORE), 0, 0);

return XP_NOERROR;

}

SRVRETCODE xp_part_finalize(SRV_PROC* pSrvProc){

typedef void (*Func)();

if(nRef == 0)

return XP_NOERROR;

Func theFunc = (Func)::GetProcAddress(hInst,”Fin“);

if((--nRef) == 0){

theFunc();

::FreeLibrary(hInst);

hInst = NULL;

}

return (XP_NOERROR);

}

我想虽然看上去不是很高明,然而问题应该是解决了的,

还有一点说明,为什么不使用Tls,老实说,我考虑过使用的,因为其实代码是有一点问题的,假如一个用户调用xp_part_init,然后另一个用户也调用xp_part_init,注意我们的存储过程可是服务器端的,然后第一个用户调用xp_part_finalize,那么会怎样,他仍然可以正常使用xp_part_process,这倒无所谓,然而第一个用户调用两次xp_part_finalize,就能够影响第二个用户了,他的xp_part_process将返回错误。

使用Tls 似乎可以解决这问题,例如再添加一个tls_index变量,调用 TlsSetValue保存用户私人数据,TlsGetValue检索私人数据,当xp_part_init时,假如该私人数据为0,执行正常的初始化过程,(即上面的xp_part_init)执行成功后存储私人数据为1,假如是1,直接返回,xp_part_finalize时,假如私人数据为1,则执行正常的xp_part_finalize,然后设私人数据为0,假如是0,直接返回。

好像想法还是不错的,这样隔离了多个用户,安全性似乎提高了不少,然而事实是不可行的。因为Tls保存的并不是私人数据,而是线程本地变量,我们不能保证一个用户的多次操作都是用同一个线程执行的,这个由SQL Server自己控制,事实上我在查询分析器里多次执行的结果显示,SQL Server内部似乎使用了一个线程池。既然如此,那这种想法也只能作罢。

篇4:Delphi与SQLServer存储过程编程详解数据库

前言 经常有很多初学者问到在delphi中如何调用 SQL Server的存储过程 ?问题其实很好解决,但问得多了,也就不愿答了,下面我将用实例进行说明,从在SQL Server中创建存储过程到调用的完整实例。 首先,打开 sql server管理器,在pubs 数据库 中建一个 测试 表

前言

经常有很多初学者问到在delphi中如何调用SQLServer的存储过程?问题其实很好解决,但问得多了,也就不愿答了。下面我将用实例进行说明,从在SQL Server中创建存储过程到调用的完整实例。

首先,打开sqlserver管理器,在pubs数据库中建一个测试表,表名为test,字段有id,name,和desc,全部为字符型,如果你不知道建表,那么打开sql查询分析器,贴上以下的代码,然后按执行,就会自动生成test表.

use pubs

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[test]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)

drop table [dbo].[test]

GO

CREATE TABLE [dbo].[test] (

[id] [char] (10) COLLATE Chinese_PRC_CI_AS NOT NULL ,

[name] [char] (12) COLLATE Chinese_PRC_CI_AS NULL ,

[descrip] [char] (30) COLLATE Chinese_PRC_CI_AS NULL

) ON [PRIMARY]

GO

然后,我们来创建一个存储过程,其功能为在test中插入一条新记录.创建存储过程的代码如下,同样的,你也可以复制到查询分析器里直接执行就可以:

CREATE PROCEDURE myInsert

@id char(10) ,

@name varchar(12),

@descrip varchar(30)

AS

begin

insert into test (id,name,descrip) values (@id,@name,@descrip)

if @@rowcount=0

begin

raiserror('error',16,1)

rollback transaction

end

end

GO

接下来,新建一个工程文件,在form1上放置如下控件,并设置属性(括号内):

一个ADOConnection1: TADOConnection;

(LoginPrompt:=false;

connectionstring:=Provider=SQLOLEDB.1;Persist Security Info=True;User ID=sa;Initial Catalog=pubs;Data Source=(local);)

一个ADOStoredProc1: TADOStoredProc;属性为:

(connection:=adoconnection1;

procedurename:=myinsert;//上面我们创建的那个)

一个ADOTable1: TADOTable;属性为:

(connection:=adoconnection1;

tablename:=test; //上面我们创建的那个)

一个Datasource1,属性为:

(dataset:=Tadotable;)

一个 DBGrid1: TDBGrid;属性为

(datasource:=datasource1;)

一个Button1,在其Onclick中写到:

with adoStoredproc1 do

begin

Parameters.ParamByName('@id').Value := '2';

parameters.ParamByName('@name').Value := 'myname';

parameters.ParamByName('@descrip').Value :='nosubject';

ExecProc;

end;

Adotable1.Close;

adotable1.Open;

原文转自:www.ltesting.net

篇5:编写安全的SQL Server扩展存储过程存储过程

SQL Server 的扩展存储过程,其实就是一个普通的 Windows DLL,只不过按照某种规则实现了某些函数而已,

近日在写一个扩展存储过程时,发现再写这类动态库时,还是有一些需要特别注意的地方。之所以会特别注意,是因为DLL运行于SQL Server的地址空间,而SQL Server到底是怎么进行线程调度的,却不是我们能了解的,即便了解也无法控制。

我们写动态库一般是自己用,即便给别人用,也很少像SQL Server这样,一个动态库很有可能加载多次,并且都是加载到一个进程的地址空间中。我们知道,当一个动态库加载到进程的地址空间时,DLL所有全局与局部变量初始化且仅初始化一次,以后再次调用 LoadLibrary函数时,仅仅增加其引用计数而已,那么很显然,假如有一全局 int ,初始化为0,调用一个函数另其自加,此时其值为1,然后再调用LoadLibray,并利用返回的句柄调用输出函数输出该值,虽然调用者觉得自己加载后立即输出,然后该值确实1而不是0。windows是进程独立的,而在线程方面,假如不注意,上面的情况很可能会程序员带来麻烦。

介绍一下我的扩展存储过程,该动态库导出了三个函数: Init,work,Final,Init读文件,存储信息于内存,work简单的只是向该内存检索信息,Final回收内存。如上所说,假如不考虑同一进程空间多次加载问题,两次调用Init将造成无谓的浪费,因为我第一次已经读进了内存,要是通过堆分配内存,还会造成内存泄露。

我使用的引用计数解决的该问题,代码很短,直接贴上来:

#include ”stdafx.h“

#include

using namespace std;

extern ”C“ {

RETCODE __declspec(dllexport) xp_part_init(SRV_PROC *srvproc);

RETCODE __declspec(dllexport) xp_part_process(SRV_PROC *srvproc);

RETCODE __declspec(dllexport) xp_part_finalize(SRV_PROC *srvproc);

}

#define XP_NOERROR 0

#define XP_ERROR 1

HINSTANCE hInst = NULL;

int nRef = 0;

void printError (SRV_PROC *pSrvProc, CHAR* szErrorMsg);

ULONG __GetXpVersion{ return ODS_VERSION;}

SRVRETCODE xp_part_init(SRV_PROC* pSrvProc){

typedef bool (*Func)();

if(nRef == 0){

hInst = ::LoadLibrary(”part.dll“);

if(hInst == NULL){

printError(pSrvProc,”不能加载part.dll“);

return XP_ERROR;

}

Func theFunc = (Func)::GetProcAddress(hInst,”Init“);

if(!theFunc()){

::FreeLibrary(hInst);

printError(pSrvProc,”不能获得分类号与专辑的对应表“);

return XP_ERROR;

}

}

++ nRef;

return (XP_NOERROR);

}

SRVRETCODE xp_part_process(SRV_PROC* pSrvProc){

typedef bool (*Func)(char*);

if(nRef == 0){

printError(pSrvProc,”函数尚未初始化,请首先调用xp_part_init“);

return XP_ERROR;

}

Func the

关 键 字:MYSQL

篇6:SQLSERVER Pager store procedure分页存储过程数据库教程

复制代码代码如下:

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

CREATE PROCEDURE [dbo].[Pagination]

@Page int = 1, -- 当前页码

@PageSize int = 10, -- 每页记录条数(页面大小)

@Table nvarchar(500), -- 表名或视图名,甚至可以是嵌套SQL:(Select * From Tab Where ID>1000) Tab

@Field nvarchar(800) = '*', -- 返回记录集字段名,”,“隔开,默认是”*\"

@OrderBy nvarchar(100) = 'ID ASC', -- 排序规则

@Filter nvarchar(500), -- 过滤条件

@MaxPage smallint output, -- 执行结果 -1 error, 0 false, maxpage true

@TotalRow int output, -- 记录总数 /* 2007-07-12 22:11:00 update */

@Descript. varchar(100) output -- 结果描述

AS

BEGIN

-- =============================================

-- Author: Jimmy.Yu

-- Create date: 2007-5-11

-- Description: SQL 2005 以上版本 通用分页存储过程

-- =============================================

Set ROWCOUNT @PageSize;

Set @Descript. = 'successful';

-------------------参数检测----------------

IF LEN(RTRIM(LTRIM(@Table))) !>0

Begin

Set @MaxPage = 0;

Set @Descript. = 'table name is empty';

Return;

End

IF LEN(RTRIM(LTRIM(@OrderBy))) !>0

Begin

Set @MaxPage = 0;

Set @Descript. = 'order is empty';

Return;

End

IF ISNULL(@PageSize,0) <= 0

Begin

Set @MaxPage = 0;

Set @Descript. = 'page size error';

Return;

End

IF ISNULL(@Page,0) <= 0

Begin

Set @MaxPage = 0;

Set @Descript. = 'page error';

Return;

End

-------------------检测结束----------------

Begin Try

-- 整合SQL

Declare @SQL nvarchar(4000), @Portion nvarchar(4000);

Set @Portion = ' ROW_NUMBER() OVER (ORDER BY ' + @OrderBy + ') AS ROWNUM FROM ' + @Table;

Set @Portion = @Portion + (CASE WHEN LEN(@Filter) >= 1 THEN (' Where ' + @Filter + ') AS tab') ELSE (') AS tab') END);

Set @SQL = 'Select TOP(' + CAST(@PageSize AS nvarchar(8)) + ') ' + @Field + ' FROM (Select ' + @Field + ',' + @Portion;

Set @SQL = @SQL + ' Where tab.ROWNUM >' + CAST((@Page-1)*@PageSize AS nvarchar(8));

-- 执行SQL, 取当前页记录集

Execute(@SQL);

--------------------------------------------------------------------

-- 整合SQL

Set @SQL = 'Set @Rows = (Select MAX(ROWNUM) FROM (Select' + @Portion + ')';

-- 执行SQL, 取最大页码

Execute sp_executesql @SQL, N'@Rows int output', @TotalRow output;

Set @MaxPage = (CASE WHEN (@TotalRow % @PageSize)0 THEN (@TotalRow / @PageSize + 1) ELSE (@TotalRow / @PageSize) END);

End Try

Begin Catch

-- 捕捉错误

Set @MaxPage = -1;

Set @Descript. = 'error line: ' + CAST(ERROR_LINE() AS varchar(8)) + ', error number: ' + CAST(ERROR_NUMBER() AS varchar(8)) + ', error message: ' + ERROR_MESSAGE();

Return;

End Catch;

-- 执行成功

Return;

END

相对应的页面逻辑中写的对应调用该存储过程的方法(C#)

一次性压缩Sqlserver中所有库日志的存储过程

SQL 存储过程基础语法之一

PostgreSQL存储过程返回数据集实例

存储过程与 SQL Server语句大比拼综合教程

一个基于ROWNUMBER的通用分页存储过程代码

下载教你SQLSERVER扩展存储过程XPCMDSHELL的简单应用(精选6篇)
教你SQLSERVER扩展存储过程XPCMDSHELL的简单应用.doc
将本文的Word文档下载到电脑,方便收藏和打印
推荐度:
点击下载文档
热门文章
    猜你喜欢
    点击下载本文文档