Am trying to connect to an site using the InternetConnect Function. But everytime I do so the InternetConnect Function is returning NULL. I 've previously called the InternetOpen Function and used the returned HANDLE to call the InternetConnect Function.

.386
.model flat, stdcall
option casemap:none

include \MASM32\include\windows.inc
include \MASM32\include\user32.inc
:::::::
:::::::

.data
lpszAgent db "     ",0
Interhwnd dd ?
dwContext dw ?
lpszServerName db "10.10.10.1",0
InterConnhwnd dd ?

.code
start:

;invoke the internetopen function
invoke InternetOpen, ADDR lpszAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, INTERNET_FLAG_ASYNC
mov Interhwnd, eax

;invoke the internetconnect function
invoke InternetConnect, Interhwnd, ADDR lpszServerName, INTERNET_DEFAULT_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, INTERNET_FLAG_ASYNC, ADDR dwContext
mov InterConnhwnd, eax

invoke ExitProcess, NULL
end start


Am unsure as to where am missing out. Any help is much appreciated. Thanks
Posted on 2009-04-22 04:51:38 by karthikeyanck
No worries on that, I got it worked.....

Now am stuck with other problems here, how to read the data that has been returned by the HTTP server after a HttpSendRequest? I could see the data is retured to the client when I capture on the packets using sniffer, but how do I get it through my code? 

Also how would I get the total number of Bytes transferred (that obviously should match the size of the file)

:sad:

Thanks for your help in advance,

C K
Posted on 2009-04-22 08:51:41 by karthikeyanck
Next we have api such as HttpQueryInfo, InternetGetLastResponseInfo, InternetOpenURL and InternetReadFile.

Unless you want to restrict yourself to the FTP, GOPHER and HTTP protocols, I would suggest not using such highlevel internet api.... depends what you want to do.
Posted on 2009-04-23 01:10:08 by Homer
Thanks Homer, Just got that worked  :D
Posted on 2009-04-24 02:23:35 by karthikeyanck
Am trying to download a file from the internet, lets say from the site http://10.10.10.10/123.txt - I need to find the size of the file that am downloading, can somebody pls post a snippet. Will HttpQueryInfo with HTTP_QUERY_CONTENT_LENGTH attribute be helpful in this instance?

I tried HttpQueryInfo but I get different values in the buffer, should I have to parse the buffer, If so how should I?

invoke HttpQueryInfo,hRequest,HTTP_QUERY_CONTENT_LENGTH, ADDR lpBufferQuery, SIZEOF lpBufferQuery, lpdwIndex
.if eax == TRUE
invoke MessageBox,NULL, ADDR lpBufferQuery, ADDR MsgBoxCaption, MB_OK
.endif



Thanks,

C K
Posted on 2009-04-27 09:51:52 by karthikeyanck
Can somebody please help me out on this  :sad:

Thanks in advance,

C K
Posted on 2009-04-30 07:12:11 by karthikeyanck
The problem is the parameter for the buffersize - its meant to be a Pointer to a variable that CONTAINS the buffersize, and after the call it will contain the size of the returned data that is in the buffer.
Since you're asking for the content length, I expect that the returned size will be 4 bytes (a dword).

Posted on 2009-04-30 07:41:57 by Homer
Homer, thanks again for the reply. Here's my complete code. Please advise,



.386
.model flat, stdcall
option casemap:none

include C:\MASM32\include\windows.inc
include C:\MASM32\include\user32.inc
include C:\MASM32\include\kernel32.inc
include C:\MASM32\include\wininet.inc

includelib C:\MASM32\lib\user32.lib
includelib C:\MASM32\lib\kernel32.lib
includelib C:\MASM32\lib\wininet.lib

