I try to write a TCP SYN port scanner. What is wrong in my code? please tell me.

tcp_hdr STRUCT
tcp_sourc_port WORD ?
tcp_dest_port WORD ?
tcp_seq DWORD ?
tcp_ack DWORD ?
tcp_len BYTE ?
tcp_flag BYTE ?
tcp_win WORD ?
tcp_cksum WORD ?
tcp_urgent WORD ?
tcp_hdr ENDS


pseudo_hdr STRUCT
src_address DWORD ?
dest_address DWORD ?
placeholder BYTE ?
protocol BYTE ?
tcp_length WORD ?
tcp tcp_hdr <?>
pseudo_hdr ENDS

*************************************
mov ax, SourcePort
MOV tcp_header. tcp_sourc_port, ax
mov ax, DestPort
MOV tcp_header.tcp_dest_port, ax
MOV tcp_header.tcp_seq, 15B9184Ah
MOV tcp_header.tcp_ack, 5D720008h
MOV tcp_header.tcp_len, 50
MOV tcp_header.tcp_flag, 11h
MOV tcp_header.tcp_win, 2000h
MOV tcp_header.tcp_cksum, 0
MOV tcp_header.tcp_urgent, 0

mov eax, SrcAddr
mov pseudo_header.src_address, eax
mov eax, DestAddr
mov pseudo_header.dest_address, eax
mov pseudo_header.placeholder, 0
mov pseudo_header.protocol, IPPROTO_TCP
mov pseudo_header.tcp_length, sizeof tcp_header

invoke memcpy, ADDR pseudo_header.tcp, ADDR tcp_header, sizeof tcp_header


invoke CheckSum, ADDR pseudo_header, sizeof pseudo_header
MOV tcp_header.tcp_cksum, ax

Mov socketaddr.sin_family, AF_INET
mov ax, DestPort
Mov socketaddr.sin_port, ax
mov eax, DestAddr
Mov socketaddr.sin_addr, eax
mov socketaddr_len, SIZEOF socketaddr



invoke sendto, TCPSock, ADDR tcp_header, 20, 0, ADDR socketaddr,\ socketaddr_len
.if eax != 20
invoke dwtoa, eax, ADDR intbuff
invoke Write2ListRet, ADDR intbuff
.endif

*************************************************
CheckSum PROC buffer:DWORD, dwSize:DWORD
LOCAL cksum : DWORD

mov cksum, 0
@@:
cmp dwSize, 1
jle @F
mov eax, buffer
xor ecx, ecx
mov cx,
mov edx, cksum
add edx, ecx
mov cksum, edx
mov eax, buffer
add eax, 2
mov buffer, eax
mov ecx, dwSize
sub ecx, 2
mov dwSize, ecx
jmp @b
@@:
cmp dwSize, 0
jz @f
mov edx, buffer
xor eax, eax
mov al,
mov ecx, cksum
add ecx, eax
mov cksum, ecx
@@:
mov edx, cksum
shr edx, 10h
mov eax, cksum
and eax, 0FFFFh
add edx, eax
mov cksum, edx
mov ecx, cksum
shr ecx, 10h
mov edx, cksum
add edx, ecx
mov cksum, edx
mov eax, cksum
not eax
ret

CheckSum ENDP
Posted on 2004-10-18 13:04:54 by veria
Although I'm not too good in raw socket stuff I really like it.
What about the tcp header's checksum!?

MOV tcp_header.tcp_cksum, 0

I think it does not work because tcp packets with an invalid checksum are simply ignored by the remote system. I don't know if it helps, but this is the best raw socket tut i know: http://bsrf.org.uk/tutorials/part3.html
Dominik
Posted on 2004-10-18 13:31:19 by Dom
invoke CheckSum, ADDR pseudo_header, sizeof pseudo_header
MOV tcp_header.tcp_cksum, ax

In this two line ,checksum is calculated.

Thank you Dominik,
But I think, error is another thing. :?

