欢迎来到 黑吧安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

使用unicorn engin还原Armariris字符串混淆

来源:本站整理 作者:佚名 时间:2019-06-26 TAG: 我要投稿

编译Armariris
git clone git@github.com:gossip-sjtu/Armariris.git
编译
cd Armariris
mkdir build
cd build
cmake ../ -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD="ARM;X86;AArch64"
make -j8
测试文件内容如下:
#include
void fun(){
    printf("test 3333\n");
}
int main(int argc, char *argv[]) {
    printf("test 1111\n");
    printf("test 2222\n");
    fun();
    return 0;
}
使用编译好的llvm编译这个测试的文件
clang -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk -mllvm -sobf test.c -o test
使用isysroot指定sdk,然后使用-mllvm -sobf开启字符串混淆
 
Armariris是如何进行字符串混淆的
我们直接看使用ida反汇编出来的代码
int __cdecl main(int argc, const char **argv, const char **envp)
{
  printf(aRcur7777, argv, envp);
  printf(&byte_100001036);
  fun();
  return 0;
}
可以看到有两个printf函数打印了一些数据出来,我们点第一个打印的字符串,双击aRcur7777跳转到 字符串定义位置,这个字符串在data段

这个字符串我们本来输出的是test 1111这里显然不是,我们查看aRcur7777的交叉引用,发现两处, 其中一处是main函数中的printf,另一处应该就是还原这个字符串的位置了

所以__datadiv_decode14953400483976599729这个函数就是还原这个字符的函数,我们看他是如何做的还原 。跳转过去按F5反编译,得到的结果如下:
__int64 datadiv_decode14953400483976599729()
{
  bool v0; // ST23_1
  bool v1; // ST17_1
  __int64 result; // rax
  bool v3; // ST0B_1
  unsigned int v4; // [rsp+8h] [rbp-1Ch]
  unsigned int v5; // [rsp+14h] [rbp-10h]
  unsigned int v6; // [rsp+20h] [rbp-4h]
  v6 = 0;
  do
  {
    aLKl[v6] ^= 0x38u;
    v0 = v6++ 0xA;
  }
  while ( v0 );
  v5 = 0;
  do
  {
    aRcur7777[v5] ^= 6u;
    v1 = v5++ 0xA;
  }
  while ( v1 );
  v4 = 0;
  do
  {
    byte_100001036[v4] ^= 0x71u;
    result = v4 - 10;
    v3 = v4++ 0xA;
  }
  while ( v3 );
  return result;
}
我们可以看到aRcur7777的还原是和6做了异或操作,那我们来验证一下是否是我们看到的这样。
aRcur7777的原始数据是[0x72, 0x63, 0x75, 0x72, 0x26, 0x37, 0x37, 0x37, 0x37]
每一位和6异或之后的结果是[0x74, 0x65, 0x73, 0x74, 0x20, 0x31, 0x31, 0x31, 0x31]
对于的ascii字符串就是test 1111
他这里做字符串混淆用的是一个很简单的原理,一个数字两次异或同一个值,得到的结果是本事的值。也就是 第一次异或就给字符串混淆了,再异或一次就把数据还原了。
 
源码分析
字符串混淆的源文件在lib/Transforms/Obfuscation/StringObfuscation.cpp这个位置, 实现字符串混淆的是一个ModulePass,关于ModulePass可以参考http://llvm.org/doxygen/classllvm11ModulePass.html#details 。在这个pass里面会遍历字符串,然后把字符串和生成的key异或,并替换原始的值,关键代码如下:
// Duplicate global variable
GlobalVariable *dynGV = new GlobalVariable(M,
                                          gv->getType()->getElementType(),
                                          !(gv->isConstant()), gv->getLinkage(),
                                          (Constant*) 0, gv->getName(),
                                          (GlobalVariable*) 0,
                                          gv->getThreadLocalMode(),

[1] [2] [3]  下一页

【声明】:黑吧安全网(http://www.myhack58.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱admin@myhack58.com,我们会在最短的时间内进行处理。
  • 最新更新
    • 相关阅读
      • 本类热门
        • 最近下载