.data
lpszAgent db "     ",0
Interhwnd dd ?
dwContext dd ?
hRequest dd ?
lpszUrl db "10.10.10.2",0
lpszServerName db "bt",0
InterConnhwnd dd ?
lpszObjectName db "/beef/css/mew11.exe",0
lpszVerb db "GET",0
lpBuffer db 41400H DUP(?)
lpdwNumberOfBytesRead dd 41400H
lpdwNumberOfBytesAvailable dd ?
hResult dd 0
lpFileName db "\\.\C:\mw112.exe",0
hfile dd ?
nBytesWritten dd ?
lpBufferQuery db 200 DUP(?)
lpdwIndex dw 0
contentLength dw ?
baseAddr dd ?

MsgBoxCaption db "InternetOpen Function",0
MsgBoxText db "InternetOpen Function Failed",0
MsgBoxText1 db "InternetOpen Function Succeeded",0
MsgBoxText2 db "InternetConnection Function Failed",0
MsgBoxText3 db "InternetConnection Function Succeeded",0
MsgBoxText4 db "Handle closed successfully",0
MsgBoxText5 db "Error in closing the handle",0
MsgBoxText6 db "Valid HTTP request handle",0
MsgBoxText7 db "Invalid HTTP request handle",0
MsgBoxText8 db "Valid HTTPSend Request",0
MsgBoxText9 db "Invalid HTTPSend Request",0
MsgBoxText10 db "Internet Query Succeeded",0
MsgBoxText11 db "Internet Query Failed",0

.code
start:

invoke InternetOpen, ADDR lpszAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0
mov Interhwnd, eax
.if Interhwnd == NULL
invoke MessageBox, NULL, ADDR MsgBoxText, ADDR MsgBoxCaption, MB_OK
.else
invoke MessageBox, NULL, ADDR MsgBoxText1, ADDR MsgBoxCaption, MB_OK
invoke ExitProcess,NULL
.endif

invoke InternetConnect, Interhwnd, ADDR lpszServerName , INTERNET_DEFAULT_HTTP_PORT, NULL, NULL,
INTERNET_SERVICE_HTTP, 0, 0
mov InterConnhwnd, eax
.if InterConnhwnd == NULL
invoke MessageBox, NULL, ADDR MsgBoxText2, ADDR MsgBoxCaption, MB_OK
.else
invoke MessageBox, NULL, ADDR MsgBoxText3, ADDR MsgBoxCaption, MB_OK
invoke ExitProcess,NULL
.endif

invoke HttpOpenRequest, InterConnhwnd, ADDR lpszVerb, ADDR lpszObjectName, NULL, NULL, 0, INTERNET_FLAG_RELOAD, 0
mov hRequest, eax
.if hRequest == NULL
invoke MessageBox, NULL, ADDR MsgBoxText7, ADDR MsgBoxCaption, MB_OK
.else
invoke MessageBox, NULL, ADDR MsgBoxText6, ADDR MsgBoxCaption, MB_OK
invoke ExitProcess,NULL
.endif

invoke HttpSendRequest, hRequest, NULL, NULL, NULL, 0
.if eax == TRUE
invoke MessageBox, NULL, ADDR MsgBoxText8, ADDR MsgBoxCaption, MB_OK
.else
invoke MessageBox, NULL, ADDR MsgBoxText9, ADDR MsgBoxCaption, MB_OK
invoke ExitProcess,NULL
.endif

invoke HttpQueryInfo,hRequest,HTTP_QUERY_CONTENT_LENGTH, ADDR lpBufferQuery, SIZEOF lpBufferQuery, lpdwIndex
.if eax == TRUE
invoke MessageBox,NULL, ADDR MsgBoxText11, ADDR MsgBoxCaption, MB_OK
.else
invoke MessageBox, NULL, ADDR MsgBoxText12, ADDR MsgBoxCaption, MB_OK
invoke ExitProcess,NULL
.endif

invoke VirtualAlloc,NULL,lpBufferQuery,MEM_COMMIT, PAGE_READWRITE ;I think the error is here when am passing the size to allocate the memory
.if != NULL
mov baseAddr, eax
.else
invoke ExitProcess, NULL
.endif

invoke InternetReadFile, hRequest, baseAddr, lpBufferQuery, OFFSET hResult
.if eax == TRUE
invoke MessageBox, NULL, baseAddr, ADDR MsgBoxCaption, MB_OK
.else
invoke ExitProcess,NULL
.endif

invoke CreateFile, ADDR lpFileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,FILE_ATTRIBUTE_SYSTEM,NULL
mov hfile, eax
invoke WriteFile, hfile, baseAddr, lpdwNumberOfBytesRead, ADDR nBytesWritten, NULL
invoke CloseHandle, hfile

invoke VirtualFree, baseAddr, NULL,MEM_RELEASE
invoke InternetCloseHandle,hRequest
invoke InternetCloseHandle,InterConnhwnd
invoke InternetCloseHandle, Interhwnd

invoke ExitProcess, NULL
end start



Thanks,

C K
Posted on 2009-04-30 08:31:04 by karthikeyanck
When I had the size of the download data input'd manually it works perfectly, but still struggling to get the data dynamically without any manual inputs
Posted on 2009-04-30 09:10:37 by karthikeyanck

Hi. Look at this. The HttpQueryInfo function expects the bufferlength to be supplied indirectly rather than as an immediate value (like you did), we should pass the address of a variable...

.data?
dwSize dword ?
.code

mov dwSize,sizeof lpBufferQuery
invoke HttpQueryInfo,hRequest,HTTP_QUERY_CONTENT_LENGTH, ADDR lpBufferQuery, ADDR dwSize, lpdwIndex


Now this call has returned, our dwSize variable will contain the size in bytes of the Response to our Query, which is now in the Buffer ... I think it will be "4".


Posted on 2009-04-30 11:00:40 by Homer
Ok fine with that, when we pass the parameter lpBufferQuery to other functions will the function take the whole value or only the byte value?

invoke VirtualAlloc,NULL,lpBufferQuery,MEM_COMMIT, PAGE_READWRITE ;I think the error is here when am passing the size to allocate the memory
.if != NULL
mov baseAddr, eax
.else
invoke ExitProcess, NULL
.endif
Posted on 2009-04-30 11:08:22 by karthikeyanck
You should allocate enough memory to hold an arbitrary http header, say 4kb, just so we can support all kinds of queries.
When the query call returns, the buffer you supplied (lpBufferQuery) should now contain a dword representing the content length (which is what you queried for). We can access that value like this:

mov eax,lpBufferQuery
mov eax,dword ptr
;eax now holds Content Length

Now we know how large the full size of the file will be, we can allocate more memory for the whole file, or we can recycle our existing buffer to read the file 'one bufferworth of data at a time'.

Posted on 2009-04-30 18:35:37 by Homer
I couldn't understand how do I pass the content of the memory to the VirtualAlloc function to allocate memory. HttpQueryInfo writes the content_length in to the memory as


mov eax,400
mov lpBufferSize, eax

invoke VirtualAlloc, NULL, lpBufferSize, MEM_COMMIT, PAGE_READWRITE
mov lpBufferQuery, eax

invoke HttpQueryInfo, hRequest, HTTP_QUERY_CONTENT_LENGTH, lpBufferQuery, ADDR lpBufferSize, NULL


Now that I have the size in the memory pointed by lpBufferQuery how do I get the memory content of lpBufferQuery? Will the below work?


invoke VirtualAlloc, NULL, lpBufferQuery, MEM_COMMIT, PAGE_READWRITE


I understand the above code is wrong, but how do I have the memory content passed as parameter? Please can someone help me out?

Thanks,

C K
Posted on 2009-05-04 09:27:03 by karthikeyanck
Please forgive any assumptions made in this reply as its been some time since I used these api functions.

The VirtualAlloc function allocates a buffer of given size, and returns a pointer to the buffer in the EAX register.

invoke VirtualAlloc, NULL, lpBufferSize, MEM_COMMIT, PAGE_READWRITE
mov lpBufferQuery, eax

