The following demo contains a hardcoded domain name, so change it :)
The demo takes a host domain name and attempts to fetch any and all MailServers by using an MX Lookup on the DNS of the host.
A few people have been asking about this for a while now, and so I finally got off my ass and translated the snippet that Thomas handed me many moons ago.
AFAIK it will only work on Win2K and up.

Somehow, somewhere, one of the structs I translated from WinDNS.h has become 16 bytes too large, and so theres a cheap fix in the code.
If anyone spots the issue in the structs, please feel free to fix it and repost it.

Have a nice day :)
Posted on 2004-01-05 03:46:30 by Homer
Too bad it works only in 2k. But how does all the SMTP server progs for win98 work(eg. Free SMTP Server, Advanced SMTP server)

Thomas ANtony:confused: :stupid: :notsure: :(
Posted on 2004-01-05 05:54:34 by thomasantony
One way for win98 is to use the undocumented ICMP.DLL
Look here for info
Posted on 2004-01-05 07:05:41 by Homer
Here is version that work all OS:
;##########################################################################

; dns-mx
; 22.06.2003 - 17.12.2003
; coded by comrade <comrade2k@hotmail.com>
; IRC: #asm, #coders, #win32asm on EFnet
; Web: [url]http://comrade64.cjb.net/[/url]
; [url]http://comrade.win32asm.com/[/url]
;##########################################################################
format PE GUI 4.0
entry start
;##########################################################################
include "%include%/win32a.inc"
include "%include%/macro/if.inc"
include "%include%/macro/macros.inc"
OFFSET equ
;##########################################################################
macro dddb long,bytes {
dd long
db bytes
}
;##########################################################################
DNS_FLAGS_QUERY = 0 shl 15 ; x1
DNS_FLAGS_RESPONSE = 1 shl 15
DNS_FLAGS_OPCODE_QUERY = 0 shl 11 ; x4
DNS_FLAGS_OPCODE_IQUERY = 1 shl 11
DNS_FLAGS_OPCODE_STATUS = 2 shl 11
DNS_FLAGS_AA = 1 shl 10 ; x1
DNS_FLAGS_TC = 1 shl 09 ; x1
DNS_FLAGS_RD = 1 shl 08 ; x1
DNS_FLAGS_RA = 1 shl 07 ; x1
DNS_FLAGS_Z = 1 shl 04 ; x3
DNS_FLAGS_RCODE = 1 shl 00 ; x4
DNS_TYPE_A = 01 shl 8
DNS_TYPE_NS = 02 shl 8
DNS_TYPE_MD = 03 shl 8
DNS_TYPE_MF = 04 shl 8
DNS_TYPE_CNAME = 05 shl 8
DNS_TYPE_SOA = 06 shl 8
DNS_TYPE_MB = 07 shl 8
DNS_TYPE_MG = 08 shl 8
DNS_TYPE_MR = 09 shl 8
DNS_TYPE_NULL = 10 shl 8
DNS_TYPE_WKS = 11 shl 8
DNS_TYPE_PTR = 12 shl 8
DNS_TYPE_HINFO = 13 shl 8
DNS_TYPE_MINFO = 14 shl 8
DNS_TYPE_MX = 15 shl 8
DNS_TYPE_TXT = 16 shl 8
DNS_CLASS_IN = 01 shl 8
DNS_CLASS_CS = 02 shl 8
DNS_CLASS_CH = 03 shl 8
DNS_CLASS_HS = 04 shl 8
struc DNSHeader {
.id dw ?
.flags dw ?
.qdcount dw ?
.adcount dw ?
.nscount dw ?
.arcount dw ?
}
struct DNSHeader ; 12 bytes
struc DNSQuestion {
.type dw ?
.class dw ?
}
struct DNSQuestion ; 4 bytes
struc DNSResource {
.type dw ?
.class dw ?
.ttl dd ?
.rdlength dw ?
}
struct DNSResource ; 8 bytes
struc DNSMX {
.preference dw ?
.exchange dw ?
}
struct DNSMX ; 4 bytes
;##########################################################################
;##########################################################################
;##########################################################################
section ".code" code readable executable
;##########################################################################
start:
;##########################################################################
;##########################################################################
push ebx esi edi
; initialize
mov eax,OFFSET sendwrap
mov ecx,OFFSET recvwrap
xchg eax,[send]
xchg ecx,[recv]
mov [ws32send],eax
mov [ws32recv],ecx
stdcall [WSAStartup],101h,OFFSET wsd
test eax,eax
jnz .quit
call [GetTickCount]
mov [dwTime],eax
stdcall [WSASetBlockingHook],OFFSET BlockHook
stdcall getMX,OFFSET szHost,OFFSET dwRootServers,0
stdcall [inet_ntoa],eax
mov ebx,eax
showfmt "MX for %s is %s",OFFSET szHost,ebx
.quit: call [WSACleanup]
pop edi esi ebx
stdcall [ExitProcess],0
;##########################################################################
proc getMX,pszDomain,lpServers,dwDepth
.addr rd 02h
.buffer rd 01h
.domain rb 100h
.answer rb 100h
.sin sockaddr_in
.dnshdr DNSHeader
.dnsq DNSQuestion
.pref rw 01h
rb 02h
enter
push ebx esi edi
xor eax,eax
mov [.pref],-1
mov [.addr+00h],eax
mov [.addr+04h],eax
mov [.answer],0
stdcall allocBuffer,10000h
mov [.buffer],eax
cmp [dwDepth],8
jge .err

mov esi,[lpServers]
.serv: push esi
mov ebx,[esi]
stdcall [socket],PF_INET,SOCK_DGRAM,0
cmp eax,INVALID_SOCKET
je .serr
xchg eax,ebx
lea edx,[.sin]
mov [edx+sockaddr_in.sin_family],AF_INET
mov [edx+sockaddr_in.sin_port],53 shl 8
mov [edx+sockaddr_in.sin_addr],eax
stdcall [connect],ebx,edx,sizeof.sockaddr_in
test eax,eax
jnz .serr
; send
lea edi,[.dnshdr]
mov ecx,sizeof.DNSHeader shr 2
rep stosd
sub edi,sizeof.DNSHeader
mov [edi+DNSHeader.id],01 shl 8
mov [edi+DNSHeader.flags],01
mov [edi+DNSHeader.qdcount],01 shl 8
mov [.dnsq.type],DNS_TYPE_MX
mov [.dnsq.class],DNS_CLASS_IN
stdcall addBuffer,[.buffer],edi,sizeof.DNSHeader
mov esi,[pszDomain]
mov edi,esi
dec esi
.next: inc esi
cmp byte [esi],"."
je @F
cmp byte [esi],0
jne .next
@@: mov eax,esi
sub eax,edi
push eax
mov eax,esp
stdcall addBuffer,[.buffer],eax,1
stdcall addBuffer,[.buffer],edi ; length on stack
inc esi
mov edi,esi
cmp byte [esi-1],0
jne .next
stdcall addBuffer,[.buffer],OFFSET szBlank,1
lea eax,[.dnsq]
stdcall addBuffer,[.buffer],eax,sizeof.DNSQuestion
stdcall getBufferLength,[.buffer]
stdcall [send],ebx,[.buffer],eax,0
; receive
stdcall [recv],ebx,[.buffer],10000h,0
stdcall setBufferLength,[.buffer],eax
cmp eax,sizeof.DNSHeader
jl .serr
mov esi,[.buffer]
movzx eax,[.dnshdr.id]
cmp [esi+DNSHeader.id],ax
jne .serr
cmp [esi+DNSHeader.flags],DNS_FLAGS_RESPONSE
jz .serr
; copy header
lea edi,[.dnshdr]
mov ecx,sizeof.DNSHeader shr 2
rep movsd
; parse questions
movzx ebx,[.dnshdr.qdcount]
test ebx,ebx
jz .qdone
rol bx,8
.qnext: lea edi,[.domain]
xor ecx,ecx
stdcall copydomain,[.buffer]
add esi,sizeof.DNSQuestion
dec ebx
jnz .qnext
.qdone: ; parse answers, authority, and additional records
movzx eax,[.dnshdr.nscount]
movzx ebx,[.dnshdr.adcount]
movzx ecx,[.dnshdr.arcount]
xchg al,ah
xchg bl,bh
xchg cl,ch
add ebx,eax
add ebx,ecx
jz .rdone
.rnext: lea edi,[.domain]
xor ecx,ecx
stdcall copydomain,[.buffer]
movzx ecx,[esi+DNSResource.rdlength]
xchg cl,ch
cmp [esi+DNSResource.type],DNS_TYPE_MX
je .rmx
cmp [esi+DNSResource.type],DNS_TYPE_NS
je .rns
cmp [esi+DNSResource.type],DNS_TYPE_A
je .ra
cmp [esi+DNSResource.type],DNS_TYPE_SOA
je .rsoa
; skip
add esi,ecx
add esi,sizeof.DNSResource
jmp .rskip
.rmx: ; MX records
add esi,sizeof.DNSResource
lodsw
rol ax,8
lea edi,[.domain]
cmp ax,[.pref]
mov [.pref],ax
jae @F
lea edi,[.answer]
@@: stdcall copydomain,[.buffer]
jmp .rskip
.rns: ; NS records
add esi,sizeof.DNSResource
cmp [.pref],-1
je @F
add esi,ecx
jmp .rskip
@@: cmp [.answer],0
je @F
add esi,ecx
jmp .rskip
@@: lea edi,[.answer]
stdcall copydomain,[.buffer]
jmp .rskip
.ra: ; A records
add esi,sizeof.DNSResource
push ecx
lea eax,[.answer]
lea ecx,[.domain]
stdcall strcmpi,ecx,eax
test eax,eax
pop ecx
jz @F
add esi,ecx
jmp .rskip
@@: lea edi,[.addr]
movsd
jmp .rskip
.rsoa: ; SOA records
add esi,sizeof.DNSResource
cmp [.answer],0
je @F
; skip
add esi,ecx
jmp .rskip
@@: add ecx,esi
push ecx
lea edi,[.answer]
stdcall copydomain,[.buffer]
pop esi
.rskip: dec ebx
jnz .rnext
.rdone: lea eax,[.answer]
;msgbox eax
mov eax,[.addr]
cmp [.answer],0
je .serr
test eax,eax
jnz @F
lea eax,[.answer]
stdcall [gethostbyname],eax
test eax,eax
jz .serr
mov eax,[eax+hostent.h_list]
mov eax,[eax]
mov eax,[eax]
mov [.addr],eax
@@: cmp [.pref],-1
jne .done
; try another nameserver
stdcall [closesocket],ebx
mov eax,[dwDepth]
inc eax
lea edx,[.addr]
stdcall getMX,[pszDomain],edx,eax
test eax,eax
jnz .done
.serr: pop esi
add esi,4
cmp dword [esi],0
jne .serv
.err: xor eax,eax
.done: pop esi
.quit: push eax
stdcall [closesocket],ebx
stdcall freeBuffer,[.buffer]
pop eax edi esi ebx
return
;##########################################################################
proc Lookup,pszValue,lpLookupTable
enter
push ebx esi edi
mov esi,[lpLookupTable]
.next: lodsd
test eax,eax
mov ebx,eax
jz .quit
stdcall strcmpi,esi,[pszValue]
test eax,eax
jz .fnd
dec esi
xor eax,eax
@@: lodsb
test eax,eax
jnz @B
jmp .next
.fnd: mov eax,ebx
.quit: pop edi esi ebx
return
;##########################################################################
proc cacheMX,pszAddress,dwAddress
enter
push ebx esi edi
cmp [dwAddress],0
je .err
stdcall Lookup,[pszAddress],OFFSET cache
test eax,eax
jnz .quit
stdcall strlen,[pszAddress]
test eax,eax
lea ecx,[eax+1]
jle .err
mov edi,[cachesz]
add eax,5
add eax,edi
cmp eax,20h
jge .del
add edi,OFFSET cache
.store: mov eax,[dwAddress]
stosd
add [cachesz],ecx
add [cachesz],4
mov esi,[pszAddress]
rep movsb
jmp .quit
.del: add ecx,4
mov esi,OFFSET cache
.next: lodsd
xor eax,eax
@@: lodsb
test eax,eax
jnz @B
mov edx,esi
sub edx,OFFSET cache
cmp edx,ecx
jl .next
push ecx
mov edi,OFFSET cache
lea esi,[edi+edx]
mov eax,[cachesz]
sub [cachesz],edx
sub edx,eax
neg edx
mov ecx,edx
shr ecx,2
rep movsd
mov ecx,edx
and ecx,03h
rep movsb
pop ecx
sub ecx,4
jmp .store
.err: xor eax,eax
.quit: pop edi esi ebx
return
;##########################################################################
proc allocBuffer,dwLength
enter
push edi
mov eax,[dwLength]
add eax,0Ch
stdcall [GlobalAlloc],GMEM_MOVEABLE,eax
test eax,eax
jz .quit
push eax
stdcall [GlobalLock],eax
test eax,eax
mov edi,eax
jnz @F
stdcall [GlobalUnlock],[esp]
call [GlobalFree]
jmp .quit
@@: mov ecx,[dwLength]
pop dword [edi+00h] ; hMemory
xor eax,eax
mov [edi+04h],ecx ; maximum length
add edi,08h
add ecx,04h ; +length
shr ecx,2
push edi
rep stosd
mov ecx,[dwLength]
add ecx,04h
and ecx,03h
rep stosb
pop eax
add eax,04h
.quit: pop edi
return
;##########################################################################
proc freeBuffer,lpBuffer
enter
mov eax,[lpBuffer]
test eax,eax
jz .quit
sub eax,0Ch
pushd [eax]
stdcall [GlobalUnlock],[eax]
call [GlobalFree]
.quit: return
;##########################################################################
proc addBuffer,lpBuffer,lpData,dwLength
enter
push esi edi
mov edi,[lpBuffer]
sub edi,0Ch
xor ecx,ecx
mov eax,[edi+08h] ; length
add eax,[dwLength]
cmp eax,[edi+04h] ; maximum length
jg .quit
mov [edi+08h],eax ; length
mov ecx,[dwLength]
mov esi,[lpData]
lea edi,[edi+eax+0Ch]
sub edi,ecx
shr ecx,2
rep movsd
mov ecx,[dwLength]
and ecx,03h
rep movsb
mov ecx,[dwLength]
.quit: mov eax,ecx
pop edi esi
return
;##########################################################################
proc clearBuffer,lpBuffer
enter
push edi ebx
mov edi,[lpBuffer]
test edi,edi
jz .quit
sub edi,0Ch
mov ebx,[edi+04h] ; maximum length
add edi,08h
add ebx,04h
mov ecx,ebx
shr ecx,2
rep stosd
mov ecx,ebx
and ecx,03h
rep stosb
.quit: pop ebx edi
return
;##########################################################################
proc getBufferLength,lpBuffer
enter
mov eax,[lpBuffer]
test eax,eax
jz .quit
mov eax,[eax-04h]
.quit: return
;##########################################################################
proc setBufferLength,lpBuffer,dwLength
enter
mov ecx,[lpBuffer]
test ecx,ecx
mov eax,[dwLength]
jz .quit
mov [ecx-04h],eax
.quit: return
;##########################################################################
proc copydomain,buffer
enter
push ecx
.next: movzx eax,byte [esi]
test eax,00C0h
jz .reg
; compressed
lodsw
rol ax,8
push esi
and eax,3FFFh
mov esi,[buffer]
add esi,eax
stdcall copydomain,[buffer]
pop esi eax
jmp .return
.reg: inc esi
mov ecx,eax
rep movsb
mov byte [edi],"."
inc edi
test eax,eax
jz .quit
dec dword [esp]
jnz .next
xor eax,eax
.quit: sub edi,2
stosb
pop eax
.return:return
;##########################################################################
proc BlockHook
enter
call [GetTickCount]
sub eax,[dwTime]
cmp eax,2500
jl .quit
call [WSACancelBlockingCall]
.quit: return
;##########################################################################
sendwrap:
stdcall hexdump,OFFSET szTitleSend,[esp+0Ch],[esp+0Ch]
push eax ecx edx
call [GetTickCount]
mov [dwTime],eax
pop edx ecx eax
jmp [ws32send]
;##########################################################################
recvwrap:
push eax ecx edx
call [GetTickCount]
mov [dwTime],eax
pop edx ecx eax
stdcall [ws32recv],[esp+10h],[esp+10h],[esp+10h],[esp+10h]
push eax
stdcall hexdump,OFFSET szTitleRecv,[esp+10h],eax
pop eax
retn 10h
;##########################################################################
proc hexdump,pszTitle,lpData,dwLength
.hFile dd ?
.chars rb 20h
enter
push ebx esi edi
stdcall [CreateFile],OFFSET szTrafficFile,GENERIC_WRITE,0,0,OPEN_ALWAYS,0,0
mov [.hFile],eax
cmp eax,INVALID_HANDLE_VALUE
je .quit
stdcall [SetFilePointer],eax,0,0,FILE_END
stdcall strlen,[pszTitle]
stdcall [WriteFile],[.hFile],[pszTitle],eax,esp,0
lea edi,[.chars]
ccall [wsprintf],edi,OFFSET szDecimalFormat,[dwLength]
add edi,eax
mov eax," byt"
stosd
mov eax,"es"
stosw
lea eax,[.chars]
sub edi,eax
stdcall [WriteFile],[.hFile],eax,edi,esp,0
call .nl
mov esi,[lpData]
mov ecx,[dwLength]
xor ebx,ebx
test ecx,ecx
jle .quit
.next: push ecx
lea edi,[.chars]
lodsb
mov ah,al
shr al,4
and ah,0Fh
cmp al,10
sbb al,69h
das
stosb
mov al,ah
cmp al,10
sbb al,69h
das
stosb
mov al," "
stosb
sub edi,3
stdcall [WriteFile],[.hFile],edi,3,esp,0
inc ebx
cmp ebx,10h
jl .skip
call .ascii
call .nl
.skip: pop ecx
loop .next
call .ascii
push OFFSET .quit
and [pszTitle],0
.nl: lea edi,[.chars]
mov word [edi],0A0Dh
stdcall [WriteFile],[.hFile],edi,2,esp,0
stdcall strlen,[pszTitle]
test eax,eax
mov ebx,eax
jz .nopad
mov byte [edi]," "
@@: stdcall [WriteFile],[.hFile],edi,1,esp,0
dec ebx
jg @B
.nopad: retn
.ascii: mov ecx,10h
sub ecx,ebx
inc ecx
test ecx,ecx
jle .anopad
lea ecx,[ecx*3]
lea edi,[.chars]
mov byte [edi]," "
@@: push ecx
stdcall [WriteFile],[.hFile],edi,1,esp,0
pop ecx
dec ecx
jg @B
.anopad:sub esi,ebx
.achar: lodsb
cmp al,20h
jae @F
mov al,"."
@@: mov [edi],al
stdcall [WriteFile],[.hFile],edi,1,esp,0
dec ebx
jg .achar
retn
.quit: stdcall [CloseHandle],[.hFile]
pop edi esi ebx
return
;##########################################################################
proc strlen,pszInput
enter
xor eax,eax
mov edx,[pszInput]
test edx,edx
jz .quit
dec eax
dec edx
@@: inc edx
inc eax
cmp byte [edx],0
jne @B
.quit: return
;##########################################################################
proc strcmpi,pszPrimary,pszSecondary
enter
push esi edi
xor eax,eax
mov esi,[pszPrimary]
mov edi,[pszSecondary]
.next: mov al,byte [esi]
mov ah,byte [edi]
cmp al,0
jne @F
sub al,ah
jmp .quit
@@: cmp ah,0
jne @F
sub al,ah
jmp .quit
@@: cmp al,"Z"
ja @F
cmp al,"A"
jb @F
add al,32
@@: cmp ah,"Z"
ja @F
cmp ah,"A"
jb @F
add ah,32
@@: inc esi
inc edi
sub al,ah
je .next
.quit: cbw
cwde
pop edi esi
return
;##########################################################################
;##########################################################################
;##########################################################################
section ".data" import data readable writeable
library kernel32,"kernel32.dll",user32,"user32.dll",wsock32,"wsock32.dll"
include "%include%/apia/kernel32.inc"
include "%include%/apia/user32.inc"
include "%include%/apia/wsock32.inc"
;##########################################################################
szTrafficFile db "traffic.txt",0
szTitleSend db "send: ",0
szTitleRecv db "recv: ",0
szTitleDump db "dump: ",0
szHost db "yahoo.com",0
szBlank db 0
szDecimalFormat db "%u",0
dwRootServers dd 040029C6h,6B000980h,0C0421C0h,5A0A0880h,0AE6CBC0h,0F10505C0h,042470C0h,35023F80h,119424C0h,1E803AC0h,810E00C1h,0C4020C6h,211B0CCAh,0
;##########################################################################
align 4
dwTime rd 01h
ws32send rd 01h
ws32recv rd 01h
cachesz rd 01h
cache rb 1000h
wsd WSADATA
;##########################################################################
;##########################################################################
Posted on 2004-01-05 07:16:29 by comrade
Wow thats a lotta code to send a lousy udp request :tongue:
Nice :alright:
Posted on 2004-01-05 07:33:22 by Homer
Thanx for that code, comrade :alright: . And EvlkHome, which funcs in the Icmp dll should I use to do a MX lookup?:confused:

Thomas Antony
Posted on 2004-01-05 07:40:53 by thomasantony
Hi comrade,
Can you convert that code into MASM syntax and post it as a zip file?:) :confused:

