Tag-Archive for » reverse engineering «

Wednesday, September 01st, 2010 | Author: Tim

It’s actually pretty trivial to do this, though it seemed like something that could be mildly interesting to post on. While it’s written in C# .Net itself, it means we can pretty much see exactly whats going on - so it’s lends itself to be a pretty easy example for people who have never actually done any unpacking before. It also lets to understand the concept of unpacking from a programmers prospective of actually packing it.

A little backstory to this is, someone sent me a “hack” for diablo2 and said it wasn’t working for them. Why they sent me this? I have no idea, but I figured I’d just take a look at it and see what was going on. Turns out it was a password stealer for d2 written in .Net - pretty cool looking stuff. The funny part about it all was that since this was “packed” with netz the person who sent me it couldn’t use reflector on it (and succeed) - thus why they sent it to me I guess. Anyway, let’s get down to the actual meat of the post.

Identification of netz is pretty simple - if you open up the application in Reflector, you’ll see the namespace nets. Also it will almost always be accompanied by a zip.dll, which is used for decompressing the resource. Essentially the main function we want to look at is StartApp:

public static int StartApp(string[] args)
{
    byte[] resource = GetResource("213213-2131223-2134234-234");
    if (resource == null)
    {
        throw new Exception("application data cannot be found");
    }
    int num = InvokeApp(GetAssembly(resource), args);
    resource = null;
    return num;
}

From here we can see that a resource of bytes is going to be loaded, and GetAssembly is called with it as an argument. Go dump the resource listed here into some directory, I named mine virgin.dump. GetAssembly is a pretty simple function that I’m not going to dive into, it essentially calls UnZip(byte[] data). This code is a little more interesting and is doing the most work we’re interested in, here is small snippet;

private static MemoryStream UnZip(byte[] data) {
    MemoryStream baseInputStream = null;
    MemoryStream stream2 = null;
    InflaterInputStream stream3 = null;

    baseInputStream = new MemoryStream(data);
    stream2 = new MemoryStream();
    stream3 = new InflaterInputStream(baseInputStream);
    byte[] buffer = new byte[data.Length];
    while (true)
    {
       int count = stream3.Read(buffer, 0, buffer.Length);
        if (count <= 0)
        {
           break;
        }
        stream2.Write(buffer, 0, count);
    }
    stream2.Flush();
    stream2.Seek(0L, SeekOrigin.Begin);
}

Ah, this looks familiar! In fact - thanks to Reflector it’s pretty much almost exactly Java code. All we need to do is inflate the resource and dump it to a file - there isn’t any encryption or anything special about it at all. Basically by looking at the code above, I through together a small little resource inflater:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.InflaterInputStream;

public class inflater {
    public static void main(String[] args) {
        try {
            FileInputStream inStream = new FileInputStream(args[0]);
            InflaterInputStream inflaterStream = new InflaterInputStream(inStream);
            FileOutputStream outStreams = new FileOutputStream(args[0] + "_unpacked");
            for (int c = inflaterStream.read(); c != -1; c = inflaterStream.read()) {
                outStreams.write(c);
            }
            outStreams.close();
        } catch (IOException ex) {
            System.err.println(ex);
        }
    }
}

Is this anything special? No, but it worked for me and my quick little need for it. Could you use a Generic .Net unpacker? Of course, I just did this since I wasn’t running Windows and didn’t want to fire up a VM instance just to debug and dump a little .Net application. :)

Wednesday, March 17th, 2010 | Author: Tim
Make money, money...

Make money, money...

It’s been a while since I’ve posted any article, sadly between work, contracts after work, spam, having a life and volleyball I don’t have much time to spend on my blog. Research is still going strong - but very little has trickled out from me over the past few months.

Something I’d like to finally post has come to my attention. Approximately a year ago when I first started looking into the mobile ad networks, I thought of something sinister. While I never intend to do anything evil, since I’m always looking for ways to protect myself, my first thoughts always seem to be, “how do I abuse this?” It all started when people started trying to think of ways to monetize their application. Do we charge up front, or do we try to make a few bucks off a huge user-base using ads?

My first question is, how are the ads secured? Much like other applications that are tracked by application, most use a “application id” or “publisher id”. This is a super-secret code that is used for identifying traffic from you, right? Alright, well unlike a website advertisement, which has a referrer - mobile ads have no actual way to differentiate traffic other than this “unique” id.

So what? Whats the issue with that? Well, there is a big issue with this. There is a coined term, “adjacking”, that essentially means “falsified” clicks. Originally this term meant you hijacked the javascript of google adsense, and made a click anywhere on your website appear to be a click on your adsense ad. Though, I’m “word-jacking” this term, because I feel my definition is a little more appropriate. Essentially, with the ability to easily decompile/modify an apk file - someone can quiet easily steal your ad traffic, this hi-jacking your ads… Adjacking.

Is this something new? No - but beware of it. I’ve had this article lying around for a bit, more uninterested in publishing for the idea that people would actually attempt to do this if I brought it up. Upon first writing this, I quickly made a program that attempted to make a database of signatures of programs. This program downloaded legit (free) applications and grabbed the signature from the META-INF folder of the apk. Then it attempted to find versions available for download on the internet…. For the most part, the version where always the same - with a rare instance of someone resigning it with little modification to the file, often to help localize it. Though now, I’ve seen and heard of an increase of people downloading their application, replacing the ID in the apk, and replacing it with their own.

Keep your code secure!

Protection from adjacking?

What to do about this? Well, hopefully the ad networks figure something out, though I’m not sure they honestly care much. I’ve sent emails to a few of the big providers with no responses and a few “we’ll look into it” replies. I don’t see a big downside for them - maybe if more people complain they’ll get the hint. I’m sure right now they’ll just get the traffic, for traffic’s sake. Most applications that have been modified probably don’t drive in much or take away much from other people. Though if they do, they could “act” upon these and actually shut people down… Will the correct developer ever see this money? Probably not… Though if your try hard enough you might see something.

The sad part is, most of the people modifying the applications are now no better than a scripting kiddie. There are enough tools available now to make this an easy job. Maybe if people start looking into this, these people will be rooted out - since they must fill in “legit” information to open an account.

Anyways, I’ve been looking at some protection schemes for this, hopefully I’ll have time to post some soon. I’ll post a little tutorial on obfuscating (manually) your adsense/admob/blah code to protect yourself :)

Wednesday, September 23rd, 2009 | Author: Tim
Mmmmm... Market Data...

Mmmmm... Market Data...

It turns out downloading a free application is actually pretty easy to reproduce. The things required by the google android servers are just four variables. The server needs to know your userId, authToken, deviceId and the applications assetId.
The userId is a unique number that is associated only with your gmail account, the one that is currently linked to the phone. I’m working on getting a generic way to grab this number, though I believe the request is buried in an ssl request to the google servers. So for now, you can obtain your own userId by doing a tcpdump of your market traffic, just do a download of an application and look for a “GET” request in wireshark. There does not appear to be a “hard” maximum character on this, I’ve seen userIds as low as 8 in length and as high as 13. A bad userId will return a 403 forbidden response.
The authToken is sent in cookie form to the server, to authenticate that the user is using a valid and non-expired token and well, is who they say they are! This is linked to the userId and must match the account that the userId is taken from. Expired tokens will return a 403 forbidden response.
The deviceId is simply your Android_ID, and is linked in anyway to the authtoken or user-id, so feel free to spoof this.
The assetId is a number (negative or positive) that identifies the current stream of the application you wish to download. More on this later when I cover how to get live market data. Note that this number is not always the same - it (appears) to change when something from the application is changed. Originally I referred to this in my research as a “cacheAppID” for just that purpose.

// Downloading apk's without vending/market
// Coded by Tim Strazzere
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.net.HttpURLConnection;

public class main {
	public static void main(String[] args) {
		// current assetId for the yahoo search apk
		String assetId = "7884814897504696499";
		// input your userId
		String userId = "12345678901";
		// spoof your deviceId (ANDROID_ID) here
		String deviceId = "2302DEAD532BEEF5367";

		// input your authToken here
		String authToken = "DQAAA...BLAHBLAHBLAHYOURTOKENHERE";

		String cookie = "ANDROID=" + authToken;

		try {
			// prepare data for being 'get'ed
			String rdata = "?" + URLEncoder.encode("assetId", "UTF-8") + "=" + URLEncoder.encode(assetId, "UTF-8");
			rdata += "&" + URLEncoder.encode("userId", "UTF-8") + "=" + URLEncoder.encode(userId, "UTF-8");
			rdata += "&" + URLEncoder.encode("deviceId", "UTF-8") + "=" + URLEncoder.encode(deviceId, "UTF-8");

			// Send data
			URL url = new URL("http://android.clients.google.com/market/download/Download" +rdata);
			HttpURLConnection conn = (HttpURLConnection)url.openConnection();

			// For GET only
			conn.setRequestMethod("GET");

			// Spoof values
			conn.setRequestProperty("User-agent", "AndroidDownloadManager");
			conn.setRequestProperty("Cookie", cookie);

			// Read response and save file...
			InputStream inputstream =  conn.getInputStream();
			BufferedOutputStream buffer = new BufferedOutputStream(new FileOutputStream("out.put"));
			byte byt[] = new byte[1024];
			int i;
			for(long l = 0L; (i = inputstream.read(byt)) != -1; l += i )
				buffer.write(byt, 0, i);

			inputstream.close();
			buffer.close();

			System.out.println("File saved...");
		}
		catch (FileNotFoundException e) {
			System.err.println("Bad url address!");
		}
		catch (UnsupportedEncodingException e) {
			System.out.println(e);
		}
		catch (MalformedURLException e) {
			System.out.println(e);
		}
		catch (IOException e) {
			if(e.toString().contains("HTTP response code: 403"))
				System.err.println("Forbidden response received!");
			System.out.println(e);
		}
	}
}

Hopefully someone will find this stuff useful ;) Better than me just sitting on it forever!