西湖论剑-Openwrt启动流程

badmonkey 2023年04月14日 144次浏览

西湖论剑-Openwrt启动流程

前言

因为西湖这块板子,采用的是openwrt系统,此外很多的国产智能设备都是采用的openwrt系统,为了快速的定位到西湖这块板子上所使用的服务(仅通过分析文件系统),并对服务进行漏洞挖掘,有很必要了解一下openwrt的启动流程,至于为什么写这篇文章,一是因为网上的分析文章分析的都是老版本的openwrt和目前的版本有所不同,二是文章过多过杂看起来有些头皮发麻,于是简单梳理一下。

老版本

老版本的话,可以看这个分析,新版本openwrt开始使用procd作为守护进程(具体从什么版本开始没有研究)。

OpenWrt/OpenWrt系统启动流程分析.md at master · peiyake/OpenWrt

因为采用了procd作为1号进程,启动时所依赖的文件也有所变化

新版本

新版的openwrt使用procd,procd是一个进程管理的程序,还可以通过ubus总线调用。可以在github上找到对应的代码

https://github.com/openwrt/procd

和老版本类似,首先是通过 uboot 调用kernel,然后执行/sbin/init 这里的/sbin/init 应该是procd编译出来的程序,可以结合源码逆向分析得出。在/sbin/init里面会先执行 /etc/preinit然后再执行/sbin/procd,将一号进程转接给procd

Untitled

老版本中是通过/sbin/init 对/etc/inittab进行解析,然后通过/etc/init.d/rcS脚本对/etc/rc.d/^S的文件进行执行。但是在新版本的openwrt中笔者并没有发现rcS文件的存在,于是翻看了procd的源码,经过分析,得出一下结论。procd对/etc/inittab进行解析,省去了rcS脚本,直接对/etc/rc.d/^S的脚本进行执行。

# inittab例子
# ::sysinit:/etc/init.d/rcS S boot
# ::shutdown:/etc/init.d/rcS K shutdown
# ::askconsole:/usr/libexec/login.sh
# 根据注册的名字调用callback方法
void procd_inittab_run(const char *handler)
{
	struct init_action *a;

	list_for_each_entry(a, &actions, list)
		if (!strcmp(a->handler->name, handler)) {
			a->handler->cb(a);
			if (!a->handler->multi)
				break;
		}
}

而这里的cb(回调函数),定义在结构体中,可以看到sysinit,shutdown都对应着runrc函数

Untitled

runrc则会解析具体的参数,然后调用rcS函数(而不是脚本)

Untitled

rcS的作用则是将/etc/rc.d/^S下的脚本添加到任务中,然后一一执行。

总的流程为

/sbin/init -> /etc/preinit -> /sbin/procd -> /etc/inittab -> /etc/rc.d/^S

其中前三步基本上没有什么可以变动的,添加新的服务也是通过 /etc/inittab 和 /etc/rc.d/^S 实现的,因此想要快速的了解目标设备部署了那些服务,可以首先分析 /etc/inittab文件和/etc/rc.d/^S 文件

总结

其实不论是老版本的openwrt还是新版本的openwrt都可以直接定位/etc/inittab和/etc/rc.d/^S 进行分析openwrt的服务。但是这里的procd能够通过ubus进行控制管理,还有待深入研究procd还能够怎么玩。

参考链接

OpenWRT procd启动过程

Preinit and Root Mount and Firstboot Scripts