“地铁偷拍门事件”真正的加害者隐藏在幕后 她作为一个新闻系的研究生明知对方没有偷拍的事实情况下,伪装成“受害者”的身份,打着“维权”的旗号,刻意制造冲突,利用网友的同情心,引导舆论攻击无辜的农民大叔,在农民大叔和儿子的要求下,该女子一边哭一边道歉,也得到了他们一家人的谅解。真的是被这操作恶心坏了,恶心的我赶紧去应用市场下载了某拍摄软件分析了一波,这些软件才是真正的偷拍!
学习目录 1. 某软件的分析
2. 某软件的复现
1. 某软件的分析 像应用市场上下载的某些app,名义上说着用于什么场景,实际上大都扮演着吞噬用户的个人信息的角色,这些软件就像早期的那些病毒软件,勒索,偷拍,恶意获取用户的个人信息,他们的操作也非常简单,对于安卓的四大组件玩的非常的溜,熟练工净整这些歪门邪道,真是可恶至极。应用市场上找了一款app很简单,看看他是怎么做的,后台可以开启摄像机,屏幕之前可以打游戏还能录别人的。 既然它需要开启摄像头直接搜索getSystemService("camera")或者 cameraManager.openCamera这些api急速定位到他的位置,和开始预想的差不多,就是通通过前台还有后台服务来进行摄像机的隐藏,让其不可见。代码简单看看记录下
private void getRunningServices() { ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE ); mServices = am.getRunningServices(Integer.MAX_VALUE); List<ActivityManager.RunningServiceInfo> list = mServices; if (list != null && !list.isEmpty()) { for (ActivityManager.RunningServiceInfo service : list) { Log.i("RunningServices" , service.service.toString()); Log.i("RunningServices" , "PID: " + service.pid + ", UID: " + service.uid); Log.i("RunningServices" , service.process + ", Foreground: " + service.foreground); } } } public void stackTrace(){ StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); for (StackTraceElement element : stackTrace) { } } String b10; Set physicalCameraIds; d9.m mVar; j0 j0Var; if (this .f18118z.get()) { return ; } this .f18118z.set(true ); synchronized (this .f18100g) { d9.d dVar = this .f18110q; if (dVar != null && (mVar = dVar.f11438a) != null && (j0Var = mVar.J) != null ) { j0Var.f(this .G); } this .A.set(false ); this .f18117y.set(false ); y8.d dVar2 = y8.d.f18541a; y8.d.g(this .f18095b).unregisterAvailabilityCallback(this .D); if (this .f18098e != null ) { return ; } m(); Object systemService = this .f18095b.getSystemService("camera" ); a6.e.i(systemService, "null cannot be cast to non-null type android.hardware.camera2.CameraManager" ); CameraManager cameraManager = (CameraManager) systemService; try { b10 = this .f18094a.b(); } catch (Exception e9) { this .f18096c.postDelayed(new v1.n(3 , this , e9, z10), 1500L); } if (!this .f18101h.tryAcquire(3000L, TimeUnit.MILLISECONDS)) { gb.c.f12939a.d("Camera onError openCamera tryAcquire" , new Object[0 ]); j.i(this , "Tried acquiring timeout" , false , 6 ); this .f18118z.set(false ); a((r12 & 1 ) != 0 ? false : false , (r12 & 2 ) != 0 , (r12 & 4 ) != 0 ? false : false , false , (r12 & 16 ) != 0 ? false : false ); return ; } if (Build.VERSION.SDK_INT >= 28 ) { if (y8.d.f18545e) { List list = y8.d.f18543c; if (list == null ) { list = w9.j.f18148s; } if (!list.contains(b10)) { Iterator it = list.iterator(); while (true ) { if (!it.hasNext()) { break ; } String str = (String) it.next(); physicalCameraIds = y8.d.c(y8.d.f18541a, this .f18095b, str).getPhysicalCameraIds(); if (physicalCameraIds.contains(b10)) { b10 = str; break ; } } } } h0.h hVar = this .f18106m; a6.e.h(hVar); cameraManager.openCamera(b10, hVar, this .N); } else { cameraManager.openCamera(b10, this .N, this .f18105l); } this .F = 0 ; public final boolean A(CaptureRequest.Builder builder, CaptureRequest.Builder builder2, boolean z10) { boolean z11; CaptureRequest.Key key; Integer num; Integer num2; b9.e eVar = this .f18094a; int s10 = eVar.s(z10); Integer num3 = (Integer) builder.get(CaptureRequest.CONTROL_AF_MODE); if (num3 == null || s10 != num3.intValue()) { builder.set(CaptureRequest.CONTROL_AF_MODE, Integer.valueOf(s10)); if (builder2 != null ) { builder2.set(CaptureRequest.CONTROL_AF_MODE, Integer.valueOf(s10)); } z11 = true ; } else { z11 = false ; } if (s10 != 0 ) { if (s10 == 1 && ((num2 = (Integer) builder.get(CaptureRequest.CONTROL_AF_TRIGGER)) == null || 1 != num2.intValue())) { builder.set(CaptureRequest.CONTROL_AF_TRIGGER, 1 ); if (builder2 == null ) { return true ; } key = CaptureRequest.CONTROL_AF_TRIGGER; num = 1 ; builder2.set(key, num); return true ; } return z11; } Float f10 = (Float) y8.d.c(y8.d.f18541a, this .f18095b, eVar.b()).get(CameraCharacteristics.LENS_INFO_HYPERFOCAL_DISTANCE); if (f10 != 0 && !a6.e.d(f10, (Float) builder.get(CaptureRequest.LENS_FOCUS_DISTANCE))) { builder.set(CaptureRequest.LENS_FOCUS_DISTANCE, f10); if (builder2 == null ) { return true ; } key = CaptureRequest.LENS_FOCUS_DISTANCE; num = f10; builder2.set(key, num); return true ; } return z11; }
2.复现 创建前台服务或者后台服务,来防止app划到后台被系统kill掉,通过点击按钮打开摄像机,将保存的视频存在本地。
创建服务 public class VideoRecorderService extends Service { private static final String TAG = "VideoRecorderService" ; private static final String CHANNEL_ID = "VideoRecorderServiceServiceChannel" ; private static final int NOTIFICATION_ID = 1 ; private CameraDevice mCameraDevice; private MediaRecorder mMediaRecorder; private CameraCaptureSession mCaptureSession; private HandlerThread mBackgroundThread; private Handler mBackgroundHandler; @Nullable @Override public IBinder onBind(Intent intent) { Log.e("yyff" , "onBind" ); return null ; } @Override public void onCreate() { super .onCreate(); startBackgroundThread(); Log.e("yyff" , "onCreate" ); // 创建通知 createNotificationChannel(); Notification notification = new NotificationCompat.Builder(this , CHANNEL_ID ) .setContentTitle("Background Video Recorder" ) .setContentText("Recording video in the background" ) .setSmallIcon(R.mipmap.ic_launcher) .build(); // 开启前台服务 startForeground(NOTIFICATION_ID , notification); } @Override public int onStartCommand(Intent intent, int flags, int startId) { startRecording(); Log.e("yyff" , "onStartCommand" ); return START_NOT_STICKY ; } @Override public void onDestroy() { stopRecording(); stopBackgroundThread(); super .onDestroy(); } private void startBackgroundThread() { mBackgroundThread = new HandlerThread("BackgroundVideoRecorderThread" ); mBackgroundThread.start(); mBackgroundHandler = new Handler(mBackgroundThread.getLooper()); } private void stopBackgroundThread() { mBackgroundThread.quitSafely(); try { mBackgroundThread.join(); mBackgroundThread = null ; mBackgroundHandler = null ; } catch (InterruptedException e) { e.printStackTrace(); } }
打开相机开始录制并将录制的视频保存在本地 private void startRecording() { CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); if (cameraManager == null ) { return ; } Log.e("yyff" , "startRecording" ); String cameraId = null ; try { for (String id : cameraManager.getCameraIdList()) { CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(id); Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING); if (facing != null && facing == CameraCharacteristics.LENS_FACING_BACK) { cameraId = id; break ; } } if (cameraId == null ) { return ; } CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId); StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); Size[] videoSizes = map.getOutputSizes(MediaRecorder.class); Size videoSize = videoSizes[0 ]; // 设置 MediaRecorder mMediaRecorder = new MediaRecorder(); mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); mMediaRecorder.setVideoSize(videoSize.getWidth(), videoSize.getHeight()); mMediaRecorder.setVideoEncodingBitRate(5000000 ); mMediaRecorder.setVideoFrameRate(30 ); File outputFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES), "background_video.mp4" ); mMediaRecorder.setOutputFile(outputFile.getAbsolutePath()); mMediaRecorder.prepare(); // 打开相机 if (ActivityCompat.checkSelfPermission(this , Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { return ; } cameraManager.openCamera(cameraId, new CameraDevice.StateCallback() { @Override public void onOpened(@NonNull CameraDevice cameraDevice) { mCameraDevice = cameraDevice; Log.e("yyff" , "onOpened" ); startCameraCaptureSession(); } @Override public void onDisconnected(@NonNull CameraDevice cameraDevice) { Log.e("yyff" , "onDisconnected" ); cameraDevice.close(); } @Override public void onError(@NonNull CameraDevice cameraDevice, int error) { cameraDevice.close(); } }, mBackgroundHandler); } catch (CameraAccessException | IOException e) { e.printStackTrace(); }
启动MediaRecorder来进行录制并设置了相机的参数为自动对焦以持续捕捉预览数据 private void startCameraCaptureSession() { try { Surface recorderSurface = mMediaRecorder.getSurface(); final CaptureRequest.Builder requestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD); requestBuilder.addTarget(recorderSurface); mCameraDevice.createCaptureSession(Arrays.asList(recorderSurface), new CameraCaptureSession.StateCallback() { @Override public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) { mCaptureSession = cameraCaptureSession; try { requestBuilder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO); mCaptureSession.setRepeatingRequest(requestBuilder.build(), null , mBackgroundHandler); mMediaRecorder.start(); } catch (CameraAccessException e) { e.printStackTrace(); } } @Override public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) { } }, mBackgroundHandler); } catch (CameraAccessException e) { e.printStackTrace(); } }
进行了还原和拼凑,一个后台运行的app诞生了。经过测试确实是可以后台运行还可以录像,以上代码仅供学习参考,未经过他人允许,偷窥、偷拍、窃听、散布他人隐私的,处五日以下拘留或者五百元以下罚款;情节较重的,处五日以上十日以下拘留,可以并处五百元以下罚款。
在拍摄过程中,未经他人允许,不能把路人的具体模样拍到视频里。如果必须要出镜,在未征得他人同意的情况下,要将被拍摄者可识别的标记去掉,如脸部及其他标志化信息。同时要注意不能跟拍、偷拍、尾随别人去拍摄,这涉嫌侵犯他人隐私权和生活安宁权。
我的公众号二维码 喜欢的可以关注下 不定期分享干货 安卓和ios逆向 移动安全 以及二进制算法还原
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2023-6-16 11:15
被涿州飞神编辑
,原因: 增加公众号二维码