[GUIDE] How to Receive and Handle SMS on Android - General Topics

Author: Apriorit (Driver Development Team)
This article is useful for you if you want to develop your own SMS (or another service) handler. As a sample, I choose received SMS handler that receives SMS, encrypts them, and puts into the SMS table of the Android system database.
Android Manifest
Manifest is a very important part of an Android application. You can find everything about the Android manifest by this link.
And now I’ll try to describe every line that is important for us.
The first are permissions . The application must receive, write and read SMS from the database. Permissions can be obtained as follows:
Code:
1.<uses-permission android:name="android.permission.WRITE_SMS" />
2.<uses-permission android:name="android.permission.READ_SMS" />
3.<uses-permission android:name="android.permission.RECEIVE_SMS" />
Now it’s time to write a standard activity starting. This is a part of an application that will show us SMS and will decrypt encrypted ones. There is nothing special:
Code:
1.<activity android:name=".SecureMessagesActivity" android:label="@string/app_name" >
2. <intent-filter>
3. <action android:name="android.intent.action.MAIN" />
4. <category android:name="android.intent.category.LAUNCHER" />
5. </intent-filter>
6.</activity>
And now we need to catch all received SMS into our SMS receiver:
Code:
1. <receiver android:name=".SmsReceiver" android:exported="true" >
2. <intent-filter android:priority="999">
3. <action android:name="android.provider.Telephony.SMS_RECEIVED" />
4. </intent-filter>
5. </receiver>
Where
Code:
android:exported
indicates that the SmsReceiver class must receive event not only from the application but also from the whole Android system.
Code:
android:priority=”999”
indicates that receiver has the highest priority and will catch the SMS event before the system. Be careful with this because incorrect work of your receiver can corrupt the system or important data in your device. You can read about priority values here.
Code:
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
indicates that we want to get received SMS.
View Model
The project contains only one XML layout. There is one button and one list. The button is used for getting inbox SMS from the system and the list is used for showing messages.
Here is the XML layout code:
Code:
01.<?xml version="1.0" encoding="utf-8"?>
02.<LinearLayout xmlns:android="'link to schemas(dot)android(dot)com/apk/res/android'"
03. android:orientation="vertical" android:layout_width="fill_parent"
04. android:layout_height="fill_parent" android:id="@+id/MainLayout"
05. android:background="@android:color/background_light">
06.
07. <Button android:layout_height="wrap_content"
08. android:layout_width="match_parent" android:id="@+id/UpdateList"
09. android:layout_margin="2dip"
10. android:text="Update SMS list" />
11.
12. <ListView android:id="@+id/SMSList"
13. android:layout_height="wrap_content"
14. android:layout_width="match_parent"
15. android:layout_margin="2dip" />
16.
17.</LinearLayout>
Listeners will be described later.
Encryption/Decryption
All incoming SMS will be encrypted. For this reason, the class, which provides encrypting and decrypting, is added.
I use the AES algorithm and standard Android libraries. You can use this class for your own purposes.
String encrypt( String password, String data ) – encrypts string where the key will be generated using a password string. The returned value is a Base64 string that was previously encrypted.
Code:
01.// Encrypts string and encodes in Base64
02.public static String encrypt( String password, String data ) throws Exception
03.{
04. byte[] secretKey = generateKey( password.getBytes() );
05. byte[] clear = data.getBytes();
06.
07. SecretKeySpec secretKeySpec = new SecretKeySpec( secretKey, CIPHER_ALGORITHM );
08. Cipher cipher = Cipher.getInstance( CIPHER_ALGORITHM );
09. cipher.init( Cipher.ENCRYPT_MODE, secretKeySpec );
10.
11. byte[] encrypted = cipher.doFinal( clear );
12. String encryptedString = Base64.encodeToString( encrypted, Base64.DEFAULT );
13.
14. return encryptedString;
15.}
String decrypt( String password, String encryptedData ) – decrypts a Base64 string with a password string.
Code:
01.// Decrypts string encoded in Base64
02.public static String decrypt( String password, String encryptedData ) throws Exception
03.{
04. byte[] secretKey = generateKey( password.getBytes() );
05.
06. SecretKeySpec secretKeySpec = new SecretKeySpec( secretKey, CIPHER_ALGORITHM );
07. Cipher cipher = Cipher.getInstance( CIPHER_ALGORITHM );
08. cipher.init( Cipher.DECRYPT_MODE, secretKeySpec );
09.
10. byte[] encrypted = Base64.decode( encryptedData, Base64.DEFAULT );
11. byte[] decrypted = cipher.doFinal( encrypted );
12.
13. return new String( decrypted );
14.}
byte[] generateKey( byte[] seed ) – generates a secret key using a seed (String.getBytes() in our case). A secret key is a byte array generated for the specific encryption algorithm.
Code:
01.public static byte[] generateKey( byte[] seed ) throws Exception
02.{
03. KeyGenerator keyGenerator = KeyGenerator.getInstance( CIPHER_ALGORITHM );
04. SecureRandom secureRandom = SecureRandom.getInstance( RANDOM_GENERATOR_ALGORITHM );
05. secureRandom.setSeed( seed );
06. keyGenerator.init( RANDOM_KEY_SIZE, secureRandom );
07. SecretKey secretKey = keyGenerator.generateKey();
08. return secretKey.getEncoded();
09.}
Handle Received SMS
The main class that receives the SMS is SmsReceiver. It extends BroadcastReceiver class. This is the main concept of any Android service or receiver. Any child of BroadcastReceiver must contain the onReceive method, which receives Context and Intent parameters. You can find all additional information on the Android developer documentation site.
So, we get event and go into the onReceive method. The first line is:
Bundle extras = intent.getExtras();
The Bundle object is a simple map. It contains pairs of keys and values. SMS are placed in this bundle. The key of SMS is pdus:
Code:
1.public static final String SMS_EXTRA_NAME =”pdus”;
2.…
3.Object[] smsExtra = (Object[]) extras.get( SMS_EXTRA_NAME );
After this, the smsExtra value contains arrays of bytes. Here is a full example:
Code:
01.public void onReceive( Context context, Intent intent )
02. {
03. // Get the SMS map from Intent
04. Bundle extras = intent.getExtras();
05.
06. String messages = "";
07.
08. if ( extras != null )
09. {
10. // Get received SMS array
11. Object[] smsExtra = (Object[]) extras.get( SMS_EXTRA_NAME );
12.
13. // Get ContentResolver object for pushing encrypted SMS to the incoming folder
14. ContentResolver contentResolver = context.getContentResolver();
15.
16. for ( int i = 0; i < smsExtra.length; ++i )
17. {
18. SmsMessage sms = SmsMessage.createFromPdu((byte[])smsExtra[i]);
19.
20. String body = sms.getMessageBody().toString();
21. String address = sms.getOriginatingAddress();
22.
23. messages += "SMS from " + address + " :\n";
24. messages += body + "\n";
25.
26. // Here you can add any your code to work with incoming SMS
27. // I added encrypting of all received SMS
28.
29. putSmsToDatabase( contentResolver, sms );
30. }
31.
32. // Display SMS message
33. Toast.makeText( context, messages, Toast.LENGTH_SHORT ).show();
34. }
35.
36. // WARNING!!!
37. // If you uncomment the next line then received SMS will not be put to incoming.
38. // Be careful!
39. // this.abortBroadcast();
40. }
So, when the SMS list gets into smsExtra, then SMS should be parsed. And the method createFromPdu from SmsMessage class should be called for this. I do not write about the methods and fields of SmsMessage class because it is documented enough.
So, SmsReceiver gets the SMS and now can do anything with it. In the example, SMS are encrypted and put into the SMS table of the device database. I need this to allow the encrypted SMS viewing by the default Android SMS viewer.
Of course, the PDU (Protocol Description Unit) can be parsed and generated manually, but its format can be changed anytime by Google. If you are interested in researching the PDU format, you can analyze it at Android sources: for CDMA phones and for GSM phones.
When SMS is got, it is shown using the Toast class. And I want to tell you about the last commented line:
// this.abortBroadcast();
I commented it because it’s dangerous. As you remember, the receiver catches SMS events before the system works with it. So, the abortBroadcast method stops the SMS dispatching to other receivers. If something is going wrong, the SMS will not be saved.
You can see the full example at the attached sources.
Read and Decrypt SMS
I want to tell you why the activity is needed. Below the click listener for the button on the main screen is listed. In the following code, all SMS that are placed in Inbox are read and then the sender information and SMS text are put into the list:
Code:
01.public void onClick( View v )
02.{
03. ContentResolver contentResolver = getContentResolver();
04. Cursor cursor = contentResolver.query( Uri.parse( "content://sms/inbox" ), null, null, null, null);
05.
06. int indexBody = cursor.getColumnIndex( SmsReceiver.BODY );
07. int indexAddr = cursor.getColumnIndex( SmsReceiver.ADDRESS );
08.
09. if ( indexBody < 0 || !cursor.moveToFirst() ) return;
10.
11. smsList.clear();
12.
13. do
14. {
15. String str = "Sender: " + cursor.getString( indexAddr ) + "\n" + cursor.getString( indexBody );
16. smsList.add( str );
17. }
18. while( cursor.moveToNext() );
19.
20. ListView smsListView = (ListView) findViewById( R.id.SMSList );
21. smsListView.setAdapter( new ArrayAdapter<String>( this, android.R.layout.simple_list_item_1, smsList) );
22. smsListView.setOnItemClickListener( this );
23.}
The SMS text is obtained from the list, decrypted and then shown. SmsReceiver.PASSWORD can be changed in any way. The list item listener is as follows:
Code:
01.public void onItemClick( AdapterView<?> parent, View view, int pos, long id )
02. {
03. try
04. {
05. String sender = smsList.get( pos ).split("\n")[0];
06. String encryptedData = smsList.get( pos ).split("\n")[1];
07. String data = sender + "\n" + StringCryptor.decrypt( new String(SmsReceiver.PASSWORD), encryptedData );
08. Toast.makeText( this, data, Toast.LENGTH_SHORT ).show();
09. }
10. catch (Exception e)
11. {
12. e.printStackTrace();
13. }
14. }

