rust在windows下使用windows-rs开发网络抓包工具

为方便查看和对比, 做了c++版, 通过c++版搬迁到rust进行改改,实际的原理c++和rust都是运用windows提供的winsock2 api接口进行操作

注意: 需要管理员权限执行

rust版:

use windows::Win32::Networking::WinSock::*;
use windows::core::PCSTR;


fn main() {
    println!("Hello, world!");

    unsafe {
        let mut wsa: WSADATA = WSADATA::default();
        let mut error: i32;
        error = WSAStartup(514, &mut wsa);
        if error != 0 {
            println!("{} : {}", "WSAStartup: ",  error);
        }

        let mut hostname: [u8; 24] = [0; 24];
        gethostname(&mut hostname);

        let hostname_str: Result<_, _> = std::str::from_utf8(&hostname);
        match hostname_str {
            Ok(s) => {
                let string: String = s.to_string();
                println!("{}", string);
            },
            Err(e) => {
                println!("Invalid UTF-8: {}", e);
            }
        }

        let mut result_default: ADDRINFOA = ADDRINFOA::default();
        let mut result: *mut ADDRINFOA = &mut result_default;
        let mut hints: ADDRINFOA = ADDRINFOA::default();

        hints.ai_family = AF_INET.0 as i32;
        hints.ai_socktype = SOCK_RAW.0;
        hints.ai_protocol = IPPROTO_IP.0;

        error = getaddrinfo(PCSTR(hostname.as_ptr()), None, Some(&hints), &mut result);
        if error != 0 {
            println!("{} : {:?}", "getaddrinfo: ",  WSAGetLastError());
            WSACleanup();
        }

        let raw_socket: SOCKET = socket( (*result).ai_family, WINSOCK_SOCKET_TYPE((*result).ai_socktype), (*result).ai_protocol);
        if raw_socket == INVALID_SOCKET {
            println!("{} : {:?}", "socket: ", WSAGetLastError());
            freeaddrinfo(Some(result));
            WSACleanup();
        }

        let r_a_l: i32 = (*result).ai_addrlen as i32;
        error = bind(raw_socket, (*result).ai_addr, r_a_l);
        if error == SOCKET_ERROR {
            println!("{} : {:?}", "bind: ", WSAGetLastError());
            freeaddrinfo(Some(result));
            closesocket(raw_socket);
            WSACleanup();
        }



        let mut dw_value: u32 = RCVALL_ON.0 as u32;
        let sio: i32 = SIO_RCVALL as i32;
        error = ioctlsocket(raw_socket, sio, &mut dw_value);
        if error != 0 {
            println!("{} : {:?}", "ioctlsocket: ", WSAGetLastError());
            freeaddrinfo(Some(result));
            closesocket(raw_socket);
            WSACleanup();
        }

        

        let mut buff: [u8; 1024] = [0; 1024];
        let mut count: i32;
        loop {
            count = recv(raw_socket, &mut buff, SEND_RECV_FLAGS(0));
            if count == SOCKET_ERROR {
                println!( "recv: " );
            }
            else {
                println!("{:?}", buff);
            }
        }

        // freeaddrinfo(Some(&result));
        // closesocket(raw_socket);
        // WSACleanup();
    }

}

c++版:

#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <mstcpip.h>
#include <comdef.h>

#pragma comment(lib, "ws2_32.lib")

int log(std::string str) {
	int lastError = WSAGetLastError();
	LPTSTR lpMsgBuf;
	if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
		FORMAT_MESSAGE_FROM_SYSTEM |
		FORMAT_MESSAGE_IGNORE_INSERTS,
		NULL,
		lastError,
		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
		(LPTSTR)&lpMsgBuf,
		0, NULL) != 0) {
		// 输出错误信息
		std::cout << str << "[" << lastError << "]" << (char*)_bstr_t(lpMsgBuf) << std::endl;
		LocalFree(lpMsgBuf);
	}
	return lastError;
}

