/* * $Id: //devel/tools/main/backstealth/mydll.cpp#1 $ * * written by : Stephen J. Friedl * Software Consultant * Tustin, California USA * steve@unixwiz.net * 2002/04/02 * * This is my implementation of the "backdll.dll" as found IN THE * Backstealth sample distribution. We have reversed engineered this * via the IDA Pro disassembler, and it does the same thing as the * DLL provided by the user, though via slightly modified logic * (we just couldn't resist doing tune-ups of the code). * * The entry point is "themain", and the program makes a connection * to a remote web server and fetches a small text file and stores * it on the hard drive. */ #include "bscommon.h" #include #include "bsdefs.h" #include "injdata.h" // prototypes static void __stdcall retrieve_file( int debuglevel, FILE *ofp, SOCKET sock, const char *h, const char *u ); extern "C" __declspec(dllexport) int __stdcall themain(struct injection_data *idata) { /*---------------------------------------------------------------- * CREATE OUTPUT FILE * * This will receive the data we fetch from the other end. */ FILE *ofp = 0; ofp = _tfopen(idata->savefile, _T("wt")); if ( ofp == 0 ) { /* ERROR */ odprintf(_T("ERROR: cannot create %s [err=%d]"), idata->savefile, errno); return -1; } /*---------------------------------------------------------------- * INIT WINSOCK * * We ask for the bare-bones version 1.1 - plenty good for us. * If we can't do it, we bail entirely. */ WSADATA wdata; int err; if (idata->debuglevel) odprintf(_T("calling WSAStartup")); if ( (err = WSAStartup( MAKEWORD(1,1), &wdata)) != 0 ) { /* ERROR */ odprintf(_T("ERROR: WSAStartup fails with err=%d"), err); return -1; } if (idata->debuglevel) odprintfA("creating TCP socket" ); SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if ( sock == INVALID_SOCKET ) { odprintf(_T("ERROR: can't make socket")); return -1; } retrieve_file( idata->debuglevel, ofp, sock, idata->remote_host, idata->remote_url ); if ( idata->debuglevel ) odprintfA( "closing socket" ); (void) closesocket(sock); if ( idata->debuglevel ) odprintfA( "closing file" ); (void) fclose(ofp); if ( idata->debuglevel ) odprintfA( "calling WSACleanup()" ); (void) WSACleanup(); if ( idata->debuglevel ) odprintfA("MYDLL done!"); return 0; } /* * retrieve_file() * * Given a TCP socket to talk on, fetch the given URL from the remote * host and store it in the FILE pointer referenced. We don't close * either the FILE or the socket here: only on the caller manages * that job. */ static void __stdcall retrieve_file( int debuglevel, FILE *ofp, SOCKET sock, const char *host, const char *url ) { // remote socket (IP + port) to connect to struct sockaddr_in addr; ZeroMemory(&addr, sizeof addr); addr.sin_family = AF_INET; /*---------------------------------------------------------------- * FIND REMOTE IP ADDRESS * * If the hostname we're given is an IP address, do a *reverse* * lookup on it to get the name back (providing the "hostent" * struct). If we need to a *forward* lookup, do that also. * * It's not clear why we bother lookup up the hostname... */ if (debuglevel) odprintf(_T("considering host {%s}"), host); unsigned long ipaddr = inet_addr(host); if ( ipaddr != INADDR_NONE ) { addr.sin_addr.s_addr = ipaddr; // memcpy(&addr.sin_addr, ipaddr, sizeof addr.sin_addr); } else { if (debuglevel) odprintf(_T("calling gethostbyname(%s)"), host); struct hostent *hostp = gethostbyname(host); if ( hostp == 0 ) { odprintf(_T("ERROR: can't lookup host {%s}"), host); return; } memcpy(&addr.sin_addr, hostp->h_addr, sizeof addr.sin_addr); } odprintfA("Connecting to %s", host ); /*---------------------------------------------------------------- * FIND DESTINATION PORT NUMBER * * We're talking to a web server, so look up "http" in the services * database, or use a hardcoded "80" if we can't find it. * * ==NOTE: it seems silly to use the service database stuff when * we are sure we're talking to a web server. */ #if 0 struct servent *servp; if ( (servp = getservbyname(_T("http"), _T("tcp"))) != 0 ) { addr.sin_port = servp->s_port; } else #endif { addr.sin_port = htons(80); } /*---------------------------------------------------------------- * CONNECT! * * Try to connect to the other end, and if we can't do it, close * the socket and bail. */ odprintfA("trying to connect to remote"); if ( connect(sock, (struct sockaddr *)&addr, sizeof addr) != 0 ) { odprintfA("ERROR: can't connect"); return; } odprintfA("connected!"); /*---------------------------------------------------------------- * Create the GET line that will be used to fetch the URL from * the connection we just made, then send it to the other end. * It's an error if we can't send it */ char buffer[512]; int n = sprintf(buffer, "GET %s\n", url); odprintfA("sending {%s}", buffer); if ( send(sock, buffer, n, 0) != n ) { odprintfA("ERROR: can't send data"); return; } odprintfA("... sent OK"); /*---------------------------------------------------------------- * read data from the other end */ while ( ( n = recv(sock, buffer, sizeof buffer, 0) ) > 0 ) { buffer[n] = '\0'; odprintfA("read %d bytes: %s", n, buffer); fwrite(buffer, (size_t)n, 1, ofp); } fflush(ofp); }