Related

[Q] BAD_XML error when trying to use ProvXML to set security settings

I am now trying my hand at provXML to query/change security settings. I realize that most would probably come back with some type of access denied exception, but I am unable to even get that far.
I have an interop unlocked samsung omnia7 with mango. I am trying to use DMProcessConfigXML to send an xml string to set a security policy (in this case SECPOLICY_CFAUTORUN (2) ). I use QueryPolicy to check its value (currently a "0" and send the xm to set it to a 1.
Here is a snippet from the relavent code
Code:
DWORD dwPolicyValue = 0;
HRESULT hr = QueryPolicy(2, &dwPolicyValue);
LPWSTR wszOutput = NULL;
LPCWSTR wszQueryXML =
L"<? xml version=\"1.0\" encoding=\"utf-16\" ?>"
L"<wap-provisioningdoc>"
L"<characteristic type=\"SecurityPolicy\">"
L"<parm name=\"2\" value=\"1\">"
L"</characteristic>"
L"</wap-provisioningdoc>";
MessageBox(NULL,wszQueryXML,L"Now sending the following xml",MB_OK);
HRESULT hr2 = DMProcessConfigXML(wszQueryXML,CFGFLAG_PROCESS,&wszOutput);
delete[] wszOutput;
The first call to QueryPolciy returns a 0. The call to DMProcessConfigXML returns -2147213303 or FFFFFFFF80042009 which I believe is CONFIG_E_BAD_XML. There may be a problem with the xml string, but I can't see it. Any suggestions as to a solution or somewhere else to look?
It seems to only be when I am accessing the security policies. I can send a query for the certificate stores
Code:
LPCWSTR wszOutput =
<wap-provisioningdoc>
<characteristic type="CertificateStore">
<characteristic-query type="Privileged Execution Trust uthorities" />
<characteristic-query type="Unprivileged Execution Trust Authorities" />
<characteristic-query type="SPC" />
<characteristic-query type="CA" />
<characteristic-query type="Root" />
<characteristic-query type="MY" />
</characteristic>
</wap-provisioningdoc>
It returns a 800704EC errorcode, which is a permission problem I think. The security policy queries however give me the bad xml error.
OK I have worked a little more with this and am now successfully able to provision certs in the MY, CA, and ROOT stores with the following code
Code:
void AddCert(const std::wstring& strCertStore, const std::wstring& strCertHash, const std::wstring& strCertEncoded)
{
LPWSTR wszOutput = NULL;
wchar_t wszXML[16384];
swprintf(wszXML,L"<wap-provisioningdoc>"
L"<characteristic type=\"CertificateStore\">"
L"<characteristic type=\"%s\">"
L"<characteristic type=\"%s\">"
L"<parm name=\"EncodedCertificate\" value=\"%s\"/>"
L"</characteristic>"
L"</characteristic>"
L"</characteristic>"
L"</wap-provisioningdoc>", strCertStore.c_str(), strCertHash.c_str(), strCertEncoded.c_str());
HRESULT hr = DMProcessConfigXML(wszXML,CFGFLAG_PROCESS,&wszOutput);
delete[] wszOutput;
}
I am unable however to add a cert to the Code Integrity store, or even query that store with the provisioning xml. The call to DMProcessConfigXML returns 86000011, and I can't find any reference as to what that error code could mean. Any thoughts?
Thanks,
Since you're using native code and messing with pretty serious stuff, you may want to try starting a thread on the Development and Hacking sub-forum (be sure to do a searcch first, of course). I do know that Heathcliff74, an XDA-Devs member, has been able to get full access to the certificate store and exposes this through his WP7 Root Tools app. This app is hosted on that sub-forum.
I know people have tried calling DMProcessConfigXML() before, and been blocked by various security policies. Have you made any changes to your phone that would increase the permissions your app runs at? Being able to make any changes using wap-provisioning straight from a sideloaded app surprises me; I didn't think they had that much permission. Have you tried using registry or filesystem provxml?
My account on these forums is relatively new, and I am unable to post on the dev forums yet. For this reason, I have been posting here and hoping someone would see it and maybe offer some insight. Either that or get enough posts to allow posting in the dev forums. All this code that I have been developing is on a custom HTC image (which is a switch from the original post), so I have TCB access for a native exe that runs on boot.
I follow Heathcliff74's posts as well as yours and a few others on the dev forums and have downloaded quite a few of the apps. I've also been talking with a few of them through private messages. Once I can post on the dev forums, I will probably post some things there, as well as chime in on some of the discussions going on.
Thanks for taking the time to reply though.
I am still working on this but have decided to approach it from a different angle. Instead of using provisioning xml to add the encoded cert to the store, I am going to try using the crypto api functions to do it. I am using the instructions
here to get the strCertEncoded value. Basically just exporting it in base64 encoding and copying the contents (minus the BEGIN CERTIFICATE and END CERTIFICATE). I am trying to add the cert and then list the contents of the store. Here is the code:
Code:
char pszNameString[256];
void* pvData;
DWORD cbData = 0;
PCCERT_CONTEXT pCertContext = NULL;
DWORD dwPropId = 0;
HCERTSTORE hSystemStore = NULL;
std::string strCertEncoded ("INSERT ENCODED VALUE HERE");
DWORD dwEncodedSize = strCertEncoded.size();
if (hSystemStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_LOCAL_MACHINE, L"Code Integrity"))
{
// try to add a cert
if (CertAddEncodedCertificateToStore(hSystemStore,MY_ENCODING_TYPE,(const BYTE*)strCertEncoded.c_str(), dwEncodedSize, CERT_STORE_ADD_REPLACE_EXISTING, NULL))
fprintf(pLog, "Certificate successfully added to Code Integrity store.\n");
else
{
fprintf(pLog, "There was an error adding the certificate to the store. %x\n", GetLastError());
}
fprintf(pLog,"===== Enumerating Code Integrity store =====");
// find certs in this store
while (pCertContext=CertEnumCertificatesInStore(hSystemStore,pCertContext))
{
// get the name
if (CertGetNameString(pCertContext, CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, (LPWSTR)pszNameString, 256))
{
fprintf(pLog,"\n%S\n",pszNameString);
// get the hash propery
CertGetCertificateContextProperty(pCertContext, CERT_HASH_PROP_ID, NULL, &cbData);
if (cbData == 0)
{
MyHandleError("CertGetCertificateContextProperty 1 failed.");
}
pvData = HeapAlloc(GetProcessHeap(), 0, cbData);
if (!CertGetCertificateContextProperty(pCertContext, CERT_HASH_PROP_ID, pvData, &cbData))
{
MyHandleError("CertGetCertificateContextProperty 2 failed.");
}
for (DWORD i = 0; i < cbData; i++)
{
fprintf(pLog,"%02X", ((byte*)pvData)[i]);
}
fprintf(pLog,"\n");
HeapFree(GetProcessHeap(), 0, pvData);
PCERT_INFO pinfo = pCertContext->pCertInfo;
SYSTEMTIME startDate;
FileTimeToSystemTime(&(pinfo->NotBefore),&startDate);
SYSTEMTIME endDate;
FileTimeToSystemTime(&(pinfo->NotAfter),&endDate);
fprintf(pLog,"Valid from %d/%d/%d to %d/%d/%d\n", startDate.wMonth, startDate.wDay, startDate.wYear, endDate.wMonth, endDate.wDay, endDate.wYear);
}
}
}
else
{
fprintf(pLog,"Error opening Code Integrity store. %d", hSystemStore);
}
The call to CertAddEncodedCertificateToStore returns with the errorcode 8009310B. The message for the error is "ASN1 bad tag value met." I have found some information on this error but have been unable to determine why I am getting it.