Thomas Antony
Posted on 2004-01-05 07:59:00 by thomasantony
OK, if nobody can translate that code:mad: :( , can you tell me what format it as?MASM, TASM, GoASM, or NASM

Thomas Antony
Posted on 2004-01-06 02:48:53 by thomasantony
Hi Thomas,

Looks like FASM to me :)
Posted on 2004-01-06 04:13:01 by donkey
Hi donkey,
I didn't get the macros.inc file when I downloaded fasm .Where can I get it?

Thomas Antony:confused: :notsure:
Posted on 2004-01-06 05:00:25 by thomasantony
Yes it is fasm. Probably marco.inc is a personalised marco include file by comrade.. Therefore I think the best is to ask him...
Posted on 2004-01-06 07:35:28 by roticv
Can someone please please translate the above file into MASM or TASM format. And comrade, can you upload that macros.inc file?

Thomas Antony
Posted on 2004-01-09 00:52:12 by thomasantony
All right! If no one wants to reply, don't:mad: . At least can you tell me what this stands for?

dwRootServers dd 040029C6h,6B000980h,0C0421C0h,5A0A0880h,0AE6CBC0h,
0F10505C0h,042470C0h,35023F80h,119424C0h,1E803AC0h
,810E00C1h,0C4020C6h,211B0CCAh,0

