2013年3月4日星期一

【转】delphi端口扫描源程序

作者:啊D 

  ------------------------------------------------ 
     本程序由“啊D”制作! 
     QQ:9269563 
     E-Mail:paf@163.net 
     主页:Http://coold.cn99.com 
     制作于:2002.8.27 
  **你可以随意修改代码! 但在转载时请保留此声名!** 
  ------------------------------------------------ 

unit main; 
interface 
uses 
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, 
  Buttons, StdCtrls, ComCtrls,winsock,SearchPortThread, Spin; 
type 
  TForm1 = class(TForm) 
    M1: TMemo; 
    Port1: TEdit; 
    Port2: TEdit; 
    Label1: TLabel; 
    Label2: TLabel; 
    Label3: TLabel; 
    Search: TSpeedButton; 
    SB1: TStatusBar; 
    MaxThread: TSpinEdit; 
    Label4: TLabel; 
    IP: TComboBox; 
    AboutButton: TSpeedButton; 
    procedure SearchClick(Sender: TObject); 
    procedure FormCreate(Sender: TObject); 
    procedure FormDestroy(Sender: TObject); 
    procedure FormKeyPress(Sender: TObject; var Key: Char); 
    procedure AboutButtonClick(Sender: TObject); 
    procedure FormShow(Sender: TObject); 
  private 
    procedure Search_ST; 
    procedure ThreadDone(Sender: TObject); 
    procedure Search_Exit; 
    function HostNameToIP(S: string): DWord; 
    procedure AddComboBox(CB: TcomboBox); 
    procedure SearchOK; 
      { Private declarations } 
  public 
    ThreadList: array of TSearchPortThread;   //线程数组 
    Portlist:Tlist; //线程要用到的Strings 
    PortIndex:integer; //正在处理的端口号 
    MaxPort,MinPort:integer; //保存最大和最小的端口号的变量 
    addr:Tsockaddr; // 
    about:string; //关于 
    StopThread:boolean; //停止线程标记 
    { Public declarations } 
  end; 
var 
  Form1: TForm1; 
implementation 
{$R *.DFM} 

============================= 
=          自定义函数       = 
============================= 

//==== 开始扫描 ==== 
procedure TForm1.Search_ST(); 
var 
i,j:integer; 
Address: DWord; 
begin 
try 
//-- 检测部分 -- 
Address := HostNameToIP(PChar(IP.text));// 检测IP是否有效! 
if (Address = INADDR_NONE) then begin 
    showmessage('输入的IP、域名无效或网络不通!'); 
    exit; 
end; 
if MaxThread.Value < 2 then begin //检测线程数 
    showMessage('线程数请选择 2-300 之间的值!'); 
    exit; 
end; 
Maxport:=strtoint(port2.text); //最大端口号 
Minport:=strtoint(port1.text); //最小端口号 
PortIndex:=Minport; 
if Minport > Maxport then begin 
    showMessage('[开始端口]不能大于[结束端口]的值!'); 
    exit; 