[Q] [SOLVED] Listbox items won't update with binding WP7 Mango

I have a listbox, with custom items. Code:
Code:
<ListBox Height="600" HorizontalAlignment="Left" Margin="7,6,0,0" Name="friendList" VerticalAlignment="Top" Width="449" ItemsSource="{Binding Friends}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="5,0">
<Image Height="120" HorizontalAlignment="Left" Name="image" Stretch="Fill" VerticalAlignment="Top" Width="120" Source="{Binding ImageUri}" GotFocus="image_GotFocus"/>
<CheckBox Height="78" HorizontalAlignment="Left" Margin="65,63,0,0" x:Name="selectedChckbox" VerticalAlignment="Top" Width="55" IsChecked="{Binding Selected, Mode=TwoWay}"/>
<TextBlock Height="58" HorizontalAlignment="Left" Margin="0,122,0,0" x:Name="nameTextBlck" VerticalAlignment="Top" Text ="{Binding Title}" Width="120" TextWrapping="Wrap" GotFocus="name_GotFocus"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I've created a veiwmodel for the values for binding, and when I click on one item I want to change the checkbox state like so:
Code:
friendSelectionViewModel.Friends[_selectFriendContent.friendList.SelectedIndex].Selected = !friendSelectionViewModel.Friends[_selectFriendContent.friendList.SelectedIndex].Selected;
But the only way the listbox gets the values updated, if I set the datacontext to null and than assign the viewmodel aggain like so:
Code:
_selectFriendContent.DataContext = null;
_selectFriendContent.DataContext = friendSelectionViewModel;
But this takes about 5-10 seconds to refresh the list. I know there is a better solution, I just cant figure out how.
Thanks in advance!
I don't know what datatype your collection 'friends' is from what you've posted, but I assume it's some kind of collection of objects of type 'Friend' class, and if so you can achieve what you want as long as the 'Friend' class itself is also a viewmodel (i.e. implements INotifyPropertyChanged) and has a property on it called 'Selected'. It's that class that any bindings in your datatemplate will look to as a viewmodel.
Taking the above to be true; what you need is to bind your ListBox's SelectedItem property, e.g.:
<ListBox
x:Name="lbFriendsList"
SelectedItem="{Binding SelectedFriend, Mode=TwoWay}"
...
in your 'friendSelectionViewModel', when an item in the list is selected it will trigger code in the 'SelectedFriend' property's "set" method, where you will have access to the Friend object that has been selected, and you will be able to do whatever you want to it, e.g. to always have it 'checked' when it is tapped, you might have this kind of code in your friendSelectionViewModel (assuming you've got the xaml in place that I've written above):
public Friend SelectedFriend
{
get
{
...
}
set
{
if(value != null)
value.Selected = true;
}
}
As long as you've set up the class Friend as a viewmodel too, and code a 'Selected' property in the Friend class (and as with most properties in viewmodels you set it up to call the typical OnPropertyChanged("Selected "); in its 'set' method) then that will trigger the update of the checkbox that you've set up in the datatemplate (because you've already got that bound to the property 'Selected' in your Xaml).
Hope that's clear and helps
Ian
yes that was the problem, and I missed to implement INotifyPropertyChanged for the TempFriends Class
thanks

[Resolved] [Q][DEV]Android Development Question about Shared Preferences.

Hi, I'm trying to do a simple login with Facebook in my app but I'm having trouble with Shared Preferences.
The idea is to start the app, it opens Activity A, checks if it's logged, and if it isn't, it sends you to activity B, you login and then go back to A.
My problem is that I can't get the SharedPreferences. I can save it, but I can't get it in the other activity.
So, it gets in a loop: A can't get the SP, so thinks it's not logged in, so send you to B, but B is logged on, and sends you to A...
That's my code in B:
Code:
public void onComplete(Bundle values) {
// TODO Auto-generated method stub
Editor edit = fbSP.edit();
edit.putString("access_token", fb.getAccessToken());
edit.putLong("access_expires", fb.getAccessExpires());
edit.commit();
aIMG();
ir();
}
And that's my code in A, where the problem is:
Code:
private SharedPreferences prefs;
public static String TOKEN = null;
public static final String FACEBOOK_DATA = "FacebookStuff";
long EXPIRES = 0;
...
private void SharedP() {
// TODO Auto-generated method stub
prefs = getSharedPreferences(FACEBOOK_DATA, MODE_PRIVATE);
TOKEN = prefs.getString("access_token", null);
EXPIRES = prefs.getLong("access_expires", 0);
if (TOKEN == null && EXPIRES == 0) { //If it's not logged in...
Intent login = new Intent("android.intent.action.FACELOGIN");
startActivity(login);
}
}
Edit: I got it. I was iniciating fbSP with getPreferences, not getSharedPreferences.

Implementing Google Play Application Silent Install Feature On Android

Hi Experts / Expert Hackers,
I'm trying to implement the Google Play application silent install feature (similar to appbrain fast web installer) on android.
So far I was able achieve the following :
1. Find out a method to retrieve the Google Play Auth Token (thus granting permission for my application to talk with Google Play application on the Phone). I've listed the code I've used for this below :
Code:
Log.i(TAG,"Getting the Google Play Auth Token Using Account Manager : START");
AccountManager accountManager = AccountManager.get(getApplicationContext());
Account[] accArr = accountManager.getAccountsByType("com.google");
for (Account acc : accArr) {
Log.i(TAG, "For Account Name : " + acc.name + " - "+ "Account Type : " + acc.type);
accountManager.getAuthToken(acc, "googleplay", null, this,new AccountManagerCallback<Bundle>() {
public void run(
AccountManagerFuture<Bundle> paramAccountManagerFuture) {
try {
Bundle localBundle = (Bundle) paramAccountManagerFuture.getResult();
String authToken = localBundle.get("authtoken") + "";
Log.i(TAG, "Got AuthToken : " + authToken);
} catch (Exception ex) {
StackTraceElement[] starray = ex.getStackTrace();
StringBuffer bf = new StringBuffer();
bf.append("Error : " + ex.getMessage()).append("\n");
for (StackTraceElement ste : starray) {
bf.append(ste.toString()).append("\n");
}
Log.e(TAG, bf.toString());
}
}
}, null);
}
Log.i(TAG,"Getting the Google Play Auth Token Using Account Manager : END");
2. Find out how to Retrieve the Android-Id of the Phone (This Id as I believe should be used when sending the appInstall request to the GPlay Servers or the Gplay/vending application on the android phone)
Code:
Log.i(TAG, "Getting the Android ID Of the Phone : START");
Uri localUri = Uri.parse("content://com.google.android.gsf.gservices");
ContentResolver localContentResolver = getContentResolver();
String[] arrayOfString = new String[1];
arrayOfString[0] = "android_id";
Cursor localCursor = localContentResolver.query(localUri, null,null, arrayOfString, null);
Log.i(TAG, "Column Count : " + localCursor.getColumnCount());
if ((localCursor != null) && (localCursor.moveToFirst())) {
String androidId = Long.toHexString(Long.parseLong(localCursor.getString(1)));
Log.i(TAG, "Received Android ID : " + androidId);
Log.i(TAG,"Other Value in Column : " + localCursor.getString(0));
}
Log.i(TAG,"Getting the Android ID of the Phone : END");
3. Find out the Protocol Buffer Request to be sent to the Google Play servers or the Gplay/vending application on the phone to Initiate the silent application download & install process.
Code:
message InstallRequest {
optional string appId = 1;
}
message RequestContext {
required string authSubToken = 1;
required bool isSecure = 2;
required int32 version = 3;
required string androidId = 4;
optional string deviceAndSdkVersion = 5;
optional string userLanguage = 6;
optional string userCountry = 7;
optional string operatorAlpha = 8;
optional string simOperatorAlpha = 9;
optional string operatorNumeric = 10;
optional string simOperatorNumeric = 11;
}
message Request {
optional RequestContext context = 1;
repeated group RequestGroup = 2 {
optional InstallRequest installRequest = 10;
}
}
4.I even used the protobuf compiler and generated the java class for manipulating the above protocol buffer request and filled the above protocol buffer fields with some sample data. See the code below :
Code:
public void buildAndSendSilentInstallProtoBuffMessage(String gplayAuthToken, String deviceAndroidId){
try{
/*
* The Root Request Object Assumed to be Holding the Silent Install Request
*/
Request.Builder request = Request.newBuilder();
//Populating the ReequestContext Object
RequestContext.Builder context = RequestContext.newBuilder();
context.setAndroidId(deviceAndroidId);
context.setAuthSubToken(gplayAuthToken);
context.setIsSecure(true);
context.setVersion(1002);
context.setDeviceAndSdkVersion("dream:4");
context.setUserLanguage("en");
context.setUserCountry("us");
context.setOperatorAlpha("Android");
context.setOperatorNumeric("310260");
context.setSimOperatorNumeric("310260");
//Building the Install Request
InstallRequest.Builder installRequest = InstallRequest.newBuilder();
installRequest.setAppId("-2564446724934482383");
//Setting the Install Request to the Request Group
RequestGroup.Builder requestGroup = RequestGroup.newBuilder();
requestGroup.setInstallRequest(installRequest);
//Setting the Request Context to the Main Request Object
request.setContext(context);
//Setting the Request Group to the Request Object
request.addRequestGroup(requestGroup);
The Sample Data for GPlay Token and the Android Id are as follows :
1. Android_ID :
3a0f901831a0f402
2. Google Play AuthToken :
DQAAAMgAAACpOyPf6apRbb0i4qhTVaf0yYoikTAb4TYlHCRLrW4mu5f14j-H35KGmO9TQKUDYCfj3-b-QIH5chfXT3bS02Uxljg7vYt4I-kgXLEJwPcynjugDcJ9fYPOh1c2FnOnywFXXxXw6hcqs5sVnJEt5zW2ditoB5VeeXG9Zfodj9dXKobObi50-XnHoGfWi2b64Uf3EHGdQTsDCMzfZrE4mb22fr9LCW1oZG5tkzwS4KhPBHWMN2fO7w-1IZ4UK5LOI80vPBLjxBaavKAXHoVUHSNV
5. I also did some sniffing using my rooted galaxy nexus phone during Gplay application silent install and found only two HTTP GET Requests.
I tried reproducing the those two Http GET requests captured using Shark for root(using my rooted android galaxy nexus phone) and the 1st Request just downloads the Market File itself (which I was able to save to the SD card of the Phone. But then it has to be installed like any unknown sources application) while the second request returns nothing.
The two get requests captured are shown below :
Code:
1. GET REQUEST ONE :
21 0.827240 192.168.135.102 173.194.36.4 HTTP 535 GET /market/download/Download?packageName=com.gau.go.launcherex.theme.appwidget.gopowermaster.futureworld&versionCode=1&token=AOTCm0QRnH3rmypWtCGoAL_SU1BSt311wpyz-_LZTodkUSAlc-f5SrdMiz5WDRDUKMMm6S3plBI9Jbh1tukT1jyCYXLgP4QhVvZvn5JLtZQ&downloadId=-165214892049282883 HTTP/1.1
Which has the following http headers :
Cookie: MarketDA=17214805622679635526\r\n
Host: android.clients.google.com\r\n
Connection: Keep-Alive\r\n
User-Agent: AndroidDownloadManager/4.1.1 (Linux; U; Android 4.1.1; Galaxy Nexus Build/JRO03C)\r\n
2. GET REQUEST TWO :
44 6.595093 192.168.135.102 222.165.163.15 HTTP 608 GET /market/GetBinary/com.gau.go.launcherex.theme.appwidget.gopowermaster.futureworld/1?expire=1346838270&ipbits=0&ip=0.0.0.0&cp=SnpybWlzSFk6OTYzMzg0MTE2NzA1ODEwOTYxMjE&sparams=expire,ipbits,ip,q:,cp&signature=2C0778C4635F6F8AE1DA8479FB08DCB9BC04C2E9.60202D8D4D2FDDA70609A3862A25852F0BAA2766&key=am2 HTTP/1.1
Which has the following http headers :
Cookie: MarketDA=17214805622679635526\r\n
Host: o-o.preferred.slt-cmb2.v12.lscache4.c.android.clients.google.com\r\n
Connection: Keep-Alive\r\n
User-Agent: AndroidDownloadManager/4.1.1 (Linux; U; Android 4.1.1; Galaxy Nexus Build/JRO03C)\r\n
I've been looking into this for about two weeks now but I still couldn't find the following :
1. Whether the AppBrain fast Web Installer uses the protocol buffer to invoke the Gplay (vending application) on the phone or the Gplay servers ?. If so is the above Protocol Buffer Request format correct ??.
2. If the Above Protocol Buffer Request format is correct then to Where in the Phone or Gplay server should I send the Protocol buffer request to to invoke the Silent Application download and installing procedure ?.
I also have a C2DM (now GCM) server and client setup around this task as well. Could anyone point me in the correct direction or give me any clues for solving this ?. Any help is much appreciated .
Seriously No one ???. I thought this forum has some expert hackers . Where are those so called android hackers anyways ??. Please guys I need help on this and it's urgent .
Hello. How you login into google play with token from account manager? Thanks.

How and where my device store fingerprint results and matches with my next attempt ?

MAIN QUESTION IS AT BOTTOM
Where my android devices stores scanned fingerprint data and in what format and how it matches with new scanned.
I also know this: :the scan of fingertip is analysed for certain control points and generates a token which is like a password hash.
It generates hash via this:
Code:
KeyStore mKeyStore;
String KEY_NAME = UUID.randomUUID().toString();
Cipher mCipher;
mKeyStore = KeyStore.getInstance("AndroidKeyStore");
keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
keyGenerator.init(new
KeyGenParameterSpec.Builder(KEY_NAME,
KeyProperties.PURPOSE_ENCRYPT |
KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setUserAuthenticationRequired(true)
.setEncryptionPaddings(
KeyProperties.ENCRYPTION_PADDING_PKCS7)
.build());
keyGenerator.generateKey();
mCipher = Cipher.getInstance(
KeyProperties.KEY_ALGORITHM_AES + "/"
+ KeyProperties.BLOCK_MODE_CBC + "/"
+ KeyProperties.ENCRYPTION_PADDING_PKCS7);
SecretKey key = (SecretKey) mKeyStore.getKey(KEY_NAME, null);
mCipher.init(Cipher.ENCRYPT_MODE, key);
Is editing/extracting or using this hash and storing somewhere else and try to match the newly generated hash with this while storing that security key of android(assuming same for all), is it possible OR ANY OTHERWAY ROUND?
ALSO
Code:
KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
ks.load(null);
KeyStore.Entry entry = ks.getEntry(alias, null);
if (!(entry instanceof PrivateKeyEntry)) {
Log.w(TAG, "Not an instance of a PrivateKeyEntry");
return null;
}
Signature s = Signature.getInstance("SHA256withECDSA");
s.initSign(((PrivateKeyEntry) entry).getPrivateKey());
s.update(data);
byte[] signature = s.sign();
boolean valid = s.verify(signature);
I saw this, but can't say helpful or not

Categories

Resources