Results 1 to 11 of 11

Thread: downloading binary files over HTTP

  1. #1

    Thread Starter
    Member
    Join Date
    Apr 2008
    Posts
    42

    downloading binary files over HTTP

    I wrote a c++ function to send a GET request with winsock, but when i send it to a .exe or any other binary file, it comes out all messed up. I'm storing the result of the request, the file data in a string, then writing it to a file with fstream. Is there some other way you have to do it ?

  2. #2
    Raging swede Atheist's Avatar
    Join Date
    Aug 2005
    Location
    Sweden
    Posts
    8,018

    Re: downloading binary files over HTTP

    Could you show the code you're using to write the response to a file?
    Rate posts that helped you. I do not reply to PM's with coding questions.
    How to Get Your Questions Answered
    Current project: tunaOS
    Me on.. BitBucket, Google Code, Github (pretty empty)

  3. #3

    Thread Starter
    Member
    Join Date
    Apr 2008
    Posts
    42

    Re: downloading binary files over HTTP

    Code:
    #include <iostream>
    #include <fstream>
    #include <winsock.h>
    #include <string>
    #pragma comment(lib, "wsock32.lib")
    #pragma warning (disable:4786)
    using namespace std;
    
    hostent* hostinfo;
    SOCKET SSocky;
    sockaddr_in sockAddr;
    
    string fGetReq(string sType,string sUrl);
    string fPostReq(string sUrl,string sPostData);
    int fCountString(string sString,string sFind);
    
    int main(int argc,char* argv[])
    {
    	WSADATA wsaData;
    	if(WSAStartup(MAKEWORD(1,1), &wsaData)!=0){
    		if(WSAStartup(MAKEWORD(2,2), &wsaData)!=0){
    			WSACleanup();
    			exit(0);
    		}
    	}
    	string sUrl,sOutFile,sContent;
    
    	sUrl = "http://www.willem.org/ZIP/29C0x0.zip"; //Some random ZIP found with google..
    	sOutFile = "29c0x0.zip";
    	sContent = fGetReq("GET",sUrl);
    	if(sContent.length()){
    		ofstream mofiz;
    		mofiz.open(sOutFile.c_str(),ios::binary);
    		mofiz.write(sContent.c_str(),sContent.length());
    		//cout << sContent << endl;
    		mofiz.close();
    		mofiz.clear();
    	}
    	else{
    		cout << "[+] No data was downloaded!" << endl;
    	}
    	return 0;
    }
    
    
    
    string fGetReq(string sType,string sUrl)
    {
    	if(sUrl.substr(0,7) == "http://" && (fCountString(sUrl,"/")>2)){
    		string sHost,sPage,sRequest,sContent;
    		char cContent[256];
    		sUrl.replace(0,7,"");
    		sHost = sUrl.substr(0,sUrl.find("/"));
    		sPage = sUrl.substr(sUrl.find("/"));
    		sRequest = sType + " " + sPage + " HTTP/1.1\r\n";
    		sRequest += "Host: " + sHost + "\r\n";
    		sRequest += "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.14) Gecko/20080404 Firefox/2.0.0.14\r\n";
    		sRequest += "Accept: *\r\n";
    		sRequest += "Connection: Close\r\n\r\n";
    
    		SSocky = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    		hostinfo = gethostbyname(sHost.c_str());
    		sockAddr.sin_family = AF_INET;
    		sockAddr.sin_port = htons(80);
    		sockAddr.sin_addr.S_un.S_addr = inet_addr(inet_ntoa(*((struct in_addr *)hostinfo->h_addr)));
    		if (connect(SSocky, (sockaddr*)(&sockAddr), sizeof(sockAddr))==INVALID_SOCKET){
    			closesocket(SSocky);
    			WSACleanup();
    			return NULL;
    		}
    		else{
    			send(SSocky,sRequest.c_str(),sRequest.length(),0);
    			while(int iBytes = recv(SSocky,cContent,sizeof(cContent),0)){
    				cContent[sizeof(cContent)] = '\0';
    				sContent += cContent;
    				memset(cContent,'\0',sizeof(cContent));
    			}
    			return sContent;
    		}
    	}
    	return NULL;
    }
    
    
    int fCountString(string sString,string sFind){
    	unsigned int iCount,iFound=0;
    	for(iCount=sString.find(sFind, 0);iCount!=string::npos;iCount=sString.find(sFind, iCount)){
    		iFound++;
    		iCount++;
    	}
    	return iFound;
    };
    Heres a random file i found to DL:
    http://www.willem.org/ZIP/29C0x0.zip

    Download that with my code above ^^ then compare it do that.

    It looks like binary data.. but just kinda wrong.

    Oh, and the headers get written as well, im going to write a function to parse it and return either headers/content, once i get this figured out.
    Last edited by hellowonn; May 26th, 2008 at 06:32 AM.

  4. #4
    Raging swede Atheist's Avatar
    Join Date
    Aug 2005
    Location
    Sweden
    Posts
    8,018

    Re: downloading binary files over HTTP

    It looks like you are writing the entire response to the file, including the response headers?
    Also, why are you setting this inside the receive loop:
    C++ Code:
    1. cContent[sizeof(cContent)] = '\0';
    Rate posts that helped you. I do not reply to PM's with coding questions.
    How to Get Your Questions Answered
    Current project: tunaOS
    Me on.. BitBucket, Google Code, Github (pretty empty)

  5. #5

    Thread Starter
    Member
    Join Date
    Apr 2008
    Posts
    42

    Re: downloading binary files over HTTP

    Quote Originally Posted by Atheist
    It looks like you are writing the entire response to the file, including the response headers?
    Also, why are you setting this inside the receive loop:
    C++ Code:
    1. cContent[sizeof(cContent)] = '\0';
    yeah i know im writing the headers as well, I open it with ultraedit and take it out.

    I dont even know why i have that line in there.

  6. #6
    Raging swede Atheist's Avatar
    Join Date
    Aug 2005
    Location
    Sweden
    Posts
    8,018

    Re: downloading binary files over HTTP

    I'd say that you remove that line inside the loop, and only return whatever comes after the headers (the 2 line breaks), and I think it'll work better.
    Rate posts that helped you. I do not reply to PM's with coding questions.
    How to Get Your Questions Answered
    Current project: tunaOS
    Me on.. BitBucket, Google Code, Github (pretty empty)

  7. #7

    Thread Starter
    Member
    Join Date
    Apr 2008
    Posts
    42

    Re: downloading binary files over HTTP

    removing that isnt going to help , its like the encoding is different or something.

  8. #8
    Raging swede Atheist's Avatar
    Join Date
    Aug 2005
    Location
    Sweden
    Posts
    8,018

    Re: downloading binary files over HTTP

    But wouldnt it be overwriting whatever was read from the response with a 0 on each 256th byte?
    Rate posts that helped you. I do not reply to PM's with coding questions.
    How to Get Your Questions Answered
    Current project: tunaOS
    Me on.. BitBucket, Google Code, Github (pretty empty)

  9. #9

    Thread Starter
    Member
    Join Date
    Apr 2008
    Posts
    42

    Re: downloading binary files over HTTP

    Sorreh, I didn't mean that, I meant removing the headers, I removed that line. But yeah, can you just try it out for yourself and you might be able to see what I mean by it not being correct?

  10. #10
    Raging swede Atheist's Avatar
    Join Date
    Aug 2005
    Location
    Sweden
    Posts
    8,018

    Re: downloading binary files over HTTP

    Ah, I think i know whats going on, you're appending the entire char array to sContents in each iteration, even if it doesnt necessarily gets entirely filled (in the last iteration),

    Here's my working modification of your code. Note that this is a pretty unefficent way of parsing out the body of the response, you could just read each header line one by one until you find the Content-Length header, get the length of the body, and then read that many bytes after the \r\n\r\n sequence.

    Code:
    #include <iostream>
    #include <fstream>
    #include <winsock.h>
    #include <string>
    #pragma comment(lib, "wsock32.lib")
    #pragma warning (disable:4786)
    using namespace std;
    
    hostent* hostinfo;
    SOCKET SSocky;
    sockaddr_in sockAddr;
    
    string fGetReq(string sType,string sUrl);
    string fPostReq(string sUrl,string sPostData);
    int fCountString(string sString,string sFind);
    string getBody(string response);
    
    int main(int argc,char* argv[])
    {
    	WSADATA wsaData;
    	if(WSAStartup(MAKEWORD(1,1), &wsaData)!=0){
    		if(WSAStartup(MAKEWORD(2,2), &wsaData)!=0){
    			WSACleanup();
    			exit(0);
    		}
    	}
    	string sUrl,sOutFile,sContent, sBody;
    
    	sUrl = "http://www.vbforums.com/images/logo.gif"; //Some random ZIP found with google..
    	sOutFile = "vbf.gif";
    	sContent = fGetReq("GET",sUrl);
    	if(sContent.length()){
    		ofstream mofiz;
    		sBody = getBody(sContent);
    		mofiz.open(sOutFile.c_str(),ios::binary);
    		mofiz.write(sBody.c_str(),sBody.length());
    		//cout << sContent << endl;
    		mofiz.close();
    		mofiz.clear();
    	}
    	else{
    		cout << "[+] No data was downloaded!" << endl;
    	}
    	return 0;
    }
    
    
    
    string fGetReq(string sType,string sUrl)
    {
    	if(sUrl.substr(0,7) == "http://" && (fCountString(sUrl,"/")>2)){
    		string sHost,sPage,sRequest,sContent;
    		char cContent[8192];
    		sUrl.replace(0,7,"");
    		sHost = sUrl.substr(0,sUrl.find("/"));
    		sPage = sUrl.substr(sUrl.find("/"));
    		sRequest = sType + " " + sPage + " HTTP/1.1\r\n";
    		sRequest += "Host: " + sHost + "\r\n";
    		sRequest += "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.14) Gecko/20080404 Firefox/2.0.0.14\r\n";
    		sRequest += "Accept: *\r\n";
    		sRequest += "Connection: Close\r\n\r\n";
    
    		SSocky = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    		hostinfo = gethostbyname(sHost.c_str());
    		sockAddr.sin_family = AF_INET;
    		sockAddr.sin_port = htons(80);
    		sockAddr.sin_addr.S_un.S_addr = inet_addr(inet_ntoa(*((struct in_addr *)hostinfo->h_addr)));
    		if (connect(SSocky, (sockaddr*)(&sockAddr), sizeof(sockAddr))==INVALID_SOCKET){
    			closesocket(SSocky);
    			WSACleanup();
    			return NULL;
    		}
    		else{
    			send(SSocky,sRequest.c_str(),sRequest.length(),0);
    			while(int iBytes = recv(SSocky,cContent,sizeof(cContent),0)){
    				sContent.append(cContent, iBytes);
    			}
    			return sContent;
    		}
    	}
    	return NULL;
    }
    
    string getBody(string response){
    	int bodyIndex;
    	bodyIndex = response.find("\r\n\r\n") + 4;
    	return response.substr(bodyIndex);
    }
    
    
    int fCountString(string sString,string sFind){
    	unsigned int iCount,iFound=0;
    	for(iCount=sString.find(sFind, 0);iCount!=string::npos;iCount=sString.find(sFind, iCount)){
    		iFound++;
    		iCount++;
    	}
    	return iFound;
    }
    Rate posts that helped you. I do not reply to PM's with coding questions.
    How to Get Your Questions Answered
    Current project: tunaOS
    Me on.. BitBucket, Google Code, Github (pretty empty)

  11. #11

    Thread Starter
    Member
    Join Date
    Apr 2008
    Posts
    42

    Re: downloading binary files over HTTP

    Thanks, works fine now. Heres what i use to get either content/headers.

    Code:
    string fReadContent(string sHeaders,string sFind)
    {
    	int iF;
    	if(sFind == "headers"){
    		iF = sHeaders.find("\r\n\r\n");
    		return sHeaders.substr(0,iF+4);
    	}
    	if(sFind == "content"){
    		iF = sHeaders.find("\r\n\r\n");
    		return sHeaders.substr(iF+4,sHeaders.length());		
    	}
    	else{
    		return 0;
    	}
    }

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width