原创  SynScan --www.iamaphex.net 收藏


program scan;

{$APPTYPE CONSOLE}

uses
  Windows,
  Winsock2;

type
  TBufferArray = array[0..65535] of byte;

  iph = record
    ip_verlen: byte;
    ip_tos: byte;
    ip_len: word;
    ip_id: word;
    ip_offset: word;
    ip_ttl: byte;
    ip_protocol: byte;
    ip_checksum: word;
    ip_saddr: longword;
    ip_daddr: longword;
  end;

  tcph = record
    th_sport: word;
    th_dport: word;
    th_seq: longword;
    th_ack: longword;
    th_len: byte;
    th_flags: byte;
    th_win: word;
    th_checksum: word;
    th_upr: word;
  end;

var
  hSocket, bSocket: integer;
  hFile: dword;
  TID: dword;
  Sequence: dword;
  Source: TInAddr;
  BatchFile: string;
  Ports: array [0..255] of word;
  PortCount: integer = 0;
  Target: dword = 0;
  Port: word;
  Delay: dword = 50;
  UseBatch: boolean = False;
  UseOutput: boolean = False;
  MaxScan: dword = 0;
  ScanCount: dword = 0;
  Verbose: dword = 0;
  Random: dword = 0;

function IntToStr(I: integer): string;
begin
  Str(I, Result);
end;

function StrToInt(S: string): integer;
begin
  Val(S, Result, Result);
end;

function Split(Input: string; Deliminator: string; Index: integer): string;
var
  StringLoop, StringCount: integer;
  Buffer: string;
begin
  StringCount := 0;
  for StringLoop := 1 to Length(Input) do
  begin
    if (Copy(Input, StringLoop, 1) = Deliminator) then
    begin
      Inc(StringCount);
      if StringCount = Index then
      begin
        Result := Buffer;
        Exit;
      end
      else
      begin
        Buffer := '';
      end;
    end
    else
    begin
      Buffer := Buffer + Copy(Input, StringLoop, 1);
    end;
  end;
  Result := Buffer;
end;

function RandomAddress(Address: dword; AddressClass: byte): dword;
var
  AddressMask: dword;
  Range: dword;
begin
  Result := ntohl(Address);
  case AddressClass of
    3:
      begin
        AddressMask := 4294967040;
        Range := 16777214;
      end;
    2:
      begin
        AddressMask := 4294901760;
        Range := 65534;
      end;
    1:
      begin
        AddressMask := 4278190080;
        Range := 254;
      end;
    else
      Exit;
  end;
  AddressMask := ntohl(AddressMask);
  Result := (Result and AddressMask) xor Result + dword(System.Random(Range)) + 1;
  Result := htonl(Result);
end;

function CheckSum(var Buffer; Size: integer): word;
type
  TWordArray = Array[0..1] of word;
var
  lSumm: LongWord;
  iLoop: integer;
begin
  lSumm := 0;
  iLoop := 0;
  while Size > 1 do
  begin
    lSumm := lSumm + TWordArray(Buffer)[iLoop];
    inc(iLoop);
    Size := Size - SizeOf(word);
  end;
  if Size = 1 then lSumm := lSumm + Byte(TWordArray(Buffer)[iLoop]);
  lSumm := (lSumm shr 16) + (lSumm and $FFFF);
  lSumm := lSumm + (lSumm shr 16);
  Result := word(not lSumm);
end;

procedure Header(FromIP: dword; FromPort: word; ToIP: dword; ToPort: word; Seq: longint; var Buffer: TBufferArray; var Socket: TSockAddr; var Size: word);
var
  ipHdr: iph;
  tcpHdr: tcph;
  TcpHeaderLen: word;
  ChecksumSize: word;
  DataPointer: ^byte;
  procedure IncPtr(Value: integer);
  begin
    DataPointer := pointer(integer(DataPointer) + Value);
  end;
