逆向学习法无源码通过两个源码比较研究路由器2天搞定ngrok离线插件开发
简书链接:逆向学习法无源码通过两个源码比较研究路由器2天搞定ngrok离线插件开发
文章字数:2515,阅读全文大约需要10分钟
首先,我没有多少linux,基础,对路由器 linux底层还是缺少系统的理解的,那么我这种程序员初次玩这个路由器系统是怎么个学习法呢?
对linux shell这些的脚本也不是很了解,
作为插件开发,如果你是设计者,设计一个插件 提供一个网页,网页点击后是不是应该交互调用具体的真实shell命令,
我虽然没有开发过路由器脚本,但是我对安卓的xposed插件,以及架构 机器人js插件大概有一定的了解,当js脚本里面执行原生代码我这边会hook执行具体的逻辑,那么 我想这大概也是一样的.
官方所有源码下载地址
https://codeload.github.com/koolshare/armsoft/zip/refs/heads/master
离线安装需要taz包,window可以用7z打包成tar,然而再次打包gzip.就可以了.
定位里面两个插件的源码,发现里面的规范写法 区别,就是从模板代码里面修改install_now()
前者是开发一个内网穿透的工具 后者只是一个小公举,所以前者通常会启动一个进程,以此卸载的时候也需要killall
进程
l另外里面的文件目录存放结构大概得出一下结论
基本上也是按模块名来起名的.
网页 配置文件会放在固定的文件夹下,
从这文件看,大概就是知道请求路由器自身的域名/_api 发送postData从而执行对应脚本,.
也就是说在_api这个服务器会执行一些固定的执行脚本操作.
初次尝试
模拟真实请求
设置Cookie和user-agent
结果
最后我做了一个修改版的ngrok 内网映射插件但是上传后提示插件里面找不到web文件夹,于是只能根据源码进行分析了
根据抓包分析得出文件名,然后linux查找文件 ,
通过比对两个插件的源码,知道大概应该改什么?
之后拷贝一份frp ,因为frp 和,ngrok,内网穿透程序相似,
大概把里面的结构改一下
比对发现其实大部分内容是高度一致的,只有部分不一样.
大概熟悉了下后
拷贝一份frp
至于里面怎么打包的结构,
需要抓包分析,
根据错误提示查找定位到文件
路由器 使用 sftp,或者ssh 拷贝下来,
怎么找到文件呢?
linux命令ls find -name "*.asp"
额,这个上面图片已经展示过了
根据提示分析为啥错了,之前我是没看懂linux命令
这句话反人类-a
,虽然我熟悉很多种语言开发,但是从没看到这么写的, 这么简单的一个字-a
没有学过就不懂了
后面查阅才知道
1 | ```-o```等于```||``` |
#!/bin/sh
source /koolshare/scripts/base.sh
alias echo_date=’echo 【$(TZ=UTC-8 date -R +%Y年%m月%d日\ %X)】:’
MODEL=
UI_TYPE=ASUSWRT
FW_TYPE_CODE=
FW_TYPE_NAME=
DIR=$(cd $(dirname $0); pwd)
module=${DIR##*/}
get_model(){
local ODMPID=$(nvram get odmpid)
local PRODUCTID=$(nvram get productid)
if [ -n “${ODMPID}” ];then
MODEL=”${ODMPID}”
else
MODEL=”${PRODUCTID}”
fi
}
get_fw_type() {
local KS_TAG=$(nvram get extendno|grep koolshare)
if [ -d “/koolshare” ];then
if [ -n “${KS_TAG}” ];then
FW_TYPE_CODE=”2”
FW_TYPE_NAME=”koolshare官改固件”
else
FW_TYPE_CODE=”4”
FW_TYPE_NAME=”koolshare梅林改版固件”
fi
else
if [ “$(uname -o|grep Merlin)” ];then
FW_TYPE_CODE=”3”
FW_TYPE_NAME=”梅林原版固件”
else
FW_TYPE_CODE=”1”
FW_TYPE_NAME=”华硕官方固件”
fi
fi
}
platform_test(){
local LINUX_VER=$(uname -r|awk -F”.” ‘{print $1$2}’)
if [ -d “/koolshare” -a -f “/usr/bin/skipd” -a “${LINUX_VER}” -eq “26” ];then
echo_date 机型:”${MODEL} ${FW_TYPE_NAME} 符合安装要求,开始安装插件!”
else
exit_install 1
fi
}
get_ui_type(){
# default value
[ “${MODEL}” == “RT-AC86U” ] && local ROG_RTAC86U=0
[ “${MODEL}” == “GT-AC2900” ] && local ROG_GTAC2900=1
[ “${MODEL}” == “GT-AC5300” ] && local ROG_GTAC5300=1
[ “${MODEL}” == “GT-AX11000” ] && local ROG_GTAX11000=1
[ “${MODEL}” == “GT-AXE11000” ] && local ROG_GTAXE11000=1
local KS_TAG=$(nvram get extendno|grep koolshare)
local EXT_NU=$(nvram get extendno)
local EXT_NU=$(echo ${EXT_NU%_*} | grep -Eo “^[0-9]{1,10}$”)
local BUILDNO=$(nvram get buildno)
[ -z “${EXT_NU}” ] && EXT_NU=”0”
# RT-AC86U
if [ -n “${KS_TAG}” -a “${MODEL}” == “RT-AC86U” -a “${EXT_NU}” -lt “81918” -a “${BUILDNO}” != “386” ];then
# RT-AC86U的官改固件,在384_81918之前的固件都是ROG皮肤,384_81918及其以后的固件(包括386)为ASUSWRT皮肤
ROG_RTAC86U=1
fi
# GT-AC2900
if [ “${MODEL}” == “GT-AC2900” ] && [ “${FW_TYPE_CODE}” == “3” -o “${FW_TYPE_CODE}” == “4” ];then
# GT-AC2900从386.1开始已经支持梅林固件,其UI是ASUSWRT
ROG_GTAC2900=0
fi
# GT-AX11000
if [ “${MODEL}” == “GT-AX11000” -o “${MODEL}” == “GT-AX11000_BO4” ] && [ “${FW_TYPE_CODE}” == “3” -o “${FW_TYPE_CODE}” == “4” ];then
# GT-AX11000从386.2开始已经支持梅林固件,其UI是ASUSWRT
ROG_GTAX11000=0
fi
# ROG UI
if [ “${ROG_GTAC5300}” == “1” -o “${ROG_RTAC86U}” == “1” -o “${ROG_GTAC2900}” == “1” -o “${ROG_GTAX11000}” == “1” -o “${ROG_GTAXE11000}” == “1” ];then
# GT-AC5300、RT-AC86U部分版本、GT-AC2900部分版本、GT-AX11000部分版本、GT-AXE11000全部版本,骚红皮肤
UI_TYPE=”ROG”
fi
# TUF UI
if [ “${MODEL}” == “TUF-AX3000” ];then
# 官改固件,橙色皮肤
UI_TYPE=”TUF”
fi
}
exit_install(){
local state=$1
case $state in
1)
echo_date “本插件适用于【koolshare merlin armv7l 384/386】固件平台!”
echo_date “你的固件平台不能安装!!!”
echo_date “本插件支持机型/平台:https://github.com/koolshare/armsoft#armsoft"
echo_date “退出安装!”
rm -rf /tmp/${module}* >/dev/null 2>&1
exit 1
;;
0|)
rm -rf /tmp/${module} >/dev/null 2>&1
exit 0
;;
esac
}
install_ui(){
# intall different UI
get_ui_type
if [ “${UI_TYPE}” == “ROG” ];then
echo_date “安装ROG皮肤!”
sed -i ‘/asuscss/d’ /koolshare/webs/Module_${module}.asp >/dev/null 2>&1
fi
if [ “${UI_TYPE}” == “TUF” ];then
echo_date “安装TUF皮肤!”
sed -i ‘/asuscss/d’ /koolshare/webs/Module_${module}.asp >/dev/null 2>&1
sed -i ‘s/3e030d/3e2902/g;s/91071f/92650F/g;s/680516/D0982C/g;s/cf0a2c/c58813/g;s/700618/74500b/g;s/530412/92650F/g’ /koolshare/webs/Module_${module}.asp >/dev/null 2>&1
fi
if [ “${UI_TYPE}” == “ASUSWRT” ];then
echo_date “安装ASUSWRT皮肤!”
sed -i ‘/rogcss/d’ /koolshare/webs/Module_${module}.asp >/dev/null 2>&1
fi
}
install_now(){
# default value
local TITLE=”ngrok内网穿透”
local DESCR=”支持多种协议的内网穿透软件”
local PLVER=$(cat ${DIR}/version)
# stop first
local ENABLE=$(dbus get ${module}_enable)
local PID=$(pidof ngrok)
if [ -n "${PID}" ];then
echo_date "安装前先关闭${TITLE}插件,以保证更新成功!"
killall ngrok >/dev/null 2>&1
fi
# isntall file
echo_date "安装插件相关文件..."
cd /tmp
cp -rf /tmp/${module}/bin/* /koolshare/bin/
cp -rf /tmp/${module}/res/* /koolshare/res/
cp -rf /tmp/${module}/scripts/* /koolshare/scripts/
cp -rf /tmp/${module}/webs/* /koolshare/webs/
cp -rf /tmp/${module}/uninstall.sh /koolshare/scripts/uninstall_${module}.sh
# Permissions
chmod 755 /koolshare/bin/${module} >/dev/null 2>&1
chmod 755 /koolshare/scripts/${module}_*.sh >/dev/null 2>&1
# intall different UI
install_ui
# dbus value
echo_date "设置插件默认参数..."
dbus set ${module}_version="${PLVER}"
dbus set softcenter_module_${module}_version="${PLVER}"
dbus set softcenter_module_${module}_install="1"
dbus set softcenter_module_${module}_name="${module}"
dbus set softcenter_module_${module}_title="${TITLE}"
dbus set softcenter_module_${module}_description="${DESCR}"
# re-enable
if [ "${ENABLE}" == "1" -a -f "/koolshare/scripts/ngrok_config.sh" ];then
echo_date "安装完毕,重新启用${TITLE}插件!"
sh /koolshare/scripts/frpc_config.sh start
fi
# finish
echo_date "${TITLE}插件安装完毕!"
exit_install
}
install(){
get_model
get_fw_type
platform_test
install_now
}
install
1 | uninstall.sh |
#!/bin/sh
export KSROOT=/koolshare
source $KSROOT/scripts/base.sh
killall frpc
find /koolshare/init.d/ -name “frpc“ | xargs rm -rf
rm -rf /koolshare/res/icon-frpc.png
rm -rf /koolshare/scripts/frpc*.sh
rm -rf /koolshare/webs/Module_frpc.asp
rm -f /koolshare/scripts/uninstall_frpc.sh
1 |
|
#!/bin/sh
eval dbus export ngrok_
source /koolshare/scripts/base.sh
mkdir -p /tmp/upload
NAME=ngrok
alias echo_date=’echo 【$(TZ=UTC-8 date -R +%Y年%m月%d日\ %X)】:’
BIN=/koolshare/bin/ngrok
INI_FILE=/tmp/upload/.ngrok.ini
LOG_FILE_TXT=/tmp/upload/ngrok_log.txt
STCP_INI_FILE=/tmp/upload/.ngrok_stcp.ini
PID_FILE=/var/run/ngrok.pid
lan_ip=nvram get lan_ipaddr
lan_port=”80”
ddns_flag=false
fun_ntp_sync(){
echo_date “[fun_ntp_sync调用]”| tee -a $LOG_FILE_TXT
ntp_server=nvram get ntp_server0
start_time=”date +%Y%m%d
“
ntpclient -h ${ntp_server} -i3 -l -s > /dev/null 2>&1
if [ “${start_time}”x = “date +%Y%m%d
“x ]; then
ntpclient -h ntp1.aliyun.com -i3 -l -s > /dev/null 2>&1
fi
}
fun_start_stop(){
echo_date “[fun_start_stop调用]”| tee -a $LOG_FILE_TXT
#ngrok_enable=1
dbus set ngrok_client_version=${BIN} version
if [ “${ngrok_enable}”x = “1”x ];then
echo_date 当前为开启状态,即将进行程序执行| tee -a $LOG_FILE_TXT
if [ “dbus get ngrok_customize_conf
“x = “1”x ];then
_ngrok_customize_conf=dbus get ngrok_config | base64_decode
|| “未发现配置文件”
cat > ${INI_FILE}<<-EOF
# ngrok custom configuration
${_ngrok_customize_conf}
EOF
else
stcp_en=dbus list ngrok_proto_node | grep stcp
cat > ${INI_FILE}<<-EOF
# ngrok configuration
[common]
server_addr = ${ngrok_common_server_addr}
#server_port = ${ngrok_common_server_port}
token = ${ngrok_common_privilege_token}
log_file = ${ngrok_common_log_file}
log_level = ${ngrok_common_log_level}
log_max_days = ${ngrok_common_log_max_days}
tcp_mux = ${ngrok_common_tcp_mux}
protocol = ${ngrok_common_protocol}
login_fail_exit = ${ngrok_common_login_fail_exit}
user = ${ngrok_common_user}
EOF
if [[ "${stcp_en}" != "" ]]; then
cat > ${STCP_INI_FILE}<<-EOF
[common]
server_addr = ${ngrok_common_server_addr}
#server_port = ${ngrok_common_server_port}
token = ${ngrok_common_privilege_token}
EOF
fi
server_nu=`dbus list ngrok_localhost_node | sort -n -t "_" -k 4|cut -d "=" -f 1|cut -d "_" -f 4`
for nu in ${server_nu}
do
array_subname=`dbus get ngrok_subname_node_$nu`
array_type=`dbus get ngrok_proto_node_$nu`
array_local_ip=`dbus get ngrok_localhost_node_$nu`
array_local_port=`dbus get ngrok_localport_node_$nu`
array_remote_port=`dbus get ngrok_remoteport_node_$nu`
array_custom_domains=`dbus get ngrok_subdomain_node_$nu`
array_use_encryption=`dbus get ngrok_encryption_node_$nu`
array_use_gzip=`dbus get ngrok_gzip_node_$nu`
if [[ "${array_type}" == "tcp" ]] || [[ "${array_type}" == "udp" ]]; then
cat >> ${INI_FILE} <<-EOF
[${array_subname}]
type = ${array_type}
local_ip = ${array_local_ip}
local_port = ${array_local_port}
remote_port = ${array_remote_port}
use_encryption = ${array_use_encryption}
use_compression = ${array_use_gzip}
EOF
elif [[ "${array_type}" == "stcp" ]]; then
cat >> ${INI_FILE} <<-EOF
[${array_subname}]
type = ${array_type}
sk = ${array_custom_domains}
local_ip = ${array_local_ip}
local_port = ${array_local_port}
EOF
cat >> ${STCP_INI_FILE}<<-EOF
[secret_tcp_vistor]
# ngrok role vistor -> frps -> ngrok role server
role = vistor
type = stcp
# the server name you want to vistor
server_name = ${ngrok_common_user}.${array_subname}
sk = ${array_custom_domains}
# connect this address to vistor stcp server
bind_addr = 127.0.0.1
bind_port = 9000
EOF
else
cat >> ${INI_FILE} <<-EOF
[${array_subname}]
type = ${array_type}
local_ip = ${array_local_ip}
local_port = ${array_local_port}
remote_port = ${array_remote_port}
custom_domains = ${array_custom_domains}
use_encryption = ${array_use_encryption}
use_compression = ${array_use_gzip}
EOF
fi
done
fi
killall ngrok || true
echo_date "杀死原有进程"| tee -a $LOG_FILE_TXT
sleep 1
export GOGC=40
echo_date "再次启动进程" | tee -a $LOG_FILE_TXT
echo_date "执行命令 start-stop-daemon -S -q -b -m -p ${PID_FILE} -x ${BIN} clientid ${ngrok_common_privilege_token}"| tee -a $LOG_FILE_TXT
start-stop-daemon -S -q -b -m -p ${PID_FILE} -x ${BIN} clientid ${ngrok_common_privilege_token}| tee -a $LOG_FILE_TXT
sleep 3
echo_date "输出等待结果${temp}" | tee -a $LOG_FILE_TXT
#A=`curl -I "http://127.0.0.1"`
A=`curl "http://127.0.0.1:4040"`
B=${A##*}
echo_date "启动程序完成,尝试访问web接口结果\n$A"| tee -a $LOG_FILE_TXT
else
echo_date "非开启状态,终止程序" | tee -a $LOG_FILE_TXT
killall ngrok || true
fi
}
fun_nat_start(){ # 添加开机启动
echo_date “[fun_nat_start调用]”| tee -a $LOG_FILE_TXT
if [ “${ngrok_enable}”x = “1”x ];then
echo_date “添加开机自启动”| tee -a $LOG_FILE_TXT
[ ! -L “/koolshare/init.d/N99ngrok.sh” ] && ln -sf /koolshare/scripts/ngrok_config.sh /koolshare/init.d/N99ngrok.sh
else
echo_date “移除开机自启动”| tee -a $LOG_FILE_TXT
rm -rf /koolshare/init.d/N99ngrok.sh >/dev/null 2>&1
fi
}
fun_crontab(){
echo_date “[fun_crontab调用]”| tee -a $LOG_FILE_TXT
if [ “${ngrok_enable}”x = “1”x ];then
if [ "${ngrok_common_cron_time}"x = "0"x ]; then
echo_date 清除定时| tee -a $LOG_FILE_TXT
cru d ngrok_monitor
else
if [ "${ngrok_common_cron_hour_min}"x = "min"x ]; then
echo_date 添加定时-${ngrok_common_cron_time}分钟重启一次 tee -a $LOG_FILE_TXT
cru a ngrok_monitor "*/"${ngrok_common_cron_time}" * * * * /bin/sh /koolshare/scripts/ngrok_config.sh start"
elif [ "${ngrok_common_cron_hour_min}"x = "hour"x ]; then
echo_date 添加定时-{ngrok_common_cron_time}小时重启一次 tee -a $LOG_FILE_TXT
cru a ngrok_monitor "0 */"${ngrok_common_cron_time}" * * * /bin/sh /koolshare/scripts/ngrok_config.sh start"
fi
fi
else
cru d ngrok_monitor
echo_date 清除定时| tee -a $LOG_FILE_TXT
fi
}
fun_ddns_stop(){
nvram unset ddns_hostname_x
nvram set ddns_enable_x=0
nvram commit
}
fun_ddns_start(){
# ddns setting
if [ “${frpc_enable}”x = “1”x ];then
# ddns setting
if [[ “${frpc_common_ddns}” == “1” ]] && [[ “${frpc_domain}” != “” ]]; then
nvram set ddns_enable_x=1
nvram set ddns_hostname_x=${frpc_domain}
ddns_custom_updated 1
nvram commit
elif [[ “${frpc_common_ddns}” == “2” ]]; then
echo “ddns no setting”
else
fun_ddns_stop
fi
else
fun_ddns_stop
fi
}
#echo “action(supportStart):$ACTION”| tee -a $LOG_FILE_TXT
=============================================
this part for start up by post-mount
case $ACTION in
start)
true > $LOG_FILE_TXT #重置日志文件内容
echo XU6J03M6 | tee -a $LOG_FILE_TXT #实时刷新
echo_date “execAction” | tee -a $LOG_FILE_TXT
fun_ntp_sync
fun_start_stop
fun_nat_start
fun_crontab
http_response “$1”
echo “execOver$2” | tee -a $LOG_FILE_TXT
;;
esac
for web submit
case $2 in
1)
true > $LOG_FILE_TXT #清空日志
http_response "$1"
echo -e "参数Action${ACTION}\n参数0:${0}\n参数1:${1}\n参数2:${2}"| tee -a $LOG_FILE_TXT
echo XU6J03M6 | tee -a $LOG_FILE_TXT #有了这个标记就可以显示一个按钮.
echo_date "提交配置更新" | tee -a $LOG_FILE_TXT
fun_ntp_sync
fun_start_stop
fun_nat_start
fun_crontab
echo "execOver$1" | tee -a $LOG_FILE_TXT
;;
esac
case $3 in
web_submit)
true > $LOG_FILE_TXT #重置日志文件内容
echo XU6J03M6 | tee -a $LOG_FILE_TXT #实时刷新
fun_nat_start
http_response “$1”
echo “execOver$2” | tee -a $LOG_FILE_TXT
;;
esac
1 | ngrok_status.sh |
#! /bin/sh
export KSROOT=/koolshare
source $KSROOT/scripts/base.sh
ngrok_version=/koolshare/bin/ngrok version
ngrok_pid=pidof ngrok
if [ -n “$ngrok_pid” ];then
http_response “ngrok ${ngrok_version} 进程运行正常!PID:$ngrok_pid”
else
http_response “ngrok ${ngrok_version} 进程未运行!”
fi