Snowming04's Blog
一颗红❤
Toggle navigation
Snowming04's Blog
主页
Cobalt Strike
Accelerated C++
区块链安全
友链
关于我
常用工具
代码积累
归档
标签
C# 实现 TCP Socket
2020-09-16 15:12:05
898
0
0
snowming
>因为蚂蚁笔记官方图片服务器极其不稳定,如果本文出现图片加载不出的问题,请转到此链接查看:https://note.roger101.com/blog/post/snowming/3958aac6882e 本文用 C# 实现简单的 socket TCP 传输,对于后续通过网络传输方式传输 shellcode 等起铺垫作用。 # 0x01 原理   >《HTTP权威指南》P84 **API 调用链:**  # 0x02 代码实现 目前实现的是短连接。 **服务端:** ``` using System; using System.Net; using System.Net.Sockets; using System.Security; using System.Text; using System.Threading; namespace 免杀Server { public class Server { //该程序创建一个套接字,然后开始无限循环。每次通过循环时,它接受一个连接并打印数据。当连接断开或连接客户端关闭时,程序接受新连接。 //1. 创建一个 Socket 来基于 TCP 协议交换数据 //AddressFamily 是一个 Enum;SocketType 也是一个 Enum //socket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Udp); //设置static其他类里面的方法使用时候就不用Server.socket static Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //从绑定的 Socket 接受数据到缓冲区,缓冲区设为一个1024字节的字节数组 private static byte[] receivedBuffer = new byte[1024]; //异常过滤器方法 private static bool LogException(Exception e) { Console.WriteLine($"\tIn the log routine. Caught {e.GetType()}"); Console.WriteLine($"\tMessage: {e.Message}"); return true; } private static Socket StartSocket(string ip, int port) { try { //2. 绑定 Socket IPEndPoint ipe = new IPEndPoint(IPAddress.Parse(ip), port); socket.Bind(ipe); //3. 开始监听 Listen(Int32):Places a Socket in a listening state. socket.Listen(128); Console.WriteLine($@"Serving Tcp on {ip} port {port}..."); //4. 开启一个新线程监听客户端连接 Thread listenClientThread = new Thread(ListenClientConnect); //使操作系统将当前线程实例的状态更改为 Running listenClientThread.Start(); //Todo: 用不用 while(true)? Console.ReadLine(); } catch (Exception e) when (LogException(e)) { SocketException h = (SocketException)e; Console.WriteLine($"\tErrorcode : {h.ErrorCode}"); } return socket; } //线程启动后,在线程上执行的方法。 private static void ListenClientConnect() { try { //5. 开始接收连接 Accept() - Creates a new Socket for a newly created connection. while (true) { Socket newConnection = socket.Accept(); // 发送祝贺语 UTF8Encoding utf8 = new UTF8Encoding(); string greetingWord = "已成功建立跟服务器之间的连接\n"; Byte[] encodedBytes = utf8.GetBytes(greetingWord); newConnection.Send(encodedBytes); //开启一个新线程接受数据 Thread ReceiveDataThread = new Thread(ReceiveData); //要把 newConnection 这个 socket 传入 ReceiveData 方法作委托函数的参数 ReceiveDataThread.Start(newConnection); } } catch (Exception e) when (LogException(e)) { } } private static void ReceiveData(object newConnection) { Socket clientConnection = (Socket)newConnection; while (true) { try { int receivedBytesNumber = clientConnection.Receive(receivedBuffer); //如果接收的数据为0字节时候,代表客户端发完了 //if (receivedBytesNumber == 0) // return; //C2 和木马建立连接就是不用关连接,一直接收数据 //打印到服务端的控制台;要注意这里中文不会乱码,传输中中文会乱码需要编码 Console.WriteLine($@"接收到来自客户端 {clientConnection.RemoteEndPoint?.ToString()} 的消息:{Encoding.UTF8.GetString(receivedBuffer)}"); //回复客户端 Byte[] reply = Encoding.UTF8.GetBytes("服务端已成功接收到您发送的数据\n"); clientConnection.Send(reply, reply.Length, 0); //这是短链接,单次会话结束后就关闭socket。对于c2一些短的命令接收1024字节足够了。下次可以重新建立连接 clientConnection.Close(); //发送完数据关闭Socket并释放资源 Console.ReadLine(); } catch (Exception e) when (LogException(e)) { clientConnection.Shutdown(SocketShutdown.Both);//禁止发送和上传 clientConnection.Close();//关闭Socket并释放资源 break; } } } static void Main(string[] args) { StartSocket("127.0.0.1", 9999); } } } ``` **客户端:** ``` using System; using System.Net; using System.Net.Sockets; using System.Text; namespace ConsoleApp5 { public class GetSocket { private static Socket ConnectSocket(string server, int port) { Socket s = null; IPHostEntry hostEntry = null; //获取主机相关的信息 //使用异常过滤器 try { hostEntry = Dns.GetHostEntry(server); }catch (Exception e) when (LogException(e)) { Console.WriteLine("解析 IP 地址出现失败!"); } //IPHostEntry 实例的 AddressList 属性 - 获取或设置与主机关联的IP地址列表。 foreach(IPAddress address in hostEntry.AddressList) { //IPEndPoint 实例将网络端点表示为IP地址和端口号 IPEndPoint ipe = new IPEndPoint(address,port); //创建一个 socket 对象来和服务器建立连接 Socket tempSocket = new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp); tempSocket.Connect(ipe); if(tempSocket.Connected) { s = tempSocket; break; } else { continue; } } return s; } //此方法请求 特定服务器的 home page 内容 public static string SocketSendReceive(string server, int port) { string request = "GET / HTTP/1.1\r\nHost: " + server + "\r\nConnection: Close\r\n\r\n"; Byte[] bytesSent = Encoding.ASCII.GetBytes(request); Byte[] bytesReceived = new Byte[256]; string page = ""; //与特定的服务器 IP 和端口建立 socket 连接; using 表示只读块 using(Socket s = ConnectSocket(server, port)) { if (s == null) return ("Connection failed!"); //向服务器发送请求 s.Send(bytesSent, bytesSent.Length, 0); //接收服务器 home page 的内容 int bytes = 0; page = "Default HTML page on " + server + ":\r\n"; //当页面接收完成之后会block do { bytes = s.Receive(bytesReceived, bytesReceived.Length, 0); page += Encoding.UTF8.GetString(bytesReceived, 0, bytes); } while (bytes > 0); } return page; } //异常过滤器 private static bool LogException(Exception e) { Console.WriteLine($"\tIn the log routine. Caught {e.GetType()}"); Console.WriteLine($"\tMessage: {e.Message}"); return true; } } } ``` **效果:**  ----------------- # 参考资料: 1. ❤[Socket Basics](https://docs.oracle.com/cd/E19683-01/816-5042/sockets-89916/index.html) 2. [Socket Class](https://docs.microsoft.com/en-us/dotnet/api/system.net.sockets.socket?view=netcore-3.1),MSDN,参考了客户端实现 3. [C#版 Socket编程(最简单的Socket通信功能)](https://blog.csdn.net/e295166319/article/details/52808012),CSDN 4. [Exception filters](https://docs.microsoft.com/en-us/dotnet/csharp/tutorials/exploration/csharp-6?tutorial-step=7),MSDN C#6 异常过滤器实现 5. [Thread Class](https://docs.microsoft.com/en-us/dotnet/api/system.threading.thread?view=netcore-3.1),MSDN,主要看里面委托函数的定义使用 6. 《HTTP 权威指南》 7. [Windows Sockets Error Codes](https://docs.microsoft.com/en-us/windows/win32/winsock/windows-sockets-error-codes-2), MSDN 8. [.NET平台下C# socket通信](http://www.jytek.com/seesharpsocket)
上一篇:
通过内核 API 免杀
下一篇:
DLL 劫持中的函数名称装饰/改编/粉碎问题
0
赞
898 人读过
新浪微博
微信
腾讯微博
QQ空间
人人网
提交评论
立即登录
, 发表评论.
没有帐号?
立即注册
0
条评论
More...
文档导航
没有帐号? 立即注册