Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Software-Projekte der Mitglieder (https://www.delphipraxis.net/26-software-projekte-der-mitglieder/)
-   -   Kleiner und schneller Portscanner (nonVCL) mit EXE! (https://www.delphipraxis.net/7105-kleiner-und-schneller-portscanner-nonvcl-mit-exe.html)

Assarbad 2. Aug 2003 02:54


Kleiner und schneller Portscanner (nonVCL) mit EXE!
 
So, hier die Version 1.00.

Der hauptsächliche Vorteil liegt in der Benutzung vieler Threads.

Als Download ACE, RAR, ZIP

Es sollten insgesamt weniger Probleme (auch auf Windows 9x) auftreten. Source ist dabei.

negaH 2. Aug 2003 13:03

Re: Kleiner und schneller Portscanner (nonVCL) mit EXE!
 
Guckst du hier :) http://www.delphipraxis.net/viewtopi...r=asc&start=15

Auf Win2k Rechnern können bis zu 2004 Threads per Prozess laufen. Im obigen Posting habe ich mal meine Quick&Dirty Lösung gepostet. Im Gegensatz zu deiner Lösung, die ja den zu scannenden Port Bereich im vorhinein auf die max. Anzahl an Threads verteilt, scannt meine Lösung sequentiell den Bereich mithilfe der Threads. Werden z.b. 1024 Threads erzeugt so scannen diese erstmal alle Ports von 1-1025. Sollte ein Thread fertig sein nimmt er den nächsthöheren Port. Man kann als max. Threadanzahl ohne Probleme einen Wert festlegen, zB. 10000, ohne das es Probleme mit der verfügbaren Anzahl an Threads pro Prozess gibt.
Sollte diese Anzahl erreicht sein so wird das OS bei CreateThread() mit einem Fehler zurückkehren. D.h. die Threaderzeugungs-Loop geht von 0-10000 aber bei 2004 Threads macht das OS dicht. Da aber die Threadfunktion linear scannt ist dies kein Problem.
Mit deinem Chunkweisen Vorgehen ist dieser Trick nicht möglich ohne das Portbereiche nicht gescannt werden.

Das Problem mit der Listbox lässt sich ganz einfach lössen. Mich interessieren nur erreichbare Ports (was soll ich mit den Ports die geschlossen sind in der Anzeige??) Es wäre also sinnvoll in der ListBox nur die geöffneten Ports anzuzeigen. Meistens sind das ca. 14-20 Ports aus einem Bereich von 65534 möglichen.

Übrigens: der Unterschied beim scannen von 65534 Ports besteht darin das mit 256 Threads 270 Sekunden zu 80 Sekunden bei 1024 Threads benötigt werden.

Gruß Hagen

Assarbad 2. Aug 2003 16:30

Re: Kleiner und schneller Portscanner (nonVCL) mit EXE!
 
Da ich inzwischen den Algo umgestellt habe (vorher waren die threads nicht komplett autark), sollte meine Lösung auch mit 1024 threads laufen *grins* ... aber ich hatte damit zuvor halt Probleme, weshalb ich die Anzahl begrenzt habe.

Daß es auf NT begrenzt ist, war mir bekannt, aber wußte nicht mehr die genaue Grenze - Danke ;)

Das mit der Listbox hat im DF schon einer vorgeschlagen, kommt also :mrgreen:

Das mit chunkweise ... ist es doch eingentlich garnicht, oder haben wir nur andere Begrifflichkeiten? Denn eigentlich werden bei mir jetzt auch zuerst die ersten Ports gescannt. Vorher hatte ich dran gedacht einen Bereich an jeden Thread zu übergeben. Aber am wichtigsten sind meistens Ports 0..1023 ;)

negaH 2. Aug 2003 17:18

Re: Kleiner und schneller Portscanner (nonVCL) mit EXE!
 
Ich habe nur kurz in den Source reingeschaut, Asche auf mein Haupt.
Deine Methode mit dem Counter + I als Index für den Thread erzeugt einen falschen Eindruck und ich musste sie nochmals analysieren. Irgendwas kam mir faul dran vor.

Also wir erzeugen 4 Threads nacheinander und IP.NumThreads = 4.

Code:
ThreadIndex = I   Portnummern im Thread

              0  =    1   5    9
              1  =    2   5   10
              2  =    3   7   11
          ------------------------
              3  =    4   8   12
In obiger Tabelle mal diese Threads 0 bis 3 mit Index I. Daneben die Portnummern die jeder Thread scannt.
Nun erzeugst du in der Schleife von 0 bis IP.NumThreads -1 deine Threads, aber beim Thread 3 meckert das OS und dieser Thread wird NICHT erzeugt. Damit entstehen Lücken im gescannten Portbereich.

