Monday, November 2, 2009

You will be redirected to the new blog

Please wait, you're being redirected to the new blog...

Sunday, July 19, 2009

No more updates here

Please check for continued updates to this blog. I have moved sites. Thanks.

Sunday, May 31, 2009

Sending messages to the Apache Error.log file when using Django

I spent a considerable amount of time reading documentation that told me how to send errors to the Apache log filewhen you use mod_wsgi. I read documentation on how to integrate mod_wsgi with Apache and Django. All of this was fine, but when I was trying to get it to work with my Django 1.0.2 installation and Apache2 running mod_wsgi, I was constantly greeted by lots of errors. The documents online didn't help at all.

Finally, after looking into the django.core.handlers.wsgi module, I figured out how to send errors to the wsgi.errors setting and subsequently send errors to your Apache2 Error.log file.

I started off with my as follows:

from django.http import HttpResponse
from django.shortcuts import render_to_response, get_object_or_404
from myapp.models import F

def index(request):
c = {}
return render_to_response('myapp/index.html',c)

def detail(request, name):
n = F.objects.get(name=name)
c = {'name': n.fof}
return render_to_response('myapp/detail.html',c)

If I needed to write to the Error.log file, I would have to change the code thusly:

from django.http import HttpResponse
from django.shortcuts import render_to_response, get_object_or_404
from myapp.models import F

def index(request):
c = {}
print >> request.environ['wsgi.errors'],"Teh Errorist!"
return render_to_response('myapp/index.html',c)

def detail(request, name):
n = F.objects.get(name=name)
c = {'name': n.fof}
return render_to_response('myapp/detail.html',c)

The change is in line 7

I felt really stupid, because the solution was so straightforward. I felt even more stupid that I couldn't find any documentation out there. Either way, I'm pleased that my app works, and in case someone else out there is searching for how to achieve this, then the above is how to do it.

Friday, May 8, 2009

Re-login plugin for Burp Suite

One of the first things I do when I begin a web application security assessment is figure out how the login sequence works. Then as I begin to annoy the application, I figure out what makes the application say, "Enough!" and kick me out by invalidating my session. With this, I can automate the process and save a huge amount of time logging into the application manually when my session is made invalid.

I'm a big fan of
Burp Suite. Burp Suite is a set of tools that I believe every web application pen-tester should find indispensable. Developed by Dafydd Stuttard a.k.a. Port Swigger, it is available in both Free and Professional (read paid) versions. Its a great set of tools and I use it's extensibility to achieve the automated login process. Dafydd has also co-authored the book The Web Application Hacker's Handbook. No, I don't personally know Dafydd, and no, he's not paying me to say these things (although I would never dare to send back a free copy of the Pro version he would send me ;) ), but I use the tools and I think they're quite awesome.

I recently pen-tested a banking application that was being launched by a large bank and dusted off my re-login plugin. Given that the bank used the F5 Big IP appliance with the application security module and the fact that it employed a ticketing system, I had to make extensive changes to my once humble re-login plugin. So I did. In the spirit of giving back, I thought someone else might find the plugin useful or can even build off my one (if you do, please do share the improved version) so I'll post my research and final plugin here.

Because of the pain in the ass Big IP, I had to craft my re-login plugin as follows:

  1. Record the error page of the Big IP and find a unique string to identify the page
  2. Record the POST request for the login page
  3. Write the plugin to detect if this string is in the response
  4. If it is, then make an HTTP GET request to the start page.
  5. Grab the cookies from the GET request
  6. Replace the cookies from the POST request with the ones from the GET request
  7. Make the HTTP POST request
  8. Grab the response and send it back to the browser.

Now when I send that incredibly long string in the "Amount" field or send a whole load of XSS in the "Description" field, I am no longer greeted by the Big IP error page. Instead, my plugin takes over, seamlessly logs me back in and brings me to the landing page.

Here is the source code:

import java.util.regex.Matcher;
import java.util.regex.Pattern;
import burp.IBurpExtender;
import burp.IBurpExtenderCallbacks;