May be my CheckSum function is not a true manner to calculate checksum. What about this?
Posted on 2004-10-18 14:40:16 by veria
ok will have a lokk at your code tomorrow... :)
here is the checksum func.
USHORT checksum(USHORT *buffer, int size)
{
unsigned long cksum=0;
while (size > 1)
{
cksum += *buffer++;
size -= sizeof(USHORT);
}
if (size)
{
cksum += *(UCHAR*)buffer;
}
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >>16);
return (USHORT)(~cksum);
}
Posted on 2004-10-18 15:14:28 by Dom
Your Header defs look okay. Defineatly use something like Etherreal to verify your checksums are okay. It'll also help you with any other errors in your packet. Remember to switch hi and lo bytes in ax for port numbers (intel stores in little endian, net-byte order is big-endian). You set your TCP len to 50, it should be 50h (hi nibble is length in dwords, lo nibble is always 0). Your flag is set to ACK/FIN. If your looking for a host listening for a tcp connection, you need to send a SYN which is 02h. A listening host will reply with an ACK/SYN (12h). You'll also have to advertise MSS (max segment size) with your SYN packet to get a host to reply. Check out TCP options in the RFC, it should be of some help there.

Is TCPSock a raw socket?

Please let me know how you make out. I had problems with Winsock blocking my hand carved TCP packets, had to do it with WinPacketCapture API instead. Thought maybe it was a 'security feature' in WinSock2.
Posted on 2004-10-18 19:42:28 by The Dude of Dudes
tcp_hdr STRUCT
tcp_sourc_port WORD ?
tcp_dest_port WORD ?
tcp_seq DWORD ?
tcp_ack DWORD ?
tcp_len BYTE ?
tcp_flag BYTE ?
tcp_win WORD ?
tcp_cksum WORD ?
tcp_urgent WORD ?
tcp_hdr ENDS


RecvTCPPacket STRUCT
IPH ip_hdr <?>
TCPH tcp_hdr <?>
RecvData db 65535 DUP (?)
RecvTCPPacket ENDS

SendTCPPacket STRUCT
ip_header ip_hdr <?>
tcp_header tcp_hdr <?>
SendTCPPacket ENDS

pseudo_hdr STRUCT
src_address DWORD ?
dest_address DWORD ?
placeholder BYTE ?
protocol BYTE ?
tcp_length WORD ?
tcp tcp_hdr <?>
pseudo_hdr ENDS
*****************************
invoke socket, AF_INET, SOCK_RAW, IPPROTO_RAW
mov TCPSock, eax

mov BytesRecv, 0
mov SourcePort, 999

mov SendPacket.ip_header.ip_hlv, 45h
mov SendPacket.ip_header.ip_tos, 0
mov SendPacket.ip_header.ip_len, sizeof ip_hdr
mov SendPacket.ip_header.ip_id, 1
mov SendPacket.ip_header.ip_off, 0
mov SendPacket.ip_header.ip_ttl, 255
mov SendPacket.ip_header.ip_p, 6
mov SendPacket.ip_header.ip_cksum, 0
mov eax, SrcAddr
mov SendPacket.ip_header.ip_src, eax
mov eax, DestAddr
mov SendPacket.ip_header.ip_dest, eax

mov ax, SourcePort
MOV SendPacket.tcp_header. tcp_sourc_port, ax
mov ax, DestPort
MOV SendPacket.tcp_header.tcp_dest_port, ax
MOV SendPacket.tcp_header.tcp_seq, 15B9184Ah
MOV SendPacket.tcp_header.tcp_ack, 5D720008h
MOV SendPacket.tcp_header.tcp_len, 50h
MOV SendPacket.tcp_header.tcp_flag, 2h
MOV SendPacket.tcp_header.tcp_win, 2000h
MOV SendPacket.tcp_header.tcp_cksum, 0
MOV SendPacket.tcp_header.tcp_urgent, 0

mov eax, SrcAddr
mov pseudo_header.src_address, eax
mov eax, DestAddr
mov pseudo_header.dest_address, eax
mov pseudo_header.placeholder, 0
mov pseudo_header.protocol, IPPROTO_TCP
mov pseudo_header.tcp_length, sizeof tcp_hdr

invoke memcpy, ADDR pseudo_header.tcp, ADDR SendPacket.tcp_header, sizeof tcp_hdr


