当我们拿到系统rom以后,就可以开始尝试挖掘系统漏洞了。系统应用分两种:一种是系统native服务,一种是系统app。本文我们介绍普通应用如何触达系统native服务。
系统服务框架
分析攻击面,先需要了解系统服务的一些基础概念以及执行入口。SystemAbility实现一般采用XXX.cfg + profile.json + libXXX.z.so的方式由init进程执行对应的XXX.cfg文件拉起相关SystemAbility进程。在/system/etc/init目录下可以看到很多自启动运行或者按需拉起的服务的cfg文件
定义IPC对外接口IXXX
定义该服务对外提供的能力集合函数,统一继承IPC接口类IRemoteBroker;同时实现该IPC对外接口唯一标识符DECLARE_INTERFACE_DESCRIPTOR(XXX);该标识符用于IPC通信的校验等目的。
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line
namespace OHOS {
classIListenAbility : public IRemoteBroker {
public:
virtual int AddVolume(int volume) = 0;
public:
enum {
ADD_VOLUME = 1,
};
public:
DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.test.IListenAbility");
}};
定义客户端通信代码XXXProxy
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line
namespaceOHOS {
classListenAbilityProxy : publicIRemoteProxy<IListenAbility> {
public:
intAddVolume(int volume);
explicitListenAbilityProxy(const sptr<IRemoteObject>& impl)
: IRemoteProxy<IListenAbility>(impl)
{
}
private:
static inline BrokerDelegator<ListenAbilityProxy> delegator_;
};
} // namespace OHOS
定义服务端通信代码XXXStub
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line
namespace OHOS {
int32_t ListenAbilityStub::OnRemoteRequest(uint32_t code,
MessageParcel& data, MessageParcel &reply, MessageOption &option)
{
switch (code) {
case ADD_VOLUME: {
return reply.WriteInt32(AddVolume(data.ReadInt32()));
}
default:
return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
}
}
}
留意此处的==OnRemoteRequest==函数,这是后续分析任意sa的关键特征。
SystemAbility的实现类
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line
namespace {
constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0xD001800, "SA_TST"};
}
REGISTER_SYSTEM_ABILITY_BY_ID(ListenAbility, DISTRIBUTED_SCHED_TEST_LISTEN_ID, true);
ListenAbility::ListenAbility(int32_t saId, bool runOnCreate) : SystemAbility(saId, runOnCreate)
{
HiLog::Info(LABEL, ":%s called", __func__);
HiLog::Info(LABEL, "ListenAbility()");
}
ListenAbility::~ListenAbility()
{
HiLog::Info(LABEL, "~ListenAbility()");
}
intListenAbility::AddVolume(int volume)
{
pid_t current = getpid();
HiLog::Info(LABEL, "ListenAbility::AddVolume volume = %d, pid = %d.", volume, current);
return (volume + 1);
}
voidListenAbility::OnDump()
{
}
voidListenAbility::OnStart()
{
HiLog::Info(LABEL, "ListenAbility::OnStart()");
HiLog::Info(LABEL, "ListenAbility:%s called:-----Publish------", __func__);
bool res = Publish(this);
if (res) {
HiLog::Error(LABEL, "ListenAbility: res == false");
}
HiLog::Info(LABEL, "ListenAbility:%s called:AddAbilityListener_OS_TST----beg-----", __func__);
AddSystemAbilityListener(DISTRIBUTED_SCHED_TEST_OS_ID);
HiLog::Info(LABEL, "ListenAbility:%s called:AddAbilityListener_OS_TST----end-----", __func__);
HiLog::Info(LABEL, "ListenAbility:%s called:StopAbility_OS_TST----beg-----", __func__);
StopAbility(DISTRIBUTED_SCHED_TEST_OS_ID);
HiLog::Info(LABEL, "ListenAbility:%s called:StopAbility_OS_TST----end-----", __func__);
return;
}
voidListenAbility::OnStop()
{
}
实战之服务端
这一节我们以真实设备上的系统服务clouddevelopproxy为例,实现如何从app到sa的路径触达。
该服务对应的cfg文件路径在/system/etc/init
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line
{
"jobs" : [
{
"name" : "services:cloud_develop_proxy",
"cmds" : [
"mkdir /data/service/el1/public/cloud_develop_proxy/ 0750 cloud_develop_proxy cloud_develop_proxy",
"mkdir /data/service/el1/public/cloud_develop_proxy/cache/ 0750 cloud_develop_proxy cloud_develop_proxy"
]
}
],
"services" : [
{
"name" : "clouddevelopproxy",
"path" : ["/system/bin/sa_main", "/system/profile/clouddevelopproxy.json"],
"uid" : "cloud_develop_proxy",
"gid" : ["cloud_develop_proxy", "netsys_socket"],
"secon" : "u:r:cloud_develop_proxy:s0",
"permission" : [
"ohos.permission.INTERNET",
"ohos.permission.GET_BUNDLE_INFO_PRIVILEGED"
],
"jobs" : {
"on-start" : "services:cloud_develop_proxy"
},
"ondemand": true
}
]
}
根据第一节的描述,一个sa由XXX.cfg + profile.json + libXXX.z.so三部分组成。在该配置文件的services.path可以看到/system/profile/clouddevelopproxy.json。
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line
{
"process": "clouddevelopproxy",
"systemability": [
{
"name": 66000,
"libpath": "libclouddevelopproxy_service.z.so",
"run-on-create": false,
"auto-restart": true,
"distributed": false,
"dump-level": 1,
"start-on-demand": {
"commonevent": [
{
"name": "usual.event.PACKAGE_INSTALLATION_STARTED"
}
]
}
}
]
}
这样我们就找到了clouddevelopproxy服务的实现代码libclouddevelopproxy_service.z.so。
此时参考前面systemability实现类的demo代码,OnStart
,OnStop
, 不难在逆向代码中找到相同的函数。以及stub的OnRemoteRequest
整体流程如下:
实战之客户端
libclouddevelopproxy_client.so
clouddevelop sa有三个函数可供调用,但是现在还停留在native层,还需要找到sdk实现和接口才能在app中调用。
根据前面分析CloudDevelopProxyServiceClient是供client调用的类。基于该特征在system/lib64/module目录下搜索
ounter(lineounter(lineounter(line
./hms/core/devicecloudgateway/libclouddatabase_napi.z.so
./hms/core/devicecloudgateway/libcloudfunction_napi.z.so
./hms/core/devicecloudgateway/libcloudstorage_napi.z.so
libcloudstorage_napi.z.so
在继续介绍前,先介绍下NAPI
NAPI简介NAPI(Native API)组件是一套对外接口基于Node.js N-API规范开发的原生模块扩展开发框架
在HarmonyOS中,C API中的N-API接口可以实现ArkTS/TS/JS与C/C++之间的交互。N-API提供的接口名与三方Node.js一致,目前支持部分接口。
cloudStorage定义了一个函数getDomain, getDomain的实现是CloudDevelopProxy::Storage::GetDomain
cloudStorage.getDomain()
因为不同的鸿蒙系统版本api都存在差异,如遇到和自己分析的rom镜像文件内容不一致,属于正常情况。以上过程仅供参考。
原文始发于微信公众号(大山子雪人):鸿蒙系统服务攻击面分析
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论