Social Icons

Monday 7 May 2012

[Tutorial/Release] Lastlogin Protection (Launcher Mod)

So with the apparent rise of lastlogin stealers in this section I thought I would try and do something to make it a bit harder for them. So in this tutorial I'm going to show you how to modify the Minecraft launcher to change the encryption key and the filename used for the password storage file (or lastlogin file). This should make it pretty hard for people to steal your legit account since they way they work at the moment is by using the fact that the password to open the file is always the same, "passwordFile". The only way they could find the password is by decompiling your specific launcher.jar, that is hard enough to do anyway, but then add the fact that they have no idea where you keep your launcher.jar and it becomes pretty impossible as far as I can tell anyway.

There is a download at the bottom of this post for a launcher with a random password if you cba to follow along but bear in mind that people might try that if "passwordfile" fails.

For those of you who want to know how to do this, simply open the spoiler at the point you want to start.

Decompiling the launcher.

So I assume you have your original minecraft.jar from minecraft.net, the next thing you want to do is grab jd-gui from this site, extract it and open it up. You should be presented with something roughly like this

[Image: Gr1lh.png]

Next click File -> Open File and open up your minecraft launcher .jar file, if all goes well it should look a bit like this.

[Image: 2XA3u.png]

Now the default setting for jd-gui add some comments to the output .java files that make editing a little tricky, so before exporting the source go to Help -> Preferences and make them look like this

[Image: d8aoV.png]