invoke CheckSum, ADDR pseudo_header, sizeof pseudo_header
MOV SendPacket.tcp_header.tcp_cksum, ax
invoke CheckSum, ADDR SendPacket.ip_header, sizeof ip_hdr
mov SendPacket.ip_header.ip_cksum, ax

Mov socketaddr.sin_family, AF_INET
mov ax, DestPort
Mov socketaddr.sin_port, ax
mov eax, DestAddr
Mov socketaddr.sin_addr, eax
mov socketaddr_len, SIZEOF socketaddr

invoke sendto, TCPSock, ADDR SendPacket, sizeof SendPacket, 0, ADDR socketaddr, socketaddr_len
mov ebx, sizeof SendPacket
.if eax != ebx
invoke Write2ListRet, ADDR szError
.endif

invoke recv, TCPSock, ADDR RecvPacket, sizeof RecvPacket, 0
mov ebx, sizeof SendPacket
.if eax != ebx
invoke dwtoa, eax, ADDR intbuff
invoke Write2ListRet, ADDR intbuff
.endif
*********************************
This is my new code to do Scanning. When I test it, sendto function successfully send 40 bytes of data, but recv function receive 60 byte of data with "2 same ip_hdr" & "1 tcp_hdr (with zero fields)".
ip_hdr+ip_hdr+tcp_hdr<0>

What about setsockopt function?
invoke setsockopt, TCPSock, IPPROTO_IP, IP_HDRINCL, ADDR bOpt, sizeof bOpt

If anyone has a code that work properly, thank him if he attache it to this froum.
Posted on 2004-10-19 19:57:35 by veria
Go Here:

www.ethereal.com

and download Ethereal. It's free and will help you solve your problem. Start capturing in Ethereal then run your code. It'll show exactly what is being sent and recieved over the wire with a detailed description of each protocol field.
Posted on 2004-10-19 20:59:53 by The Dude of Dudes
Thank you Dude,
I know what's sending & receiving, but I don't know why?
Posted on 2004-10-19 21:04:57 by veria
Black Sun Research Facility - Raw Sockets Tutorial:


