Eigene IP auslesen

Hier könnt ihr sowohl zur x86 Architektur als auch zu Win32ASM Fragen stellen.

Moderatoren: crack, Krüsty, Marwin

Beitragvon Peter III » Montag 16. August 2004, 14:14

Hallo zusammen,

ich stehe vor dem Problem meine eigene/öffentliche IP-Adresse auszulesen.
Alle Beispiele dazu hab ich nur in C/C++ und anderen Sprachen gefunden.
Also hier ist die Beispiel :
Code: Alles auswählen

int __fastcall TForm1::GetIPs(TStrings* Strings)
{
    WSAData wsa;
    char HostName[255];
    hostent* HostEntry = NULL;
    in_addr InetAddress;
    int RetVal = 0;

    // Winsock initialisieren:
    if(WSAStartup( MAKEWORD(2, 1), &wsa) == 0)
    {
        // eigene Hostnamen herausfinden:
        if(gethostname(HostName, 255))
            return 0;

        // Hostinformationen abrufen:
        HostEntry = gethostbyname(HostName);
        if(HostEntry == NULL)
            return 0;

        // IP-Adressen auslesen
        Strings->Add("IP-Adresse:");
        for(int AddrIndex=0; HostEntry->h_addr_list[AddrIndex]; AddrIndex++)
        {
            InetAddress.S_un.S_addr = *((DWORD*)HostEntry->h_addr_list[AddrIndex]);
            if(Strings != NULL)
                Strings -> Add(inet_ntoa(InetAddress));
            RetVal++;
        }
    }
    else
        return 0;
    WSACleanup();
    return RetVal;
}


diese Funktion (laut ihre Autor) muß alle IPs auslesen, in ein ListBox schreiben und Anzahl IPs als Rückgabewert liefern.

Nun versuche ich das ganze in ASM zu schreiben

Code: Alles auswählen

.data
szHostName    db 255 DUP (0)
HostEntry         hostent <?>

.code
start:
......
viel viel Code
.....

; Alle IP-Addressen auslesen
invoke WSAStartup, 0002h, addr wsadata       ; Winsock2 initialisieren
cmp eax, 0
jnz _exit               
invoke gethostname, addr szHostName, FUNC(lstrlen, addr szHostName)   
cmp eax, 0
jne _exit
   
invoke gethostbyname, addr szHostName
mov [HostEntry], eax  ; <<<<<<<<<<<<<<<<<<<<  Fehler

.....

END start


Der Assembler meldet folg. Fehler:
error A2022: instruction operands must be the same size

Ja es ist mir schon klar, das ich versuche in eine Variable von Typ hostent, Inhalt des EAX zu schreiben.
Nun funktioniert das irgendwie in C
Meine Frage wie mache/portiere ich diese Funktion in ASM-Code???

Danke ;)
Peter III
Member
 
Beiträge: 17
Registriert: Montag 16. August 2004, 13:53

Beitragvon Marwin » Montag 16. August 2004, 20:43

Hallo Peter,

hostent ist keine 32-Bit Variable (in diesem Fall wäre es kein Problem, in ihr einen Wert aus dem EAX-Register zu speichern, so wie du es getan hast), sondern sie ist eine Struktur. Siehe Windows.inc:

hostent STRUCT
  h_name      DWORD      ?
  h_alias    DWORD      ?
  h_addrtype  WORD      ?
  h_length    WORD      ?
  h_addr_list DWORD      ?
hostent ENDS


Da die Funktion gethostbyname einen Zeiger auf die Struktur hostent zurückliefert, muss deine Variable HostEntry vom Typ DoubleWord (deklarieren mit DWORD oder dd) sein:

Code: Alles auswählen
.data
szHostName    db 255 DUP (0)
HostEntry dd ?


Das gethostbyname eine Adresse zurückliefert kann u.a. daran erkennen, dass im C++ Code bei der die Variablendeklaration nach dem Typnamen ein Sternchen folgt. HostEntry ist demnach eine Variable, die auf eine Datenstruktur vom Typ HostEntry zeigt.

Grüße, Marwin
Benutzeravatar
Marwin
Moderator
 
Beiträge: 307
Registriert: Donnerstag 8. Mai 2003, 21:19
Wohnort: Seelow, Deutschland

Beitragvon Peter III » Montag 16. August 2004, 22:43

Na also doch hätte ich das gleich probieren müßen :D :D :D
Erlich gesagt hab ich mir auch gedacht den HostEntry einfach als DWORD zu deklarieren.
Das muß ich mal gleich ausprobieren :)


Moment mal, was hat dann Structur hostent damit zutun???
Wenn ich den HostEntry einfach als DWORD deklariere, dann fehlt die Structur hostent bei uns ganz aus!
Ist das normal???? :o

Am bessten probiere ich es erst aus, und dann melde mich wieder wenn was nicht klappt.



Bis dahin vielen vielen Dank und schönen Abend noch!!! :)
Peter III
Member
 
Beiträge: 17
Registriert: Montag 16. August 2004, 13:53

Beitragvon Peter III » Montag 16. August 2004, 23:46

Hallo ich bins wieder,
Code: Alles auswählen

invoke WSAStartup, 0002h, addr wsadata                                  ; Winsock initialisieren
   cmp eax, 0
   jnz _exit   
   
   invoke gethostname, addr szHostName, sizeof szHostName      ; eigene Hostname ermitteln
   cmp eax, 0
   jne _exit
   
   invoke gethostbyname, addr szHostName                                  ; Hostinformationen holen
   cmp eax, 0
   je _exit
   mov [HostEntry], eax      ; <<<<<<<<<<<<<<   Zeiger auf Struktur hostent

also hatt geklappt mit dem DWORD
Danke!

nun tritt gleich ein zweites Problem auf:
in_addr InetAddress
lässt sich nicht deklarieren, ich versuche es wie folgt:
InetAddress in_addr [?] ; denn in_addr ist ja auch eine Struktur, oder???
Fehlermeldung:
error A2138: invalid data initializer
error A2036: too many initial values for structure

soll ich sie auch als dd deklarieren???

Und das wichtigste:
irgenwie kann ich nicht nachvollziehen was in dieser Schleife passiert:

for(int AddrIndex=0; HostEntry-]h_addr_list[AddrIndex]; AddrIndex++)
{
InetAddress.S_un.S_addr = *((DWORD*)HostEntry-]h_addr_list[AddrIndex]);
if(Strings != NULL)
Strings -] Add(inet_ntoa(InetAddress));
RetVal++;
}
kannst du mir bitte erklären???
Wie lange wird die Schleife durchlaufen??? ( ich nemme an solange bis alle IPs durchgelaufen sind)
und die Zeile:
InetAddress.S_un.S_addr = *((DWORD*)HostEntry-]h_addr_list[AddrIndex]
verstehe ich überhaupt nicht. Genauer zusein habe keine Ahnung wie ich die Zeile in ASM-Code umwandel ???

Need help :( :( :(
Peter III
Member
 
Beiträge: 17
Registriert: Montag 16. August 2004, 13:53

Beitragvon Marwin » Dienstag 17. August 2004, 21:07

Hallo Peter,

ja, in_addr ist auch eine Struktur. Diesmal ist die Variable InetAddress aber kein Zeiger auf eine Struktur, deshalb musst du in diesem Fall:

Code: Alles auswählen
InetAddress in_addr <>


verwenden.

Was den C++ Code anbetrifft folgendes: ich habe mich mit dieser Sprache bisher nur sehr wenig beschäftigt. Ich kann deshalb nicht mit Gewissheit schreiben, was der Code macht.

Das Element h_addr_list der Struktur hostent stellt ein Datenfeld aus 32-Bit Werten dar. Jeder dieser Werte zeigt auf einen String (also eine Zeichenfolge, welche mit einem NULL-Byte endet). Das Element dieses Datenfeldes, welches den Wert NULL hat, besagt, dass es keine weiteren Strings gibt. Sprich: die Liste ist zuende.
Die FOR-Schleife wird daher solange durchlaufen, bis die Liste abgearbeitet worden ist:

Code: Alles auswählen
; benutze ECX als AddrIndex
xor edi, edi  ; int RetVal = 0;
xor ecx, ecx  ; int AddrIndex=0;
mov eax, HostEntry
@Loop:
  lea  edx, [eax + ecx*4]; = HostEntry->h_addr_list[AddrIndex]
  test edx, edx  ; = am Ende der Liste angelangt?
  jz   @ExitLoop   ; = ja, Schleife verlassen

    [...]

    add  edi, 1  ; RetVal++;

  add  ecx, 1  ; = AddrIndex++
  jmp  @Loop  ; = nächstes Element des Datenfeldes abarbeiten

@ExitLoop:


Die Struktur in_addr (Variable InetAddress) ist folgendermaßen aufgebaut:

in_addr STRUCT
  S_un ADDRESS_UNION []
in_addr ENDS

ADDRESS_UNION UNION
  S_un_b S_UN_B []
  S_un_w S_UN_W []
  S_addr DWORD ?
ADDRESS_UNION ENDS


Ich würde den Code für die erste Zeile innerhalb der Schleife also so schreiben (oben für den Teil [...] einsetzen):

Code: Alles auswählen
mov InetAddress.S_un.S_addr, edx


Zu inet_ntoa ein Zitat aus dem Platform SDK:
The inet_ntoa function converts an (Ipv4) Internet network address into a string in Internet standard dotted format.


Über die nachfolgenden zwei Zeilen kann ich nichts Bestimmtes, sondern nur Vermutungen äußern. Strings ist ein Zeiger auf ein Datenfeld von Strings. Wenn Strings ein gültiger Zeiger ist (also auf einen Speicherbereich mit einer Adresse ungleich NULL zeigt), dann wird mit der Methode Add der konvertierte String, welcher von inet_ntoa zurückgegeben wurde, dem Datenfeld hinzugefügt.

Grüße, Marwin
Benutzeravatar
Marwin
Moderator
 
Beiträge: 307
Registriert: Donnerstag 8. Mai 2003, 21:19
Wohnort: Seelow, Deutschland

Beitragvon Peter III » Mittwoch 18. August 2004, 21:30

Hallo Marwin,

erstmal danke für deine Hilfe!

hoffe dass ich dich noch nicht nerve ;)

Also wenn ich die Deklaration von Strukture hostent näher ansehe, dann fellt mir auf das d. Element h_addr_list als fünfte
deklariert ist.
Laut dein Beispiel, greifst du auf das fünfte Element des Strukt. hostent in dem du folg. Zeile verwendest:
Code: Alles auswählen
lea  edx, [eax + ecx*4]; = HostEntry->h_addr_list[AddrIndex]


wobei beim erstem Schleifendurchlauf ECX gleich NULL ist.
Ist das korrekt so??? vor dem h_addr_list im Strukt. stehen noch zwei char und zwei schort Werten.
Wäre es nicht besser wenn wir auf h_addr_list mit
Code: Alles auswählen
mov eax, HostEntry
lea edx, [eax+6]  ; da 2xCHAR=2Byte  + 2xSHORT=4Byte

zugreifen ???

Irgendwie funktioniert dein Beispiel nicht/nicht ganz.
Also damit ich nur erste IP herausbekomme habe ich es wie folgt gemacht:

Code: Alles auswählen
invoke WSAStartup, 0002h, addr wsadata                                            ; Winsock initialisieren
   cmp eax, 0
   jnz _exit   
   
   invoke gethostname, addr szHostName, sizeof szHostName
   cmp eax, 0
   jne _exit
   
   invoke gethostbyname, addr szHostName
   cmp eax, 0
   je _exit
   mov [HostEntry], eax
;#############################################################################
; ab hier klappt es nicht
   
; benutze ECX als AddrIndex
   xor edi, edi                                    ; int RetVal = 0;
   xor ecx, ecx                                    ; int AddrIndex=0;
   mov eax, HostEntry                        ; Variable HostEntry nach eax laden
   lea edx, [eax+6]                            ; Offset des h_addr_list nach edx          <<<<<<  :wacko:
   
   mov DWORD PTR [InetAddress.S_un.S_addr],edx  ; InetAddress.S_un.S_addr = *((DWORD*)HostEntry->h_addr_list[AddrIndex]);
   invoke inet_ntoa, addr InetAddress        ; IP-Addresse in String konvertieren
   invoke MessageBox, NULL, eax, eax, 0    ; erste IP-Addresse per MessBox ausgeben  


Also d. Beispiel zeigt mir zwar die IP-Addresse, die stimmt aber mit meinem nicht überein
Bin voll am ende :( :( :(
need help :( :( :(
Sorry für die Schreibfehler, bin ein Auslaender :P
Peter III
Member
 
Beiträge: 17
Registriert: Montag 16. August 2004, 13:53

Beitragvon Marwin » Mittwoch 18. August 2004, 22:20

Hallo Peter,

hoffe dass ich dich noch nicht nerve

Ach was, wozu ist dieses Forum denn da?


Du hast recht, auf die hostent Struktur greift mein Assemblercode nicht korrekt zu. Richtig wäre folgendes:

Code: Alles auswählen
mov eax, HostEntry.h_addr_list


Das Element h_addr_list enthält (meines Erachtens) einen Zeiger auf eine Liste von Zeigern. Jeder dieser Zeiger zeigt letztendlich auf einen String. Und die Adresse dieses Strings (sprich der Wert des Zeigers, der auf den jeweiligen String zeigt) muss dann in InetAddress.S_un.S_addr gespeichert werden.

Wenn du die fehlerhafte Codezeile durch die oben geschriebene ersetzt, dann sollte es ohne Probleme funktionieren. Auch in einer Schleife, sod ass du dir alle IPs ausgeben kannst.

Sorry für die Schreibfehler, bin ein Auslaender

:) Und du bist nicht der einzigste in diesem Board. *zu Ignat schiel*


Grüße, Marwin
Benutzeravatar
Marwin
Moderator
 
Beiträge: 307
Registriert: Donnerstag 8. Mai 2003, 21:19
Wohnort: Seelow, Deutschland

Beitragvon Peter III » Mittwoch 18. August 2004, 23:42

Hallo Marwin,

also ich habe deinen Rat gefolgt, und versuche auf h_addr_list über HostEntry.h_addr_list zu zugreifen.
Und nun passiert das, wovon ich oben gesprochen habe:

Fehlermeldung: error A2006: undefined symbol : h_addr_list

Da wir von Funktion gethostbyname zurück gelieferten Zeiger (auf hostent), im HostEntry abgelegt haben. Muß auch möglich sein auf h_addr_list über HostEntry.h_addr_list zu zugreifen, oder?

Geht aber nicht :wacko:

Code: Alles auswählen
invoke WSAStartup, 0002h, addr wsadata
   cmp eax, 0
   jnz _exit   
   
   invoke gethostname, addr szHostName, sizeof szHostName
   cmp eax, 0
   jne _exit
   
   invoke gethostbyname, addr szHostName
   mov [HostEntry], eax
   cmp eax, 0
   je _exit
   
   mov eax, HostEntry.h_addr_list                  
mov [InetAddress.S_un.S_addr],eax            ; InetAddress.S_un.S_addr = *((DWORD*)HostEntry->h_addr_list[AddrIndex]);
   invoke inet_ntoa, addr InetAddress                 ; IP-Addresse in String konvertieren
   invoke MessageBox, NULL, eax, eax, 0             ; erste IP-Addresse per MessBox ausgeben  


Was kann ich noch tun???
Danke!
Peter III
Member
 
Beiträge: 17
Registriert: Montag 16. August 2004, 13:53

Beitragvon Marwin » Donnerstag 19. August 2004, 21:26

Hallo Peter,

die Struktur hostent ist in meiner Version der Windows.inc definiert, und zwar so, wie ich sie oben einmal gepostet habe. Schau doch bitte einmal in deiner Windows.inc nach.

Ansonsten solltest du vielleicht doch einfach den Offset zur Struktur hinzuaddieren, um zum h_addr_list-Element zu kommen. Allerdings sind es nicht 6 Byte, sondern 10: DWORD + DWORD + WORD + WORD = 4 + 4 + 2 + 2 (siehe Windows.inc im Verzeichnis \MASM32\INCLUDE\).

Grüße, Marwin
Benutzeravatar
Marwin
Moderator
 
Beiträge: 307
Registriert: Donnerstag 8. Mai 2003, 21:19
Wohnort: Seelow, Deutschland

Beitragvon Peter III » Samstag 21. August 2004, 15:31

Hallo,

:( ich weiss nicht, vielleicht bin ich einfach zudumm ? :o

irgendwie kriege ich es nicht hin, meine verdammte IP auszulesen.

Aber trotzdemm Danke für deine/eure Hilfe.

Grüß
Peter
Peter III
Member
 
Beiträge: 17
Registriert: Montag 16. August 2004, 13:53

Beitragvon CDW » Samstag 21. August 2004, 16:44

hm, ich hab hier einen code der funktioniert:
Code: Alles auswählen
   
   invoke WSAStartup,WSOCK_VERSION, addr WSAData
      .if eax!=0
      invoke MessageBox,0,addr msg_WSAStartup_error,addr msg_Error,MB_ICONERROR
      mov eax,1
      ret
     .endif   
    
   lea ecx, User_options
   invoke inet_addr,addr (tUser_options ptr [ecx]).ServerName
   .if eax==INADDR_NONE
     lea ecx, User_options
;<= ab hier ist es für dich relevant
     invoke gethostbyname,addr (tUser_options ptr [ecx]).ServerName
     .if eax==NULL
         mov eax,1
         ret
     .endif
     mov     eax, [(hostent ptr [eax]).h_list]
        test    eax, eax
        jz      _error
        
        mov     eax, [eax]
        test    eax, eax
        jz      _error
    
        mov   eax , [eax]
        lea ecx,User_options
        mov  (tUser_options ptr [ecx]).ServerIp,eax
;<=bis hier... hier speichere ich die serverip
        jmp ENDE
        _error:
          mov eax,1
          ret
     ENDE:
   .else
    lea ecx, User_options
    mov (tUser_options ptr [ecx]).ServerIp,eax
   .endif
  

es ist vielleicht etwas verwirrend, allerdings wird das beim lesen der doku etwas klarer:

The gethostbyname function returns a pointer to a HOSTENT structure — a structure allocated by Windows Sockets. The HOSTENT



HOSTENT
Windows Sockets allocates this structure is allocated. An application should never attempt to modify this structure or to free any of its components. Furthermore, only one copy of this structure is allocated per thread, and so the application should copy any information that it needs before issuing any other Windows Sockets API calls.

struct hostent {
    char FAR *      h_name;
    char FAR * FAR * h_aliases;
    short            h_addrtype;
    short            h_length;
    char FAR * FAR * h_addr_list;
};



die h_addr_list scheint in der MASM include datei als h_list definiert zu sein, zumindest in meiner MASM8 version.

der code stammt übrigens aus einem Chatprogramm, kompletter quelltext ist unter cdw.de.vu unter MFY-projekt verfügbar. madwizard.org ist eine noch größere hilfe.
ich weiß nicht genau was du für einen Debugger benutzt, aber versuchs mal mit dem masm-mitgeliefertem (vkdebug)
setzt dann nach jeder funktione eine Printdec oder PrintString ausgabe und schau dir genau an wo etwas nicht stimmt... manchmal ist der fehler wirklich harmlos und nur aus flüchtigkeit entstanden...
CDW
Alter Hase
 
Beiträge: 62
Registriert: Donnerstag 2. Oktober 2003, 17:17

Beitragvon Peter III » Samstag 21. August 2004, 22:02

Hallo Leute :) :) :)

na ich habe es endlich hin gekriegt :D

Natürlich nicht ohne eure Hilfe ;)

CDW danke für die Links und Code, das hat mir sehr geholfen

und falls es hier noch jemanden interessiert hier ist der Stück code:
Code: Alles auswählen
invoke WSAStartup, 0002h, addr wsadata
   cmp eax, 0
   jnz _exit   
   
   invoke gethostname, addr szHostName, sizeof szHostName  ; eigene Hostnamen herausfinden:
    invoke gethostbyname,addr szHostName      ; Hostinformationen abrufen
    cmp eax, 0
    jz _error
    
    mov     eax, [(hostent ptr [eax]).h_list]
    test    eax, eax
    jz      _error
      
     mov     eax, [eax]
    test    eax, eax
    jz      _error
  
     mov   eax , [eax]
   invoke inet_ntoa,  eax
   invoke MessageBox, 0, eax, eax, 0
    jmp ENDE
    
    _error:
         mov eax,1
         ret
    ENDE:



Grüß
Peter
Peter III
Member
 
Beiträge: 17
Registriert: Montag 16. August 2004, 13:53

Beitragvon Marwin » Samstag 21. August 2004, 23:25

CDW hat geschrieben: die h_addr_list scheint in der MASM include datei als h_list definiert zu sein, zumindest in meiner MASM8 version.

Mhm, in meiner Version der Windows.inc wird die Struktur so definiert, wie ich es im ersten Beitrag angegeben habe. Aber seis wie es sei, jetzt funktioniert es ja :P

Grüße, Marwin
Benutzeravatar
Marwin
Moderator
 
Beiträge: 307
Registriert: Donnerstag 8. Mai 2003, 21:19
Wohnort: Seelow, Deutschland


Zurück zu Assembler

 


  • { RELATED_TOPICS }
    Antworten
    Zugriffe
    Letzter Beitrag

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder

cron