Now we are ready to actually export the source (you should be glad to hear that it's not obfuscated at all). So go to File -> Save All Sources and chose a location to store the .zip file (the desktop should be fine for now, since we need to move it later on). This zip will then contain the .java files that make up the launcher.

Getting the decompiled source into Eclipse
Before we can edit the code we will need a project set up in Eclipse File -> New -> Project and select "Java Project". You can use whatever name you like, I went for "MinecraftLauncher", once you have entered the name just hit Finish. You should now have something that looks like this

[Image: mxYAb.png]

The next step is to get the code into this src folder so we can mess with it, the simplest way to do this is to open up the zip file created in the first step and drag the files into your workspace folder (Note: Not onto the Eclipse GUI, you need to manually place them in the src folder form the screenshot above) You only need the "net" folder to be extracted since that is where all the code is and the other stuff will just get in the way.

Assuming you have done that correctly you will be able to refresh the project in Eclipse (Right click on it's name -> Refresh) and have the source files show up. It should look like this

[Image: dMqAp.png]

That's this step done :)

Fixing the compile errors that result from decompiling
In the final screenshot in the above section you should notice that there are a few errors, these are a result of the decompiling process and there is no alternative other than to fix them manually, luckily it's not too hard and Eclipse helps us out along the way. Lets start at the top with GameUpdater.java

Scroll down to the first red flag which should be this line
Code:
if (skip[i] != 0) {
The problem here is that the data type of the skip[] array is boolean but it's being compared to an int. Since it's being compared != 0 it's likely that it should be
Code:
if (skip[i]) {

Keep scrolling until you get to the next flag which should be
Code:
int bufferSize;
The error here is a duplicate variable definition, notice that the variable is also defined above the while loop (which is where it should be) so just remove this line.

The next one is a block that looks a bit like this
Code:
Thread t = new Thread(is, urlconnection) {
  public void run() {
    try {
    this.val$is[0] = this.val$urlconnection.getInputStream();
    }
    catch (IOException localIOException)
    {
    }
  }
  };
The val$is is a result of the decompiling so remove those
Code:
Thread t = new Thread(is, urlconnection) {
  public void run() {
    try {
    this.is[0] = this.urlconnection.getInputStream();
    }
    catch (IOException localIOException)
    {
    }
  }
  };
The main problem here is that two parameters are being passed into the Thread which you can't do so remove those
Code:
Thread t = new Thread() {
  public void run() {
    try {
    this.is[0] = this.urlconnection.getInputStream();
    }
    catch (IOException localIOException)
    {
    }
  }
  };
the error should immediately look less horrible, but not gone away. Since we do need to access the variables is and urlConnection we have to remove the this. prefix from them and mark their definitions as final (you can get Eclipse to do that by hovering over the red underlined variable for a second or so.

The final problem in this file is another duplicated
Code:
int bufferSize;
so just remove the line with the red flag.

On to the next file, LoginForm.java

The first error is similar to the Thread one described above so just follow the same procedure. Ultimately you need to change this
Code:
this.offlineButton.addActionListener(new ActionListener(launcherFrame) {
  public void actionPerformed(ActionEvent ae) {
  this.val$launcherFrame.playCached(LoginForm.this.userName.getText());
  }
    });
to this
Code:
this.offlineButton.addActionListener(new ActionListener() {
  public void actionPerformed(ActionEvent ae) {
  launcherFrame.playCached(LoginForm.this.userName.getText());
  }
    });
And this
Code:
this.optionsButton.addActionListener(new ActionListener(launcherFrame) {
  public void actionPerformed(ActionEvent ae) {
  new OptionsPanel(this.val$launcherFrame).setVisible(true);
  }
    });
to this
Code:
this.optionsButton.addActionListener(new ActionListener() {
  public void actionPerformed(ActionEvent ae) {
  new OptionsPanel(launcherFrame).setVisible(true);
  }
    });
letting Eclipse make the "final" modifications as necessary.

Scroll on down to the next one which should be
Code:
DataInputStream dis;
  DataInputStream dis;
Pretty obvious what to do here, remove the duplicate. The same goes for the next one too.

The final problem for this file is the same Thread issue as before, so following the above steps you should end up with
Code:
new Thread() {
  public void run() {
    try {
    editorPane.setPage(new URL("http://mcupdate.tumblr.com/"));
    } catch (Exception e) {
    e.printStackTrace();
    editorPane.setText("






Failed to update news
" + e.toString() + "
");
    }
  }
  }

The next file with red flags is OptionsPanel.java, luckily only one this time and it's the exact same problem as above again. Here is the correct code for reference
Code:
final JButton forceButton = new JButton("Force update!");
    forceButton.addActionListener(new ActionListener() {
  public void actionPerformed(ActionEvent ae) {
  GameUpdater.forceUpdate = true;
  forceButton.setText("Will force!");
  forceButton.setEnabled(false);
  }
    });

The next file is also an easy one, TexturedPanel.java only has one problem, this being a missing import. Just hover over the underlines text for a second and have Eclipse ad the import for you.

Finally we made it to Util.java, the most awkward by far since this requires some guessing. The first problem is just some duplicated lines so just remove those.

We then get to
Code:
switch ($SWITCH_TABLE$net$minecraft$Util$OS()[getPlatform().ordinal()]) {
which does not make a huge amount of sense. Looking at the code here we can see that this is clearly trying to create the minecraftDir in the correct place depending on the operating system.
so instead of switching on that confusing thing, lets try using the conveniently placed function below that gets the OS and see how that works out.
Code:
switch (getPlatform()) {
Okay better, but the cases are now all wrong so lets fix that.
We know that Windows uses an %appdata% folder and we can see "APPDATA" here so lets assume that block is for windows and change
Code:
case 3:
to
Code:
case windows:
This being one of the possible Enums returned by the below function.
Next we know that Linux machines use ~/./ for their data, which means the first two cases are Linux based OSs looking at the return values for the getPlatform() function we see only two possibilities so change
Code:
case 1:
    case 2:
to
Code:
case solaris:
    case linux:
Now by the process of elimination
Code:
case 4:
must be
Code:
case macos:
which makes sense since OS X uses "Library/Application Support/"

There are also a couple of duplicated lines in this file, but I'll let you find those for yourselves :)

Finally, the line
Code:
throw localObject;
can just be removed.

And finally ! We are finished with error fixing. Hopefully you have a bit of sympathy for the MCP devs now.

Modifying the password storage
This part is really simple, everything is done in LoginForm.java so look for the methods readUsername() and writeUsername(), they should look like this

[Image: ZVUQY.png]

There are two instances of "passwordfile" here and also two of "lastlogin", you need to change both of those and make sure they stay the same, for example

[Image: TmxwL.png]

Here I have renamed my lastlogin file to "notlastlogin" and set it's password to a very hard to guess string.

We are now ready to test the modified launcher, so click the little green "Run" button in the upper bar and watch the Console window. The normal Minecraft launcher should pop up and you should see that your password is not in the field (even if you set it to remember) and you should see something that ends in "notlastlogin (No such file or directory)" in the console output which is fine because the file does not exist yet.

Now log in to your account (make sure to tick remember password) and close the game once you are in. Now click run again and hopefully your password will still be there in the box ready to log in. As a final check go your your .minecraft folder and make sure the new file has been created.

Finally (and most importantly), delete your old lastlogin file. If you don't do that all this hard work will have been for nothing.

Exporting
Go to File -> Export -> As Runnable Jar File then select the project name you chose from the dropdown and a location to save the file to. That's it ! You now have a slightly more secure Minecraft Launcher that those bad Alphas will have to go to a bit of trouble to get your valued account out of.

Note that since we have exported the jar as a runnable jar file, the launch command is simplified a little to
Code:
java -Xmx1024M -Xms512M -jar MinecraftLauncher.jar
for Windows users you might need to use Google to find out how to run it :)

Here is a version that uses a random password and a new filename.
Download: http://uppit.com/ym073v4kx7dc/MinecraftLauncher.jar

Also here is a unmodified version of the source with the errors all fixed
Download: http://uppit.com/29607mxp8910/launcher_src.zip

Disclaimer !
Yes this can probably be worked around, but it's an additional layer of protection, layers are good :D It would be easy enough to work out the filename but I don't think the password would be easy to get, if you can correct me on that I would be happy to admit that I was wasted an hour on this and you can laugh at me ;


credit to:.

No comments:

Post a Comment