ZwLoadDriver函数调用出错

hjzwl1018 2009-05-14 05:27:14
加精
生成了驱动hidedriver.sys,想通过ZwLoadDriver动态加载该驱动,程序调用源码如下:

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;

// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
cerr << _T("Fatal Error: MFC initialization failed") << endl;
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.

char szDriverName[32] = {0};
char szDriverPath[256] = {0};

/*
if (argc != 3)
{
printf("Usage: %s <DriverFilename> <DriverPath>\r\n", argv[0]);
exit(-1);
}*/

// ·½±ãµ÷ÊÔ
strcpy(szDriverPath, "C:\\hidedriver.sys");

printf("Input driver name:\n");
scanf("%s", szDriverName);
//printf("Input driver path:\n");
//scanf("%s", szDriverPath);

// Load ntdll
HMODULE hNtdll = NULL;
hNtdll = LoadLibrary( "ntdll.dll" );

//´Óntdll.dllÀï»ñÈ¡º¯Êý
if ( !hNtdll )
{
printf( "LoadLibrary( NTDLL.DLL ) Error:%d\n", GetLastError() );
return false;
}

RtlAnsiStringToUnicodeString = (RTLANSISTRINGTOUNICODESTRING)\
GetProcAddress( hNtdll, "RtlAnsiStringToUnicodeString");
RtlFreeUnicodeString = (RTLFREEUNICODESTRING)\
GetProcAddress( hNtdll, "RtlFreeUnicodeString");
ZwLoadDriver = (ZWLOADDRIVER)\
GetProcAddress( hNtdll, "ZwLoadDriver");

// ×¢²áÇý¶¯³ÌÐò
if (-1 == LoadDriver(szDriverName, szDriverPath) )
{
printf("Error to load driver!\nProgramme will quit...\n");
return -1;
}
//return 0;
}

return nRetCode;
}

int LoadDriver(char *szDrvName, char *szDrvPath)
{
// ÐÞ¸Ä×¢²á±íÆô¶¯Çý¶¯³ÌÐò
char szSubKey[200], szDrvFullPath[256];
LSA_UNICODE_STRING buf1;
LSA_UNICODE_STRING buf2;
int iBuffLen;
HKEY hkResult;
char Data[4] = {0};
DWORD dwOK;

iBuffLen = sprintf(szSubKey, "System\\CurrentControlSet\\Services\\%s", szDrvName);
szSubKey[iBuffLen] = 0;
dwOK = RegCreateKey(HKEY_LOCAL_MACHINE, szSubKey, &hkResult);
if (dwOK != ERROR_SUCCESS)
return -1;

dwOK = RegSetValueEx(hkResult, "Type", 0, 4, (const unsigned char *)Data, 4);
dwOK = RegSetValueEx(hkResult, "ErrorControl", 0, 4, (const unsigned char *)Data, 4);
dwOK = RegSetValueEx(hkResult, "Start", 0, 4, (const unsigned char *)Data, 4);

GetFullPathName(szDrvPath, 256, szDrvFullPath, NULL);
printf("Loading driver: %s\r\n", szDrvFullPath);
memset(szSubKey, 0, sizeof(szSubKey) );
iBuffLen = sprintf(szSubKey, "\\??\\%s", szDrvFullPath);
szSubKey[iBuffLen] = 0;
dwOK = RegSetValueEx(hkResult, "ImagePath", 0, 1, (const unsigned char *)szSubKey, iBuffLen);
RegCloseKey(hkResult);

iBuffLen = sprintf(szSubKey,"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\%s", szDrvName);
szSubKey[iBuffLen] = 0;
buf2.Buffer = (PVOID)szSubKey;
buf2.Length = iBuffLen;
RtlAnsiStringToUnicodeString(&buf1, &buf2, 1);

// ¼ÓÔØÇý¶¯³ÌÐò
dwOK = ZwLoadDriver(&buf1);
if (dwOK != ERROR_SUCCESS)
{
printf("Error code is:%d\n", dwOK);
return -1;
}

RtlFreeUnicodeString(&buf1);

// ɾ³ý×¢²á±íÏî
iBuffLen = sprintf(szSubKey, "%s%s\\Enum", "System\\CurrentControlSet\\Services\\", szDrvName);
szSubKey[iBuffLen] = 0;
RegDeleteKey(HKEY_LOCAL_MACHINE, szSubKey);

iBuffLen = sprintf(szSubKey, "%s%s\\Security", "System\\CurrentControlSet\\Services\\", szDrvName);
szSubKey[iBuffLen] = 0;
RegDeleteKey(HKEY_LOCAL_MACHINE, szSubKey);

iBuffLen = sprintf(szSubKey, "%s%s", "System\\CurrentControlSet\\Services\\", szDrvName);
szSubKey[iBuffLen] = 0;
RegDeleteKey(HKEY_LOCAL_MACHINE, szSubKey);

iBuffLen = sprintf(szSubKey, "\\\\.\\%s", szDrvName);
szSubKey[iBuffLen] = 0;

return 0;
}

