PortScan

Anfängerfragen zum Programmieren mit PureBasic.
Toshy
Beiträge: 713
Registriert: 22.03.2005 00:29
Computerausstattung: Computer und Strom vorhanden
Wohnort: LK Wolfenbüttel

Beitrag von Toshy »

Hi,

da scheint Assembler drinn zu sein, das ich nicht kann. Aber ich vermute es ist ähnlich wie ich es mache nur halt in PB.

Code: Alles auswählen

If AktuellerPort > #maxPort 
      ThreadCount-1 
      Pure_LeaveCS(CS) ;<- WICHTIG! Sonst warten die anderen Threads unendlich 
      ProcedureReturn 1 
    EndIf 
    LokalerPort = AktuellerPort 
    AktuellerPort+1 
    Pure_LeaveCS(CS)  
Was ich aber wissen möchte ist, warum das obere Pure_leaveCS(CS) wichtig ist?, denn nach der If-Abfrage, besser nach dem NEXT kommt ja auch nochmal ein Pure_leaveCS(CS), was ja auf jedenfall abgerufen wird, also dürfte es doch gar nicht passieren, das die anderen Thread unendlich warten!?

Ich habe das zwar auch nur in PB, aber da muß ich ja aufpassen das das setzten des "Warteflags", so will ich es mal nennen, auch nicht gleichzeitig von zwei Thread gesetzt wird, daher macht dies ein extra Thread, der als einziger "Schreibrechte" darauf hat. Ist also nicht so schön und einfach wie hier. Ich vermute mal, das Assembler so direkt am System ist, das es hier keine Syncronisationsprobleme gibt, da immer nur "einer" zugriff auf den Speicher haben kann / darf oder es keine Thread im PB-sinne gibt. Aber das ist nur so ne vermutung ich würde es gerne erklärt haben. Ich will ja lernen.

[edit]
Habe noch gleich ne Frage.
Wie verhält sich dieser Assemblercode (wenn es denn welcher ist)? So wie PB code, da ja auch soweit ich gelesen haben in Assembler (ASM) umgesetzt wird? Wenn dieser Code nun einfach normal mit jedem Thread ausgeführt wird, kann dann nicht auch theoretisch gleichzeitig (ich meine jetzt nicht diese Beispiel) von 2 Thread in den selben (ASM)Speicher(Variable) geschrieben werden?
Wenn ich das richtig verstehe wird mit z.B. *PCS\Cnt=0 der Wert NULL gespeichert. Wenn dieser Wert nun durch den Assemblercode auf EINS gesetzt wird und gehen wir mal davon aus, das mehrere Thread mit dem selben ASM code diesen Wert gleichzeitig setzen wollen, hier auch der Speicher gleichzeitig genutzt werden könnte (wenn man mal die überprüfung durch die warteschleife wegläßt). nur ob es möglich wäre?

Gruß
Toshy
Benutzeravatar
Rob
Shadow Admin
Beiträge: 258
Registriert: 26.08.2004 01:39
Kontaktdaten:

Beitrag von Rob »

Danilo bat mich, dass ich dies für ihn poste. Läuft sicher, auch mit 10.000 Threads:

Code: Alles auswählen

;
; by Danilo, 2005/11/05
;
;    run 10000 threads with string operations, PB 3.93 + WinAPI
;
DisableDebugger ; needed when using threads! (debugger locks sometimes if enabled)

#THREAD_COUNT = 10000
#TIMEOUT      = 30000

Global Thread_Count.l
Global cs.CRITICAL_SECTION

Procedure MyThread(Thread.l)

  For i = 100 To 101+Random(1000)
    EnterCriticalSection_(cs)
      ; do string operations
      A$ + Hex(Random($FF)+Random($FF))
    LeaveCriticalSection_(cs)
  Next i

  EnterCriticalSection_(cs)
    ; do string and debug operations
    EnableDebugger
      Debug RSet(Str(Thread),5,"0")+": "+A$
    DisableDebugger
  LeaveCriticalSection_(cs)

  ; end thread
  InterlockedDecrement_(@Thread_Count)   ; threadsafe 'Thread_Count - 1'

  ExitThread_(0)

EndProcedure



InitializeCriticalSection_(cs)

;
; create the threads
;
For i = 0 To #THREAD_COUNT-1
  If CreateThread(@MyThread(),i)
    InterlockedIncrement_(@Thread_Count) ; threadsafe 'Thread_Count + 1'
  EndIf
Next i


