如何使用反射访问安全元素

Posted

技术标签:

【中文标题】如何使用反射访问安全元素【英文标题】:How to use reflection to access secure element 【发布时间】:2014-04-26 00:10:28 【问题描述】:

我正在尝试将以下代码块添加到现有类中

Class nfcExtrasClazz = Class.forName("com.android.nfc_extras.NfcAdapterExtras");
Method getMethod = nfcExtrasClazz .getMethod("get", Class.forName("android.nfc.NfcAdapter"));
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(this);
Object nfcExtras = getMethod .invoke(nfcExtrasClazz, adapter);
Method getEEMethod = nfcExtras.getClass().getMethod("getEmbeddedExecutionEnvironment", (Class[]) null);
Object ee = getEEMethod.invoke(nfcExtras , (Object[]) null);
Class eeClazz = se.getClass();
Method openMethod = eeClazz.getMethod("open", (Class[]) null);
Method transceiveMethod = ee.getClass().getMethod("transceive",new Class[]  byte[].class );
Method closeMethod = eeClazz.getMethod("close", (Class[]) null);
openMethod.invoke(se, (Object[]) null);
Object response = transceiveMethod.invoke(se, command);
closeMethod.invoke(se, (Object[]) null);

我意识到我需要将此代码放在另一个线程中。所以我得到了一个现有的本地服务实现,并尝试将上面的代码添加到它。但在服务实现代码中,我收到以下错误:“NfcAdapter 类型中的方法 getDefaultAdapter(Context) 不适用于参数 (BackgroundService.ServiceWorker)" 包中有两个类;一个是主要的: 公共类 MainActivity 扩展 Activity 私有静态最终字符串 TAG = "MainActivity"; 私人 int 计数器 = 1; 私有 NfcAdapter 适配器;

        @Override
        public void onCreate(Bundle savedInstanceState)
        
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
        

        public void doClick(View view) 
            switch(view.getId()) 
            case R.id.startBtn:
                Log.v(TAG, "Starting service... counter = " + counter);
                adapter = NfcAdapter.getDefaultAdapter(this);
                Intent intent = new Intent(MainActivity.this,
                    BackgroundService.class);
            intent.putExtra("counter", counter++);
            startService(intent);
            break;
        case R.id.stopBtn:
            stopService();
        
    

    private void stopService() 
        Log.v(TAG, "Stopping service...");
        if(stopService(new Intent(MainActivity.this,
                    BackgroundService.class)))
            Log.v(TAG, "stopService was successful");
        else
            Log.v(TAG, "stopService was unsuccessful");
    

    @Override
    public void onDestroy()
    
        stopService();
        super.onDestroy();
    

这是实现本地服务的类: 公共类 BackgroundService 扩展服务 私人静态最终字符串标签=“后台服务”; 私人 NotificationManager 通知管理器; 私有 NfcAdapter 适配器; private ThreadGroup myThreads = new ThreadGroup("ServiceWorker");

    @Override
    public void onCreate() 
        super.onCreate();

        Log.v(TAG, "in onCreate()");
        notificationMgr =(NotificationManager)getSystemService(
               NOTIFICATION_SERVICE);
        displayNotificationMessage("Background Service is running");
    

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) 
        super.onStartCommand(intent, flags, startId);
        int counter = intent.getExtras().getInt("counter");
        Log.v(TAG, "in onStartCommand(), counter = " + counter +
                ", startId = " + startId);

        new Thread(myThreads, new ServiceWorker(counter), "BackgroundService")
            .start();

        return START_NOT_STICKY;
    

    class ServiceWorker implements Runnable
    
        private int counter = -1;
        public ServiceWorker(int counter) 
            this.counter = counter;
        

        public void run() 
            final String TAG2 = "ServiceWorker:" + Thread.currentThread().getId();
            // do background processing here...
            try 
                Log.v(TAG2, "sleeping for 10 seconds. counter = " + counter);
                Thread.sleep(10000);
                // I added the following code; I temprarily commented all of lines out
                //NfcAdapterExtras adapterExtras = NfcAdapterExtras.get(NfcAdapter.getDefaultAdapter(this));
                //NfcExecutionEnvironment nfceEe = adapterExtras.getEmbeddedExecutionEnvironment();
                Class nfcExtrasClazz = null;
                try 
                    nfcExtrasClazz = Class.forName("com.android.nfc_extras.NfcAdapterExtras");
                 catch (ClassNotFoundException e) 
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                
                Method getMethod = null;
                try 
                    getMethod = nfcExtrasClazz .getMethod("get", Class.forName("android.nfc.NfcAdapter"));
                 catch (NoSuchMethodException e) 
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                 catch (ClassNotFoundException e) 
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                
                adapter = NfcAdapter.getDefaultAdapter(this);
                Object nfcExtras = null;
                try 
                    nfcExtras = getMethod .invoke(nfcExtrasClazz, adapter);
                 catch (IllegalAccessException e) 
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                 catch (IllegalArgumentException e) 
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                 catch (InvocationTargetException e) 
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                

                Method getEEMethod = null;
                try 
                    getEEMethod = nfcExtras.getClass().getMethod("getEmbeddedExecutionEnvironment", 
                                      (Class[]) null);
                 catch (NoSuchMethodException e) 
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                
                Object ee = null;
                try 
                    ee = getEEMethod.invoke(nfcExtras , (Object[]) null);
                 catch (IllegalAccessException e) 
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                 catch (IllegalArgumentException e) 
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                 catch (InvocationTargetException e) 
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                
                Class eeClazz = ee.getClass();
                Method openMethod = null;
                try 
                    openMethod = eeClazz.getMethod("open", (Class[]) null);
                 catch (NoSuchMethodException e) 
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                
                Method transceiveMethod = null;
                try 
                    transceiveMethod = ee.getClass().getMethod("transceive",
                                        new Class[]  byte[].class );
                 catch (NoSuchMethodException e) 
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                
                Method closeMethod = null;
                try 
                    closeMethod = eeClazz.getMethod("close", (Class[]) null);
                 catch (NoSuchMethodException e) 
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                

                try 
                    openMethod.invoke(ee, (Object[]) null);
                 catch (IllegalAccessException e) 
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                 catch (IllegalArgumentException e) 
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                 catch (InvocationTargetException e) 
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                
                String command = "00000000";
                try 
                    Object myresponse = transceiveMethod.invoke(ee, command );
                 catch (IllegalAccessException e) 
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                 catch (IllegalArgumentException e) 
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                 catch (InvocationTargetException e) 
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                
                try 
                    closeMethod.invoke(ee, (Object[]) null);
                 catch (IllegalAccessException e) 
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                 catch (IllegalArgumentException e) 
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                 catch (InvocationTargetException e) 
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                
                Log.v(TAG2, "... waking up");
             catch (InterruptedException e) 
                // TODO Auto-generated catch block
                Log.v(TAG2, "... sleep interrupted");
            
        
    

    @Override
    public void onDestroy()
    
        Log.v(TAG, "in onDestroy(). Interrupting threads and cancelling notifications");
        myThreads.interrupt();
        notificationMgr.cancelAll();
        super.onDestroy();
    

    @Override
    public IBinder onBind(Intent intent) 
        Log.v(TAG, "in onBind()");
        return null;
    

    private void displayNotificationMessage(String message)
    
        Notification notification = new Notification(R.drawable.emo_im_winking, 
                message, System.currentTimeMillis());

        notification.flags = Notification.FLAG_NO_CLEAR;

        PendingIntent contentIntent = 
                PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0);

        notification.setLatestEventInfo(this, TAG, message, contentIntent);

        notificationMgr.notify(0, notification);
    

我想我可能没有将主要活动中的 nfcadapter 实例添加到服务中?有人可以看看吗?

【问题讨论】:

openMethod.invoke(se, (Object[]) null);您可能错过了初始化 se 的行。 @BarışcanKayaoğlu;感谢您的快速回复。它代表安全元件。我不太了解反射,无法知道 Nik 在做什么。我希望我做到了。 好吧,因为它是一个变量名并且没有初始化,所以它实际上不需要任何含义。检查我的答案。 【参考方案1】:

看链接,把你的se换成ee,打错了。

【讨论】:

这里可以看得很清楚,Class eeClazz = se.getClass(); eeClazz 必须用 ee.getClass(); 初始化; openMethodcloseMethod之后..里面还有其他se【参考方案2】:

se 从未使用此代码创建,因此无法解析为对象。

我们第一次看到se是在通话中

Class eeClazz = se.getClass();

这大概就是你得到错误的地方。

【讨论】:

非常感谢您的帮助。我必须在代码中添加一些 try/catch 块,并定义其中一个变量。代码现在编译。但我无法让它运行。我应该用当前代码更新这个线程,或者添加日志还是应该打开另一个线程?我查看了日志,并没有发现任何可能的问题。我也在网上查找了一些可能的问题,但它们与其他包有关。 只是对我之前帖子的更新:当前问题似乎与此日志消息有关:在 libnativehelper.so 0x0 中找不到 JNI_OnLoad,跳过初始化。我想知道我是否应该尝试将它作为同一线程的一部分进行讨论,或者打开另一个线程,因为它似乎是一个不同的问题。我还找到了其他线程,可能会解决这个问题。 No JNI_OnLoad found in libnativehelper.so 0x0, skipping init. 只是警告您没有在 .so 文件中实现 JNI_OnLoad。这不是什么大问题。 是的,与 /data/local/tmp 文件夹关联的权限存在问题。我改变了它们,我走得更远了。该应用程序仍然无法运行。您能看看我在原始帖子中放置的日志,看看您能否指出正确的方向吗? 我认为我必须将该代码用于反映在服务中?我的理解是,如果 main 中有太多代码,它会崩溃。但我的甚至没有加载!

以上是关于如何使用反射访问安全元素的主要内容,如果未能解决你的问题,请参考以下文章

提高反射效率

如何使用 TypeScript 以类型安全的方式访问 React 子元素道具?

如何使用反射访问内部类

使用带反射的安全管理器访问 jar 文件

如何限制开发人员使用反射访问Java中的私有方法和构造函数?

如何使用反射访问对象中的字段值