public class BurpExtender implements IBurpExtender {

public burp.IBurpExtenderCallbacks callBacks;

public void applicationClosing() {

public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) {
callBacks = callbacks;

public void setCommandLineArgs(String[] cla) {

public byte[] processProxyMessage(
int messageReference,
boolean messageIsRequest,
String remoteHost,
int remotePort,
boolean serviceIsHttps,
String httpMethod,
String url,
String resourceType,
String statusCode,
String responseContentType,
byte[] message,
int[] action)

byte[] firstRequest;
byte[] nextRequest;
String initialCookies = "";

callBacks.issueAlert("Attempting to re-login...");
firstRequest = new String("[Enter GET Request Here, one string seperate with '\r\n']").getBytes();
nextRequest = new String("[Enter POST Request Here, one string seperate with '\r\n'").getBytes();
byte[] firstResp = callBacks.makeHttpRequest(remoteHost, remotePort, serviceIsHttps, firstRequest);
initialCookies = grabCookies(firstResp);
byte[] interimReq = buildRequest(initialCookies,nextRequest);
message = callBacks.makeHttpRequest(remoteHost, remotePort, serviceIsHttps, interimReq);
} catch (Exception e) {
return message;

private String grabCookies(byte[] getRequest){
String getReq = new String(getRequest);
String regEx = "Set-Cookie:\\s(.*?);";
Pattern pattern = Pattern.compile(regEx, Pattern.DOTALL | Pattern.MULTILINE);
Matcher matcher = pattern.matcher(getReq);
StringBuilder cookies = new StringBuilder();
cookies.append("Cookie: ");
cookies.append("; ");
return cookies.toString();

private byte[] buildRequest(String cookies, byte[] postRequest){
String[] carvedPost = {};
String postReq = new String(postRequest);
carvedPost = postReq.split("\r\n\r\n");
postReq = carvedPost[0]+"\r\nContent-Length: "+carvedPost[1].length()+"\r\n\r\n"+carvedPost[1];
StringBuffer finalReq = new StringBuffer();
String regEx = "Cookie:\\s(.*?)\r\n";
Pattern pattern = Pattern.compile(regEx, Pattern.DOTALL | Pattern.MULTILINE);
Matcher matcher = pattern.matcher(postReq);
return finalReq.toString().getBytes();

private boolean isBigIPError(byte[] msg){
String message = new String(msg);
boolean result =false;
String regEx = "[Enter your RegEx for the Error Page here]";
Pattern pattern = Pattern.compile(regEx,Pattern.DOTALL|Pattern.MULTILINE);
Matcher matcher = pattern.matcher(message);
callBacks.issueAlert("Received error from F5 Big-IP!");
result = true;

} catch (Exception e) {
return result;

To get this to work in Burp, I will provide you with instructions directly from PortSwigger:

Before you proceed, make sure to change the GET, POST and RegEx to match your own scenario. Just place them into the areas surrounded by square brackets. Remove the square brackets after that.


If you want to play with this example yourself, you can download the source code. The steps to compile and run the plugin are as follows:

  1. If you don't already have it, download and install the Java Development Kit (JDK) from Sun.

  2. Create a directory to work in, and cd into it from the command line.

  3. Copy the plugin source file ( into your working directory.

  4. Create a subdirectory called "burp", and copy file into this directory. You will need this file in the correct relative path, because the plugin code makes use of the IBurpExtenderCallbacks interface.

  5. In your working directory, compile the source file into a .class file using javac, the Java compiler. The exact command will depend on the location of your JDK - for example, on Windows, you might type: "\Program Files\Java\jdk1.6.0_04\bin\javac.exe"

  6. Confirm that the file BurpExtender.class has appeared in your working directory.

  7. Build a Java archive (JAR) file containing your .class file. Depending again on your JDK location, you might type:"\Program Files\Java\jdk1.6.0_04\bin\jar.exe" -cf burpextender.jar BurpExtender.class

  8. Confirm that the file burpextender.jar has appeared in your working directory.

  9. Copy your normal Burp JAR file into your working directory.

  10. Using the actual name of your Burp JAR file, start Burp using the command: java -Xmx512m -classpath burpextender.jar;burp.jar burp.StartBurp

If everything works, Burp should launch with a number of entries in the alerts tab, confirming which IBurpExtender methods were successfully loaded from your plugin (in this case, processProxyMessage and registerExtenderCallbacks):


If you need any clarifications on this or some help, just post some comments and I'll do my best to answer them.

That should be it for now. Go forth and Haxx0r!


Saturday, August 4, 2007

Dissecting the GoDaddy email notifier - Part 4

Ok, this is hopefully the last part of my Dissecting series for the email notifier. I last left you with the fact that I had reverse engineered the encryption and decryption algorithm. I simply poked around the calls to the registry key write function calls and found the encryption and decryption routines. I will list them here:

004046D7 /$ 55 PUSH EBP ; Main Encrypter
004046D8 |. 8BEC MOV EBP,ESP
004046DA |. 51 PUSH ECX
004046DB |. 51 PUSH ECX
004046DC |. 837E 14 00 CMP DWORD PTR DS:[ESI+14],0
004046E0 |. 8BC6 MOV EAX,ESI
004046E2 |. 0F84 CC000000 JE 004047B4
004046E8 |. 53 PUSH EBX
004046E9 |. 8B5E 14 MOV EBX,DWORD PTR DS:[ESI+14]
004046EC |. 895D FC MOV DWORD PTR SS:[EBP-4],EBX
004046EF |. 57 PUSH EDI
004046F0 |. 4B DEC EBX
004046F1 |. 8BFB MOV EDI,EBX
004046F3 |. E8 A0010000 CALL 00404898
004046F8 |. 0FB608 MOVZX ECX,BYTE PTR DS:[EAX]
004046FB |. 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4]
004046FE |. 6A 05 PUSH 5
00404700 |. 33D2 XOR EDX,EDX
00404702 |. 5F POP EDI
00404703 |. F7F7 DIV EDI
00404705 |. 8BFB MOV EDI,EBX
00404707 |. C1E2 08 SHL EDX,8
0040470A |. 66:0FB68411 4>MOVZX AX,BYTE PTR DS:[EAX+ECX+427F48]
00404713 |. 0FB7C0 MOVZX EAX,AX
00404716 |. 8945 FC MOV DWORD PTR SS:[EBP-4],EAX
00404719 |. 8BC6 MOV EAX,ESI
0040471B |. E8 78010000 CALL 00404898
00404720 |. 66:8B00 MOV AX,WORD PTR DS:[EAX]
00404723 |. 66:25 00FF AND AX,0FF00
00404727 |. 66:0B45 FC OR AX,WORD PTR SS:[EBP-4]
0040472B |. 0FB7C0 MOVZX EAX,AX
0040472E |. 8945 FC MOV DWORD PTR SS:[EBP-4],EAX
00404731 |. 8BC6 MOV EAX,ESI
00404733 |. E8 60010000 CALL 00404898
00404738 |. 66:8B4D FC MOV CX,WORD PTR SS:[EBP-4]
0040473C |. 66:8908 MOV WORD PTR DS:[EAX],CX
0040473F |. 8BC6 MOV EAX,ESI
00404741 |. E8 52010000 CALL 00404898
00404746 |. 0FB700 MOVZX EAX,WORD PTR DS:[EAX]
00404749 |. 6A 05 PUSH 5
0040474B |. 99 CDQ
0040474C |. 59 POP ECX
0040474D |. F7F9 IDIV ECX
0040474F |. 33FF XOR EDI,EDI
00404751 |. 85DB TEST EBX,EBX
00404753 |. 8955 FC MOV DWORD PTR SS:[EBP-4],EDX
00404756 |. 76 58 JBE SHORT 004047B0
00404758 |> 8BC6 /MOV EAX,ESI
0040475A |. E8 39010000 |CALL 00404898
0040475F |. 0FB600 |MOVZX EAX,BYTE PTR DS:[EAX]
00404762 |. 8B4D FC |MOV ECX,DWORD PTR SS:[EBP-4]
00404765 |. C1E1 08 |SHL ECX,8
00404768 |. 66:0FB68408 4>|MOVZX AX,BYTE PTR DS:[EAX+ECX427F48]
00404771 |. 0FB7C0 |MOVZX EAX,AX
00404774 |. 8945 F8 |MOV DWORD PTR SS:[EBP-8],EAX
00404777 |. 8BC6 |MOV EAX,ESI
00404779 |. E8 1A010000 |CALL 00404898
0040477E |. 66:8B00 |MOV AX,WORD PTR DS:[EAX]
00404781 |. 66:25 00FF |AND AX,0FF00
00404785 |. 66:0B45 F8 |OR AX,WORD PTR SS:[EBP-8]
00404789 |. 0FB7C0 |MOVZX EAX,AX
0040478C |. 8945 F8 |MOV DWORD PTR SS:[EBP-8],EAX
0040478F |. 8BC6 |MOV EAX,ESI
00404791 |. E8 02010000 |CALL 00404898
00404796 |. 66:8B4D F8 |MOV CX,WORD PTR SS:[EBP-8]
0040479A |. 66:8908 |MOV WORD PTR DS:[EAX],CX
0040479D |. 8B45 FC |MOV EAX,DWORD PTR SS:[EBP-4]
004047A0 |. 47 |INC EDI
004047A1 |. 6A 05 |PUSH 5
004047A3 |. 40 |INC EAX
004047A4 |. 33D2 |XOR EDX,EDX
004047A6 |. 59 |POP ECX
004047A7 |. F7F1 |DIV ECX
004047A9 |. 3BFB |CMP EDI,EBX
004047AB |. 8955 FC |MOV DWORD PTR SS:[EBP-4],EDX
004047AE |.^ 72 A8 \JB SHORT 00404758
004047B0 |> 5F POP EDI
004047B1 |. 8BC6 MOV EAX,ESI
004047B3 |. 5B POP EBX
004047B4 |> C9 LEAVE
004047B5 \. C3 RET

The code above is for the Encrypter and the code below is the Decrypter:

004047B6 /$ 55 PUSH EBP ; Main Decrypter
004047B7 |. 8BEC MOV EBP,ESP
004047B9 |. 51 PUSH ECX
004047BA |. 51 PUSH ECX
004047BB |. 53 PUSH EBX
004047BC |. 8B5E 14 MOV EBX,DWORD PTR DS:[ESI+14]
004047BF |. 85DB TEST EBX,EBX
004047C1 |. 8BC6 MOV EAX,ESI
004047C3 |. 0F84 CC000000 JE 00404895
004047C9 |. 57 PUSH EDI
004047CA |. 4B DEC EBX
004047CB |. 8BFB MOV EDI,EBX
004047CD |. E8 C6000000 CALL 00404898
004047D2 |. 0FB700 MOVZX EAX,WORD PTR DS:[EAX]
004047D5 |. 6A 05 PUSH 5
004047D7 |. 99 CDQ
004047D8 |. 59 POP ECX
004047D9 |. F7F9 IDIV ECX
004047DB |. 33FF XOR EDI,EDI
004047DD |. 85DB TEST EBX,EBX
004047DF |. 8955 FC MOV DWORD PTR SS:[EBP-4],EDX
004047E2 |. 76 58 JBE SHORT 0040483C
004047E4 |> 8BC6 /MOV EAX,ESI
004047E6 |. E8 AD000000 |CALL 00404898
004047F1 |. C1E1 08 |SHL ECX,8
004047F4 |. 66:0FB68408 4>|MOVZX AX,BYTE PTR DS:[EAX+ECX+428448]
004047FD |. 0FB7C0 |MOVZX EAX,AX
00404800 |. 8945 F8 |MOV DWORD PTR SS:[EBP-8],EAX
00404803 |. 8BC6 |MOV EAX,ESI
00404805 |. E8 8E000000 |CALL 00404898
0040480A |. 66:8B00 |MOV AX,WORD PTR DS:[EAX]
0040480D |. 66:25 00FF |AND AX,0FF00
00404811 |. 66:0B45 F8 |OR AX,WORD PTR SS:[EBP-8]
00404815 |. 0FB7C0 |MOVZX EAX,AX
00404818 |. 8945 F8 |MOV DWORD PTR SS:[EBP-8],EAX
0040481B |. 8BC6 |MOV EAX,ESI
0040481D |. E8 76000000 |CALL 00404898
00404822 |. 66:8B4D F8 |MOV CX,WORD PTR SS:[EBP-8]
00404826 |. 66:8908 |MOV WORD PTR DS:[EAX],CX
00404829 |. 8B45 FC |MOV EAX,DWORD PTR SS:[EBP-4]
0040482C |. 47 |INC EDI
0040482D |. 6A 05 |PUSH 5
0040482F |. 40 |INC EAX
00404830 |. 33D2 |XOR EDX,EDX
00404832 |. 59 |POP ECX
00404833 |. F7F1 |DIV ECX
00404835 |. 3BFB |CMP EDI,EBX
00404837 |. 8955 FC |MOV DWORD PTR SS:[EBP-4],EDX
0040483A |.^ 72 A8 \JB SHORT 004047E4
0040483C |> 8B46 14 MOV EAX,DWORD PTR DS:[ESI+14]
0040483F |. 8945 F8 MOV DWORD PTR SS:[EBP-8],EAX
00404842 |. 8BFB MOV EDI,EBX
00404844 |. 8BC6 MOV EAX,ESI
00404846 |. E8 4D000000 CALL 00404898
0040484B |. 0FB608 MOVZX ECX,BYTE PTR DS:[EAX]
0040484E |. 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8]
00404851 |. 6A 05 PUSH 5
00404853 |. 33D2 XOR EDX,EDX
00404855 |. 5F POP EDI
00404856 |. F7F7 DIV EDI
00404858 |. 8BFB MOV EDI,EBX
0040485A |. C1E2 08 SHL EDX,8
0040485D |. 66:0FB68411 4>MOVZX AX,BYTE PTR DS:[ECX+EDX+428448]
00404866 |. 0FB7C0 MOVZX EAX,AX
00404869 |. 8945 F8 MOV DWORD PTR SS:[EBP-8],EAX
0040486C |. 8BC6 MOV EAX,ESI
0040486E |. E8 25000000 CALL 00404898
00404873 |. 66:8B00 MOV AX,WORD PTR DS:[EAX]
00404876 |. 66:25 00FF AND AX,0FF00
0040487A |. 66:0B45 F8 OR AX,WORD PTR SS:[EBP-8]
0040487E |. 0FB7C0 MOVZX EAX,AX
00404881 |. 8945 F8 MOV DWORD PTR SS:[EBP-8],EAX
00404884 |. 8BC6 MOV EAX,ESI
00404886 |. E8 0D000000 CALL 00404898
0040488B |. 66:8B4D F8 MOV CX,WORD PTR SS:[EBP-8]
0040488F |. 66:8908 MOV WORD PTR DS:[EAX],CX
00404892 |. 8BC6 MOV EAX,ESI
00404894 |. 5F POP EDI
00404895 |> 5B POP EBX
00404896 |. C9 LEAVE
00404897 \. C3 RET

I will leave you with the python source code for the encryption and decryption routines so that you can look at the algorithm and get a feel for what was going on. You will need the static data which can be found in the .rdata section. This is the cipher text that is looked up during the encryption and decryption phase. I have included it in the tool as a separate file.
I may decide to start developing a Linux variant for checking my GoDaddy mail, but don’t hold your breath. Mail me any questions you may have. If you’re interested.

The tool can be found here.

Sunday, July 29, 2007

Dissecting the GoDaddy email notifier - Part 3

It’s been sometime since I made a post and that kinda sucks. I’ve been a bit swamped with work and have not had any real time to do my own stuff. Presently out in Cairo. Pyramids are phun.

You must be wondering why the hell I chose OllyDbg to make a simple hex edit in the previous post. The truth is, I was using it to try and study at exactly what point the SSL protocol is chosen and I found it at 0×414356.

By changing the CMP operation as in the picture above with 0×2E instead of 0×00, I can get the client to select plain old HTTP to speak to the main server. This is good, because I can now look at all the Web Service calls it makes and hopefully try to write a Linux version.
One other reason I chose OllyDbg is to study what the client actually does. My next quest is to study where my credentials are stored. Since this is Windows, I figure the first place to look would be the registry. By sniffing around the “string references” of the client, I did notice a specific registry key which is referenced: “HKEY_CURRENT_USER\Software\Starfield\WBEN\Settings”

Examining this registry key with regedit, I see the following:

That looks interesting. If I count the characters, it equates to the exact number for both my email address and password*. This means that their encryption algorithm generates fixed length cipher text. This most likely means that they’re using a substitution algorithm. Tsk, tsk, tsk. Substitution algorithms rely on some form of calculation (if any) and lookup in order to generate cipher text. Again, by looking at the encrypted strings, it is possible to determine the fact that a calculation involving the string length is also done. How do I deduce this? By looking at the last two characters in my email address (d1). They are both “qq” for “om” the last two letters in “.com”. This means that both “o” and “m” are equal to “q”. Not possible in direct lookups with calculation.

Another good thing is the fact that I know the credentials are stored in the registry. This shortens my hunt significantly because I only have to trace any specific registry calls to find out where the Encryption/Decryption algorithms are lurking. If I trace any references or calls to the specific registry key, then I will most likely find where the algorithms exist.

Using the “search for all string references” in Olly, I try to pull up all the calls to “HKEY_CURRENT_USER\Software\Starfield\WBEN\Settings”. I end up with this list:

The column “Called from” is what I’m interested in. This list contains all the addresses where the call to this registry key is made. I now have to follow each one and see if there is a “RegistrySetValue” call made. I look through each call one by one until I stumble upon this one:

It’s interesting because of the entry I have highlighted. This Unicode “d1” that’s on the stack is the registry entry for my email address. I follow this one to see where it goes and wind up discovering both the encryption and decryption algorithm. I will list them in the next part of this series. I think this post is dragging on long enough and I think it is about time I wrap it up. I will do just that in the next post and save everyone a lot of misery. I have successfully reversed the encryption/decryption algorithm and will post the python source code in my next post.

Saturday, July 14, 2007

Dissecting the GoDaddy email notifier - Part 2

Welcome back. In our last installment, we had just figured out that the GoDaddy Email notifier uses SSL to communicate with the server. Today, I will look at ways of trying to bypass this and sniff traffic in order to figure out how the client communicates with the server.

Like I described in my previous post, I hooked up an stunnel/replug proxy chain to try and decrypt traffic, sniff it, and encrypt the traffic back on its way to the server. I first setup stunnel in both daemon and client modes. Here is a description of each:

Daemon mode. This instance of stunnel will listen on localhost:443 and forward traffic to localhost:8888 all over SSL.

sheran@azazel:~$ sudo stunnel -d 443 -r localhost:8888

Client mode. This instance will listen in non-SSL mode on port 8889 and re-establish the connection in SSL mode to the server. (When sniffing traffic, the DNS lookup for the notifier was noted. It looks up

sheran@azazel:~$ sudo stunnel -c -d 8889 -r

How do we plug the hole in the middle? Simple, use replug found in BlackBag. Here's how:

sheran@azazel:~$ bkb replug localhost:8889@8888

This will start replug and listen on localhost:8888. Whatever it listens to on this port it will forward down to localhost:8889. The way traffic flows will be similar to this:

Client ---> localhost:443 (stunnel) ---> localhost:8888 (replug) ---> localhost:8889 (stunnel) --->

Now for the client to think it's talking to an authentic server, I need to replicate the server certificate as well. This is not going to be an easy task since I don't own a CA; especially not the one that issues GoDaddy's certificates. So I do the next best thing and create a self-signed certificate almost identical to the GoDaddy certificate (weirder things have worked for me in the past). No dice. The client notifier program refuses to negotiate SSL with my first instance of stunnel. Shit.

Since this is not going to be as simple as I thought, I will have to resort to the next best thing: disassemble the notifier executable and try to patch it to talk non-SSL. So I fire up my favorite disassembler OllyDbg and try to locate any strings in the executable to give me a clue as to where the connection is made.

Well, here's something. Looking through strings (Right-click->Search for->All Referenced Strings) gives me several entries to a string reference called "http://" and "https://". I wonder if changing "https://" to "http://" will have any effect. Let's see:

In the "Strings window", right click and do a "Follow in Disassembler"; then when you're in the disassembler window, right click on the line with the "https://" and do a "Follow in Dump"->"Immediate Constant"

This should then bring the string up on the lower left window where you can change the "https://" entry to "http://". Then, right-click, choose "Copy to Executable", right-click on the window that opens up and select "Save File". Save it as another name and try it out for yourself. Now you can see all the traffic flowing between the client and server on Wireshark.

At this point, you will notice that GoDaddy's email notifier uses SOAP to transfer XML messages to and from the server. The URL is and a listing of available operations and WSDL file.

I personally felt that it was easier to get the client to do various operations and sniff the traffic to get an idea of how things are implemented. I think I'm well on my way to writing my linux variant of the notifier.

Next time, I'll look into how the credentials are stored and if they are encrypted and if this is a trivial encryption to break.