调用ZwLoadDriver出错,什么原因?
...全文
2023 60 打赏 收藏 转发到动态 举报
写回复
用AI写文章
60 条回复
切换为时间正序
请发表友善的回复…
发表回复
hjzwl1018 2009-06-09
  • 打赏
  • 举报
回复
问题终于得到解决,按照jingzhongrong告诉我的方法试试,一步一步用windbg调试,最后发现其实错误发生在驱动里面,跟加载驱动程序关系不大。过程大概是这样的:安装虚拟机,使用虚拟机作为目标PC(主要是蓝屏电脑就会重启),把IP设置成跟主PC的网段一致,这样做的好处是可以方便主PC跟目标PC共享文件,同时WinDbg也可以打开虚拟机上的调试文件;下载DbgView软件,这个软件是免费的,可以查看调试输出信息,使用也非常方便,具体参考微软官方网站,驱动程序的调试信息将打印在DbgView上,这样便于知道程序了到底发生了什么错误。我这里没使用自己的程序加载驱动,使用了一个软件(OSRLOADER.exe),这个可以google一下,这个软件就是加载驱动程序用的,注意这个软件只能在本机运行,所以这个软件要拷贝到目标虚拟机上去;使用这个软件启动服务或者停止服务都有可能导致蓝屏,这时DbgView也看不了调试信息了,因为系统崩溃了,但是注意系统崩溃之前,操作系统会将当前的调用堆栈记录成一个dump文件,不过首先要确定计算机是否让操作系统存储了Dump信息,方法如下:右键单击"我的电脑", 选择"属性",弹出"系统属性"对话框,在对话框中,单击"高级"选项卡,然后单击"设置"按钮(第三个设置按钮),弹出一个对话框,在弹出的对话框中选中所有的复选框,OK了,这样dump文件将存放在C:\WINDOWS\Minidump目录下,等待虚拟机重启之后,使用WinDbg打开这个目录下刚刚崩溃产生的dump文件可以知道错误发生在什么地方,这时需要先设置好Image File Path,WinDbg--File--Image File Path,将sys文件的目录写上去,这个.sys文件应该是驱动程序目录下的.sys文件,这点要注意,关于符号表路径设置,这里就不啰嗦了,接着打开dump文件后可以看到command窗口,选择View--Call Stack,看到函数调用栈,这种函数调用关系式系统崩溃前的一个快照,因此可以分析出调用中的那句话导致了系统崩溃;如果系统可以注册服务,但是启动不了服务,这时系统不会蓝屏,可以使用DbgView查看调试信息,这时需要先打开DbgView,确保Capture--Capture Kernel是勾选的,这样就可以捕获内核调试信息。同时使用DbgView与WinDbg,跟踪发现是附加设备函数IoAttachDevice调用出错,检查返回值,查看ntstatus文件,找到对应错误吗,从而确定了错误的根源。
hjzwl1018 2009-05-25
  • 打赏
  • 举报
回复
[Quote=引用 48 楼 killcpp 的回复:]
笑笑:
23楼正解。
以手动启动的方式注册到Service,然后在应用程序启动的时候StartService。
LoadDriver(...){
//首先使用OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS)
SC_HANDLE schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);

//将之前的驱动卸载
SC_HANDLE schService = OpenService(schSCManager,DriverName,SERVICE_ALL_ACCESS);

DeleteService(schService);

C…
[/Quote]
前几天出差,谢谢各位的回答!这种方法有试过,还是不行的~现在只能按照jingzhongrong告诉我的方法试试,一步一步用windbg调试。
hjzwl1018 2009-05-25
  • 打赏
  • 举报
回复

bool _util_load_sysfile(char *theDriverName)
{
char aPath[1024];
char aCurrentDirectory[515];
SC_HANDLE sh = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);

if (!sh)
{

return false;
}

GetCurrentDirectory( 512, aCurrentDirectory);
_snprintf(aPath,
1022,
"\\??\\C:\\WINDOWS\\system32\\drivers\\%s.sys",
theDriverName);

printf("loading %s\n", aPath);
SC_HANDLE rh = CreateService(sh, \
theDriverName, \
theDriverName, \
SERVICE_ALL_ACCESS, \
SERVICE_KERNEL_DRIVER, \
SERVICE_DEMAND_START, \
SERVICE_ERROR_NORMAL, \
aPath, \
NULL, \
NULL, \
NULL, \
NULL, \
NULL);

if (!rh)
{
if (GetLastError() == ERROR_SERVICE_EXISTS)
{
printf("Service exists.\n");
// service exists
rh = OpenService(sh, \
theDriverName, \
SERVICE_ALL_ACCESS);

if (!rh)
{
CloseServiceHandle(sh);
printf("Cann't open service.\n");
return false;
}
}

else
{
CloseServiceHandle(sh);
return false;
}
}

