黑客业务

24小时接单的黑客,黑客业务,黑客怎么找,网络黑客,黑客技术

网络安全编程:Winsock编程基础

网络攻防是一个比较大的话题,比如端口扫描,SQL Injection基本技术,如扫描、数据包嗅探、网络密码猜测、后门、木马等。这些技术是入侵分析中常见的技术。

在学习扫描仪、嗅探器、木马等知识之前,我们必须首先学习网络编程的基本知识。网络编程的基础是深入学习网络的开始。没有基本知识,扫描和嗅探都是空谈。

01 网络基础知识

计算机通过互联网通信主要依靠互联网TCP/IP。本协议为应用层、传输层、网际层、链路层四层协议。TCP/IP下层协议总是为上层协议服务,下层协议的细节对上层协议透明。分层设计的优点是每层的功能都很清晰,修改一层的实现不会影响其他层。TCP/IP很多不同的协议都定义在每一层协议中,比如网际层协议ICMP、IGMP等,传输层TCP、UDP等。在众多协议中,最具代表性的协议是TCP和IP,因此,互联网协议被称为TCP/IP不要这么想TCP和IP是互联网协议的全部)。

IP协议是“Internet Protocol”简称是为计算机网络相互连接通信而设计的协议。IP协议中最重要的是IP地址,IP地址是网络上唯一识别计算机主机的地址。互联网上没有两台机器有相同的地址IP地址,所以来识别网络主机的。IP地址为32位长,用点分十进制法表示,例如“10.10.30.12”。IP地址指定的不是主机,而是网络接口设备。因此,如果主机有两个网络接口,就会有两个IP地址。一般情况下,普通主机只有一个网络接口设备,也只有一个IP地址,比如个人使用的地址,PC通常只有一个IP地址;对于服务器或网络设备(交换机、路由器等),将有多个网络接口设备,每个网络接口设备将有一个IP对于路由器这样的网络设备,会有多个地址IP地址。

IP地址分为五类,即A类、B类、C类、D类和E类。各类IP地址范围如表1所示。

表1 各类IP地址的范围

IP工作在TCP/IP 4层协议的“网际层”,网络层最重要的工作是路由数据包。这里说的IP被路由协议,即在路由过程中,IP该协议将用于路由协议。真正的数据包选择协议(实际上是路由算法,如何转发数据包)被称为路由协议,具体的路由协议有RIP、OSPF、BGP等待。对于入门,只要你知道IP地址是什么,IP地址的作用是什么?

传输层主要有两个协议,即TCP协议和UDP协议。

TCP是“Transmission Control Protocol”简称是指传输控制协议。TCP是面向连接的可靠通信协议。TCP协议是IP协议的上层协议,IP服务于TCP。

UDP是“User Datagram Protocol”简称是指用户数据报告协议。UDP为事务提供简单不可靠的信息传输服务,是一种无连接的传输层协议。

传输层为应用层提供服务,部分应用层协议是基于TCP的,比如FTP、HTTP,部分是基于的UDP的,比如DNS。IP层提供了IP地址用于识别网络主机,传输层提供了识别主机过程的端口。IP网络上的主机和主机上的通信过程由地址和端口号决定。

传输层为识别通信过程提供端口号。根据协议,端口分为TCP端口和UDP端口,TCP端口和UDP各有65536个端口。对于应用程序,一般使用1024以上的端口号,因为1024以下的端口号属于保留端口。Internet许多服务使用不到1024的端口号。为了避免冲突,程序员编写的应用程序不应使用不到1024的端口号。同一协议的端口不能冲突,例如Web服务器占了服务器TCP80端口不能再使用其他程序TCP80端口。常用的端口号如表2所示。

表2

除了不到1024的端口号,还有一些知名的端口号,比如MS SQL Server的端口号是1433,Windows远程桌面端口号为3389等。程序员在编写自己的网络应用程序时,应避免与这些常用端口发生冲突。

02用于面向连接协议和非面向连接协议的函数

1. 连接协议

在面向连接的协议中,在收发数据之前,必须在两台计算机之间建立一个通信通道,以确保两台计算机之间有一条相互通信的路径。数据传输后,切断通信通道。这种方式相当于打电话。用户在手机上拨打10086。客户服务人员接听后,用户可以开始打电话,打完电话后挂断电话。

面向连接的协议使用TCP,建立服务器和客户端通信信道所需的基本信息Winsock函数如下。

服务器端函数:

  • socket()->bind()->listen()->accept()->send()/recv()->closesocket()
  • 客户端函数:

  • socket()->connet()->send()/recv()->closesocket()
  • 2. 非面向连接协议

    在非面向连接的协议中,只要发送端直接传输要发送的数据,就不需要关注接收端是否能收到数据。当接收端收到数据时,它不会响应信息通知并发送给发送端。这样,它就相当于写信,把写好的信放在邮箱里,但不能保证收件人真的能收到这封信。

    非面向连接的协议使用的是UDP,服务器和客户端通信所需的基本信息Winsock函数如下:

    服务器端函数:

  • socket()->bind()->sendto()/recvfrom()->closesocket()
  • 客户端函数:

  • socket()->sendto()/recvfrom()->closesocket()
  • 03 Winsock网络编程知识

    Winsock是Windows以下是网络编程的基础。Winsock常用函数。

    1. Winsock初始化和释放

    在使用Winsock相关函数需要正确Winsock库初始化,使用后需要Winsock释放库Winsock库的初始化和释放函数如下。

    Winsock定义库的初始化函数:

  • intWSAStartup(WORDwVersionRequested,LPWSADATAlpWSAData);
  • 函数的第一个参数wVersionRequested是需要初始化Winsock库的版本号。第二个参数lpWSAData是一个指向WSADATA指针。函数的返回值为0,表明函数调用成功。如果函数调用失败,则返回其他值。初始化函数可以在程序开始时使用Winsock相关的所有API函数。

    Winsock库释放函数的定义:

  • intWSACleanup(void);
  • 该函数没有参数,在程序的结束处直接调用该函数,即可释放Winsock库。

    初始化和释放Winsock图书馆的代码示例如下:

  • WORDwVersionRequested;
  • WSADATAwsaData;
  • interr;
  • wVersionRequested=MAKEWORD(2,2);
  • err=WSAStartup(wVersionRequested,&wsaData);
  • if(err!=0)
  • {
  • return-1;
  • }
  • if(LOBYTE(wsaData.wVersion)!=2||
  • HIBYTE(wsaData.wVersion)!=2)
  • {
  • WSACleanup();
  • return-1;
  • }
  • //……
  • WSACleanup();
  • 2. 创建和关闭套接字

    套接字用于根据指定的协议类型分配套接字描述符。该描述符主要用于客户端和服务器端之间的通信连接。当使用套接字时,应关闭套接字以释放资源。创建套接字和关闭套接字的函数socket()和closesocket()。

    创建套接字的函数定义如下:

  • SOCKETsocket(intaf,inttype,intprotocol);
  • socket()函数有三个参数,第一个参数af在Windows有多个参数值可以使用,但只有两个参数可以真正使用,即AF_INET和PF_INET。这两个宏在Winsock2.h下面的定义是相同的,分别如下:

  • #defineAF_INET2/*internetwork:UDP,TCP,etc.*/
  • /*
  • *Protocolfamilies,sameasaddressfamiliesfornow.
  • */
  • #definePF_INETAF_INET
  • 摘自以上两个定义Winsock2.h从定义中可以看出,PF_INET和AF_INET是一样的PF_INET宏定义上面的注释,AF表示地址族(Address Family),而PF表示协议族(Protocol Family)。对于Windows两者是一样的;对于Unix/Linux两者是不同的。一般来说,在调用中socket()函数应使用PF_INET,并在设置地址时使用AF_INET。FP_INET上面的注释也来自Winsock2.h头文件中。“Protocol families,same as address families for now.”,也就是说,目前PF和AF是一样的。注释说目前是一样的,这个定义可能是为了保持良好的兼容性。socket()函数应使用PF_INET尽量避免或不使用宏AF_INET宏。

    socket()函数的第 2 个参数 type 是指定新套接字描述符的类型。这里通常有三个值,即 SOCK_STREAM、SOCK_DGRAM 和 SOCK_RAW,分别表示流套接字、数据包接字和原协议接口。

    socket()函数第 3 参数 protocol 用于指定应用程序中使用的通信协议,可在此选择 IPPROTO_TCP、IPPROTO_UDP、IPPROTO_ICMP 等协议,该参数的值根据 2 参数的值进行选择。如果使用第二个 参数SOCK_STREAM,那么应该使用第三 参数IPPROTO_TCP;如果使用 3 参数SOCK_DGRAM,那么第 3 参数应该用 IPPROTO_UDP。为了简单地写作,如果第 2 参数是 SOCK_STREAM 或 SOCK_DGRAM,那么第 3 参数可以默认为 0。如果第 2 参数指定为 SOCK_RAW,必须指定第 3 参数,而不是 0 值。

    socket()函数调用成功返回值为新的套接字描述符。如果调用失败,返回 INVALID_SOCKET。调用失败后,如果你想知道调用失败的原因,调用 WSAGetLastError()函数得到错码。

    所有的Winsock函数出错后,都可以调用WSAGetLastError()函数得到错码,但是WSAStartup()不能通过WSAGetLastError()因为()得到了错码而得到错误码WSAStartup()调用不成功,不能调用WSAGetLastError()函数。

    关闭套接字的函数定义如下:

  • intclosesocket(SOCKETs);
  • closesocket()函数参数为 socket()函数创建的套接字描述符。

    对于WSAStartup()/WSACleanup()和socket()/closesocket()最好保持这样的函数成对出现。也就是说,写完一个函数后,立即写下另一个函数的呼叫,以免忘记资源的释放。

    3. 面向连接协议的函数

    bind()、listen()、accept()、connect()、send()和recv()这些函数是常用的面向连接函数,它们都是Winsock最基本的面向连接函数。以下是使用几个函数的方法。

    通过socket()函数可以创建一个新的连接字描述符,但它只是一个描述符,它为网络的一些资源做准备。要真正在网络上通信,需要当地地址和当地端口号信息。当然,地址和端口号信息应该与连接字描述符绑定。Winsock使用函数bind()函数完成套接字与地址端口信息的绑定。bind()函数的定义如下:

  • intbind(SOCKETs,conststructsockaddrFAR*name,intnamelen);
  • 该函数有三个参数,第一个参数s是新创建的套接字描述符,即使用socket()函数创建的描述符,第二个参数name是一个sockaddr第三个参数提供地址和端口信息namelen是sockaddr结构体的大小。

    在第二个参数中sockaddr结构定义如下:

  • structsockaddr{
  • u_shortsa_family;
  • charsa_data[14];
  • };
  • 结构体共有16字节,结构体前使用的结构体为sockaddr_in,结构体的定义如下:

  • structsockaddr_in{
  • shortsin_family;
  • u_shortsin_port;
  • structin_addrsin_addr;
  • charsin_zero[8];
  • };
  • sockaddr设计结构体是为了保持每个特定协议之间的结构体兼容性。bind()函数指定地址和端口时,向sockaddr_in结构体填充相应的内容,调用函数时应使用sockaddr结构体。

    在sockaddr_in结构体中,还有一个结构体in_addr,该结构体在winsock2.h定义如下:

  • structin_addr{
  • union{
  • struct{u_chars_b1,s_b2,s_b3,s_b4;}S_un_b;
  • struct{u_shorts_w1,s_w2;}S_un_w;
  • u_longS_addr;
  • }S_un;
  • };
  • 该结构是一个共同体S_un,包括两个结构的变量和一个u_long类型变量。一般使用IP地址用点分十进制表示,in_addr结构体内没有提供保存点十进制表示IP此时,需要使用转换函数来表示地址的数据类型IP地址转换成in_addr可接受的结构类型。这里使用的转换函数是inet_addr()函数的定义如下:

  • unsignedlonginet_addr(constcharFAR*cp);
  • 函数表示点分十IP地址转换成unsigned long类型值。函数的参数cp指向点分十进制IP地址的字符指针。同时,函数有一个逆函数,是将unsigned long型的数值型IP地址转换为点分十进制IP函数的定义如下:

  • charFAR*inet_ntoa(structin_addrin);
  • sockaddr_in 结构体中的 sin_port 表示端口需要大尾字节序存储(大尾和小尾是两种不同的存储方式)。Intel X86 在架构下,默认情况下,数值存储模式是小尾字节序, TCP/IP 的数值存储方式都是大尾方式的字节序。为了实现方便的转换,winsock2.h即 htons()和 htonl()两个函数,并提供它们的逆函数 ntohs()和 ntohl()。

    htons()和 htonl()函数的定义如下:

  • u_shorthtons(u_shorthostshort);
  • u_longhtonl(u_longhostlong);
  • ntohs()和 ntohl()函数的定义如下:

  • u_shortntohs(u_shortnetshort);
  • u_longntohl(u_longnetlong);
  • 在这四个函数中,前两个函数将主机字节序转换为网络字节序(host to network),后两个函数将网络字节序转换为主机字节序(network to host)。在一些架构系统下,主机字节序与网络字节序相同,因此转换函数没有任何转换,但为了代码的移植,转换函数仍然会被调用。

    具体bind()函数的使用方法如下:

  • ///创建套接字
  • SOCKETsLisent=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
  • //对sockaddr_in结构填充地址、端口等信息
  • structsockaddr_inServerAddr;
  • ServerAddr.sin_family=AF_INET;
  • ServerAddr.sin_addr.S_un.S_addr=inet_addr("10.10.30.12");
  • ServerAddr.sin_port=htons(1234);
  • ///绑定套接字和地址信息
  • bind(sLisent,(SOCKADDR*)&ServerAddr,sizeof(ServerAddr));
  • 服务器端的地址可以指定为INADDR_ANY宏,表示“任意地址”或“所有地址”。当客户端启动连接时,服务器操作系统会根据网络配置自动选择客户端连接IP通信地址和客户端。

    当套接字符与地址端口信息绑定时,需要监控端口。当端口处于监控状态时,其他主机可以连接。监控端口和接收连接请求的函数分别为listen()和accept()。

    监控端口的函数定义如下:

  • intlisten(SOCKETs,intbacklog);
  • 该函数有两个参数,第一个参数s指定要监控的套接字描述符,第二个参数backlog允许进入请求连接队列的数量,backlog最大值由系统指定winsock2.h其最大值由中SOMAXCONN该值的定义如下:

  • #defineSOMAXCONN0x7fffffff
  • 接收连接请求的函数定义如下:

  • SOCKETaccept(SOCKETs,structsockaddrFAR*addr,intFAR*addrlen);
  • 该函数从连接请求队列中获取连接信息,创建新的套接字描述符并获取客户端地址。新创建的套接字用于与客户端通信。服务器和客户端通信完成后,还需要使用套接字closesocket()关闭函数以释放相应的资源。该函数有三个参数,第一个参数s第二个参数是监字描述符,第二个参数addr是一个指向sockaddr第三个参数用于返回客户端的地址信息addrlen是一个指向int该类型的指针变量用于传输sockaddr结构体的大小。

    以上是连接到服务器端的函数,完成了服务器应有的一系列基本动作,具体如下。

    ① bind()函数绑定套接字描述符和地址信息。

    ② listen()函数将绑定过套接字描述符置于监听状态。

    ③ accept()函数获取连接队列中的连接信息,创建与客户端通信的新套接字描述符。

    面向连接的客户端只需完成与服务器的连接,即可实现与服务器端的通信。创建套接字描述符后,使用connect()函数可以与服务器连接。

    connect()函数的定义如下:

  • intconnect(SOCKETs,conststructsockaddrFAR*name,intnamelen);
  • 该函数的功能是连接套接字。该函数有三个参数,第一个参数s第二个参数表示创建的套接字描述符name是指向sockaddr结构体指针,sockaddr服务器保存在结构中IP地址和端口号,第3个参数namelen是指定sockaddr结构体的长度。

    使用客户端时connect()函数与服务器连接后,客户端和服务器可以通信。通信主要是发送信息和接收信息。这里有两个函数,即send()和recv()。

    发送函数send()定义如下:

  • intsend(SOCKETs,constcharFAR*buf,intlen,intflags);
  • 该函数有四个参数,第一个参数s是套接字描述符,用于服务器端。accept()函数返回的套接字描述符用于客户端socket()函数创建的套接字描述符,第二个参数buf第三个参数是发送消息的缓冲区len第四个参数是缓冲区的长度flags通常给0值。

    接收函数recv()定义如下:

  • intrecv(SOCKETs,charFAR*buf,intlen,intflags);
  • 函数有四个参数。函数的使用方法和send()函数的使用方法相同,这里就不介绍了。

    从send()和recv()两个函数的名称分别意味着发送和接受,但实际上数据的发送和接收取决于网络协议,send()函数和recv()函数只是从网络协议使用的缓冲区复制数据的动作。

    4. 非面向连接协议的函数

    面向连接TCP在服务器端绑定套接字描述符和地址后,需要监控端口,等待接收客户端的连接请求,客户端需要连接服务器,以确保面向连接TCP调用可靠传输connect()函数的过程中也完成了TCP的“三次握手”过程。非面向连接的过程。UDP协议在开发过程中基本向连接TCP协议是一样的。非面向连接UDP在开发过程中,服务器端不需要监控端口,也不需要等待接收客户端的连接请求,客户端也不需要完成与服务器端的连接。“三次握手”这个过程被省略了,所以UDP相对于TCP它似乎不可靠,但在效率方面要快TCP。

    服务器端不再需要在非面向连接协议开发中调用listen()、accept()函数,客户端不再需要调用connect()函数。使用服务器和客户端的通信函数sendto()和recvfrom()函数。

    sendto()函数的定义如下:

  • intsendto(
  • SOCKETs,
  • constcharFAR*buf,
  • intlen,
  • intflags,
  • conststructsockaddrFAR*to,
  • inttolen
  • );
  • 这个函数是用来的UDP通信双方发送数据的函数有6个参数和第一个参数s第二个参数是套接字描述符buf第三个参数是发送数据的缓冲区len指定第二个参数的长度,第四个参数通常赋予0值,第五个参数to是一个指向sockaddr结构体指针,这里给出接收信息的地址信息,第六个参数tolen指定第五个参数的长度。

    recvfrom()函数的定义如下:

  • intrecvfrom(
  • SOCKETs,
  • charFAR*buf,
  • intlen,
  • intflags,
  • structsockaddrFAR*from,
  • intFAR*fromlen
  • );
  • 该函数是用来在UDP通信双方接收数据的函数。函数的用法和sendto()同样,这里不再介绍。

    sendto()函数和recvfrom()函数的功能与send()函数和recv()函数相似,都是用来复制网络协议缓冲区数据的函数,并不是真正完成数据的发送和接收。

    04 字节顺序

    由于架构不同,字节序的存在CPU访问数据时采用的顺序不同,计算机内存中存储数值的标准也不同于系统架构。了解字节存储顺序是逆向工程的基本知识。在动态分析程序时,通常需要观察内存数据的变化。如果您不了解字节存储顺序,您可能会迷失在内存的海洋中,无法继续逆向航行。

    1. 字节序基础

    通常,内存中存储数值的方法有两种,一种是大尾方法(大尾字节目是网络字节目),另一种是小尾方法。

    先来看一个简单的例子,比如0x01020304这样的值,如果存储在大尾部,存储在01 02 03 04,而小尾部存储在04 03 02 01。这意味着它可能不直观,并以表格的形式显示其具体差异,如表3所示。

    表3 字节顺序对比表

    以下结论可从表中得出。

    大尾存储方式:内存高位地址存储数据低位字节数据,内存低位地址存储数据高位字节数据;

    小尾存储模式:内存高位地址存储数据高位字节数据,内存低位地址存储数据低位字节数据。

    2. 主机字节序和网络字节序

    主机字节序和网络字节序是相对概念。

    所谓主机字节序,是指主机存储数据时的字节顺序,主机字节序因系统架构而异。Windows兼容操作系统CPU而小尾的方式UNIX兼容操作系统CPU大多数是大尾巴。因此,主机字节序不是固定字节序,需要根据不同的系统架构来确定。

    所谓网络字节序,是指网络传输相关协议规定的字节传输顺序,TCP/IP使用的字节序是大尾法。

    3. 字节序相关函数

    与字节序常用相关的函数有关htons()、htonl()、ntohs()和ntohl()。这四个函数的定义如下:

  • u_shorthtons(u_shorthostshort);
  • u_longhtonl(u_longhostlong);
  • u_shortntohs(u_shortnetshort);
  • u_longntohl(u_longnetlong);
  • 在Windows下面,由于内存中的存储方式发生了变化,使用上述四个转换函数会改变值的大小。UNIX在系统下,使用上述四个转换函数不会发生任何变化。无论是哪个系统,在网络开始时都需要调用这些函数进行转换,因为这可以有效地确保网络是网络字节序。

    4. 编程判断主机字节序

    “编程判断主机字节序”这是许多杀毒软件公司或安全开发职位的面试问题,因为这个问题更基本。以下是实现这个问题的方法。有两种方法可以完成这个问题,第一种方法是“取值比较法”,第2种方法是“直接转换比较法”。

    方法一:取值比较法

    所谓的值比较法首先定义了4字节的16进制数。由于使用调试器查看内存最直观的是16进制值,因此定义16进制数是一种更直观的操作方法。然后通过指针取出这个16进制数“内存”最后,将中间的字节与实际值中相应的数量进行比较。由于字节序的问题,内存中的字节可能与实际值中的字节不同,以确定字节序。

    代码如下:

  • intmain(intargc,char*argv[])
  • {
  • DWORDdwSmallNum=0x01020304;
  • if(*(BYTE*)&dwSmallNum==0x04)
  • {
  • printf("SmallSequence.\r\n");
  • }
  • else
  • {
  • printf("BigSequence.\r\n");
  • }
  • return0;
  • }
  • 定义了上述代码0x0102030416进制数,其在小尾内存中的存储顺序为04 03 02 01。*(BYTE *)&dwSmallNum内存中低地址位值,如果是小尾法,则低地址位存储值为0x04,假如是大尾的方式0x01。

    方法二:直接转换比较法

    所谓直接转换比较法,是利用字节序转换函数将所定义的值进行转换,然后用转换后的值和原值进行比较。如果原值与转换后的值相同,说明为大尾方式,否则为小尾方式。

    代码如下:

  • intmain(intargc,char*argv[])
  • {
  • DWORDdwSmallNum=0x01020304;
  • if(dwSmallNum==htonl(dwSmallNum))
  • {
  • printf("BigSequence.\r\n");
  • }
  • else
  • {
  • printf("SmallSequence.\r\n");
  • }
  • return0;
  • }
  • 这种方法比较直接。如果转换后的结果等于原值,则表示为大尾法,因为转换后的结果是网络字节序,网络字节序等于大尾法。

    我们必须调试和体验字节序的内容,因为在网络开发中只需要简单的转换,不需要太在意它的细节。如果是逆向工程,在内存中搜索数据,那么字节序的知识就会被使用。

       
    • 评论列表:
    •  辞眸里予
       发布于 2022-05-29 21:30:35  回复该评论
    • 数s是新创建的套接字描述符,即使用socket()函数创建的描述符,第二个参数name是一个sockaddr第三个参数提供地址和端口信息namelen是sockaddr结
    •  孤央邶谌
       发布于 2022-05-30 05:28:45  回复该评论
    • 7fffffff接收连接请求的函数定义如下:SOCKETaccept(SOCKETs,structsockaddrFAR*addr,intFAR*addrlen);该函数从连接请求队列中获取连接
    •  惑心珞棠
       发布于 2022-05-29 23:27:59  回复该评论
    • ro[8];};sockaddr设计结构体是为了保持每个特定协议之间的结构体兼容性。bind()函数指定地址和端口时,向sockaddr_in结构体填充相应的内容,调用函数时应使用sockaddr结构体。在

    发表评论:

    Powered By

    Copyright Your WebSite.Some Rights Reserved.