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 youruserId, authToken, deviceId and the applicationsassetId.
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.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
// 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!