printf("Sevice handle is: %d\n", rh);
// start the drivers
if (rh)
{
if(0 == StartService(rh, 0, NULL))
{
DWORD errcode;
errcode = GetLastError();
if(ERROR_SERVICE_ALREADY_RUNNING == errcode)
{
// no real problem
}
else
{
printf("Error to start the service: %d\n", errcode);
CloseServiceHandle(sh);
CloseServiceHandle(rh);
return false;
}
}
CloseServiceHandle(sh);
CloseServiceHandle(rh);
}

return true;
}

StartService返回2(ERROR_FILE_NOT_FOUND),什么原因?
手抓饼加辣 2009-05-24
  • 打赏
  • 举报
回复
路过
wsq279024988 2009-05-22
  • 打赏
  • 举报
回复
学习一下啊
光宇广贞 2009-05-22
  • 打赏
  • 举报
回复
看看这个。
光宇广贞 2009-05-22
  • 打赏
  • 举报
回复
http://www.phpweblog.net/GaRY/archive/2007/05/08/Load_Driver_With_ZwLoadDriver.html
killcpp 2009-05-22
  • 打赏
  • 举报
回复
看了一下你的代码,你的driver name不正确,应该是\\\\.\\+driver name....
killcpp 2009-05-22
  • 打赏
  • 举报
回复
漏了,还要用CreateFile打开设备。
LoadDriver(...){
//首先使用OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS)
SC_HANDLE schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);

//将之前的驱动卸载
SC_HANDLE schService = OpenService(schSCManager,DriverName,SERVICE_ALL_ACCESS);

DeleteService(schService);

CloseServiceHandle(schService);

//创建新的驱动服务
schService = CreateService(schSCManager, DriverName, DriverName, SERVER_ALL_ACCESS,.....)
//打开新创建的服务
schService = OpenService(schSCManager,DriverName,SERVICE_ALL_ACCESS);
StartService(schService,0,NULL);

TCHAR completeDeviceName[64];
wsprint(completeDeviceName, TEXT("\\\\.\\%s"),DriverName);
HANDLE hDevice = CreateFile(completeDeviceName,....);

return hDevice; //使用这个HANDLE即可访问设备,以及DeviceIoControl(...)
}
killcpp 2009-05-22
  • 打赏
  • 举报
回复
笑笑:
23楼正解。
以手动启动的方式注册到Service,然后在应用程序启动的时候StartService。
LoadDriver(...){
//首先使用OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS)
SC_HANDLE schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);

//将之前的驱动卸载
SC_HANDLE schService = OpenService(schSCManager,DriverName,SERVICE_ALL_ACCESS);

DeleteService(schService);

CloseServiceHandle(schService);

//创建新的驱动服务
schService = CreateService(schSCManager, DriverName, DriverName, SERVER_ALL_ACCESS,.....)
//打开新创建的服务
schService = OpenService(schSCManager,DriverName,SERVICE_ALL_ACCESS);
StartService(schService,0,NULL);
...
}
yangjue1 2009-05-21
  • 打赏
  • 举报
回复
学习
redhat4 2009-05-21
  • 打赏
  • 举报
回复
提权



.


人力资源

fiveofhearts 2009-05-21
  • 打赏
  • 举报
回复
你自己网上搜索一下虚拟机+Windbg教程吧。就是你机器装winddbg,让他连到虚拟机去。虚拟机运行你的驱动,你机器windbg调试它。


具体你代码不清楚。不过有些驱动是不能动态加载的。我觉得是你驱动方面的事。调试一下吧。
yd4401 2009-05-21
  • 打赏
  • 举报
回复
就飞碟uioejuei饿诶ureiowurdjifd fodiuf dof doffdfdf
tisunpaul 2009-05-21
  • 打赏
  • 举报
回复
ding~~~~~~~~~
hjzwl1018 2009-05-21
  • 打赏
  • 举报
回复
[Quote=引用 38 楼 jingzhongrong 的回复:]
在DriverEntry中创建符号链接。
调试:虚拟机+Windbg
[/Quote]
谢谢!那还需要在虚拟机中安装这个软件了?
chaochaoltt 2009-05-21
  • 打赏
  • 举报
回复
1111111111111111111111111111111
星空仰望者 2009-05-21
  • 打赏
  • 举报
回复
好帖要顶
jingzhongrong 2009-05-20
  • 打赏
  • 举报
回复
在DriverEntry中创建符号链接。
调试:虚拟机+Windbg
hjzwl1018 2009-05-20
  • 打赏
  • 举报
回复
加了100分,请大家帮帮忙解决。
加载更多回复(36)

2,640

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 硬件/系统
社区管理员
  • 硬件/系统社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