In meinem Source bin ich anders vorgegangen. Globale Variablen CurrentPort und MaxPort. CurrentPort wird auf den ersten zu scannenden Port gesetzt, MaxPort auf den höchsten zu scannenden Port. Nun werden die x Threads erzeugt und jeder Thread arbeitet in einer Schleife. Der Thread holt mit ScanPort := InterlockedExchangeAdd(CurrentPort, 1) seinen nächsten Port ab und erhöht gleichzeitig threadsafe CurrentPort um +1. Sollte ScanPort >= MaxPort sein so terminiert der Thread.
Durch diese Vorgehensweise ist garantiert das wenn 10000 Threads erzeugt werden sollen aber nur 5 tatsächlich beginnen zu laufen, keine Lücken entstehen. 2. kann man anhand von CurrentPort erkennen was der höchste gerade gescannte Port ist. 3. kann man MaxPort noch nachträglich reduzieren. Die Threads die schneller connecten holen sich öfters den nächsten Port.
Werden also 4 Threads erzeugt und CurrentPort ist 1, dann würden diese 4 Threads sich ihren Port holen und CurrentPort wäre 5. Nun connectet der Thread 2 mit ScanPort = 3 schneller als alle anderen, dann würde er mit Port 5 weitermachen und CurrentPort wäre 6. Usw. usw. d.h. je nach Geschwindigkeit beim connecten holen sich die Threads die Ports ab.


Gruß Hagen

negaH 2. Aug 2003 17:22

Re: Kleiner und schneller Portscanner (nonVCL) mit EXE!
 
Das Problem ist hier:

Delphi-Quellcode:
    while (IP.StartPort + i + Counter) <= IP.EndPort do
    begin
// Scan ports ...
      inc(Counter, IP.Numthreads); <----
    end;
IP.NumThreads ist 4, aber nur 3 Threads laufen tatsächlich.
Damit entstehen Lücken im Portbereich.

Gruß Hagen

negaH 2. Aug 2003 17:29

Re: Kleiner und schneller Portscanner (nonVCL) mit EXE!
 
Achso eines habe ich vergessen. Wenn man so viele Threads nacheinander erzeugt dann beginnt ein Teil der Threads schon zu arbeiten und ein anderer Teil muß erst warten bis er überhaupt startet. Ist eigentlich logisch. Das OS kann nicht erst 1024 Thread erzeugen und dann alle in einem Rutsch starten. Anscheinend startet es immer ruckweise einen Block von wartenden Threads. Dies hat aber Konsequenzen für uns. Wir können nämlich nicht sagen ob das OS diese wartenden Thread gemäß ihrer Erstellungsreihenfolge startet. Da in deinem Source über Index I und Counter + IP.NumThreads jedem Thread ein fester Portbereich zugeordnet wurde, kann es durchaus vorkommen das bestimmte Portbereiche ungleichmäßig und zeitversetzt gescannt werden.

Du solltest den Port nicht vom Thread abhänig machen. Jeder Thread holt sich wenn er bereit ist sequentiell den nächsten zu scannenden Port. Eben so wie in meinem Source :)

Gruß Hagen

Assarbad 2. Aug 2003 19:53

Re: Kleiner und schneller Portscanner (nonVCL) mit EXE!
 
Hi Hagen,

auch wenns simple Mathematik ist, schau lieber nochmal auf den Code mit der WHILE-Schleife ;) Ich sehe da keine Lücken ... eher Überschneidungen, sobald ich IP.Numthreads-1 nehme ;)

Außerdem sollte ich vielleicht klarstellen, daß es hier eher darum ging ein Programm zu schreiben, welches mal die Grenzen bei Threads austestet. Es ging mir keinesfalls darum einen perfekten Portscanner abzuliefern. Aber es ging mir durchaus darum einen Scanner abzuliefern, der schneller ist als der Durchschnitt (daher so viele Threads) ... außerdem wollte ich eben einige Sachen, wie Parameterübergabe bei Threads etc pp austesten.

Also Kleinigkeiten werd' ich mglw noch beheben, aber ansonsten steht der Source zur Verfügung, jeder der will kann ihn selbst modifizieren ;)

Übr.: Du hast natürlich recht, daß es schneller ginge, wenn sich immer sofort der nächste freie Thread den nächsten Port grabscht .... ich werd's mir mal anschauen. Wichtiger ist mir erstmal was anderes ;)

Danke fürs Feedback anyway.

negaH 2. Aug 2003 20:57

Re: Kleiner und schneller Portscanner (nonVCL) mit EXE!
 
Zitat:

Ich sehe da keine Lücken
Also entweder schnalle ich da was nicht oder ich kann dein Source nicht lesen. Hier noch mal die Tabelle aber erweitert:


Code:
ThreadIndex = I   Portnummern im Thread

              0  =    1   7   13 
              1  =    2   8   14 
              2  =    3   9   15 
          ------------------------ 
              3  =    4  10   16 
              4  =    5  11   17
              5  =    6  12   18
Man will vom Port 1 bis 18 scannen und möchte dazu 6 Threads benutzen.
In deiner Loop mit CreateThread() gehst du von I := 0 to IP.NumThreads -1, wobei IP.NumThreads := 6 ist. Um mit diesen 6 Threads bis Port 18 zu scannen muß jeder Thread 3 mal pingen. So wie oben in der Tabelle dargestellt. Nun kann das OS nur 3 = DREI Threads erstellen, d.h. deine CreateThread() Schleife erzeugt Thread Nummer 0,1,2 schlägt aber fehl bei Thread Nummer 3,4,5. Deine while Schleife im Thread Code sieht so aus.