Here you have allocated some memory, and stored the returned bufferpointer into 'lpBufferQuery' ...

invoke HttpQueryInfo, hRequest, HTTP_QUERY_CONTENT_LENGTH, lpBufferQuery, ADDR lpBufferSize, NULL

You made your request for content length, now we want to access the data in the buffer...
Lets get that bufferpointer we stored earlier... we'll load it back into EAX once more.

mov eax,lpBufferQuery

Now eax is pointing to the buffer, we can access the data in the buffer via EAX register.
I THINK that the buffer will contain a DWORD which represents the content length integer.
We can check that guess out, because lpBufferSize will now contain the value "4" (bytes worth of data in our buffer).
Assuming this is true, we want to access a DWORD...
mov eax,dword ptr

Remember that EAX currently contains a pointer to our buffer.
The opcode I just issued means "move (into eax register) the first dword value stored at the address pointed to (by eax register)"

Read that a few times if it did not make sense.

EAX now contains the first dword from inside the buffer, which we think is our content length.
Posted on 2009-05-05 01:45:14 by Homer
Ok, I understand that now...  Remember that the return value is in the terms of bytes, so that if the data am downloading is about 4GB, the return value is 4294967296, that lpQueryBuffer would have...

Now the part here is I should have this whole value passed to VirtualAlloc function so that they could allocate memory for the data....

Sorry am still learning assembly :oops:
Posted on 2009-05-05 05:44:10 by karthikeyanck
Well, in your existing code you allocated a buffer of 400 bytes for the query.
I suggest you make the buffer 4096 bytes.
When you have completed the query, copy the content length out of the buffer, and RECYCLE the buffer.
Download the file data in 4kb chunks.

Note that InternetReadFile allows you to read the file in 'chunks' this way.
Posted on 2009-05-05 08:54:52 by Homer
Not sure how useful this is but... if I'm not mistaken, the HTTP content length is an optional field.
The server does not always know what the size of the page is at the start of a request (or it may not bother to tell).
At least, that's what I recall from writing my own server-side CGIs and such. When I generated HTML on-the-fly, I didn't know the size of the page either. You could tell that browsers handled it in a different way. If they got the length, they'd start downloading and rendering the page immediately. If they didn't get a length, they'd wait until the connection was closed.
Posted on 2009-05-05 09:40:48 by Scali

When you have completed the query, copy the content length out of the buffer,


How would I do that, that was the question, I will have to get the complete value represented in bytes from the buffer. As stated earlier for a file that is of size 4GB the value would be 4294967296, which I think cannot be moved into a register (if so partial value can be moved like mov eax, DWORD PTR lpBufferQuery)........ There lies the real challenge, I also believe that memory to memory move can't be achieved....  Correct me if am wrong...

If possible can you help me out with a code snippet?

Thanks,

C K
Posted on 2009-05-05 09:51:55 by karthikeyanck

Not sure how useful this is but... if I'm not mistaken, the HTTP content length is an optional field.


You are right saying that Content length is an optional field, but the server which am accessing has this field set for the data which am downloading  8)

Thanks,

C K
Posted on 2009-05-05 09:55:54 by karthikeyanck
Actually the largest value you can encode with a dword is 4294967295 - just one short of your mark.
That's why I GUESSED that the content length will be returned in the buffer as a dword.
If I'm wrong and larger files are supported, the dBufferSize value will contain a larger value, say '8' instead of  the '4' I suggested earlier, that would indicate that the buffer contains a QWORD integer, which is eight bytes (2 dwords) in length.
If thats the case, you could do this:

mov eax,lpBufferQuery
mov edx,dword ptr   ;edx = second dword in buffer
mov eax,dword ptr   ;eax = first dword in buffer

Now eax contains the 'lower' half of the content length, and edx contains the 'upper' half.
This is the commonly accepted "edx::eax" form for 64-bit integers.



Posted on 2009-05-05 12:01:44 by Homer