#include #include #include #include #include #ifndef __APPLE__ #include #include #endif #define _FILE_OFFSET_BITS 64 /* for pre libcurl 7.19.0 curl_off_t magic */ #include #include "sha1.h" #define CUR_PROTOVER 1110 char notesbuf[256]; char str[1024]; char username[64]; char password[64]; char credentials[64]; char url[256]; char url_extparams[256]; char url_postparams[256]; char hashfn[42]; unsigned char hash[20]; char dlstreamfn[256]; char headersfn[256]; char tadhaxfn[256]; FILE *hdrfile; unsigned char *footerbuf; unsigned int footerpos = 0; size_t writeheaders(const void *ptr, size_t size, size_t nmemb, void* usrptr) { return fwrite(ptr, size, nmemb, hdrfile); } size_t readupload(const void *ptr, size_t size, size_t nmemb, void* usrptr) { int sz = size*nmemb; if(0x40f4 >= (footerpos + sz))sz = 0x40f4 - footerpos; memcpy((void*)ptr, &footerbuf[footerpos], sz); footerpos+=sz; return sz; } /********* Sample code generated by the curl command line tool ********** * Lines with [REMARK] below might need to be modified to make this code * usable. Add error code checking where appropriate. * Compile this with a suitable header include path. Then link with * libcurl. * If you use any *_LARGE options, make sure your compiler figure * out the correct size for the curl_off_t variable. * Read the details for all curl_easy_setopt() options online on: * http://curlm.haxx.se/libcurl/c/curl_easy_setopt.html ************************************************************************/ int libcurl_request(char *url, FILE *outfile, int upload, char *updfn, char *postparams) { CURLcode ret; CURL *hnd = curl_easy_init(); //struct curl_slist *headers=NULL; //if(upload)headers = curl_slist_append(headers, "Content-Type: Application/octect"); //struct curl_forms forms[3]; struct curl_httppost *post = NULL, *last = NULL; /* curl_easy_setopt(hnd, CURLOPT_WRITEDATA, 0xbf834b6c); [REMARK] */ /* curl_easy_setopt(hnd, CURLOPT_WRITEFUNCTION, 0x804e200); [REMARK] */ /* curl_easy_setopt(hnd, CURLOPT_READDATA, 0xbf834bac); [REMARK] */ /* curl_easy_setopt(hnd, CURLOPT_READFUNCTION, 0x804e190); [REMARK] */ /* curl_easy_setopt(hnd, CURLOPT_SEEKDATA, 0xbf834bac); [REMARK] */ /* curl_easy_setopt(hnd, CURLOPT_SEEKFUNCTION, 0x804e150); [REMARK] */ curl_easy_setopt(hnd, CURLOPT_INFILESIZE_LARGE, (curl_off_t)-1); curl_easy_setopt(hnd, CURLOPT_URL, url); curl_easy_setopt(hnd, CURLOPT_PROXY, NULL); curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 1); curl_easy_setopt(hnd, CURLOPT_HEADER, 0); curl_easy_setopt(hnd, CURLOPT_FAILONERROR, 0); curl_easy_setopt(hnd, CURLOPT_UPLOAD, 0); /* curl_easy_setopt(hnd, CURLOPT_DIRLISTONLY, 0);*/ /* curl_easy_setopt(hnd, CURLOPT_APPEND, 0); */ curl_easy_setopt(hnd, CURLOPT_NETRC, 0); curl_easy_setopt(hnd, CURLOPT_FOLLOWLOCATION, 0); curl_easy_setopt(hnd, CURLOPT_UNRESTRICTED_AUTH, 0); curl_easy_setopt(hnd, CURLOPT_TRANSFERTEXT, 0); if(credentials[0])curl_easy_setopt(hnd, CURLOPT_USERPWD, credentials); if(credentials[0]==0)curl_easy_setopt(hnd, CURLOPT_USERPWD, NULL); curl_easy_setopt(hnd, CURLOPT_FILE, outfile); if(upload) { curl_formadd(&post, &last, CURLFORM_COPYNAME, "footer", CURLFORM_FILENAME, "enc.footer", CURLFORM_FILE, updfn, CURLFORM_CONTENTTYPE, "application/octet-stream", CURLFORM_END); curl_easy_setopt(hnd, CURLOPT_HTTPPOST, post); } else if(postparams) { curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, postparams); } curl_easy_setopt(hnd, CURLOPT_HEADERFUNCTION, writeheaders); curl_easy_setopt(hnd, CURLOPT_PROXYUSERPWD, NULL); //curl_easy_setopt(hnd, CURLOPT_NOPROXY, NULL); curl_easy_setopt(hnd, CURLOPT_RANGE, NULL); /* curl_easy_setopt(hnd, CURLOPT_ERRORBUFFER, 0xbf834cdc); [REMARK] */ curl_easy_setopt(hnd, CURLOPT_TIMEOUT, 0); curl_easy_setopt(hnd, CURLOPT_REFERER, NULL); curl_easy_setopt(hnd, CURLOPT_AUTOREFERER, 0); curl_easy_setopt(hnd, CURLOPT_USERAGENT, "curl/7.19.7 (i486-pc-linux-gnu) libcurl/7.19.7 OpenSSL/0.9.8k zlib/1.2.3.3 libidn/1.15 injectrawsav/1.1"); curl_easy_setopt(hnd, CURLOPT_FTPPORT, NULL); curl_easy_setopt(hnd, CURLOPT_LOW_SPEED_LIMIT, 0); curl_easy_setopt(hnd, CURLOPT_LOW_SPEED_TIME, 0); /* curl_easy_setopt(hnd, CURLOPT_MAX_SEND_SPEED_LARGE, (curl_off_t)0);*/ /* curl_easy_setopt(hnd, CURLOPT_MAX_RECV_SPEED_LARGE, (curl_off_t)0);*/ curl_easy_setopt(hnd, CURLOPT_RESUME_FROM_LARGE, (curl_off_t)0); curl_easy_setopt(hnd, CURLOPT_COOKIE, NULL); curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, NULL); curl_easy_setopt(hnd, CURLOPT_SSLCERT, NULL); curl_easy_setopt(hnd, CURLOPT_SSLCERTTYPE, NULL); curl_easy_setopt(hnd, CURLOPT_SSLKEY, NULL); curl_easy_setopt(hnd, CURLOPT_SSLKEYTYPE, NULL); /* curl_easy_setopt(hnd, CURLOPT_KEYPASSWD, NULL);*/ curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50); curl_easy_setopt(hnd, CURLOPT_CRLF, 0); curl_easy_setopt(hnd, CURLOPT_QUOTE, NULL); curl_easy_setopt(hnd, CURLOPT_POSTQUOTE, NULL); curl_easy_setopt(hnd, CURLOPT_PREQUOTE, NULL); /* curl_easy_setopt(hnd, CURLOPT_WRITEHEADER, 0xbf834b50); [REMARK] */ curl_easy_setopt(hnd, CURLOPT_COOKIEFILE, NULL); curl_easy_setopt(hnd, CURLOPT_COOKIESESSION, 0); curl_easy_setopt(hnd, CURLOPT_SSLVERSION, 0); curl_easy_setopt(hnd, CURLOPT_TIMECONDITION, 0); curl_easy_setopt(hnd, CURLOPT_TIMEVALUE, 0); curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, NULL); /* curl_easy_setopt(hnd, CURLOPT_STDERR, 0x479580); [REMARK] */ curl_easy_setopt(hnd, CURLOPT_HTTPPROXYTUNNEL, 0); curl_easy_setopt(hnd, CURLOPT_INTERFACE, NULL); /* curl_easy_setopt(hnd, CURLOPT_KRBLEVEL, NULL);*/ curl_easy_setopt(hnd, CURLOPT_TELNETOPTIONS, NULL); curl_easy_setopt(hnd, CURLOPT_RANDOM_FILE, NULL); curl_easy_setopt(hnd, CURLOPT_EGDSOCKET, NULL); curl_easy_setopt(hnd, CURLOPT_CONNECTTIMEOUT, 0); curl_easy_setopt(hnd, CURLOPT_HTTPAUTH, 2); curl_easy_setopt(hnd, CURLOPT_ENCODING, NULL); curl_easy_setopt(hnd, CURLOPT_FTP_CREATE_MISSING_DIRS, 0); curl_easy_setopt(hnd, CURLOPT_IPRESOLVE, 0); curl_easy_setopt(hnd, CURLOPT_FTP_ACCOUNT, NULL); /* curl_easy_setopt(hnd, CURLOPT_IGNORE_CONTENT_LENGTH, 0);*/ /* curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 0);*/ /* curl_easy_setopt(hnd, CURLOPT_FTP_FILEMETHOD, 0);*/ /* curl_easy_setopt(hnd, CURLOPT_FTP_ALTERNATIVE_TO_USER, NULL);*/ /* curl_easy_setopt(hnd, CURLOPT_SSL_SESSIONID_CACHE, 1);*/ /* curl_easy_setopt(hnd, CURLOPT_SOCKOPTFUNCTION, 0x804da00); [REMARK] */ /* curl_easy_setopt(hnd, CURLOPT_SOCKOPTDATA, 0xbf834924); [REMARK] */ //curl_easy_setopt(hnd, CURLOPT_POSTREDIR, 0); ret = curl_easy_perform(hnd); curl_easy_cleanup(hnd); //if(upload)curl_slist_free_all(headers); /* free the header list */ return (int)ret; } /**** End of sample code ****/ void stop_mainret() { #ifdef WIN32 system("PAUSE"); #endif } int main(int argc, char **argv) { struct stat tadstat, dlstream_stat; FILE *ftad, *fdlstream; unsigned char *tadbuf, *dlstream; int argi, i, len, retval, contentsize; unsigned int *parts; int num_parts; int curpos = 0, printoff = 0, strpos; int releasenotes_sz = 0, printsz; char *hdrptr; unsigned int protover = 0; int redirect = 0; char *urlend; unsigned int readbytes=0; printf("injectrawsav v1.1\n"); if(argc<2) { printf("Usage:\n"); printf("injectrawsav \n"); printf("If the second output hax param filename isn't specified, an output filename is generated automatically from the input filename, the output is similar to input filename with \"hax\" inserted before \".bin\" in the filename.\n"); printf("For valid titleids, see the README.\n"); printf("Options:\n"); printf("--username= Use webauth and use for webauth username.\n"); printf("--updurl= Use for the upload url instead of the default bootmii.org url.\n"); printf("--extparams= Send the additional server params in the request.\n"); stop_mainret(); return 0; } memset(username, 0, 64); memset(password, 0, 64); memset(credentials, 0, 64); memset(url, 0, 256); memset(url_extparams, 0, 256); memset(tadhaxfn, 0, 256); if(argc>2 && argv[2][0]!='-') { strncpy(tadhaxfn, argv[2], 255); } else { len = strlen(argv[1]); for(strpos=0; argv[1][strpos]!='.' && strpos255)len=255; strncpy(tadhaxfn, argv[1], len); strncat(tadhaxfn, "hax.bin", 255); } for(argi=2; argi CUR_PROTOVER)printf("The client software was updated and this update is required, now aborting.\n"); if(protover < CUR_PROTOVER)printf("This old protocol version is not supported, aborting.\n"); free(dlstream); free(tadbuf); unlink(dlstreamfn); stop_mainret(); return 5; } } free(dlstream); if(!redirect) { if(stat(dlstreamfn, &dlstream_stat)<0) { printf("Failed to stat %s\n", dlstreamfn); free(tadbuf); stop_mainret(); return 2; } fdlstream = fopen(dlstreamfn, "rb"); if(fdlstream==NULL) { printf("Failed to open %s\n", dlstreamfn); free(tadbuf); stop_mainret(); return 2; } dlstream = (unsigned char*)malloc(dlstream_stat.st_size+1); if(dlstream==NULL) { printf("Memory alloc fail.\n"); fclose(fdlstream); free(tadbuf); unlink(dlstreamfn); stop_mainret(); return 3; } memset(dlstream, 0, dlstream_stat.st_size+1); if((readbytes = fread(dlstream, 1, dlstream_stat.st_size, fdlstream))!=dlstream_stat.st_size) { printf("dlstream is %x bytes but only %x bytes was read, aborting.\n", (unsigned int)dlstream_stat.st_size, readbytes); free(dlstream); fclose(fdlstream); free(tadbuf); stop_mainret(); return 2; } fclose(fdlstream); contentsize = dlstream_stat.st_size; if(contentsize<0x1000)//response should only be <4KB when there's an error or infomsg. { printoff = 0; if(strncmp((char*)dlstream, "ERROR", 5)==0) { printoff+=5; printf("Error, server reply:"); } else if(strncmp((char*)dlstream, "INFOMSG", 7)==0) { printoff+=7; printf("Server message:"); } else { printf("Request failed, server reply:"); } printf("\n%s\n", (char*)&dlstream[printoff]); if(strncmp((char*)dlstream, "INFOMSG", 7)!=0) { free(dlstream); free(tadbuf); stop_mainret(); return 5; } unlink(dlstreamfn); } free(dlstream); if(contentsize>=0x1000)break; } memset(str, 0, 1024); if(!redirect)printf("Sending request...\n"); redirect = 0; unlink(dlstreamfn); fdlstream = fopen(dlstreamfn, "wb"); hdrfile = fopen(headersfn, "wb"); retval = libcurl_request(url, fdlstream, 0, NULL, url_postparams); fclose(fdlstream); fclose(hdrfile); stat(dlstreamfn, &dlstream_stat); if(dlstream_stat.st_size==0)unlink(dlstreamfn); stat(headersfn, &dlstream_stat); if(dlstream_stat.st_size==0)unlink(headersfn); if(retval!=0) { printf("libcurl request failed: %d\n", retval); free(tadbuf); stop_mainret(); return 1; } } fdlstream = fopen(dlstreamfn, "rb"); if(fdlstream==NULL) { printf("Failed to open %s\n", dlstreamfn); free(tadbuf); stop_mainret(); return 2; } dlstream = (unsigned char*)malloc(dlstream_stat.st_size+1); if(dlstream==NULL) { printf("Memory alloc fail.\n"); fclose(fdlstream); free(tadbuf); stop_mainret(); return 3; } memset(dlstream, 0, dlstream_stat.st_size+1); if((readbytes = fread(dlstream, 1, dlstream_stat.st_size, fdlstream))!=dlstream_stat.st_size) { printf("dlstream is %x bytes but only %x bytes was read, aborting.\n", (unsigned int)dlstream_stat.st_size, readbytes); free(dlstream); fclose(fdlstream); free(tadbuf); stop_mainret(); return 2; } fclose(fdlstream); unlink(dlstreamfn); printf("Reading metadata...\n"); memcpy(&releasenotes_sz, &dlstream[curpos], 4); curpos+=4; memcpy(&num_parts, &dlstream[curpos], 4); curpos+=4; #ifndef __APPLE__ releasenotes_sz = le32toh(releasenotes_sz); num_parts = le32toh(num_parts); #endif if((num_parts*2*4)+8 >= dlstream_stat.st_size) { printf("Dlstream is invalid.\n"); free(dlstream); free(tadbuf); stop_mainret(); return 5; } parts = (unsigned int*)malloc(num_parts*2*4); memset(parts, 0, num_parts*2*4); printf("Total patch bins: %x\n", num_parts); for(i=0; i255)printsz = 255; for(printoff=0; printoff tadstat.st_size) { printf("Dlstream is invalid.\n"); free(parts); free(dlstream); free(tadbuf); stop_mainret(); return 5; } memcpy(&tadbuf[parts[(i*2)+0]], &dlstream[curpos], parts[(i*2)+1]); curpos+= parts[(i*2)+1]; } free(parts); free(dlstream); ftad = fopen(tadhaxfn, "wb"); if(ftad==NULL) { printf("Failed to open %s\n", tadhaxfn); free(tadbuf); return 2; } fwrite(tadbuf, 1, tadstat.st_size, ftad); fclose(ftad); free(tadbuf); printf("Done.\n"); stop_mainret(); return 0; }