int main()
{
	WSADATA wsa;
	int errror;
	if (errror = WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {
		log("WSAStartup: ");
		return -1;
	}

	char name[100];
	gethostname(name, sizeof(name));

	struct addrinfo *result = NULL, *ptr = NULL, hints;



	ZeroMemory(&hints, sizeof(hints));
	hints.ai_family = AF_INET6;
	hints.ai_socktype = SOCK_RAW;
	hints.ai_protocol = IPPROTO_IP;

	if (errror = getaddrinfo(name, 0, &hints, &result) != 0) {
		std::cout << errror << std::endl;
		log("getaddrinfo: ");
		WSACleanup();
		return 1;
	}

	SOCKET rawSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
	if (rawSocket == INVALID_SOCKET) {
		std::cout << rawSocket << std::endl;
		log("socket: ");
		freeaddrinfo(result);
		WSACleanup();
		return -1;
	}

	//struct sockaddr_in addr;
	//addr.sin_family = AF_INET;
	//addr.sin_port = 0;
	//addr.sin_addr = in4addr_any;

	struct sockaddr_in6 addr;
	addr.sin6_family = AF_INET6;
	addr.sin6_port = 0;
	addr.sin6_flowinfo = 0;
	addr.sin6_addr = in6addr_any;
	addr.sin6_scope_id = 0;
	//if (errror = bind(rawSocket, result->ai_addr, (int)result->ai_addrlen) == SOCKET_ERROR) {
	if (errror = bind(rawSocket, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) {
		std::cout << errror << std::endl;
		log("bind: ");
		freeaddrinfo(result);
		closesocket(rawSocket);
		WSACleanup();
		return -1;
	}

	//BOOL bValue = TRUE;
	//if (errror = setsockopt(rawSocket, result->ai_protocol, IPPROTO_RAW, (char*)&bValue, sizeof(bValue)) == SOCKET_ERROR) {
	//	std::cout << errror << std::endl;
	//	log("setsockopt: ");
	//	freeaddrinfo(result);
	//	closesocket(rawSocket);
	//	WSACleanup();
	//	return -1;
	//}

	DWORD dwValue = RCVALL_ON;
	if (errror = ioctlsocket(rawSocket, SIO_RCVALL, &dwValue) != 0) {
		std::cout << errror << std::endl;
		log("ioctlsocket: ");
		freeaddrinfo(result);
		closesocket(rawSocket);
		WSACleanup();
		return -1;
	}

	char buff[4096];
	int nRet;
	struct sockaddr_in6 from;
	int fromLen = sizeof(from);
	while (true) {
		nRet = recv(rawSocket, buff, 4096, 0);
		//nRet = recvfrom(rawSocket, buff, sizeof(buff), 0, (struct sockaddr*)&from, &fromLen);
		std::cout << nRet << std::endl;
		if (nRet == SOCKET_ERROR) {
			log("recv: ");
		}
	}

	freeaddrinfo(result);
	closesocket(rawSocket);
	WSACleanup();
	return 0;
}

使用 GTK-rs 库需要先安装 GTK+3,可以在 Linux 系统下通过包管理器安装,也可以在 Windows 和 macOS 下从官网下载安装程序进行安装。 安装 GTK+3 后,可以在 Rust 项目中添加 gtk 和 gdk 两个依赖: ```toml [dependencies] gtk = "0.9" gdk = "0.9" ``` 然后在 Rust 代码中引入 gtk 和 gdk 库: ```rust extern crate gtk; extern crate gdk; ``` 在 GTK-rs 中,主要有两种方式创建 GUI 窗口:Builder 和手动创建。下面分别介绍这两种方式。 ### 使用 Builder 创建 GUI 窗口 使用 Builder 可以通过 XML 文件描述 GUI 界面,然后使用 Rust 代码加载并显示窗口。以下是一个简单的例子: ```xml <?xml version="1.0" encoding="UTF-8"?> <interface> <object class="GtkWindow" id="main_window"> <property name="title">Hello, World!</property> <property name="default-width">400</property> <property name="default-height">300</property> <child> <object class="GtkLabel" id="label"> <property name="label">Hello, World!</property> </object> </child> </object> </interface> ``` 在 Rust 代码中,可以使用 gtk::Builder 加载并显示窗口: ```rust use gtk::prelude::*; use gtk::{Builder, Window}; fn main() { if let Err(err) = gtk::init() { eprintln!("Failed to initialize GTK: {}", err); return; } let glade_src = include_str!("path/to/glade/file.glade"); let builder = Builder::from_string(glade_src); let window: Window = builder.get_object("main_window").unwrap(); window.show_all(); gtk::main(); } ``` ### 手动创建 GUI 窗口 手动创建 GUI 窗口需要在 Rust 代码中定义窗口和窗口中的组件,以下是一个简单的例子: ```rust use gtk::prelude::*; use gtk::{Window, WindowType, Label}; fn main() { if let Err(err) = gtk::init() { eprintln!("Failed to initialize GTK: {}", err); return; } let window = Window::new(WindowType::Toplevel); window.set_title("Hello, World!"); window.set_default_size(400, 300); let label = Label::new(Some("Hello, World!")); window.add(&label); window.show_all(); gtk::main(); } ``` 以上代码中,创建了一个顶层窗口和一个标签组件,将标签添加到窗口中并显示窗口。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值