Delphi-Quellcode:
    while (IP.StartPort + i + Counter) <= IP.EndPort do
    begin
// Scan ports ...
      if ScanTCPPort(IP.IP, IP.StartPort + i + Counter, TCPsock) then
        PostMessage(hDlg, WM_ADDIP_TCPCONNPORT, IP.IP, IP.StartPort + i + Counter)
      else
        PostMessage(hDlg, WM_ADDIP_TCPPORT, IP.IP, IP.StartPort + i + Counter);

// Increase by number of threads
      inc(Counter, IP.Numthreads);
    end;
Damit würde Thread 0 bei Port 19 terminieren, Thread 1 bei Port 20 und Thread 2 bei Port 21. Die Ports 4,5,6,10,11,12,16,17,18 würden aber nicht gescannt da Thread 3,4,5 überhaupt nicht durch das OS erzeugt wurden.

So das nenne ich Lücken.

Wenn ich dennoch falsch liege dann kläre mich bitte auf, denn durch deinen Kommentar habe ich das Gefühl bekommmen das ich da was nicht schnalle.

Gruß Hagen

Assarbad 2. Aug 2003 21:52

Re: Kleiner und schneller Portscanner (nonVCL) mit EXE!
 
Sorry, mir ist das zu hoch, ich verstehe einfach deine Beispiele nicht. Also bei mir gibts im Praxistest keine Probleme :-/

Und rein logisch sollte es auch funzen ...

Thread 0 scannt zuerst Port 0 und geht dann zu 0+IP.Numthreads ... also exakt einen Port weiter als der letzte andere Thread.

Aber ich werd trotzdem mal schauen, ob ich das mit deiner Logik implementieren kann. Ist mir einfach zu affig fremden Code zu nehmen ... ich machs lieber selber ;)

negaH 2. Aug 2003 22:38

Re: Kleiner und schneller Portscanner (nonVCL) mit EXE!
 
Delphi-Quellcode:
type
  PIP = ^TIP;
  TIP = record
    IP,StartPort,EndPort: DWORD;
    NumThreads: DWORD;
  end;

var
  IP: TIP;

function ScanThread(I: DWORD): DWORD; stdcall;
var
  Counter: DWORD; // Local remainder
begin
  Result := 0;
  Counter := 0;
  while (IP.StartPort + I + Counter) <= IP.EndPort do
  begin
    Write( IP.StartPort + I + Counter, ', ' );

    Inc(Counter, IP.Numthreads);
  end;
end;

procedure Test;
var
  I: Integer;
begin
  IP.NumThreads := 6;
  IP.StartPort := 1;
  IP.EndPort := 18;
  for I := 0 to IP.NumThreads -1 do
    if I > 3 then Break
      else ScanThread(I);
end;
In obigem Code simmuliere ich mal deinen Algo. Aber so als ob 6 Threads laufen sollten aber nur 3 Threads durch's Operation System erzeugt wurden. D.h. die Schleife mit der Erzeugung der Threads erzeugt nur Threads 0,1,2 und Threads 3,4,5 werden durch's OS nicht erzeugt.

Die Threadfunction ScanThread() wird direkt aufgrufen, statt wie bei Threads im eigenen Context.

Das WriteLn sollte alle Ports von 1 bis 18 ausgeben, ich erhalte aber nur (1, 7, 13) + (2, 8, 14) + (3, 9, 15) + (4, 10, 16). Also genau wie ich es gesagt habe.

Wird also NumThreads = 2048 angegeben und das OS lässt aber nur 128 Threads zu, dann bleiben Lücken.


Und hier meine Lösung:

Delphi-Quellcode:
type
  PIP = ^TIP;
  TIP = record
    IP,StartPort,EndPort: DWORD;
    NumThreads: DWORD;
  end;

var
  IP: TIP;

function ScanThread(I: DWORD): DWORD; stdcall;
var
  Port: Integer;
begin
  Result := 0;
  repeat
    Port := InterlockedExchangeAdd(@IP.StartPort, 1);
    if Port > IP.EndPort then Break;
    Write( Port, ', ' );
  until False;
end;

procedure Test;
var
  I: Integer;
begin
  IP.NumThreads := 6;
  IP.StartPort := 1;
  IP.EndPort := 18;
  for I := 0 to IP.NumThreads -1 do
    if I > 3 then Break
      else ScanThread(I);
end;

Ausgabe:
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
Der Schönheitsfehler dabei ist nur das ScanThread() hier nicht als separater Thread parallel ausgeführt wird. Aber das Prinzip bleibt gleich.

Übrigens, wenn du globale Variablen unschön findest, warum ist IP: TIP auch global ??


Gruß Hagen


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:12 Uhr.
Seite 1 von 3  1 23      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz