Page 1 of 1

Dns lookup without 'RunProgram("nslookup.exe", ...' ?

Posted: Fri Mar 18, 2016 6:24 am
by registrymechanic22
Hi.
Help please.

nslookup in cmd.exe - several IP addresses

Code: Select all

nslookup google.com
Addresses:  2a00:1450:4010:c0f::65
          213.158.11.241
          213.158.11.245
          213.158.11.226
          213.158.11.215
          213.158.11.249
          213.158.11.221
          213.158.11.222
          213.158.11.251
          213.158.11.219
          213.158.11.230
          213.158.11.236
          213.158.11.207
          213.158.11.234
          213.158.11.237
          213.158.11.211
DnsQuery - only one IP address :cry:

Code: Select all

#DNS_TYPE_A          = $0001      ; //  1
#DNS_TYPE_NS         = $0002      ; //  2
#DNS_TYPE_MD         = $0003      ; //  3
#DNS_TYPE_MF         = $0004      ; //  4
#DNS_TYPE_CNAME      = $0005      ; //  5
#DNS_TYPE_SOA        = $0006      ; //  6
#DNS_TYPE_MB         = $0007      ; //  7
#DNS_TYPE_MG         = $0008      ; //  8
#DNS_TYPE_MR         = $0009      ; //  9
#DNS_TYPE_NULL       = $000a      ; //  10
#DNS_TYPE_WKS        = $000b      ; //  11
#DNS_TYPE_PTR        = $000c      ; //  12
#DNS_TYPE_HINFO      = $000d      ; //  13
#DNS_TYPE_MINFO      = $000e      ; //  14
#DNS_TYPE_MX         = $000f      ; //  15
#DNS_TYPE_TEXT       = $0010      ; //  16

#DNS_QUERY_STANDARD                  = $00000000
#DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE = $00000001
#DNS_QUERY_USE_TCP_ONLY              = $00000002
#DNS_QUERY_NO_RECURSION              = $00000004
#DNS_QUERY_BYPASS_CACHE              = $00000008

#DNS_QUERY_NO_WIRE_QUERY             = $00000010
#DNS_QUERY_NO_LOCAL_NAME             = $00000020
#DNS_QUERY_NO_HOSTS_FILE             = $00000040
#DNS_QUERY_NO_NETBT                  = $00000080

#DNS_QUERY_WIRE_ONLY                 = $00000100
#DNS_QUERY_RETURN_MESSAGE            = $00000200

#DNS_QUERY_TREAT_AS_FQDN             = $00001000
#DNS_QUERY_DONT_RESET_TTL_VALUES     = $00100000
#DNS_QUERY_RESERVED                  = $ff000000

Enumeration ; DNS_FREE_TYPE
  #DnsFreeFlat = 0
  #DnsFreeRecordList
  #DnsFreeParsedMessageFields
EndEnumeration 

Structure DNS_A_DATA
  IpAddress.l
EndStructure

Structure DNS_PTR_DATAA
  *pNameHost
EndStructure

Structure DNS_RECORD 
  *pNext.DNS_RECORD;  
  pName.s
  wType.w
  wDataLength.w
  StructureUnion
    DW.l 
    S.l
  EndStructureUnion
  dwTtl.l
  dwReserved.l
  
  StructureUnion
    A.DNS_A_DATA 
    PTR.DNS_PTR_DATAA
    CNAME.DNS_PTR_DATAA
  EndStructureUnion 
EndStructure

Prototype DnsQuery_(Name.s, wType.w, fOptions.l, *aopServers, *ppQueryResultSet, *pReserved)
Prototype DnsRecordListFree(*RecordList, FreeType)
Global DnsQuery_.DnsQuery_, DnsRecordListFree.DnsRecordListFree

Procedure LoadDnsApi(Library)
  Protected Result
  Result = OpenLibrary(Library, "Dnsapi.dll")
  If Result
    If Library = #PB_Any
      Library = Result
    EndIf
    CompilerIf #PB_Compiler_Unicode
      DnsQuery_ = GetFunction(Library, "DnsQuery_W")
    CompilerElse
       DnsQuery_ = GetFunction(Library, "DnsQuery_A")
    CompilerEndIf
    DnsRecordListFree = GetFunction(Library, "DnsRecordListFree")    
    If DnsQuery_ = 0 Or  DnsRecordListFree = 0
      CloseLibrary(Library)
      Result = 0
    EndIf      
  EndIf
  ProcedureReturn Result