Does it indicate the addresses of name servers?:confused: :stupid:

Thomas Antony
Posted on 2004-01-10 07:47:15 by thomasantony
You do not macros.inc. Yes, those are addresses of Internet root servers.
Posted on 2004-01-10 16:03:41 by comrade
IcmpCreateFile, IcmpSendEcho, IcmpCloseHandle :)
All the information is in the link I provided.
Jeez :grin:
Posted on 2004-01-10 17:04:30 by Homer
Hi,
Comrade, what do you mean I don not need macros.ionc.How can I compile the above code without it. :confused: .ANd EvilHome, where is the link 'provided' .:confused: :stupid: :notsure: .

Thomas Antony
Posted on 2004-01-10 23:39:41 by thomasantony
Hi Thomas,

EvilHomer2K's link was in his post :

http://tangentsoft.net/wskfaq/examples/dllping.html

I could not see any macros called in the source Comrade provided but I may have missed one, download fasm and try to compile it. If you are missing a specific macro I am sure Comrade will provide it.
Posted on 2004-01-10 23:51:44 by donkey
I am talking abt this line comrade's code

include "%include%/macro/macros.inc"

He uses some macro called showfmt. Thats why I said I wanted that include file.

:confused: :stupid: :notsure:

Thomas Antony
Posted on 2004-01-11 00:33:55 by thomasantony
You can replace it with a call to wsprintf and MessageBox, that is basically what the macro does.
Posted on 2004-01-11 00:53:14 by comrade
Hi,
I understood the code a little. What structs in which order should we send after we are connected to the name server on port 53:confused: :stupid: :notsure: ?

Thomas Antony
Posted on 2004-01-11 03:23:59 by thomasantony