The setsockopt() function is very important in raw sockets, its here
that we tell the winsock that we want to use our own headers for this
packet and for it to not add its own to ours.
...
setsockopt(myraw, IPPROTO_IP, IP_HDRINCL, (char *)&bOpt, sizeof(bOpt)


might help....besides, doesn't the ip header contains the length of the whole packet?

mov SendPacket.ip_header.ip_len, sizeof ip_hdr


And try to understand the bsrf tut I quoted off (the complete tut is linked in some above post). It says that the checksum for the tcp header is calculated using a pseudo header.

Dominik
Posted on 2004-10-20 06:23:56 by Dom
Thank you, Dominic

You say right.
mov SendPacket.ip_header.ip_len, sizeof ip_hdr + sizeof tcp_hdr + sizeof data

But...
In the following function
setsockopt(myraw, IPPROTO_IP, IP_HDRINCL, (char *)&bOpt, sizeof(bOpt)
I must define IP_HDRINCL, because this constant didn't define in the masm32 inc files. but i don't know its amount.
IP_HDRINCL equ ?
You know?
Posted on 2004-10-20 16:59:58 by veria
noprob: #define IP_HDRINCL 2

By the way, did you already implement the pseudo header for calculating the checksum!?

As we all know this should be the fastest way of scanning a machine. Actually, does it work already? In order to improve needed time I would recommend to work with several threads later on....let me know if it works.

Dominik
Posted on 2004-10-20 18:35:26 by Dom
noprob: #define IP_HDRINCL 2

By the way, did you already implement the pseudo header for calculating the checksum!?



Yes I do;
and you say right, when my code do one thread scanning I try to write multithread version of it.

But for now, when I define IP_HDRINCL equ 2, and:
bOpt byte 1
TCPSock SOCKET 0
***********************************
invoke socket, AF_INET, SOCK_RAW, IPPROTO_RAW
mov TCPSock, eax

invoke setsockopt, TCPSock, IPPROTO_IP, IP_HDRINCL, ADDR bOpt, sizeof bOpt
.if eax == SOCKET_ERROR
invoke WSAGetLastError
invoke dwtoa, eax, ADDR intbuff
invoke Write2ListRet, ADDR intbuff
ret
.endif
************************************
In this way, an error(10014) recieve.

**WSAEFAULT (10014)
Bad address
The system detected an invalid pointer address in attempting to use a pointer argument of a call. This error occurs if an application passes an invalid pointer value, or if the length of the buffer is too small. For instance, if the length of an argument which is a struct sockaddr is smaller than sizeof(struct sockaddr).**

What's wrong in my code Dominik?
Posted on 2004-10-20 19:28:36 by veria
I'm sorry that I skipped the pseudo header part of your code :)

As windows likes 32-bit more than optimization I got it to work like this:



LOCAL bOpt:DWORD
mov bOpt, TRUE
invoke setsockopt, hsock, IPPROTO_IP, IP_HDRINCL, addr bOpt, 4d



Dominik
Posted on 2004-10-20 20:14:45 by Dom
Thank you Dominik, for your replys,
I do this changes, but still error(10014) is been.
Posted on 2004-10-20 20:25:35 by veria
When I change position of calling setsockopt function, the 10014 error was disapear, but came back again in this line:

invoke sendto, TCPSock, ADDR SendPacket, sizeof SendPacket, 0, ADDR socketaddr, socketaddr_len
mov ebx, sizeof SendPacket
.if eax != ebx
invoke WSAGetLastError
invoke dwtoa, eax, ADDR intbuff
invoke Write2ListRet, ADDR intbuff
.endif
Posted on 2004-10-20 21:48:53 by veria
You can use this macro in order to get the winsock error msg.



WSAShowLastError macro
.data
errc dd ?
pmsg dd ?
.code
invoke WSAGetLastError
mov errc, eax
invoke FormatMessage, FORMAT_MESSAGE_ALLOCATE_BUFFER or FORMAT_MESSAGE_FROM_SYSTEM, 0h, errc, 0h, addr pmsg, 0h, 0h
invoke MessageBox, 0h, pmsg, S('WSA Error Notification'), MB_ICONERROR
invoke LocalFree, pmsg
endm


S macro data:VARARG
LOCAL Buff
.data
Buff db data, 0h
.code
exitm <addr Buff>
endm


I think your 10014 err is the following: "The System detected an invalid pointer address in attempting to use a pointer argument in a call."
Dominik
Posted on 2004-10-21 06:28:40 by Dom
Thank you Dominik,
But I can't understand, what's wrong in my code. My mind is conflicted.
I post my last attempt to do this. If you will can do it at any time, thank you for sending me your expriments.


sockaddrlen DWORD 0
bOpt byte TRUE

SendPacket SendTCPPacket <>
socketaddr sockaddr_in <>
TCPSock SOCKET 0
szlocalhost db "127.0.0.1", 0
pPacket dd 0

*******************************************
invoke socket, AF_INET, SOCK_RAW, IPPROTO_RAW
.if eax == SOCKET_ERROR
invoke WSAGetLastError
invoke dwtoa, eax, ADDR intbuff
invoke Write2ListRet, ADDR intbuff
ret
.endif
mov TCPSock, eax
invoke setsockopt, TCPSock, IPPROTO_IP, IP_HDRINCL, ADDR bOpt, sizeof bOpt
.if eax == SOCKET_ERROR
invoke WSAGetLastError
invoke dwtoa, eax, ADDR intbuff
invoke Write2ListRet, ADDR intbuff
ret
.endif

invoke inet_addr, ADDR szlocalhost
.if eax==INADDR_NONE
invoke gethostbyname, ADDR szlocalhost
mov eax,[eax+12]
mov eax,[eax]
mov eax,[eax]
mov DestinationAddr,eax
.else
mov DestinationAddr,eax
.endif
invoke GetLocalIPAddress
mov eax, IPAddress
mov SourceAddr, eax
mov i, 1
invoke htons, i
mov port, ax
mov SourcePort, 999

invoke GlobalAlloc, 0, 40
mov pPacket, eax
invoke memset, pPacket, 0, 40
mov ebx, pPacket
mov (ip_hdr ptr [ebx]).ip_hlv, 45h
mov (ip_hdr ptr [ebx]).ip_tos, 0
mov (ip_hdr ptr [ebx]).ip_len, sizeof ip_hdr + sizeof tcp_hdr
mov (ip_hdr ptr [ebx]).ip_id, 1
mov (ip_hdr ptr [ebx]).ip_off, 0
mov (ip_hdr ptr [ebx]).ip_ttl, 128
mov (ip_hdr ptr [ebx]).ip_p, 6
mov (ip_hdr ptr [ebx]).ip_cksum, 0
mov eax, SourceAddr
mov (ip_hdr ptr [ebx]).ip_src, eax
mov eax, DestinationAddr
mov (ip_hdr ptr [ebx]).ip_dest, eax
xor eax, eax
mov al, (ip_hdr ptr [ebx]).ip_ttl
invoke dwtoa, eax, ADDR intbuff
invoke Write2ListRet, ADDR intbuff

add ebx, 20
invoke htons, SourcePort
MOV (tcp_hdr ptr [ebx]).tcp_sourc_port, ax
mov ax, port
MOV (tcp_hdr ptr [ebx]).tcp_dest_port, ax
MOV (tcp_hdr ptr [ebx]).tcp_seq, 15B9184Ah
MOV (tcp_hdr ptr [ebx]).tcp_ack, 5D720008h
MOV (tcp_hdr ptr [ebx]).tcp_len, 50h
MOV (tcp_hdr ptr [ebx]).tcp_flag, 2
invoke htons, 65535
MOV (tcp_hdr ptr [ebx]).tcp_win, ax
MOV (tcp_hdr ptr [ebx]).tcp_cksum, 0
MOV (tcp_hdr ptr [ebx]).tcp_urgent, 0

mov eax, SourceAddr
mov pseudo_header.src_address, eax
mov eax, DestinationAddr
mov pseudo_header.dest_address, eax
mov pseudo_header.placeholder, 0
mov pseudo_header.protocol, IPPROTO_TCP
invoke htons, sizeof tcp_hdr
mov pseudo_header.tcp_length, ax

invoke memcpy, ebx, ADDR pseudo_header.tcp, sizeof tcp_hdr

invoke CheckSum, ADDR pseudo_header, sizeof pseudo_header
MOV (tcp_hdr ptr [ebx]).tcp_cksum, ax
sub ebx, 20
invoke CheckSum, ebx, sizeof ip_hdr
mov (ip_hdr ptr [ebx]).ip_cksum, ax

Mov socketaddr.sin_family, AF_INET
mov ax, port
Mov socketaddr.sin_port, ax
mov eax, DestinationAddr
Mov socketaddr.sin_addr, eax
mov socketaddr_len, SIZEOF sockaddr_in


invoke sendto, TCPSock, pPacket, 40, 0, ADDR socketaddr, socketaddr_len
.if eax == SOCKET_ERROR
invoke WSAGetLastError
invoke dwtoa, eax, ADDR intbuff
invoke Write2ListRet, ADDR intbuff
.endif

invoke recv, TCPSock, ADDR RecvPacket, sizeof RecvPacket, 0
mov ebx, sizeof SendPacket
.if eax != ebx
invoke ntohs, eax
invoke dwtoa, eax, ADDR intbuff
invoke Write2ListRet, ADDR intbuff
.endif
Posted on 2004-10-21 17:13:21 by veria
Veria,


Change your flag size in setsockopt. You have bOpt defined as a byte, change it to a dword.
Posted on 2004-10-23 10:36:08 by The Dude of Dudes
Hi,
Are you using win2k? I use win98 so I had the same prob and abadoned the idea :( . IP_HDRINCL works only on Win2k and above ( I think XP too). Hope this helps!!

Thomas Antony
Posted on 2004-10-23 11:03:58 by thomasantony
The Dude of Dudes,
I use the DWORD type for it, previously, but nothing was change.

Thomas Antony,
I use WinXP.
Posted on 2004-10-23 14:22:33 by veria