;
; wait for all threads - with timeout
;
time_start = ElapsedMilliseconds()
While Thread_Count
  If ElapsedMilliseconds()>time_start + #TIMEOUT
    If MessageRequester("TIMEOUT!","Quit?",#PB_MessageRequester_YesNo)=#IDYES
      Break
    EndIf
  Else
    Delay(10)
  EndIf
Wend

DeleteCriticalSection_(cs)


MessageRequester("INFO","APPLICATION ENDS!")
Build a man a fire and he's warm for a day. Set a man on fire and he's warm for the rest of his life
Benutzeravatar
DataMiner
Beiträge: 220
Registriert: 10.10.2004 18:56

Beitrag von DataMiner »

:allright:
Ein riesen DANKE an Danilo!
(und natürlich an Rob, fürs posten)
__________________________________________
Weniger glauben - mehr wissen!
------------------------------------------------------
Proud beneficial owner of SpiderBasic, PureBasic 3.x, 4.x, 5.x and PureVisionXP
Toshy
Beiträge: 713
Registriert: 22.03.2005 00:29
Computerausstattung: Computer und Strom vorhanden
Wohnort: LK Wolfenbüttel

Windows API !?

Beitrag von Toshy »

Hi.

Das ist aber doch WindowsApi-abhängig oder geht das dann auch unter Linux?
Das habe ich zwar auch in der WindowsApi gefunden, aber wenn es nur unter Windows läuft, dann kann es nicht jeder nutzen.
Auch ich will es gleich für später korrekt für Linux im Code haben.

Oder täusche ich mich und das ist auch in Linux vorhanden?

[edit]
Ach ja, sagt mal. "CRITICAL_SECTION " ist ja wohl eine Struktur die Automatisch in PB bekannt ist (scheint ne WIndowsstruktur zu sein), aber wo steht, wie die aufgebaut ist. In meiner WindowsApihilfe steht nichts zum Aufbau. Habe aber auch nicht mehr die Neuste.

Gruß
Toshy
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8808
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Werkzeuge -> Strukturenverzeichnis
Benutzeravatar
jpd
Beiträge: 380
Registriert: 14.02.2005 10:33

Beitrag von jpd »

Hi @all,

habe versucht diesen code mit 4.x zu verwenden,

kriege leider eine "invalid access memory"
on line 85...

kann das jemand korregieren?

Grüsse
jpd


PureFan hat geschrieben:Hier mal ein Beispiel, wie man einen Portscann am besten machen sollte.

Dauernd Threads zu killen und neu zu erstellen halte ich persönlich nicht für sinnvoll, viel besser ist es die Anzahl der Threads konstant zu halten!

Das ganze System ist im Prinzip eine Art Automat zum Nummern ziehen. Solange Nummern vorhanden sind "zieht" sich jeder Thread eine und führt die Überprüfungen durch! Dadurch sind Konflike zwischen den Threads ausgeschlossen.

Hier im Test wird "localhost" gescannt, dadurch sind auch 1000 Überprüfungen gleichzeitig möglich (#ChecksAtSameTime)! Sollte der Code aber für das Internet umgebaut werden ist es unbedingt notwendig die Anzahl zu reduzieren, da es sonst zu Verbindungs-Überlastungen und Timeouts bei anderen Programmen kommen kann.

Code: Alles auswählen

;- PureFan's Critical Section
DisableDebugger
Structure Pure_CS 
  Cnt.l 
EndStructure 
Procedure Pure_InitCS(*PCS.Pure_CS) 
  *PCS\Cnt=0 
EndProcedure 
Procedure Pure_EnterCS(*PCS.Pure_CS) 
  !POP Edi           ;POP/PUSH dient zum schnellen Einlesen des Parameters *PCS in das Register EDI 
  !PUSH Edi 
  
  !.loop: 
  Delay(1)
  
  !MOV Esi,1 
  !XCHG [Edi],Esi    ;Wir lesen den alten Wert aus und schreiben als neuen 1 rein! 
  
  !CMP Esi,0         ;Alter Wert war null, d.h. die vorige CS ist fertig 
  !JNE .loop         ;Durch das XCHG haben wir automatisch wieder 1 im Speicher 
EndProcedure 
 Procedure Pure_LeaveCS(*PCS.Pure_CS) 
  *PCS\Cnt=0 
EndProcedure
EnableDebugger


;- Definitionen

#minPort = $0000
#maxPort = $FFFF
#ChecksAtSameTime = 1000

Global AktuellerPort:  AktuellerPort=#minPort
Global CS.Pure_CS   :  Pure_InitCS(CS)
Global ThreadCount  :  ThreadCount = 0
NewList OpenPorts.l()

;- Thread ScanPorts

DisableDebugger
Procedure ScanPorts(OhneFunktion.l)
  Repeat
    
    ;Jeder Thread zieht eine Nummer zum Überprüfen!
    ;Der Code hier darf nicht mehrfach gleichzeichtig ausgeführt werden!
    ;Dies wird durch die CriticalSection gewährleistet
    Pure_EnterCS(CS)
    If AktuellerPort > #maxPort
      ThreadCount-1
      Pure_LeaveCS(CS) ;<- WICHTIG! Sonst warten die anderen Threads unendlich
      ProcedureReturn 1
    EndIf
    LokalerPort = AktuellerPort
    AktuellerPort+1
    Pure_LeaveCS(CS)
    
    ;=> Jeder Thread hat eine einmalige Nummer = Port!
    
    ;ACHTUNG: OpenNetworkConnection ist hier nur Threadsicher, da ein
    ;konstanter String verwendet wird!
    check=OpenNetworkConnection("localhost",LokalerPort)
    If check
      CloseNetworkConnection(check)
      
      ;=> Der Port ist offen => LL eintragen
      Pure_EnterCS(CS)
      AddElement(OpenPorts())
      OpenPorts()=LokalerPort
      Pure_LeaveCS(CS)
    EndIf
    
  ForEver
EndProcedure
EnableDebugger

;- Main

InitNetwork()

;1. Starte alle Threads! Es kann passieren, dass das Starten manchmal fehlschlägt,
;   daher müssen wir mitzählen
For I=1 To #ChecksAtSameTime
  If CreateThread(@ScanPorts(),0)
    Pure_EnterCS(CS)
    ThreadCount+1
    Pure_LeaveCS(CS)
  EndIf
Next I

;2. Die Hauptschleife! Sie kann dazu genutzt werden den aktuellen Status
;   anzuzeigen
Repeat
  Delay(1000)
  
  ;Berechne den Status in Prozent und zeige ihn an
  Pure_EnterCS(CS)
  Cur.l=(AktuellerPort-#minPort)*100/(#maxPort-#minPort)
  Debug Str(Cur)+"%"
  Pure_LeaveCS(CS)
  
Until ThreadCount=0 ;=> Bis kein Thread mehr offen ist!

Debug "DONE!"
  
;3. Ergebnisse auswerten!
ForEach OpenPorts()
  Debug OpenPorts()
Next

End
Mfg,
PureFan

EDIT: Ganz kleiner Rechtschreibfehler korrigiert, der jedoch keinen Einfluss auf die Funktionsweise hat ;)

EDIT2: Eine weitere kleine Modifikation durchgeführt, die das ganze möglicherweise etwas stabiler macht.
PB 5.10 Windows 7 x64
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

es ist unnötig, komplette zitate einzubinden.

auch zwischen quote-tags kann editiert werden.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8808
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Ich glaube es funktioniert, wenn du es so abänderst:

Code: Alles auswählen

Procedure Pure_EnterCS(*PCS.Pure_CS)
  ;!POP Edi           ;POP/PUSH dient zum schnellen Einlesen des Parameters *PCS in das Register EDI
  ;!PUSH Edi
  MOV Edi, *PCS
  ...
Allerdings musst du dafür die Inline-ASM-Unterstützung in den
Compiler-Optionen einschalten.
Benutzeravatar
PureBasic4.0
Beiträge: 785
Registriert: 29.10.2006 17:26
Wohnort: 127.0.0.1

Beitrag von PureBasic4.0 »

Im CT&T Forum gibt's nen Code OpenNetworkConnectionEx. Wenn ein Port nich offen ist, braucht die built-in funktion ewigkeiten. Mit OpenNetworkConnectionEx kann man einen Timeout hinzufügen. :allright:
PB 4.50 RC1 + Ubuntu 10.04 LTS + Windows 7 x64
Benutzeravatar
jpd
Beiträge: 380
Registriert: 14.02.2005 10:33

Beitrag von jpd »

Hi NicTheQuick,

tut's! :allright:


@kaeru Gaman
auch zwischen quote-tags kann editiert werden.
meinst'du so?


@PureBasic4.0 mal schauen..


Danke an Alle

jpd
PB 5.10 Windows 7 x64
Antworten