Popular Content

Showing content with the highest reputation on 12/15/2009 in all areas

  1. 2 points
    A few years ago I started putting together a graphic novel comic story born from many different sources including this forum... Thread regarding the first book. Thread regarding book 2 Ultimately the story is going to take a total of four books to complete. Book 3 is finished and in the process of going to the printer. Here's the cover if you're interested and/or curious That being said, I decided to embrace Creative Commons and make the first 2 volumes available in their entirety in a single PDF to read and distribute freely. http://edpiskor.com/wizzywig_volume1_and_2.zip I appreciate everybody who picked up the books in the past. You're interest has made finishing the rest of the story possible!
  2. 1 point
    Hey, long time no post, I'm working on a little project and I could use your help... So I've been trying to create a program in C to decode the stored passwords that Firefox offers to store for you. Right now I am in the research phase of my project, and I'm trying to figure out the encryption technique that Firefox uses to encrypt its stored passwords. The stored passwords, in Windows, are stored at C:\Docume~1\<your username here>\Applic~1\Mozilla\Firefox\Profiles\<some number>.default\signons2.txt this file looks something like this: #2d http://www.spine-health.com https://www.google.com https://my.screenname.aol.com http://www.bluebottle.com . https://secure-web8.secondlife.com form[lastname] XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX== *form[password] XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX https://secure-web8.secondlife.com . https://login.facebook.com XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX== *pass XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX https://login.facebook.com . The == at the end of some of the strings tells me that they are most probably base64 encoded. However, looking at the Firefox source which deals with encoding the passwords in the password manager, located at <wherever you have the Firefox source saved>\mozilla-1.9.1\toolkit\components\passwordmgr\src\storage-mozStorage.js The helpful code appears to be: /* * _addLogin * * Private function wrapping core addLogin functionality. */ _addLogin : function (login, isEncrypted) { let userCanceled, encUsername, encPassword; // Throws if there are bogus values. this._checkLoginValues(login); if (isEncrypted) { [encUsername, encPassword] = [login.username, login.password]; } else { // Get the encrypted value of the username and password. [encUsername, encPassword, userCanceled] = this._encryptLogin(login); if (userCanceled) throw "User canceled master password entry, login not added."; } // Clone the login, so we don't modify the caller's object. let loginClone = login.clone(); // Initialize the nsILoginMetaInfo fields, unless the caller gave us values loginClone.QueryInterface(Ci.nsILoginMetaInfo); if (loginClone.guid) { if (!this._isGuidUnique(loginClone.guid)) throw "specified GUID already exists"; } else { loginClone.guid = this._uuidService.generateUUID().toString(); } // Determine encryption type let encType = ENCTYPE_SDR; if (isEncrypted && (encUsername.charAt(0) == '~' || encPassword.charAt(0) == '~')) encType = ENCTYPE_BASE64; let query = "INSERT INTO moz_logins " + "(hostname, httpRealm, formSubmitURL, usernameField, " + "passwordField, encryptedUsername, encryptedPassword, " + "guid, encType) " + "VALUES (:hostname, :httpRealm, :formSubmitURL, :usernameField, " + ":passwordField, :encryptedUsername, :encryptedPassword, " + ":guid, :encType)"; let params = { hostname: loginClone.hostname, httpRealm: loginClone.httpRealm, formSubmitURL: loginClone.formSubmitURL, usernameField: loginClone.usernameField, passwordField: loginClone.passwordField, encryptedUsername: , encryptedPassword: encPassword, guid: loginClone.guid, encType: encType }; let stmt; try { stmt = this._dbCreateStatement(query, params); stmt.execute(); } catch (e) { this.log("_addLogin failed: " + e.name + " : " + e.message); throw "Couldn't write to database, login not added."; } finally { stmt.reset(); } // Send a notification that a login was added. if (!isEncrypted) this._sendNotification("addLogin", loginClone); }, More specifically, // Determine encryption type let encType = ENCTYPE_SDR; if (isEncrypted && (encUsername.charAt(0) == '~' || encPassword.charAt(0) == '~')) encType = ENCTYPE_BASE64; Makes it appear like there might be multiple types of encryption. Furthermore, passing some of the encrypted values in my signons2.txt file that appear to be base64 encoded (the strings ending in ==) to an online base64 encryption/decryption service (http://www5.rptea.com/base64/base64.aspx) gives garbage data as output. Looking through the code some more yields the following function: _decrypt : function (cipherText) { let plainText = null, userCanceled = false; try { let plainOctet; if (cipherText.charAt(0) == '~') { // The old Wallet file format obscured entries by // base64-encoding them. These entries are signaled by a // leading '~' character. plainOctet = atob(cipherText.substring(1)); } else { plainOctet = this._decoderRing.decryptString(cipherText); } plainText = this._utfConverter.ConvertToUnicode(plainOctet); } catch (e) { this.log("Failed to decrypt string: " + cipherText + " (" + e.name + ")"); // In the unlikely event the converter threw, reset it. this._utfConverterReset(); // If the user clicks Cancel, we get NS_ERROR_NOT_AVAILABLE. // If the cipherText is bad / wrong key, we get NS_ERROR_FAILURE // Wrong passwords are handled by the decoderRing reprompting; // we get no notification. if (e.result == Components.results.NS_ERROR_NOT_AVAILABLE) userCanceled = true; } return [plainText, userCanceled]; }, As can be seen above, according to the source, strings that are base64 encoded are started with a ~, while strings that are ciphered by the decoderRing.decryptString() function are not. The decoderRing function is: __decoderRing : null, // nsSecretDecoderRing service get _decoderRing() { if (!this.__decoderRing) this.__decoderRing = Cc["@mozilla.org/security/sdr;1"]. getService(Ci.nsISecretDecoderRing); return this.__decoderRing; }, This is as far as I've gotten. I'm mainly a C programmer, so all this Java is unfamiliar to me, though I can figure most of it out. What I'm trying to do is figure out how decoderRing.decryptString() works, I can't find the actual function, the only function I can find that has anything to do with it is the above. Can you guys give me a few tips? Attached is the decompiled storage-mozStorage.js file (Now saved as a text file) storage-mozStorage.txt
  3. 1 point
    You don't need to for your purposes (barring general curiosity of course). Like you said you are primarily a C programmer and not a Java programming...actually this is JavaScript, completely independent of Java...so what they are doing seems a little weird. Even though you are cutting up chunks of code to show your point which is cool naturally, it might confuse the OOP nature of the code. For instance, decoderRing uses an interface and that interface is extended by another interface...no analogs in C (yes in C++) but what's cool is that you don't need to know that other than to understand how decoderRing is being used. If you want to really figure it out then you'll have to trace all the objects that it is a child of and see how it is implemented (this will start you off). In addition, decoderRing doesn't require a full instance of nsISecretDecoderRing to operate. It is only using a service of this important class. Firefox uses a lot of classes that don't need to be fully instantiated in order to acquire "services" from them. Think of services here as being able to access methods of a class without actually creating instances of them...in C terms it is like using a part of a record without actually declaring a variable of that record type... So if your goal is to actually decrypt them then you can do so through Firefox itself...in fact this is how most browser password managers are broken...they use the browser API to do the work kinda like a plugin just without creating an instance of the window. let query = "INSERT INTO moz_logins " + "(hostname, httpRealm, formSubmitURL, usernameField, " + "passwordField, encryptedUsername, encryptedPassword, " + "guid, encType) " + "VALUES (:hostname, :httpRealm, :formSubmitURL, :usernameField, " + ":passwordField, :encryptedUsername, :encryptedPassword, " + ":guid, :encType)"; This part of the code confirms that they are using a database. Firefox itself uses SQLite. In fact, you can directly access this database independently of Firefox and if you figure out how decrypt works you can crack everything the 'old fashion way' rather than using Firefox calls to do it for you which is more in the 'spirit' of what you want to do. SQLite is easily accessible through C so that shouldn't be too hard. Hope this info is useful to you.