AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Projekte Kleiner und schneller Portscanner (nonVCL) mit EXE!
Thema durchsuchen
Ansicht
Themen-Optionen

Kleiner und schneller Portscanner (nonVCL) mit EXE!

Ein Thema von Assarbad · begonnen am 2. Aug 2003 · letzter Beitrag vom 18. Aug 2003
Antwort Antwort
Seite 1 von 3  1 23      
Assarbad
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.
 
Benutzerbild von negaH
negaH
 
#2
  Alt 2. Aug 2003, 13:03
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
  Mit Zitat antworten Zitat
Assarbad
 
#3
  Alt 2. Aug 2003, 16:30
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

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
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH
 
#4
  Alt 2. Aug 2003, 17:18
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
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH
 
#5
  Alt 2. Aug 2003, 17:22
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
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH
 
#6
  Alt 2. Aug 2003, 17:29
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
  Mit Zitat antworten Zitat
Assarbad
 
#7
  Alt 2. Aug 2003, 19:53
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.
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH
 
#8
  Alt 2. Aug 2003, 20:57
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
  Mit Zitat antworten Zitat
Assarbad
 
#9
  Alt 2. Aug 2003, 21:52
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
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH
 
#10
  Alt 2. Aug 2003, 22:38
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
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:03 Uhr.
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