木马,你好!(七)远程弹出记事本写字

RemoteNotepad

要实现这个功能其实挺简单的:

  1. 客户顿通信服务端(第二讲已经实现)
  2. 远程端 CreateProcess,创建一个 notepad
  3. 拿到这个 notepad 的句柄,在调用 SendMessage

创建记事本

进程编程相关知识请参阅:Windows API教程(四) 进程编程

BOOL CreateNotepad()
{
	BOOL flag;
	STARTUPINFO start_info;

	ZeroMemory( &process_info, sizeof(process_info) );
	ZeroMemory( &start_info, sizeof(start_info) );

	start_info.cb = sizeof(start_info);

	flag = CreateProcess( 
		NULL,           // 不传程序路径, 使用命令行
		"notepad.exe",  // 命令行命令
		NULL,           // 不继承进程句柄(默认)
		NULL,           // 不继承线程句柄(默认)
		FALSE,          // 不继承句柄(默认)
		0,              // 没有创建标志(默认)
		NULL,           // 使用默认环境变量
		NULL,           // 使用父进程的目录
		&start_info,    // STARTUPINFO 结构
		&process_info );// PROCESS_INFORMATION 保存相关信息

	if ( !flag )
	{
		printf( "创建失败 Error: (%d).n", GetLastError() );
		return 0;
	}
	return 1;
}

将字符串写到记事本的 RichEdit 控件中

更多 RichEdit 控件的 Message 请参阅:Windows SDK 教程(四) 记事本与 SendMessage

void WriteNotepadText(char *str)
{
	char text[250];
	HWND hNotepad = FindWindow(TEXT("Notepad"), NULL);
	HWND hEdit = FindWindowEx(hNotepad, NULL, TEXT("Edit"), NULL);
	wsprintf(text, "%srn", str);
	SendMessage(hEdit, EM_REPLACESEL, NULL, (LPARAM)text);
}

完整客户端代码

#include <Winsock2.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")

#define MSG_LEN 1024
PROCESS_INFORMATION process_info;

BOOL strstart(char *text, char *begin);
BOOL CreateNotepad();
void WriteNotepadText(char *str);
void CloseNotepad();

int run(char *recvCmd, char *message)
{
	if (strcmp(recvCmd, "test") == 0)
	{
		strcpy(message, "服务端你好,有什么事吗~");
	}
	else if (strcmp(recvCmd, "open") == 0)
	{
		if(CreateNotepad())
		{
			strcpy(message, "记事本创建成功");
		} else {
			strcpy(message, "记事本创建失败!");
		}
	}
	else if (strcmp(recvCmd, "close") == 0)
	{
		CloseNotepad();
		strcpy(message, "Closed.");
	}
	else if (strstart(recvCmd, "write"))
	{
		WriteNotepadText(recvCmd + sizeof("write"));
		strcpy(message, "send");
	}
	else if (strcmp(recvCmd, "exit") == 0)
	{
		return 1;
	}
	
	return 0;
}

void main()
{
	int err = 0;
	char message[MSG_LEN] = {0};
	char recvCmd[100] = {0};

	SOCKET sockClient; // 客户端 Scoket
	SOCKADDR_IN addrServer; // 服务端地址

	WSADATA wsaData;
	WORD wVersionRequested;

	wVersionRequested = MAKEWORD( 2, 2 );

	err = WSAStartup( wVersionRequested, &wsaData );

	if ( err != 0 )
	{
		return;
	}

	if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 )
	{
		// 启动错误,程序结束
		WSACleanup( );
		return;
	}

	// 新建客户端 scoket
	sockClient = socket(AF_INET, SOCK_STREAM, 0);

	// 定义要连接的服务端地址
	addrServer.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");  // 目标IP (127.0.0.1是本机地址)
	addrServer.sin_family = AF_INET;                           // 协议类型是INET
	addrServer.sin_port = htons(6000);                         // 连接端口1234

	// 让 sockClient 连接到 服务端
	connect(sockClient, (SOCKADDR *)&addrServer, sizeof(SOCKADDR));

	while(1)
	{
		// 清空字符串
		ZeroMemory(recvCmd, sizeof(recvCmd));
		ZeroMemory(message, sizeof(message));
		// 从服务端获取数据
		recv(sockClient, recvCmd, MSG_LEN, 0);
		// 打印数据
		printf("-- 收到命令: [%s]n", recvCmd);

		run(recvCmd, message);

		if (strlen(recvCmd) > 0)
		{
			// 发送数据到服务端
			send(sockClient, message, strlen(message) + 1, 0);
		}
	}

	// 关闭socket
	closesocket(sockClient);
	WSACleanup();
}

/*
 * 创建一个记事本
 */
BOOL CreateNotepad()
{
	BOOL flag;
	STARTUPINFO start_info;

	ZeroMemory( &process_info, sizeof(process_info) );
	ZeroMemory( &start_info, sizeof(start_info) );

	start_info.cb = sizeof(start_info);

	flag = CreateProcess( 
		NULL,           // 不传程序路径, 使用命令行
		"notepad.exe",  // 命令行命令
		NULL,           // 不继承进程句柄(默认)
		NULL,           // 不继承线程句柄(默认)
		FALSE,          // 不继承句柄(默认)
		0,              // 没有创建标志(默认)
		NULL,           // 使用默认环境变量
		NULL,           // 使用父进程的目录
		&start_info,    // STARTUPINFO 结构
		&process_info );// PROCESS_INFORMATION 保存相关信息

	if ( !flag )
	{
		printf( "创建失败 Error: (%d).n", GetLastError() );
		return 0;
	}
	return 1;
}

/*
 * 将字符串写到记事本的 RichEdit 控件中
 */
void WriteNotepadText(char *str)
{
	char text[250];
	HWND hNotepad = FindWindow(TEXT("Notepad"), NULL);
	HWND hEdit = FindWindowEx(hNotepad, NULL, TEXT("Edit"), NULL);
	wsprintf(text, "%srn", str);
	SendMessage(hEdit, EM_REPLACESEL, NULL, (LPARAM)text);
}

/*
 * 关闭记事本
 */
void CloseNotepad() 
{
	// 关闭进程句柄和线程句柄
	DWORD dwDesiredAccess = PROCESS_TERMINATE;
	BOOL  bInheritHandle  = FALSE;
	HANDLE hProcess = OpenProcess(dwDesiredAccess, bInheritHandle, process_info.dwProcessId);
	if (hProcess == NULL)
		return;
	TerminateProcess(hProcess, 0);
	CloseHandle(hProcess);
}

/*
 * 判断 text 字符串是否以 begin 字符串开头
 */
BOOL strstart(char *text, char *begin)
{
	while(*begin)
		if (*begin++ != *text++)
			return FALSE;
	return TRUE;
}

服务端代码

代码依旧是老样子:

#include <stdio.h>
#include <string.h>
#include <Winsock2.h>
#pragma comment(lib, "ws2_32.lib")

void main()
{
	int err; // 错误信息
	int len = sizeof(SOCKADDR);

	char  cmdStr[100] = {0};
	char sendBuf[100] = {0}; // 发送至客户端的字符串
	char recvBuf[100] = {0}; // 接受客户端返回的字符串
	char * ip;

	SOCKET sockServer;     // 服务端 Socket
	SOCKADDR_IN addrServer;// 服务端地址
	SOCKET sockClient;     // 客户端 Scoket
	SOCKADDR_IN addrClient;// 客户端地址

	WSADATA wsaData;       // winsock 结构体
	WORD wVersionRequested;// winsock 的版本

	// 配置 Windows Socket版本
	wVersionRequested = MAKEWORD( 2, 2 );

	// 初始化 Windows Socket
	err = WSAStartup( wVersionRequested, &wsaData );

	if ( err != 0 )
	{
		// 启动错误,程序结束
		return;
	}

	if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 )
	{
		// 启动错误,程序结束
		WSACleanup(); // 终止Winsock 2 DLL (Ws2_32.dll) 的使用
		return;
	}

	// 定义服务器端socket
	sockServer = socket(AF_INET, SOCK_STREAM, 0);
	//  设置服务端 socket
	addrServer.sin_addr.S_un.S_addr = htonl(INADDR_ANY); // 本机IP
	addrServer.sin_family = AF_INET;                   // 协议类型是INET
	addrServer.sin_port = htons(6000);                 // 绑定端口6000
	// 将服务器端socket绑定在本地端口
	bind(sockServer, (SOCKADDR *)&addrServer, sizeof(SOCKADDR));
	// Listen 监听端口
	listen(sockServer, 5); // 5 为等待连接数目

	printf("服务器已启动:n监听中...n");

	// 等待客户端连接
	sockClient = accept(sockServer, (SOCKADDR *)&addrClient, &len);
	// 获取ip地址
	ip = inet_ntoa(addrClient.sin_addr);
	// 输出连接提示
	printf("-- IP %s 连接到服务端n", ip);

	while (1)
	{
		if (strcmp(cmdStr, "exit") == 0)
		{
			break;
		}

		printf("-- %s: %s n>>", ip, recvBuf);
		gets(cmdStr);

		send(sockClient, cmdStr, strlen(cmdStr) + 1, 0);
		recv(sockClient, recvBuf, 100, 0);
	}

	closesocket(sockClient);
	WSACleanup();
}

文章索引

上一讲:木马,你好!(六)Hook 监听木马(截图监控)
下一讲:木马,你好!(八)注册表操作

7 thoughts on “木马,你好!(七)远程弹出记事本写字

      • 博主 你好,后面的是不是不出了呀??这算是windows核心编程吗??

      • Hi, 你好, 这些大部分是我 3, 4 年前关注的领域, 后来已经从 windows 弃坑转投 linux/mac 阵营 😂

  1. 博主,这么多年了,我也来学习了,后面四篇是不是不能更新了,哈哈!

  2. 博主 我最近在做这方面的程序 感觉很有帮助 要坚持更啊啊啊!!!!

留下评论