Jump to content


Active Members
  • Content Count

  • Joined

  • Last visited

About AlfAlfa

  • Rank
    Hak5 Fan ++

Recent Profile Visitors

1,334 profile views
  1. You can just secure it with a WPA passphrase, rather than just having the network open. I do this with my PC, perhaps check my signature for the link to "Hosting you're own access point to share from one interface to another". Just adapt it for the pineapple, pretty similar it is. Aside from that, you just made me think of a really cool idea and I'm going to see how quickly I can create it! Another way I just thought of
  2. Just as an update, I had to get caught up in my other work, but I finally got uploadwpa2 into a state that it has been much improved and is a worthy update! Also something looks different about this module, dependency? The main difference is adding SSL support, but also switching from hard coded specialized functions which would have to be coded for each site and re-done if the site changed, to a json config file with the default config stored at ~/.uploadwpa2/sites.cfg It's a pretty simple format, and should be able to be configured for most sites except that require a logged in session or captcha. (maybe future features) So with the standard openwrt sdk now I'm fairly sure I got the packaging right this time, so check the package out or it can be just built from source again. additional dependencies: +libopenssl +libcrypto makefile has been updated. "I cant put enough emphasis on this, this is not an official package provided from the hak5 team, and there for is NOT supported by them. Until if and or when they add it into their official repos, and you download it from their official repos, this is all installed at YOUR OWN RISK. so using this provided ipk, do not go to the hak5 team for support for which are not officially provided by them. i also hold no responsibility for any damage or for your usage that may occur, i can provide the sources and installable ipk, and can give you my word that their is no malicious code added to this ipk, it is clean and has no infection. it is your choice and responsibility if you want to use them or not." You've been warned, now here is the goods :) --------------------------------------------------------------------------------------------------------------- IPK: http://www.filedropper.com/uploadwpa21ar71xx http://www.speedyshare.com/jwNNd/uploadwpa2-1-ar71xx.ipk Source: https://github.com/Alf-Alfa/uploadwpa EDIT: I've just realized I completely overlooked the javascript and php side of things, I'll have to flesh it out with support for the newer features. Like being able to give it more than 10 hashes at a time (you just configure how many hashes it accepts per post) and it sends out as many post requests as necessary to complete the job. (example of one new feature)
  3. I know sftp is kind of similar to scp but not exactly so what about scp?, did you try scp when you said 'webinterface or sftp etc'? I wonder if that will work: scp root@ ~/caps/largecap.pcap Excuse my post if you've already tried it, but you weren't clear on that. Maybe when downloading it uses up all or too much memory and that causes something vital to crash creating the issue you find... That's just a guess though because it's hard to see what's going on from your log files (as it looks almost like it was unplugged and re-plugged). Which is the first line that the transfer stops '[ 459.450000] usb 1-1.2: USB disconnect, device number 6' that one?
  4. Yes that's true, it should upgrade to HTTPS which it does for me. You're also right there isn't a 'disable HSTS setting' but a trick to get it to bypass HSTS (at least in firefox): "According to several forums, you can disable HSTS by introducing a new configuration variable. First, go to the Firefox configuration page (about:config), right-click, choose "New Integer", then provide the name "test.currentTimeOffsetSeconds" (no quotes) with a value of 11491200. This should bypass HSTS, although you may also need to clear the Cache and Active Logins in the Clear Recent History dialog (Ctrl-Shift-Del). This apparently works because of a function called GetPreloadListEntry that checks to see if the current time is less than the next list expiration time; since the time is effectively calculated to be later than the expiration time, no check is performed. This effectively disables HSTS checks." If you're on the box you can disable it is the point, but yes I agree it shouldn't be able to be disabled just through a MITM. Though setting that variable could be a neat trick to allow the old sslstrip to work again on a compromised box, until they change the code where that doesn't work anymore that is.
  5. Well then it's working then! That is a security feature called HSTS built into the browser. Once you go to the TLS/SSL version you can't go to the unsecured version anymore! That's what I think your issue is anyway, see this for a possibly working bypass: https://forums.hak5.org/index.php?/topic/37642-hsts-bypass-and-ssl-stripping/?hl=hstsOr use a custom browser, or one that lets you disable the feature.
  6. WOOT WO0T! Awesome! So you've got it going! I'll just get the standard OpenWrt SDK then, the issue lies somewhere in the sdk i've downloaded which is more specific to the mk5. At least now I can see that it works! (I've removed that wrong ipk so there'll be no confusion as you've asked) Version 2.0 is almost complete, it also links to libopenssl and libcrypto and I've gotten it to compile even with my broken sdk, (except openssl didn't have the version it was requesting anymore and had to source it from somewhere else (1.0.1e)) Perhaps the standard OpenWrt sdk will have a newer version anyway (like 1.0.2)!
  7. Thank you again, I really do appreciate you trying to help me! I think the problem is I shouldn't of used that outside of the httpclient that's the only place I used it outside of it. replace line 43 in uploadwpa.cpp: if(!file) { http->Log("ERROR Cannot open file"); return false; }With:if(!file) { std::cout << "ERROR Cannot open file"; return false; }And if you have a version of HTTPClient.hpp that doesn't have these headers add them to the top as well: #include <stdio.h> #include <cstdlib> When I was compiling I had to add those, as the reduced version of the standard library doesn't automatically include them with iostream like the normal desktop verison does...You still didn't say what you're using though for your compiling, is it that much of a secret? lol
  8. Thanks for checking it out, as for the Tetra not being a mips I guess I read that wrong he said a newer RISC architecture but that didn't mean it's not mips just a newer better mips arch... As for it failing to extract the control file, I think there's something wrong with the way it's packaging it since the file is actually in there if I do this I can extract it manually: Alf@UNKNOWN:~/Downloads/uploadwpa-ipk$ tar xzvf uploadwpa_1_ar71xx.ipk ./debian-binary ./data.tar.gz ./control.tar.gz Alf@UNKNOWN:~/Downloads/uploadwpa-ipk$ tar xzvf control.tar.gz ./ ./control Alf@UNKNOWN:~/Downloads/uploadwpa-ipk$ tar xzvf data.tar.gz ./ ./bin/ ./bin/uploadwpa Alf@UNKNOWN:~/Downloads/uploadwpa-ipk$ ls bin/ uploadwpa Alf@UNKNOWN:~/Downloads/uploadwpa-ipk$ The control file itself contains: Package: uploadwpa Version: 1 Depends: libc, libstdcpp Provides: Source: package/uploadwpa Section: utils Status: unknown ok not-installed Essential: no Priority: optional Maintainer: OpenWrt Developers Team <openwrt-devel@openwrt.org> Architecture: ar71xx Installed-Size: 8198 Description: Uploads a WPA handshake to various online crackers! And the binary itself is mips so it wont execute on my x86_64 (didn't even try, just looked at it with readelf) I think I see the problem, when I open the individual control.tar.gz and data.tar.gz with a visual extractor I see: and inside the . folder is the control file! Unless that's how it's supposed to be, then that appears to be the problem. What could be wrong with my configuration that it creates that extra "." (dot) folder and that's why it isn't finding it. Downloaded another ipk for something else extracted it and it has the same thing, so that .(dot) folder actually does appear to be normal so that's not the problem! Looking more closely at the information you gave me though I think I see the actual problem. I'm using the older MK5 toolchain aren't I, and that isn't going to work for the nano and Tetra is it!? AR71XX is not AR93XX!! Or is it? Because it says when I enter the menuconfig with "make menuconfig" and select the first option 'Target System' I get: ───────────────────────── Target System ───────────────────────────┐ │ Use the arrow keys to navigate this window or press the hotkey of │ │ the item you wish to select followed by the <SPACE BAR>. Press │ │ <?> for additional information about this option. │ │ ┌───────────────────^(-)─────────────────────────────────────────┐ │ │ │ ( ) ARM Ltd. Realview board (qemu) │ │ │ │ ( ) Atheros AR231x/AR5312 │ │ │ │ (X) Atheros AR7xxx/AR9xxx │ │ │ │ ( ) Atmel AT91 │ │ │ │ ( ) Atmel AVR32 │ │ │ │ ( ) Broadcom BCM2708/BCM2835 I do have that option selected as well. Should a ar93xx*.ipk be generated or do the packages called ar71xx*.ipk fit under the same umbrella and are combined supported for both? So I'm confused, will the MK5 toolchain work, or do I need the newer one! You said you've got the environment set up, I bet you're not using the MK5 toolchain! I'll keep it in case I want to make my work backwards compatible for it, but I really should have the newer toolchain! I don't really need the firmware unless that's required since I'm not intending on extending the firmware or making anything 'baked into' the firmware, but just a way to produce a binary with a proper magic number. When looking at a valid binary what does the magic number look like? Is it different than: Magic: 7f 45 4c 46 01 02 01 00 01 00 00 00 00 00 00 00 ? CONFIG_TARGET_ar71xx: │ │ │ │ Build firmware images for Atheros AR7xxx/AR9xxx based boards. │ │ │ │ │ │ Symbol: TARGET_ar71xx [=y] │ │ Prompt: Atheros AR7xxx/AR9xxx │ │ Defined at tmp/.config-target.in:59 │ │ Depends on: <choice> │ │ Location: │ │ -> Target System (<choice> [=y]) │ │ Selects: HAS_SUBTARGETS [=y] && mips [=y]
  9. Would the gateway be or though? You can also set the DNS server to the same as the proper gateway address and it'll grab the DNS from the router/gateway instead of entering it manually. Are you sure foxtrot? Maybe I'm confusing regular router manual configuration with configuration for pineapples. On windows 7 if I don't put the gateway for a manual config with my router it doesn't work. That has probably changed in newer versions of windows and it does a better job of figuring it out automatically? However there has been cases where I had two interfaces up and had to not set the gateway in the second interface and only in the first. Also had to change the metric of the second interface to be higher than the first interface. (since I wanted it to get the internet access from the first interface, but still have the second connected at the same time) So just to be clear if you have two interfaces connected simultaneously in windows, set the one you want it to grab internet access to with a lower metric value than the one you just want connected but not to use for internet access. (the metric value is somewhere in the advanced settings)
  10. Well I've done it, at least for the nano I believe so: Does this look good? (Yes certainly, you can take a look and see if I did it correctly and test it for me, compiling it yourself, then let me know how I can do the same for the Tetra!) Look I don't want you to have to do everything for me, see I'm putting the effort in here! I should add: Thank you ahead of time. Alf@UNKNOWN:~/pineapple-builder/MK5/package/uploadwpa/package/bin$ readelf -a -d uploadwpa ELF Header: Magic: 7f 45 4c 46 01 02 01 00 01 00 00 00 00 00 00 00 Class: ELF32 Data: 2's complement, big endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 1 Type: EXEC (Executable file) Machine: MIPS R3000 Version: 0x1 Entry point address: 0x401770 Start of program headers: 52 (bytes into file) Start of section headers: 0 (bytes into file) Flags: 0x70001005, noreorder, cpic, o32, mips32r2 Since the MK5 and nano have a similar mips architecture is that correct? The Tetra on the other hand is different... Where can I download the firmware and cross compiler toolkit for it? See now this wasn't so hard was it, my github has been updated but the ipk isn't there just the updated source with the new makefiles and instructions on what I did to compile it. I did successfully generate an ipk though and extracted it and checked the binary to confirm it is in fact compiled for mips! As DataHead posted It previously when he's done this, I have to post this here too: I cant put enough emphasis on this, this is not an official package provided from the hak5 team, and there for is NOT supported by them. Until if and or when they add them into their official repos, and you download it from their official repos, this is all installed at YOUR OWN RISK. so using this provided ipk, do not go to the hak5 team for support for which are not officially provided by them. i also hold no responsibility for any damage or for your usage that may occur, i can provide the sources and installable ipk, and can give you my word that their is no malicious code added to these ipk, they are clean and no infection. it is your choice and responsibility if you want to use them or not. You've been warned, now here is the goods :) ------------------------------------------------------------ the main github has been updated to reflect successful compilation in a openwrt environment, if you would like to compile it yourself -> https://github.com/Alf-Alfa/uploadwpa [iPK link will be placed here shortly] Once copied to to your MK5 or nano: opkg install uploadwpa-1-ar71xx.ipk Then if nano you can also copy the 'UploadWPA' to /pineapple/modules for the GUI Otherwise you must use it from the command line once you have a terminal to your pineapple! Tetra version coming soon, as soon as I get the proper environment setup to cross compile for RISC.
  11. Well that just means I still haven't made it to pineapple module status yet ;)! I really thought you were going to help get my code compiled for the pineapple archs, but I guess you aren't proficient in native code cross compiling or just didn't want to accept a payment for just compiling someone else's module so you re-built it entirely yourself so you felt more like you earned it. That's understandable, however I'm going to do it bigger and better and enough work that you won't want to rebuild it entirely again this time! :) I'll let you have the capturing handshakes module though how about that! I'm also working on a completely different idea for a module that I don't want to let on to yet. I'll have to figure out how to cross compile though myself it seems... I'm just not sure if I need to link to libstdcpp or uclibcxx and which sdk to use is it Kamikaze or White Russian? Or a more pineapple specific sdk for cross compilation? this program uses strings and iostreams which are a feature of the C++ standard template library (STL). However, because memory is so critical in an embedded application like OpenWrt, the standard template library is not available by default. What needs to be done to fix the problem depends on which version of OpenWrt you are running. If you are running Kamikaze, the problem is much easier to fix than if you are running White Russian. If you are running Kamikaze, you only need to install the libstdcpp library. If you are running White Russian, as I am, you must install the uclibcxx library, as well as make certain changes to the Makefiles to use this library, which is a special implementation of the standard library for embedded devices I'll figure it out, I'm confident of that :) EDIT: Found this great post here by Darren https://forums.hak5.org/index.php?/topic/36422-cross-compile-c-code-to-mips/?hl=%2Bcross+%2BcompileThe thread starter was wanting to cross compile for the turtle, but this should get me set up so I can cross compile for the pineapple as well and there is a pineapple specific guide (though for the MK5) All I should need to do though is use the RISC and MIPS arch of the newer pineapples and it'll help me out to get there! Thanks Darren for that post, this should keep me busy for a while. Turns out it's libstdcpp selected Y to that on the configuration and I'm now building the MK5 firmware and toolkit with it: Almost there!
  12. Never gonna give you upNever gonna let you downNever gonna run around and.... no, just no... lol
  13. Heck yea Whistle Master! Thanks for making it into an actual pineapple module! So wait a minute though does this count as my first module? and it's a shell script now? If that's the case you just used cURL or something like it to send the http posts? Maybe it doesn't count as my first module since you had to rebuild it as a shell script, however I'd still like to see how you did that with only a shell script so PM me a way how I can download it and take a look! (without a pineapple) Still either way I like that it's at least made it's way onto the module manager :) @WIFIjuice: I was feeling that you wouldn't want to just upload every single handshake you have to an online site, and people would only use it in cases where for example the company you need to get the passphrase for doesn't care how you get it, just that you get it! So you'd only upload a handshake in circumstances like that, and that's why I wanted to have it separate from capturing them. As others were saying it is relatively simple and there's plenty of software to capture a handshake. You basically just need to be listening with an interface in monitor mode to a particular access point, and as soon as any client authenticates or re-authenticates with the access point you'll get the handshake (if you are close enough, or your antenna 'gets' you close enough) You just have to be patient and wait for it, or you can de-authenticate a client to try to get it quicker. When it tells you you have the handshake that capture file you were capturing packets to is what you can use with this module!
  14. Alright that's a deal Foxtrot, after this one that is! I'll save C++ for the real l33t applications from now on and gain some more experience with python. It's easy but I'm a lot less familiar with it than C++ so that's why C++ is generally easier for me. You're right though so I'm not going to code every single thing in it from now on. [Here though there really isn't that much code in this I'll help with the review process here] Including the http client class and setting up some global variables and my pointer where I'll create my http object and a printHelp function which just prints the usage information: /* uploadwpa 1.1 ~ AlfAlfa */ #include "HTTPClient.hpp" std::unique_ptr<HTTPClient> http; std::string email, hashes, capture_file, file_name, boundary, useThisUserAgent; int success = 0, verbose = 0; Then in main I'm just grabbing the passed in arguments if they have been passed in: (email, capture file path, capture file name extracted from it, hashes extracted depending on how many there are, whether you passed in a custom user agent string, verbose mode, and checking if you want to just print the help screen) int main(int argcount, char *args[]) { for(int i = 0; i < argcount; i++) { if(strcmp(args[i],"-e") == 0 || strcmp(args[i],"--email") == 0) { if(i < (argcount - 1)) email = args[i+1]; } if(strcmp(args[i],"-c") == 0 || strcmp(args[i],"--capture-file") == 0) { if(i < (argcount - 1)) { capture_file = args[i+1]; size_t lastSlash = capture_file.rfind('/'); if(lastSlash != std::string::npos) file_name = capture_file.substr(lastSlash+1); else file_name = capture_file; } } if(strcmp(args[i],"-a") == 0 || strcmp(args[i],"--hashes") == 0) { int z = i; while(*args[++z] != '-') { hashes += args[z]; if(z == (argcount - 1) || *args[z+1] == '-') break; hashes += "\r\n"; } } if(strcmp(args[i],"-u") == 0 || strcmp(args[i],"--user-agent") == 0) { if(i < (argcount - 1)) useThisUserAgent = args[i+1]; } if(strcmp(args[i],"-v") == 0 || strcmp(args[i],"--verbose") == 0) { verbose = 1; } if(strcmp(args[i],"-h") == 0 || strcmp(args[i],"--help") == 0) { printHelp(); return 2; } } Finally the main piece of code that does the thing! If the email argument wasn't passed in it'll also just print the help. If it has been create the http client object. If it has successfully been created (should always but you never know lol) then set the user agent that member function will only actually change it if it has been passed in, otherwise it uses iceweasel kali user agent string. verbosity, then if we have hashes passed in post the hashes as urlencoded form data with provided email and / or if we have a capture file path post multipart form data containing the passed in email and binary of that capture file. Successful will have a 0 if any of the two that were tried failed and 1 if either one succeeded and 2 if both succeeded. Return 0 for success as long as one was a success or 1 for failure. if(!email.empty()) { http = HTTPClient::make(); if(http.get()) { http->setUserAgent(useThisUserAgent); http->setVerbosity(verbose); if(!hashes.empty()) success += postHashesTo_onlinehashcrack(); if(!capture_file.empty()) success += postWPAHandshakeTo_onlinehashcrack(); if(success > 0) { std::cout << "Successful! " << success << "\n"; return 0; } } return 1; } printHelp(); return 2; The postHashesTo function just creates a string with the post variables the site requires with the hashes and email urlencoded, then uses the http client object to connect to the site on port 80 and finally it does a http post for x-www-form-urlencoded data with the concatenated data string to the /hash-cracking.php page: int postHashesTo_onlinehashcrack() { std::string postData = "textareaHashes="; postData += HTTPClient::urlEncode(hashes) + "&emailHashes="; postData += HTTPClient::urlEncode(email) + "&submit=Submit"; //if(!http->Connect("",80)) return 0; if(!http->Connect("www.onlinehashcrack.com",80)) return 0; bool successful = http->Post("/hash-cracking.php", postData.c_str()); http->Close(); return successful; } postWPAHandshake function is a bit more complex, where you take a named 'boundary' and use that between the different pieces of data as boundaries which tell the server where things begin and where they end in this certain format of 'multipart formdata'. I emulated firefox/iceweasal's method of generating a random number appended to a number of dashes as best I could so it would be like firefox for the most part. Following the format of "--" (two dashes) then boundary start and proper amounts of \r\n / CR+LF's in between, then reading the capture file passed in and appending it where it should go. Connect and post that data along with the boundary we used to the proper php page that expects the data this way. Then close the connection and return whether it was successful or not! bool postWPAHandshakeTo_onlinehashcrack() { boundary = HTTPClient::getRandomBoundary(); std::string postData = "--" + boundary + "\r\nContent-Disposition: form-data; name=\"emailWpa\"\r\n\r\n" + email + "\r\n"; postData += "--" + boundary + "\r\nContent-Disposition: form-data; name=\"wpaFile\"; filename=\"" + file_name + "\""; postData += "\r\nContent-Type: application/vnd.tcpdump.pcap\r\n\r\n"; FILE *file = fopen(capture_file.c_str(), "rb"); if(!file) { http->Log("ERROR Cannot open file"); return false; } fseek(file, 0, SEEK_END); long fileLen = ftell(file); rewind(file); size_t previousLen = postData.size(); postData.resize(previousLen + fileLen); fread((void*)&postData.data()[previousLen], fileLen, 1, file); fclose(file); postData += "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"submit\"\r\n\r\nSubmit\r\n"; postData += boundary + "--\r\n\r\n"; //if(!http->Connect("",80)) return false; if(!http->Connect("www.onlinehashcrack.com",80)) return false; bool successful = http->PostMultiPart("/wifi-wpa-rsna-psk-crack.php", postData, boundary); http->Close(); return successful; } [Now the HTTPClient code] Connect function creates a unix socket tcp type and then dns queries the ip for the hostname and turns it into a server and then server address / sock address structure that we can use with the socket connect function. If all is well set the host and port of the object to match what we've established our connection with and set a default referrer which in this case happens to be the referrer that the site expects and return true. bool HTTPClient::Connect(const char *host, int port) { sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { Log("ERROR opening socket"); return false; } server = gethostbyname(host); if (server == 0) { Log("ERROR no such host"); return false; } bzero((char*)&serverAddress, sizeof(serverAddress)); bcopy((char*)server->h_addr, (char*)&serverAddress.sin_addr.s_addr, server->h_length); serverAddress.sin_family = AF_INET; serverAddress.sin_port = htons(port); if(connect(sock,(struct sockaddr*)&serverAddress, sizeof(serverAddress)) < 0) { Log("ERROR connecting"); return false; } this->host = host; this->port = port; setReferer("http://" + this->host + "/"); //default referer return true; } HTTP Get: that I didn't end up using but still wrote anyway since It's a necessity for an http client to have. bool HTTPClient::Get(const char *page) { if(!page) return false; request = "GET "; request += page; request += " HTTP/1.1\r\n"; if(!host.empty()) request += "Host: " + host + "\r\n"; request += userAgent + "\r\n"; request += "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"; request += "Accept-Language: en-US,en;q=0.5\r\n"; request += "Accept-Encoding: gzip, deflate\r\n"; if(!referer.empty()) request += "Referer: " + referer + "\r\n"; request += "Connection: keep-alive\r\n\r\n"; requestHeaders = request; Log("\n[Request: ]"); Log(request, true); return WriteRequestReadResponse(); } HTTP Post just posts the x-www-form-urlencoded as described above as used for the space separated hashes... bool HTTPClient::Post(const char *page, const char *data) { if(!page || !data) return false; request = "POST "; request += page; request += " HTTP/1.1\r\n"; if(!host.empty()) request += "Host: " + host + "\r\n"; request += userAgent + "\r\n"; request += "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"; request += "Accept-Language: en-US,en;q=0.5\r\n"; request += "Accept-Encoding: identity\r\n"; //gzip, deflate if(!referer.empty()) request += "Referer: " + referer + "\r\n"; request += "Connection: keep-alive\r\n"; request += "Content-Type: application/x-www-form-urlencoded\r\n"; request += "Content-Length: "; char dataLenStr[21]{0}; sprintf(dataLenStr, "%lu", strlen(data)); request += dataLenStr; request += "\r\n\r\n"; requestHeaders = request; request += data; request += "\r\n\r\n"; Log("\n[Request: ]"); Log(request, true); return WriteRequestReadResponse(); } Same as above except posts multipart from data with the boundary style format... bool HTTPClient::PostMultiPart(const char *page, std::string &data, std::string &boundary) { if(!page || data.empty()) return false; request = "POST "; request += page; request += " HTTP/1.1\r\n"; if(!host.empty()) request += "Host: " + host + "\r\n"; request += userAgent + "\r\n"; request += "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"; request += "Accept-Language: en-US,en;q=0.5\r\n"; request += "Accept-Encoding: identity\r\n"; if(!referer.empty()) request += "Referer: " + referer + "\r\n"; request += "Connection: keep-alive\r\n"; request += "Content-Type: multipart/form-data; boundary=" + boundary + "\r\n"; request += "Content-Length: "; char dataLenStr[21]{0}; sprintf(dataLenStr, "%lu", data.size()); request += dataLenStr; request += "\r\n\r\n"; requestHeaders = request; Log("\n[Request: ]"); Log(request.c_str(), true); request += data; request += "\r\n\r\n"; return WriteRequestReadResponse(); } WriteRequestReadResponse is just exactly as described writes all data of the request and get's back all or at least the start of the response up to a 4kb buffer. bool HTTPClient::WriteRequestReadResponse() { int wroteNum = Write((char*)request.c_str(), request.size()); if(wroteNum > 0) { int readNum = Read(4096); if(readNum > 0) { interpretResponse(); return true; } } return false; } Interpret response extracts the response headers from the response and I didn't fully implement it yet as it wasn't necessary for this application but it would be simple to finish it off and just after getting the content length keep reading from the socket until all the bytes are received and perhaps send a keep alive packet in between successive reads to ensure the connection stays alive if it's a large transfer (like downloading a large file, also I'd have to support chunked encoding as well) size_t HTTPClient::interpretResponse() { char *startOfHeader = response.get(); char *endOfHeader = strstr(startOfHeader, "\r\n\r\n"); if(endOfHeader == 0) return 0; size_t headerSize = (endOfHeader - startOfHeader) + 4; responseHeaders.resize(headerSize); bcopy(response.get(), (void*)responseHeaders.data(), headerSize); offset = headerSize; Log("\n[Response Headers: ]"); //more work needs to be done here, to make sure to get the whole response Log(responseHeaders.c_str()); //eg. get the content length and however many bytes received of it so far, then get the rest if necessary. return headerSize; } Read+Write pretty self explanatory, read upto a certain number of bytes from socket, write all bytes in write buffer to socket. int HTTPClient::Read(int maxBytes) { if(!response.get() || (bufferSize < maxBytes)) { response = std::unique_ptr<char[]>(new char[maxBytes]); bufferSize = maxBytes; } if(!response.get()) return -1; bzero(response.get(), bufferSize); Log("recieving..."); int num = recv(sock, response.get(), maxBytes, 0); if(num <= 0) { Log("ERROR reading from socket"); return 0; } responseSize = num; return num; } int HTTPClient::Write(char *writeBuffer, int writeSize) { int num, total = 0, bytesLeft = writeSize; while(total < writeSize) { num = send(sock, writeBuffer+total, bytesLeft, 0); if(num <= 0) break; total += num; bytesLeft -= num; } if(total < writeSize) { Log("ERROR writing to socket"); return 0; } return total; } Creates the randomized boundary from /dev/urandom this could have been done better, but it's good enough and the boundary could really be anything you want since the client chooses it. I just didn't want to make it static and wanted it to at least be mostly like firefox/iceweasal. std::string HTTPClient::getRandomBoundary() { std::string randomBoundary = "---------------------------"; { uint64_t random128bits[2]; FILE *randomness = fopen("/dev/urandom", "rb"); if(randomness) { fread(&random128bits[0], 16, 1, randomness); fclose(randomness); for(int i = 0; i < 2; i++) { char randomNum[30]; sprintf(randomNum,"%lu",random128bits[i]); randomBoundary += randomNum; } srand(time(0)); int losehowmanydigits = rand() % 3 + 11; randomBoundary.resize(randomBoundary.size()-losehowmanydigits); //resulting in a 23 - 29 digit number appended to 27 dashes (like how iceweasal does it) return randomBoundary; } } return ""; } url encode and url decode... url encode necessary for the hashes data post but not the multi-part form data post. Should an http client have a url decode? Perhaps only and http server object should but even though I didn't have a use for it it could be used possibly. std::string HTTPClient::urlEncode(std::string str) { std::string new_str = ""; char c; int ic; const char* chars = str.c_str(); char bufHex[10]; int len = strlen(chars); for(int i=0;i<len;i++) { c = chars[i]; ic = c; // uncomment this if you want to encode spaces with + /*if (c==' ') new_str += '+'; else */ if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') new_str += c; else { sprintf(bufHex,"%X",c); if(ic < 16) new_str += "%0"; else new_str += "%"; new_str += bufHex; } } return new_str; } std::string HTTPClient::urlDecode(std::string str) { std::string ret; char ch; int i, ii, len = str.length(); for (i=0; i < len; i++) { if(str[i] != '%') { if(str[i] == '+') ret += ' '; else ret += str[i]; } else { sscanf(str.substr(i + 1, 2).c_str(), "%x", &ii); ch = static_cast<char>(ii); ret += ch; i = i + 2; } } return ret; } Finally a templated log function for the client object that just takes any object that can be put through cout and automatically concatenates a newline unless you specify not to! template<class T> void HTTPClient::Log(T str, bool noNewline) { if(verbosity > 0) { std::cout << str; if(!noNewline) std::cout << "\n"; } } There! See nothing at all malicious or nefarious in the code it just does what it does and that's it! This should help to get it reviewed and accepted as a legitimate module although not useful to everyone for some that are willing to use online services for wpa handshakes this can be helpful indeed. Customization of sites and variables coming soon, along with SSL/TLS support so it can work with practically any site!
  15. Good to know that it is possible to get into the repo, so I'll work towards that, and in the meantime let's get it going on our own! I also just committed a newer version (I forgot to remove an extra comma in an $api.request call although that was still probably okay syntax, and I was using tabs and it was spaces originally so that screwed my formatting, that's fixed now too) Yes cross compilation is required, I've just discovered that as well when I went searching for how to create a OpenWrt standardized Makefile. Also it seems the STL will possibilty require the libstdcpp or uclibcxx according to this page I'm reading: http://gargoyle-router.com/old-openwrt-coding.html Here's what I have in terms of my make file so far: (I need HTTPClient.cpp compiled first, then uploadwpa.cpp then I can compile both object files.o into the uploadwpa binary. from how I understand it) My application is only a tiny bit more complex then the example hello world on that web page. I also need c++11 features since I use some of them, I was using -std=c++0x but it seems to be the same as passing -std=c++11 or -std=gnu++11 # build uploadwpa executable when user executes "make" uploadwpa.o: uploadwpa.cpp $(CXX) $(CXXFLAGS) -std=c++11 -c HTTPClient.cpp uploadwpa.cpp $(CXX) $(LDFLAGS) -std=c++11 HTTPClient.o uploadwpa.o -o uploadwpa # remove object files and executable when user executes "make clean" clean: rm *.o uploadwpa Lets get this working Whistle Master, I know you know how to compile this tiny c++ application. This compiles on my linux machine, but now it has to be expanded and set up to compile for the architecture of the pineapple Nano and Tetra... So the Tetra is a "A 533 MHz RISC CPU from Atheros is running the WiFi Pineapple firmware" and Nano "CPU: 400 MHz MIPS Atheros AR9331 SoC" So each will have to have it's own cross compilation makefile and will result in two binaries one of RISC architecture and other of MIPS for the respective devices... :)
  • Create New...