begin
  Size := sizeof(ipHdr) + sizeof(tcpHdr);
  ipHdr.ip_verlen := ((4 shl 4) or sizeof(ipHdr) div sizeof(longword));
  ipHdr.ip_tos := 0;
  ipHdr.ip_len := htons(Size);
  ipHdr.ip_id := 0;
  ipHdr.ip_offset := 0;
  ipHdr.ip_ttl := 128;
  ipHdr.ip_protocol := 6;
  ipHdr.ip_checksum := 0;
  ipHdr.ip_saddr := FromIP;
  ipHdr.ip_daddr := ToIP;
  ChecksumSize := 0;
  tcpHdr.th_sport := htons(FromPort);
  tcpHdr.th_dport := htons(ToPort);
  tcpHdr.th_seq := htons(Seq);
  tcpHdr.th_ack := 0;
  tcpHdr.th_len := 80;
  tcpHdr.th_flags := 2;
  tcpHdr.th_win := htons(65535);
  tcpHdr.th_checksum := 0;
  tcpHdr.th_upr := 0;
  DataPointer := @Buffer[0];
  FillChar(Buffer, SizeOf(Buffer), 0);
  Move(ipHdr.ip_saddr, DataPointer^, SizeOf(ipHdr.ip_saddr));
  IncPtr(SizeOf(ipHdr.ip_saddr));
  ChecksumSize := ChecksumSize + sizeof(ipHdr.ip_saddr);
  Move(ipHdr.ip_daddr, DataPointer^, sizeof(ipHdr.ip_daddr));
  IncPtr(SizeOf(ipHdr.ip_daddr));
  ChecksumSize := ChecksumSize + sizeof(ipHdr.ip_daddr);
  IncPtr(1);
  Inc(ChecksumSize);
  Move(ipHdr.ip_protocol, DataPointer^, sizeof(ipHdr.ip_protocol));
  IncPtr(sizeof(ipHdr.ip_protocol));
  ChecksumSize := ChecksumSize + sizeof(ipHdr.ip_protocol);
  TcpHeaderLen := htons(sizeof(tcpHdr));
  Move(TcpHeaderLen, DataPointer^, sizeof(TcpHeaderLen));
  IncPtr(sizeof(TcpHeaderLen));
  ChecksumSize := ChecksumSize + sizeof(TcpHeaderLen);
  Move(tcpHdr, DataPointer^, sizeof(tcpHdr));
  IncPtr(sizeof(tcpHdr));
  ChecksumSize := ChecksumSize + sizeof(tcpHdr);
  tcpHdr.th_checksum := CheckSum(Buffer, ChecksumSize);
  FillChar(Buffer, sizeof(Buffer), 0);
  DataPointer := @Buffer[0];
  Move(ipHdr, DataPointer^, sizeof(ipHdr));
  IncPtr(sizeof(ipHdr));
  Move(tcpHdr, DataPointer^, sizeof(tcpHdr));
  Socket.sin_family := 2;
  Socket.sin_port := htons(0);
  Socket.sin_addr.S_addr := ToIP;
end;

procedure Send(TargetIP: dword; TargetPort: integer; SourceIP: dword; SourcePort: integer; Sequence: longint);
var
  Buffer: TBufferArray;
  Sck: TSockAddr;
  Size: Word;
begin
  Header(SourceIP, SourcePort, TargetIP, TargetPort, Sequence, Buffer, Sck, Size);
  while SendTo(hSocket, Buffer, Size, 0, Sck, sizeof(Sck)) = -1 do Sleep(1);
end;

function GetInAddr: TInAddr;
var
  Host: array[0..128] of char;
  HostEnt: PHostEnt;
begin
  GetHostName(@Host, 128);
  HostEnt := GetHostByName(@Host);
  Result := PInAddr(HostEnt^.h_addr_list^)^
end;

procedure Init;
var
  WSAdata: TWSAdata;
  SockAddrIn: TSockAddrIn;
  Option: integer;
  Control, BytesReceived: longint;
begin
  WSAStartup($0002, WSAdata);
  hSocket := Socket(2, 3, 0);
  Option := 1;
  SetSockOpt(hSocket, 0, 2, @Option, SizeOf(Option));
  bSocket := Socket(2, 3, 0);
  SockAddrIn.sin_family := 2;
  SockAddrIn.sin_addr := GetInAddr;
  SockAddrIn.sin_port := htons(0);
  bind(bSocket, @SockAddrIn, SizeOf(SockAddrIn));
  WSAIoctl(bSocket, IOC_IN or $18000000 or 1, @Control, SizeOf(Control), nil, 0, @BytesReceived, nil, nil);
end;

procedure ReceiveResults;
var
  Data: array [0..39] of char;
  BytesReceived: longint;
  IPHeader: iph;
  TCPHeader: tcph;
  Result: string;
  BytesWritten: Cardinal;
  StartInfo: TStartupInfo;
  ProcInfo: TProcessInformation;
begin
   while True do
   begin
     BytesReceived := recv(bSocket, Data, 40, 0);
     if BytesReceived = 40 then
     begin
       IPHeader := iph(pointer(@Data)^);
       TCPHeader := tcph(pointer(longint(@Data) + 20)^);
       if TCPHeader.th_flags = 16 then
       begin
         if ntohs(TCPHeader.th_dport) = Port then
         begin
           if Verbose <> 0 then
           begin
             Result := string(inet_ntoa(TInAddr(IPHeader.ip_saddr))) + ':' + IntToStr(ntohs(TCPHeader.th_sport)) + #13#10;
             Write('[CONNECTION] ' + Result);
           end;
           if UseOutput then
           begin
             Result := string(inet_ntoa(TInAddr(IPHeader.ip_saddr))) + ':' + IntToStr(ntohs(TCPHeader.th_sport)) + #13#10;
             WriteFile(hFile, pointer(Result)^, Length(Result) + 1, BytesWritten, nil);
           end;
           if UseBatch then
           begin
             Result := BatchFile + ' ' +  string(inet_ntoa(TInAddr(IPHeader.ip_saddr))) + ' ' + IntToStr(ntohs(TCPHeader.th_sport));
             ZeroMemory(@StartInfo, SizeOf(TStartupInfo));
             StartInfo.cb := SizeOf(TStartupInfo);
             StartInfo.dwFlags := STARTF_USESHOWWINDOW;
             StartInfo.wShowWindow := SW_HIDE;
             CreateProcess(nil, pchar(Result), nil, nil, False, 0, nil, nil, StartInfo, ProcInfo);
           end;
         end;
       end;
     end;
   end;