end; 
//端口范围检测 
if (minport < 1) or (minport >65535) or (Maxport < 1) or (Maxport >65535) then begin 
    showMessage('输入数值超过了指定的范围!'#13#10'数值范围:1-65535'); 
    exit; 
end; 
//------扫描部分------- 
search.Caption := '停止扫描'; 
search.tag :=1; 
AddComboBox(IP); //把IP或域名加入列表! 
m1.lines.Clear; 
m1.Lines.Add('正在扫描: ' + ip.text + #13#10'[端口] | [说明 
]'#13#10'-------------------------------------'); 
m1.Update; 
  SetLength(ThreadList,MaxThread.Value);  //创建 MaxThread.Value 个线程数组 
  if (length(threadlist) >1) then j:=length(threadlist)-1; 
  if (maxport-minport)<j then j:=maxport-minport; 
  for i:=0 to j do 
  begin 
    addr.sin_family:=AF_INET; // 
    addr.sin_addr.S_addr:=Address;  //地址 
    addr.sin_port:=htons(PortIndex); //端口 
    threadlist[i]:=TSearchPortThread.Create(m1,addr);  //创建线程1 
    threadlist[i].OnTerminate :=ThreadDone; //线程处理完后要处理的事 
    Portlist.Add(threadlist[i]);  //把线程加入 Portlist 
    sb1.Panels[0].Text :=format('已扫描端口: %s',[inttostr(Portindex)]); 
    PortIndex:=PortIndex+1; 
end; 
//出错处理代码 
except 
showMessage('出错了!'); 
end; 
end; 
//===== END ===== 

//==== 线程退出代码 ====== 
procedure TForm1.ThreadDone(Sender: TObject); 
var 
Index:integer; 
begin 
try 
if (PortIndex >= maxport) and (StopThread=false) then begin 
    SearchOK(); 
    StopThread:=true; 
    exit; 
end; 
if (PortIndex > maxport) or (StopThread = true) then exit; 
Index := PortList.IndexOf(Sender); //在Filst 中查找刚才的线程对象 
PortList.Delete(Index); 
addr.sin_port:=htons(portindex); //端口 
threadlist[Index]:=TSearchPortThread.Create(m1,addr);  //创建线程1 
threadlist[Index].OnTerminate :=ThreadDone; //线程处理完后要处理的事 
Portlist.Add(threadlist[Index]);  //把线程加入 Portlist 
sb1.Panels[0].Text :='已扫描端口: ' + inttostr(Portindex); 
PortIndex:=PortIndex+1; 
except //错误处理 
//    sb1.Panels[0].Text :='程序出错[线程退出]!'; 
end; 
end; 
//===== END ===== 

//==== 停止扫描 ===== 
Procedure Tform1.Search_Exit; 
var 
i:integer; 
temp:TSearchPortThread; 
begin 
try 
 m1.Lines.Add('[ 用户中断 ]'); 
 sb1.Panels[0].Text :='正在关闭线程.....'; 
for i:=0 to portlist.Count  - 1 do 
begin 
    temp:=portlist.Items[i]; 
    temp.Terminate;  //结束线程 
end; 
      SearchOK(); //显示开始扫描 
      StopThread:=true; //StopThread为真,为停止扫描 
except //错误处理 
//   sb1.Panels[0].Text :='程序出错[停止扫描]!'; 
end; 
end; 
//===== END ===== 
// ===== 扫描完成 ========= 
procedure Tform1.SearchOK(); 
begin 
      search.Caption :='开始扫描'; 
      search.Enabled :=true; 
      search.tag:=0; 
      sb1.Panels[0].Text :='扫描完成'; 
      m1.Lines.Add('-------------------------------------'#13#10'扫描完成!'); 
      portlist.Free;//释放PortList的内存空间 
end; 
//==== END ==== 
//==== 域名、IP自动转为IP ==== 
function TForm1.HostNameToIP(S:string):DWord; 
const 
  INADDR_NONE = $FFFFFFFF; 
var 
Host:pHostent; 
Address:DWord; 
begin 
Address := inet_addr(PChar(S)); 
if (Address = INADDR_NONE) then begin 
   Host:=GetHostByName(Pchar(S)); 
   if Host = nil then begin 
        HostNameToIP:=INADDR_NONE; 
        exit; 
   end 
   else begin 
        hostNametoip:=longint(pointer(Host^.h_addr_list^)^); 
        exit; 
   end; 
end 
else begin 
  HostNameToIP:=Address; 
  exit; 
end; 
end; 
//==== END ==== 
//==== 自动把ComboBox控件的内容里没有的内容加入列表中 =====! 
procedure Tform1.AddComboBox(CB:TcomboBox); 
var 
a :integer; 
begin 
    a:=CB.Items.IndexOf(CB.Text); 
    if a=-1 then CB.Items.Add(CB.Text); 
end; 
//== END === 
// ◎◎◎ 自定义函数 END ◎◎◎ 
  


============================= 
          控件部分 
============================== 

//==== Search按钮 ===== 
procedure TForm1.SearchClick(Sender: TObject); 
begin 
if search.tag =0 then begin 
    portlist:=Tlist.Create; //创建Tstring 
    Search_ST(); //开始 
    StopThread:=false; //停止为假时,为扫描 
end 
else begin 
    Search_Exit(); //停止 
end; 
end; 
//===== END ===== 

//===== Form 创建 ===== 
procedure TForm1.FormCreate(Sender: TObject); 
var 
Wsadata:Twsadata; 
begin 
WSAStartup(Makeword(2,0),Wsadata);// 
about:=m1.Text; //把简介内容保存到About变量中 
end; 
//===== END ===== 

//===== Form 退出 ====== 
procedure TForm1.FormDestroy(Sender: TObject); 
begin 
//PortList.free; //释放PortList的内存空间 
WSAcleanUP;// 
end; 
//===== END ====== 

//===== 当按‘回车’、‘Esc’键时的动作 ====== 
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char); 
begin 
if (key =#13) and (search.Tag=0) then  SearchClick(Sender); //开始扫描 
if (key =#27) and (search.Tag=1) then  SearchClick(Sender); //停止扫描 
end; 
//===== END ====== 
  
//==== 关于 ===== 
procedure TForm1.AboutButtonClick(Sender: TObject); 
begin 
showMessage(About + 
'地址:深圳市龙岗区坪山镇石井太阳村'#13#10#13#10 + 
'注:'#13#10 + 
'本软件为免费软件,对使用本软件产生'#13#10 + 
'的后果,本人不承担任何的责任!'#13#10#13#10 + 
'本程序用Delphi编写,如要源码,请和作者联系!'#13#10#13#10 + 
'制作时间: 2002年8月27日' 
); 
//m1.Text:=About; 
end; 
//==== END ===== 
//====== 窗口居中 ====== 
procedure TForm1.FormShow(Sender: TObject); 
begin 
     Left := (Screen.Width - Width) div 2; 
     Top := (Screen.Height - Height) div 2; 
end; 
//===== END ==== 
// ◎◎◎ 控件部分 END ◎◎◎ 
end. 
 __________________________________________________________ 
如果你写扫描程序可千万不要直接去连接,应该使用别的链接方法,否则你的踪迹会被别人 
发现.例如使用sys扫描或者fin扫描: 
我给你异步socket的api代码: 

unit Unit1; 
interface 
uses 
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, 
  StdCtrls,WInSock, ExtCtrls; 
const WM_SOCKET=WM_USER+1;   //socket消息 
type 
  TForm1 = class(TForm) 
    Button1: TButton; 
    Edit1: TEdit; 
    Panel1: TPanel; 
    Memo1: TMemo; 
    procedure FormCreate(Sender: TObject); 
    procedure FormDestroy(Sender: TObject); 
    procedure Button1Click(Sender: TObject); 
    procedure Button2Click(Sender: TObject); 
    procedure Button3Click(Sender: TObject); 
  private 
    Sockhd : integer;   //socket句柄 
    Serv_Addr : Tsockaddr;//目标地址 
  procedure SockEvent(var msg: Tmessage);message WM_SOCKET;   //处理cocket消息 
  procedure DspMsg(msg : string);   //显示信息 
    { Private declarations } 
  public 
    { Public declarations } 
  end; 
  Form1: TForm1; 
implementation 
{$R *.DFM} 
function lookup_hostname(const hostname:string):longint;  //把域名转化成IP地址 
var 
  RemoteHost : PHostEnt;  (* no, don't free it! *) 
  ip_address: longint; 
begin 
  ip_address:=-1; 
  try 
    if hostname='' then 
      begin  (* no host given! *) 
        lookup_hostname:=ip_address; 
        EXIT; 
       end 
    else 
      begin 
        ip_address:=Winsock.Inet_Addr(PChar(hostname));  (* try a xxx.xxx.xxx.xx first *) 
        if ip_address=SOCKET_ERROR then begin 
        RemoteHost:=Winsock.GetHostByName(PChar(hostname)); 
        if (RemoteHost=NIL) or (RemoteHost^.h_length<=0) then 
          begin 
            lookup_hostname:=ip_address; 
            EXIT;  (* host not found *) 
          end 
        else 
          ip_address:=longint(pointer(RemoteHost^.h_addr_list^)^); 
      end; 
      end; 
   except 
    ip_address:=-1; 
  end; 
  lookup_hostname:=ip_address; 
end; 
procedure TFOrm1.DspMsg(msg: string); 
begin 
 memo1.Lines.Add(msg+'...'); 
 if Memo1.Lines.Count>200 then Memo1.Lines.Delete(0); 
end; 
procedure TForm1.SockEvent(var msg : tmessage);  //处理socket消息 
begin 
 case msg.LParam of 
  FD_READ: begin    //标识可以读数据,当然肯定已经链接上了 
    dspmsg('可以读取数据'); 
    //do what you want do 
  end; 
  FD_WRITE: begin 
    dspmsg('可以发送数据'); 
    //do what you want do 
  end; 
  FD_ERROR: begin 
    dspmsg('发生错误'); 
     //如果你是客户端,则应该是连接不上,即端口没有开 
  end; 
  FD_CLOSE: Begin 
    dspmsg('服务器断开连接'); 
    //对方关闭连接 
  end; 
  FD_CONNECT: begin 
    dspmsg('连结上服务器'); 
    //表示对方端口开放 
  end; 
  FD_ACCEPT: begin 
    dspmsg('接收一个请求'); 
   //这个消息只有服务端可能出现 
  end; 
 end; 
end; 
procedure TForm1.FormCreate(Sender: TObject); 
 var  wsaData:TwsaData; 
begin                 //启动winsock动态链接库 
  if WSAStartup (makeword(2,2), wsaData)<>0 then begin 
    messagebox(application.handle,'无法启动winsock动态连接库!','警告',MB_OK or MB_APPLMODAL or 
MB_ICONWARNING); 
    Application.Terminate; 
  end;   
end; 
procedure TForm1.FormDestroy(Sender: TObject); 
begin    //关闭dll 
 WSACleanup; 
end; 
procedure TForm1.Button1Click(Sender: TObject); 
begin 
 Sockhd := socket(AF_INET,SOCK_STREAM,0);  //创建socket句柄 
 if Sockhd<0 then begin 
   messagebox(application.handle,'无法创建句柄!','警告',MB_OK or MB_APPLMODAL or 
MB_ICONWARNING); 
   exit; 
 end; 
  Serv_addr.sin_addr.s_addr:= lookup_hostname(edit1.Text);  //主机名 
  Serv_addr.sin_family := PF_INET; 
  Serv_addr.sin_port := htons(23);      //any port you want to connect 
  if WSAAsyncSelect(Sockhd,Form1.handle,WM_SOCKET,FD_ACCEPT or FD_CONNECT or FD_CLOSE or   
FD_READ or FD_WRITE)=SOCKET_ERROR 
  then begin 
   messagebox(application.handle,'无法创建句柄!','警告',MB_OK or MB_APPLMODAL or 
MB_ICONWARNING); 
   exit; 
  end;   //异步socket 
  connect(sockhd,serv_addr,sizeof(serv_addr));  //连接,结果会在前面的处理函数处理 
end; 
end. 

没有评论: