안드로이드 빈더훅의 실현
Binder Hook은 현재 App에서 사용하는 시스템 서비스 서비스를 Hook에서 제거할 수 있습니다.Location Manager의 경우 Location Manager를 가져올 때 2단계입니다.첫째, Ibinder 객체 가져오기;둘째, Ibinder 객체는 asInterface()를 통해 Location Manager Service 객체로 전환됩니다.마지막으로 Location Manager를 초기화합니다. 응용 프로그램 층에서 사용하는 것은 모두 Location Manager입니다.Hook의 대략적인 원리는 서비스 관리자가 어떤 Binder를 가져올 때 로컬에 캐시된 Binder가 있으면 프로세스를 뛰어넘어 Binder를 요청하지 않는다는 것이다.Service Manager가 로컬 캐시를 질의할 때 사용자 정의된 Custom Binder 객체를 캐시에 추가하여 프로세스 간에 시스템에 요청하지 않도록 할 수 있습니다.ILocationManagerStub.asInterface 메서드는 사용자 정의된 서비스 객체를 반환합니다.이 안에는 사용자 정의 대상을 사용해야 하는 두 곳이 있다.Hook의 일부 기능만 있고 다른 기능은 보존해야 하기 때문에 동적 에이전트로 사용자 정의 Binder와 사용자 정의 서비스를 만듭니다.
다음 내용을 이해하기 전에 다음과 같은 지식을 알아야 한다.
2. Context에서 시스템 서비스 가져오기 프로세스
Activity 같은 클래스는 시스템 서비스를 가져올 때 getSystem 서비스 (서비스Name) 방법을 호출해서 가져옵니다.
Title: Context Service
Context->SystemServiceRegistry: getSystemService(name)
SystemServiceRegistry->ServiceFetcher: getSystemService(name)
ServiceFetcher->ServiceManager: getService(contetx)
ServiceManager->return: getService(name)
Context의 getSystemService () 방법은 SystemServiceRegistry의 getSystemService () 방법을 호출합니다.SystemServiceRegistry 의 SYSTEM 상수SERVICE_FETCHERS, 이것은 Map입니다.ServiceName과 해당 ServiceFetcher가 저장되어 있습니다.ServiceFetcher는 구체적인 서비스를 만드는 데 사용되는 클래스입니다.ServiceFetcher의 주요 방법은createService() 방법입니다.ServiceFetcher의createService() 방법에서
ServiceManager.getService(name)
방법이 호출되었습니다.Location Manager에 해당하는 ServiceFetcher의 경우 create Service() 메소드 소스는 다음과 같습니다.@Override
public LocationManager createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService("location");
return new LocationManager(ctx, ILocationManager.Stub.asInterface(b));
}
만약 우리가 Location Manager의 getLastKnownLocation () 방법을 수정하려고 한다면 (다음은 모두).우리가 해야 할 일은 서비스 관리자에게getService("location")는 사용자 정의 Binder를 반환합니다.먼저 이 방법의 간소화 후의 원본 코드를 살펴보자.
public static IBinder getService(String name) {
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
return getIServiceManager().getService(name);
}
}
sCache는 시스템에 요청한 Binder를 캐시하는 Map입니다.만약 우리가 이 방법을 우리 자신의 binder로 되돌려야 한다면, sCache에 있는 사용자 정의 Binder를 미리 입력하면 된다.put 전에 사용자 정의 Binder를 만들어야 합니다.이 Binder는 ILocationManager에 의해Stub.asInterface 처리 후 사용자 정의 LocationManager Service를 반환할 수 있습니다.먼저 Binder의 asInterface() 구현을 살펴보겠습니다.
public static android.location.ILocationManager asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof android.location.ILocationManager))) {
return ((android.location.ILocationManager) iin);
}
return new android.location.ILocationManager.Stub.Proxy(obj);
}
query Local Interface () 방법을 사용자 정의 서비스로 되돌려서if 문장 내부를 걷고else를 걷지 않으면 Hook이 성공한 셈입니다.
오류: asInterface (binder) 는 binder를 형식 변환을 한 번 한 것입니다. 실제
XXX service = XXX.Stub.asInterface(binder)
의 반환값은 binder의 출처에 따라 두 가지 상황이 있습니다.3 사용자 지정 서비스 및 Binder 작성
3.1 사용자 지정 서비스 객체
만약 우리가 시스템의 LocationManager가 되돌아오게 하려는 위치 정보가 모두 천안문(116.23, 39.54)에 있다고 가정하자.Location Manager 서비스의 getLastLocation () 방법을 모두 (116.23, 39.54) 로 되돌려야 합니다.시스템의 이 서비스 대상을 직접 가져올 수 없기 때문에, 먼저 시스템의 Location Manager 서비스를 반사적으로 받을 수 있습니다.그런 다음 getLastLocation() 방법을 차단합니다.
package com.zhp.binderhook;
import android.location.Location;
import android.location.LocationManager;
import android.os.IBinder;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* Handler
* @author ZHP
* @since 16/12/25 17:36
*/
public class ServiceHookHandler implements InvocationHandler {
private Object mOriginService;
/**
* @param binder Binder
*/
@SuppressWarnings("unchecked")
public ServiceHookHandler(IBinder binder) {
try {
// Binder , Service ,
// : this.mOriginService = ILocationManager.Stub.asInterface(binder);
Class ILocationManager$Stub = Class.forName("android.location.ILocationManager$Stub");
Method asInterface = ILocationManager$Stub.getDeclaredMethod("asInterface", IBinder.class);
this.mOriginService = asInterface.invoke(null, binder);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
switch(method.getName()) {
case "getLastLocation":
//
Location location = new Location(LocationManager.GPS_PROVIDER);
location.setLongitude(116.23);
location.setLatitude(39.54);
return location;
default:
return method.invoke(this.mOriginService, args);
}
}
}
3.2 사용자 정의 Binder 객체
기본 Binder 객체는query LocalInterface() 메서드를 호출할 때 기본 서비스 객체를 반환합니다.3.1의 사용자 지정 서비스로 돌아가기를 원합니다.그래서 여기서 query Local Interface () 방법을 차단합니다.
package com.zhp.binderhook;
import android.os.IBinder;
import android.os.IInterface;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* Handler, Binder
* @author ZHP
* @since 16/12/25 17:36
*/
public class BinderHookHandler implements InvocationHandler {
private IBinder mOriginBinder;
private Class ILocationManager;
@SuppressWarnings("unchecked")
public BinderHookHandler(IBinder binder) {
this.mOriginBinder = binder;
try {
this.ILocationManager = Class.forName("android.location.ILocationManager");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
switch (method.getName()) {
// Service
case "queryLocalInterface":
ClassLoader classLoader = mOriginBinder.getClass().getClassLoader();
Class[] interfaces = new Class[] {IInterface.class, IBinder.class, ILocationManager};
ServiceHookHandler handler = new ServiceHookHandler(this.mOriginBinder);
return Proxy.newProxyInstance(classLoader, interfaces, handler);
default:
return method.invoke(mOriginBinder, args);
}
}
}
4. 사용자 정의 Binder를 Service Manager에 배치
사용자 정의 Binder가 생기면 서비스 관리자의 sCache 변수에 주입하면 훅이 완성됩니다~
package com.zhp.binderhook;
import android.content.Context;
import android.os.IBinder;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;
/**
* @author ZHP
* @since 16/12/25 17:56
*/
public class HookManager {
@SuppressWarnings("unchecked")
public static boolean hookLocationManager() {
try {
// 1. Binder
Class ServiceManager = Class.forName("android.os.ServiceManager");
Method getService = ServiceManager.getDeclaredMethod("getService", String.class);
IBinder binder = (IBinder) getService.invoke(null, Context.LOCATION_SERVICE);
// 2. Binder
ClassLoader classLoader = binder.getClass().getClassLoader();
Class[] interfaces = {IBinder.class};
BinderHookHandler handler = new BinderHookHandler(binder);
IBinder customBinder = (IBinder) Proxy.newProxyInstance(classLoader, interfaces, handler);
// 3. ServiceManager sCache
Field sCache = ServiceManager.getDeclaredField("sCache");
sCache.setAccessible(true);
Map cache = (Map) sCache.get(null);
// 4. Binder Binder
cache.put(Context.LOCATION_SERVICE, customBinder);
sCache.setAccessible(false);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}
5. 테스트
package com.zhp.binderhook;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Hook
HookManager.hookLocationManager();
}
/**
*
*/
private void requestLocation() {
//
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
Log.i(" ", " ");
Toast.makeText(this, " ", Toast.LENGTH_SHORT).show();
return;
}
//
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
String message = "(" + location.getLongitude() + ", " + location.getLatitude() + ")";
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
Log.i(" ", message);
}
public void onClick(View view) {
this.requestLocation();
}
}
온클릭이 호출될 때 토스트와 로그는 천안문의 좌표(116.23, 39.54)를 표시한다.훅 성공 증명!
Binder Hook으로 Activity Manager를 제거할 수도 있습니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.