EndProcedure

ProcedureDLL.l DnsQuery(ServerName$, nRecordType = #DNS_TYPE_A)
  Protected IP = 0, CName$, *Record.DNS_RECORD
  If DnsQuery_ And DnsRecordListFree
    If DnsQuery_(ServerName$, nRecordType, #DNS_QUERY_STANDARD|#DNS_QUERY_NO_HOSTS_FILE, #Null, @*Record.DNS_RECORD, #Null) = 0 And *Record
      If *Record\wType = #DNS_TYPE_A
        IP = *Record\A\IpAddress
      ElseIf *Record\wType = #DNS_TYPE_CNAME Or *Record\wType = #DNS_TYPE_MX
        CName$ = PeekS(*Record\CNAME\pNameHost)
        If CName$
          IP = DnsQuery(CName$)
        EndIf
      EndIf 
      DnsRecordListFree(*Record, #DnsFreeRecordList)
    EndIf
  EndIf
  ProcedureReturn IP
EndProcedure

InitNetwork()
ServerName$="google.com"
Debug ServerName$
LoadDnsApi(#PB_Any)

IP=DnsQuery(ServerName$, #DNS_TYPE_A)
Debug IPString(IP)
How to get all IP addresses (as in "nslookup.exe"), but without using "nslookup.exe", only code PB?

Best regards!

Re: Dns lookup without 'RunProgram("nslookup.exe", ...' ?

Posted: Fri Mar 18, 2016 8:03 am
by infratec
Hi,

you need something like this:

Code: Select all

        Repeat
          Debug IPString(*Record\A\IpAddress)
          *Record = *Record\pNext          
        Until *Record = #Null
I added a list to your procedure parameters, but get a warning because of dll and lists.
Also your recursive call is not needed:

Code: Select all

ProcedureDLL.i DnsQuery(ServerName$, List IPList.i(), nRecordType = #DNS_TYPE_A)
  Protected IP = 0, CName$, *OrgRecord.DNS_RECORD, *Record.DNS_RECORD
  If DnsQuery_ And DnsRecordListFree
    If DnsQuery_(ServerName$, nRecordType, #DNS_QUERY_STANDARD|#DNS_QUERY_NO_HOSTS_FILE, #Null, @*OrgRecord.DNS_RECORD, #Null) = 0 And *OrgRecord
        
        *Record = *OrgRecord
        
        Repeat
          AddElement(IPList())
          IPList() = *Record\A\IpAddress
          *Record = *Record\pNext          
        Until *Record = #Null
        
      DnsRecordListFree(*OrgRecord, #DnsFreeRecordList)
    EndIf
  EndIf
  ProcedureReturn #True
EndProcedure

InitNetwork()
ServerName$="google.com"
Debug ServerName$
LoadDnsApi(#PB_Any)

NewList DNSList.i()

IP=DnsQuery(ServerName$, DNSList(), #DNS_TYPE_MX)
ForEach DNSList()
  Debug IPString(DNSList())
Next
Bernd

Re: Dns lookup without 'RunProgram("nslookup.exe", ...' ?

Posted: Fri Mar 18, 2016 9:31 am
by registrymechanic22
infratec wrote:Hi,

Code: Select all

        Repeat
          Debug IPString(*Record\A\IpAddress)
          *Record = *Record\pNext          
        Until *Record = #Null
Bernd
Very big Thank!
you are the best ! :D

Code: Select all

EnableExplicit

Structure DNS_A_DATA
  IpAddress.l
EndStructure

Structure DNS_PTR_DATAA
  *pNameHost
EndStructure

Structure DNS_RECORD 
  *pNext.DNS_RECORD;  
  pName.s
  wType.w
  wDataLength.w
  StructureUnion
    DW.l 
    S.l
  EndStructureUnion
  dwTtl.l
  dwReserved.l
  
  StructureUnion
    A.DNS_A_DATA 
    PTR.DNS_PTR_DATAA
    CNAME.DNS_PTR_DATAA
  EndStructureUnion 
EndStructure

Prototype DnsQueryW(Name.s, wType.w, fOptions.l, *aopServers, *ppQueryResultSet, *pReserved)
Prototype DnsRecordListFree(*RecordList, FreeType)
Global DnsQueryW.DnsQueryW, DnsRecordListFree.DnsRecordListFree

Procedure LoadDnsApi()
  Protected Result
    Result = OpenLibrary(0, "Dnsapi.dll")
      If Result
        DnsQueryW = GetFunction(0, "DnsQuery_W")
        DnsRecordListFree = GetFunction(0, "DnsRecordListFree")
          If DnsQueryW = 0 Or  DnsRecordListFree = 0
            CloseLibrary(0)
            Result = 0
          EndIf      
      EndIf
  ProcedureReturn Result
EndProcedure

Procedure.i NSlookUP(ServerName$, Array ArrayNSlookUP.s(1))
  Protected result.a=0, CName.s, *Record.DNS_RECORD, numDNS.i
    If DnsQueryW(ServerName$, 1, 0|64, #Null, @*Record.DNS_RECORD, #Null) = 0 And *Record
      If *Record\wType = 1
        numDNS=ArraySize(ArrayNSlookUP.s())
        Repeat
          ReDim ArrayNSlookUP(numDNS)
          ArrayNSlookUP(numDNS)=IPString(*Record\A\IpAddress)
          numDNS+1
            If *Record\pNext <> #Null
              *Record = *Record\pNext
            EndIf
        Until *Record\pNext = #Null
        result+1
      ElseIf *Record\wType = 5 Or *Record\wType = 15
        CName = PeekS(*Record\CNAME\pNameHost)
        If CName
          result+NSlookUP(CName, ArrayNSlookUP.s())
        EndIf
      EndIf 
      DnsRecordListFree(*Record, 1)
    EndIf
ProcedureReturn result
EndProcedure

InitNetwork()
LoadDnsApi()

Define x.i
Dim ArrayNSlookUP.s(0)

If NSlookUP("google.com", ArrayNSlookUP.s())>0
  For x = 0 To ArraySize(ArrayNSlookUP())
    Debug ArrayNSlookUP(x)
  Next
Else  
  MessageRequester("Info.", "Domain name not found.") 
EndIf

Re: Dns lookup without 'RunProgram("nslookup.exe", ...' ?

Posted: Fri Mar 18, 2016 8:32 pm
by Lunasole
It is all long and unhandy code ^^

Try this cool & beautiful hack. Works on all OS, no firewall can detect query (so no need to care about it). Here on forum is topic about this, but I didn't remember what exactly

Code: Select all

InitNetwork ()

Structure IP4Adress
	StructureUnion
		IP.l			; long representation of IP. use IPString () to convert it to separated string
		IP_byte.a [4]	; separated bytes of IP4 adress
	EndStructureUnion
EndStructure

; ======================================================

Procedure.l GetIPByHost(Host$="")
	Protected Result.l = 0
	If Host$=""
		Host$=Hostname()
	EndIf
	Protected SelfLoop = OpenNetworkConnection(Host$,0 , #PB_Network_UDP)
	
	If SelfLoop
		Result=GetClientIP(SelfLoop)
		CloseNetworkConnection(SelfLoop)
	EndIf
	ProcedureReturn Result
EndProcedure

; ======================================================

Define X.IP4Adress
X\IP = GetIPByHost ("google.com")
MessageRequester (" ", IPString (X\IP))
PS. Sorry, didn't read you need all the IPs

Re: Dns lookup without 'RunProgram("nslookup.exe", ...' ?

Posted: Sat Mar 19, 2016 12:59 am
by Keya
Lunasole wrote:Works on all OS, no firewall can detect query
wouldn't a firewall monitoring UDP port 53 detect it?

Re: Dns lookup without 'RunProgram("nslookup.exe", ...' ?

Posted: Sat Mar 19, 2016 3:47 am
by Lunasole
Keya wrote:wouldn't a firewall monitoring UDP port 53 detect it?
If you totally block this port on you firewall you will not be able to resolve any address in any application which uses OS-implemented DNS. So at least system resolving process (one of services withing svchost.exe on Windows) must have DNS queries allowed.

And that code doesn't send any request -- it just calls OS API and then network activity is performed from system process name, the resolving is side-effect. Firewall can't do anything in this case (it is useless to block network access for application), except maybe if firewall intercepts API calls that app does and control them.