Tag-Archive for » vending.apk «

Monday, October 05th, 2009 | Author: Tim
Changing the properties..

Changing the properties..


Note: This might be well, a little low level for some people to understand -
though I’m sure this will end up finding the right people. If you understand this post -
then you’ll understand the significance of what the purposes of doing this would be
for
:)

Just randomly looking to do specific things with the Market, I finally figured out a way
to force the Market into accepting any certificate. It turns out there is actually a little bit
of code (leftover from testing?) that if special parameters are set, will allow you to
disable ssl certificate checking. This essentially allows us to well, do lots of things we
otherwise wouldn’t be able to do!

Obviously your going to need root to enable this - and I’m going to provide you the
way I’ve enabled it; using adb. Again like I’ve stated countless times, anything you do
via ADB you should be able to do via a console on the device, I’m not sure why people
always repaste everything and say just do it via a console thinking it’s some big news…
The two variables we’re going to have to set are ro.secure and
vending.disable_ssl_cert_check. Personally, my devices both have ro.secure
already set (properly) to 0. Vending.disable_ssl_cert_check is a new variable that we
will be creating, setting it to “TRUE”. Simply fire up adb and run the following
commands (as root);

setprop ro.secure 0
setprop vending.disable_ssl_cert_check TRUE

You can quickly run a “getprop” to verify you typed everything correctly; ro.secure
should be located as the first variable and the vending one is the last (since it is new).
You can verify that these settings are correct and working by watching your console
log for the Vending.apk via DDMS. The following string should appear while loading
the Market: “Turning off SSL certification check.” This can be seen below:

"Turning off SSL Check"

Also as a final reminder, every reboot these variables must be reset, since there is no program actually setting them already. You must reinitialize these variables (in my case, I only have to initialize vending.disable_ssl_cert_check) if you would like to use this mode.

Hopefully this will be of use to someone other than myself!

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!

Tuesday, September 15th, 2009 | Author: Tim

Mmmmm... Market Data...

Mmmmm... Market Data...


I’ve been sitting on this code for a while now. I had been tooling around with it mostly about a year ago when I was collecting live market data - it actually took a long time to figure out what the actual token was. Not sure if this method will be changed since there is apparently a big update for the market coming up, I’m assuming it won’t change though - otherwise older versions of the market would break. For people who don’t know - the http requests the vending apk is sending holds a “token” which there was no link to how it was obtained or formed. It turns out to just be a simple token requested like any other google service. The “service” name just turned out to be “android”. Other “services” that the market uses are “androidsecure” and “sierra” - the latter being the codename for google-checkout.

The main reason this was a pain to figure out was because it’s being handled by the com.google.android.googleapps package, not the vending.apk package.

Hopefully this snippet will be useful for some people, like the MyMarket creators or anyone else trying to do market data analysis. I’ll try to post later how to actually send data and receive it using this token. Enjoy for now!

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;

public class auth {

	// declare variables for use in gettig auth-token
	private final static String account = "yourAccount@gmail.com";
	private final static String password = "yourPassword";

	// service must be 'android' for market-data
	private final static String service = "android";

	public static void main(String[] args) throws UnsupportedEncodingException, MalformedURLException, IOException {

		// Prepare data for being posted
		String rdata = URLEncoder.encode("accountType", "UTF-8") + "=" + URLEncoder.encode("HOSTED_OR_GOOGLE", "UTF-8");
        rdata += "&" + URLEncoder.encode("Email", "UTF-8") + "=" + URLEncoder.encode(account, "UTF-8");
        rdata += "&" + URLEncoder.encode("Passwd", "UTF-8") + "=" + URLEncoder.encode(password, "UTF-8");
        rdata += "&" + URLEncoder.encode("service", "UTF-8") + "=" + URLEncoder.encode(service, "UTF-8");

      // Send data
      URL url = new URL("https://www.google.com/accounts/ClientLogin");
      URLConnection conn = url.openConnection();
      conn.setDoOutput(true);

      // Write post
      OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
      wr.write(rdata);
      wr.flush();

      // Get the response
      BufferedReader rd;
      String line;
      StringBuffer resp = new StringBuffer();
      try {
    	  rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
    	  while ((line = rd.readLine()) != null) {
    		  resp.append(line);
    		  System.out.println(line);
    	  }
    	  wr.close();
    	  rd.close();
      } catch (FileNotFoundException e1) {
    	  // Catch bad url
    	  System.out.println("Error: Bad url address!");
      } catch (IOException e1) {
    	  // Catch 403 (usually bad username or password
    	  if(e1.toString().contains("HTTP response code: 403"))
    		  System.out.println("Error: Forbidden response! Check username/password or service name.");
      }

      String token = resp.toString().substring(resp.toString().indexOf("Auth=")+5);

      try{
           //Create file
          FileWriter fstream = new FileWriter("auth.token");
              BufferedWriter out = new BufferedWriter(fstream);
          out.write(token);
          //Close the output stream
          out.close();
          }catch (Exception e){//Catch exception if any
           System.err.println("Error: " + e.getMessage());
          }
	}
}