|
-
May 26th, 2008, 05:16 AM
#1
Thread Starter
Member
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 ?
-
May 26th, 2008, 05:26 AM
#2
Re: downloading binary files over HTTP
Could you show the code you're using to write the response to a file?
-
May 26th, 2008, 06:28 AM
#3
Thread Starter
Member
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.
-
May 26th, 2008, 06:33 AM
#4
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:
cContent[sizeof(cContent)] = '\0';
-
May 26th, 2008, 06:44 AM
#5
Thread Starter
Member
Re: downloading binary files over HTTP
 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:
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.
-
May 26th, 2008, 06:47 AM
#6
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.
-
May 26th, 2008, 07:32 AM
#7
Thread Starter
Member
Re: downloading binary files over HTTP
removing that isnt going to help , its like the encoding is different or something.
-
May 26th, 2008, 07:33 AM
#8
Re: downloading binary files over HTTP
But wouldnt it be overwriting whatever was read from the response with a 0 on each 256th byte?
-
May 26th, 2008, 08:00 AM
#9
Thread Starter
Member
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?
-
May 26th, 2008, 08:30 AM
#10
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;
}
-
May 27th, 2008, 06:12 AM
#11
Thread Starter
Member
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|