end;

procedure ScanAddresses;
var
  PortLoop: integer;
begin
  while ((ScanCount <= MaxScan) or (MaxScan = 0)) do
  begin
    if Verbose = 2 then
    begin
      if ntohl(Target) mod 256 = 0 then
      begin
        Target := htonl(ntohl(Target) + 1);
      end;
      if ScanCount mod 255 = 0 then
      begin
        WriteLn('[STATUS] ' + string(inet_ntoa(TInAddr(Target))));
      end;
    end;
    for PortLoop := 0 to PortCount - 1 do
    begin
      Send(Target, Ports[PortLoop], dword(Source), Port, Sequence);
      Send(Target, Ports[PortLoop], dword(Source), Port, Sequence);
      Sleep(Delay);
      Inc(ScanCount);
    end;
    if Random > 0 then
    begin
      Target := RandomAddress(Target, Random)
    end
    else
      Target := htonl(ntohl(Target) + 1);
  end;
  Halt(0);
end;

procedure Usage;
begin
  WriteLn('AFX Syn Scanner 0.2 for 2000/XP/2003');
  WriteLn('http://www.iamaphex.cjb.net');
  WriteLn('aphex@iamaphex.net');
  WriteLn;
  WriteLn('Usage: scan -h:host -p:port -i:scancount -d:delay -b:batch -o:output -v:verboselevel -r:randomlevel');
end;

procedure ParseOption(Cmd, Arg: string);
begin
  if lstrcmp('-h:', pchar(Cmd)) = 0 then
  begin
    Target := inet_addr(pchar(Arg));
  end
  else if lstrcmp('-p:', pchar(Cmd)) = 0 then
  begin
    Ports[PortCount] := StrToInt(Arg);
    Inc(PortCount);
  end
  else if lstrcmp('-d:', pchar(Cmd)) = 0 then
  begin
    Delay := StrToInt(Arg);
  end
  else if lstrcmp('-i:', pchar(Cmd)) = 0 then
  begin
    MaxScan := StrToInt(Arg);
  end
  else if lstrcmp('-b:', pchar(Cmd)) = 0 then
  begin
    BatchFile := Copy(Arg, 1, Length(Arg));
    UseBatch := True;
  end
  else if lstrcmp('-o:', pchar(Cmd)) = 0 then
  begin
    hFile := CreateFile(pchar(Arg), GENERIC_WRITE, FILE_SHARE_WRITE, nil, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
    SetFilePointer(hFile, 0, nil, FILE_END);
    UseOutput := True;
  end
  else if lstrcmp('-v:', pchar(Cmd)) = 0 then
  begin
    Verbose := StrToInt(Arg);
  end
  else if lstrcmp('-r:', pchar(Cmd)) = 0 then
  begin
    Random := StrToInt(Arg);
  end
  else
  begin
    Usage;
    Halt(0);
  end;
end;

procedure ProcessCommandLine;
var
  CmdLn: integer;
begin
  CmdLn := 1;
  while Length(ParamStr(CmdLn)) <> 0 do
  begin
    ParseOption(Copy(ParamStr(CmdLn), 1, 3), Copy(ParamStr(CmdLn), 4, Length(ParamStr(CmdLn)) - 2));
    Inc(CmdLn);
  end;
  if Target = 0 then
  begin
    Usage;
    Halt(0);
  end;
end;

begin
  ProcessCommandLine;
  Randomize;
  Sequence := System.Random(4294967294) + 1;
  Port := System.Random(65534) + 1;
  Init;
  CreateThread(nil, 0, @ReceiveResults, nil, 0, TID);
  Source := GetInAddr;
  CreateThread(nil, 0, @ScanAddresses, nil, 0, TID);
  while True do Sleep(1);
end.

发表于 @ 2005年11月25日 11:41:00 | 评论( loading... ) | 编辑| 举报| 收藏

旧一篇:Delphi Winsock Hooking Example by Aphex | 新一篇:AFX Lite TCP Firewall by Aphex

  • 发表评论
  • 评论内容:
  •  
Copyright © hnxyy
Powered by CSDN Blog