Git Product home page Git Product logo

ollvm-breaker's Introduction

ollvm-breaker

使用Binary Ninja去除ollvm流程平坦混淆

使用

使用IDA打开tests目录下的libvdog.so,运行tests下的fix-libvdog.py反混淆,重新分析程序. 当前修复了vdog五个函数,JNI_OnLoad,crazy::GetPackageName,prevent_attach_one,attach_thread_scn,crazy::CheckDex.

效果

混淆代码

jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
  jint v2; // w9
  int v3; // w8
  int v4; // w9
  int i; // w8
  int v6; // w9
  const char *v7; // x0
  int v8; // w8
  bool v9; // zf
  const char *v10; // x0
  int v11; // w8
  crazy *v12; // x0
  _JNIEnv *v13; // x1
  crazy *v14; // x8
  int j; // w9
  unsigned int v16; // w0
  int k; // w8
  crazy *v18; // x0
  int l; // w8
  __int64 v21; // [xsp-FA0h] [xbp-1210h]
  __int64 v22; // [xsp-7D0h] [xbp-A40h]
  __int64 v23; // [xsp-30h] [xbp-2A0h]
  __int64 v24; // [xsp-20h] [xbp-290h]
  char *v25; // [xsp+8h] [xbp-268h]
  void *v26; // [xsp+10h] [xbp-260h]
  jint v27; // [xsp+18h] [xbp-258h]
  jint v28; // [xsp+1Ch] [xbp-254h]
  JavaVM *v29; // [xsp+20h] [xbp-250h]
  char *v30; // [xsp+28h] [xbp-248h]
  char *v31; // [xsp+30h] [xbp-240h]
  crazy::String *v32; // [xsp+38h] [xbp-238h]
  __int64 (__fastcall **v33)(JavaVM *, void *); // [xsp+40h] [xbp-230h]
  const char *v34; // [xsp+48h] [xbp-228h]
  int v35; // [xsp+54h] [xbp-21Ch]
  int v36; // [xsp+58h] [xbp-218h]
  int v37; // [xsp+5Ch] [xbp-214h]
  JavaVM *v38; // [xsp+60h] [xbp-210h]
  char *v39; // [xsp+68h] [xbp-208h]
  const char *v40; // [xsp+70h] [xbp-200h]
  int v41; // [xsp+7Ch] [xbp-1F4h]
  char *v42; // [xsp+80h] [xbp-1F0h]
  FILE *v43; // [xsp+88h] [xbp-1E8h]
  int v44; // [xsp+94h] [xbp-1DCh]
  crazy *v45; // [xsp+98h] [xbp-1D8h]
  JavaVM *v46; // [xsp+A0h] [xbp-1D0h]
  int v47; // [xsp+A8h] [xbp-1C8h]
  int v48; // [xsp+ACh] [xbp-1C4h]
  crazy *v49; // [xsp+B0h] [xbp-1C0h]
  JavaVM *v50; // [xsp+B8h] [xbp-1B8h]
  crazy *v51; // [xsp+C0h] [xbp-1B0h]
  crazy *v52; // [xsp+C8h] [xbp-1A8h]
  jint (**v53)(JavaVM *, void **, jint); // [xsp+D0h] [xbp-1A0h]
  crazy::String **v54; // [xsp+E8h] [xbp-188h]
  const char *v55; // [xsp+F0h] [xbp-180h]
  char *v56; // [xsp+F8h] [xbp-178h]
  int v57; // [xsp+104h] [xbp-16Ch]
  const char *v58; // [xsp+108h] [xbp-168h]
  JavaVM *v59; // [xsp+110h] [xbp-160h]
  crazy::String *v60; // [xsp+118h] [xbp-158h]
  __int64 v61; // [xsp+218h] [xbp-58h]

  v26 = reserved;
  v29 = vm;
  v61 = *(_QWORD *)off_DFF90;
  v3 = 1718907589;
  v27 = v2;
LABEL_2:
  v28 = v2;
  while ( 1 )
  {
    while ( 1 )
    {
      while ( 1 )
      {
        while ( 1 )
        {
          while ( 1 )
          {
            v4 = v3;
            if ( v3 > -1796611739 )
              break;
            v3 = -1591680163;
          }
          if ( v3 > 2122517887 )
            crazy::AbortProcess((crazy *)vm);
          if ( v3 <= 2071858715 )
            break;
          vm = (JavaVM *)strstr(v40, "sg.bigo.enterprise.live:service");
          v50 = vm;
          v3 = -1796611738;
        }
        if ( v3 > 2038211856 )
          crazy::AbortProcess((crazy *)vm);
        if ( v3 <= 1985452749 )
          break;
        v52 = 0LL;
        for ( i = -641593896; ; i = 1602492537 )
        {
          do
          {
            while ( 1 )
            {
              while ( 1 )
              {
                v6 = i;
                if ( i > -959375403 )
                  break;
                v53 = &(*v59)->GetEnv;
                i = 1919464359;
              }
              i = -959375402;
              if ( v6 > -641593897 )
                break;
              if ( v6 != -959375402 )
              {
                while ( 1 )
                  ;
              }
              v59 = v29;
              i = -1329367337;
            }
          }
          while ( v6 == -641593896 );
          if ( v6 != 1919464359 )
            break;
          v60 = (crazy::String *)*v53;
        }
        vm = (JavaVM *)((__int64 (__fastcall *)(JavaVM *, crazy **, __int64))v60)(v29, &v52, 65540LL);
        if ( (_DWORD)vm )
          v3 = 152851513;
        else
          v3 = -225316631;
      }
      if ( v3 <= 1919761782 )
        break;
      v3 = -1591680163;
    }
    if ( v3 > 1873022920 )
      return v28;
    if ( v3 > 1838028940 )
    {
      if ( v35 )
        v3 = 2122517888;
      else
        v3 = 484421971;
    }
    else if ( v3 > 1734873926 )
    {
      vm = (JavaVM *)j_aop_init();
      v3 = -930274867;
    }
    else if ( v3 > 1718907588 )
    {
      v30 = (char *)&v22;
      v31 = (char *)&v21;
      v3 = -7854534;
    }
    else if ( v3 > 1609266205 )
    {
      vm = (JavaVM *)sub_F688();
      v48 = (int)vm;
      v3 = -319607287;
    }
    else if ( v3 > 1465118877 )
    {
      v27 = -1;
      v3 = -1719305536;
    }
    else if ( v3 > 1433580932 )
    {
      if ( v43 )
        v3 = 300194280;
      else
        v3 = 1919761783;
    }
    else if ( v3 > 1297281499 )
    {
      *off_DFF18 = 23;
      v3 = -455933748;
    }
    else if ( v3 > 1182817588 )
    {
      if ( v41 == 15 )
        v3 = 1734873927;
      else
        v3 = -930274867;
    }
    else if ( v3 > -1782315967 )
    {
      if ( v3 > 1038839700 )
      {
        vm = (JavaVM *)strcmp(v34, (const char *)v38);
        v35 = (int)vm;
        v3 = 1838028941;
      }
      else if ( v3 > 1027871973 )
      {
        vm = (JavaVM *)sub_76F60(v51);
        if ( (unsigned __int8)vm & 1 )
          v3 = -1618151004;
        else
          v3 = -990688990;
      }
      else if ( v3 > 939162912 )
      {
        vm = (JavaVM *)crazy::GetPackageName((crazy *)vm);
        v3 = -1039152186;
      }
      else if ( v3 > 775964469 )
      {
        *off_DFEE8 = 1;
        v3 = -376454767;
      }
      else if ( v3 > 742678025 )
      {
        if ( v37 )
          v3 = -625239653;
        else
          v3 = -1665109333;
      }
      else if ( v3 > 585706880 )
      {
        vm = (JavaVM *)crazy::checkdex_1(v49, (_JNIEnv *)reserved);
        if ( (unsigned __int8)vm & 1 )
          v3 = -208592878;
        else
          v3 = 2038211857;
      }
      else if ( v3 > 542546871 )
      {
        v3 = 1985452750;
      }
      else if ( v3 > 492398670 )
      {
        v7 = (const char *)crazy::GetPlatformVersion(v45, (_JNIEnv *)reserved);
        vm = (JavaVM *)strchr(v7, 77);
        if ( vm )
          v3 = 1297281500;
        else
          v3 = -455933748;
      }
      else if ( v3 > 484421970 )
      {
        crazy::String::~String(v32);
        v3 = -1237920250;
      }
      else if ( v3 > 411468606 )
      {
        vm = (JavaVM *)crazy::checkSignature_1(v52, (_JNIEnv *)reserved);
        if ( (unsigned __int8)vm & 1 )
          v3 = -847794275;
        else
          v3 = -648924866;
      }
      else if ( v3 > 300194279 )
      {
        v39 = v31;
        vm = (JavaVM *)memset(v31, 0, 0x7D0u);
        v3 = -1781762611;
      }
      else if ( v3 > 152851512 )
      {
        v8 = 152851513;
LABEL_122:
        v9 = v4 == v8;
        v3 = v4;
        if ( v9 )
        {
          v28 = -1;
          v3 = 1873022921;
        }
      }
      else if ( v3 > 117134184 )
      {
        vm = (JavaVM *)anti_debug_start();
        v3 = -1974907953;
      }
      else if ( v3 > 105840861 )
      {
        v3 = 939162913;
      }
      else if ( v3 > 79862069 )
      {
        vm = (JavaVM *)sub_2E998();
        v38 = vm;
        if ( *(_BYTE *)vm )
          v3 = 105840862;
        else
          v3 = -1237920250;
      }
      else if ( v3 > -7854535 )
      {
        v32 = (crazy::String *)&v24;
        v33 = (__int64 (__fastcall **)(JavaVM *, void *))&v23;
        v3 = -1413870337;
      }
      else if ( v3 > -139557228 )
      {
        v10 = (const char *)sub_2E728();
        vm = (JavaVM *)strlen(v10);
        v46 = vm;
        v3 = -554839129;
      }
      else if ( v3 > -208592879 )
      {
        vm = (JavaVM *)sub_E7EC(*off_DFE98[0], "JNI_OnLoad", v33);
        v37 = (int)vm;
        v3 = 742678026;
      }
      else if ( v3 > -225316632 )
      {
        v11 = 1488047907;
        while ( v11 > -588102432 )
        {
          if ( v11 > 939763251 )
          {
            if ( v11 == 939763252 )
            {
              v59 = *(JavaVM **)v58;
              v11 = 1689158789;
            }
            else if ( v11 == 1689158789 )
            {
              v53 = (jint (**)(JavaVM *, void **, jint))(v59 + 219);
              v11 = -588102431;
            }
            else
            {
              v58 = (const char *)v52;
              v11 = 939763252;
            }
          }
          else
          {
            v60 = (crazy::String *)*v53;
            v11 = -1117867482;
          }
        }
        ((void (__fastcall *)(crazy *, __int64))v60)(v52, off_DFF58);
        v12 = v52;
        *off_DFFF8 = (__int64)v52;
        vm = (JavaVM *)crazy::GetApiLevel(v12, v13);
        v14 = v52;
        *off_DFF18 = (_DWORD)vm;
        v45 = v14;
        v3 = 492398671;
      }
      else if ( v3 > -319607288 )
      {
        if ( v48 )
          v3 = -1781655590;
        else
          v3 = 1465118878;
      }
      else if ( v3 > -376454768 )
      {
        vm = (JavaVM *)sub_2E738();
        v47 = (int)vm;
        v3 = -647280407;
      }
      else if ( v3 > -455933749 )
      {
        v36 = *off_DFF18;
        v3 = -711396653;
      }
      else if ( v3 > -554839130 )
      {
        if ( v46 )
          v3 = -1679856594;
        else
          v3 = -853626539;
      }
      else if ( v3 > -625239654 )
      {
        vm = (JavaVM *)(*v33)(v29, v26);
        v3 = -1782315966;
      }
      else if ( v3 > -647280408 )
      {
        if ( v47 == 2 )
          v3 = -1525365595;
        else
          v3 = -1618151004;
      }
      else
      {
        if ( v3 > -648924867 )
          crazy::AbortProcess((crazy *)vm);
        if ( v3 > -711396654 )
        {
          if ( v36 <= 23 )
            v3 = -376454767;
          else
            v3 = 775964470;
        }
        else if ( v3 > -847794276 )
        {
          v3 = 79862070;
        }
        else if ( v3 > -853626540 )
        {
          v3 = -1719305536;
          v27 = 65540;
        }
        else if ( v3 > -930274868 )
        {
          vm = (JavaVM *)anti_section_hook();
          v3 = 411468607;
        }
        else
        {
          if ( v3 > -990688991 )
          {
            v8 = -990688990;
            goto LABEL_122;
          }
          if ( v3 > -1039152187 )
          {
            for ( j = -1458226292; j == -1458226292; j = -1943834868 )
              v60 = v32;
            v34 = *(const char **)v60;
            v3 = 1038839701;
          }
          else if ( v3 > -1155919955 )
          {
            if ( v44 == 1 )
              v3 = 1609266206;
            else
              v3 = -1781655590;
          }
          else if ( v3 > -1237920251 )
          {
            vm = (JavaVM *)sub_2E738();
            v44 = (int)vm;
            v3 = -1155919954;
          }
          else if ( v3 > -1413870338 )
          {
            v3 = 542546872;
          }
          else if ( v3 > -1525365596 )
          {
            v51 = v52;
            v3 = 1027871974;
          }
          else if ( v3 > -1591680164 )
          {
            v41 = *off_DFF18;
            v3 = 1182817589;
          }
          else if ( v3 > -1618151005 )
          {
            v42 = v30;
            memset(v30, 0, 0x7D0u);
            v25 = v30;
            v16 = getpid();
            sprintf(v25, "/proc/%d/cmdline", v16);
            vm = (JavaVM *)fopen(v25, "r");
            v43 = (FILE *)vm;
            v3 = 1433580933;
          }
          else if ( v3 > -1665109334 )
          {
            v3 = -139557227;
          }
          else if ( v3 > -1679856595 )
          {
            for ( k = -1119912898; ; k = -1679727783 )
            {
              while ( 1 )
              {
                while ( 1 )
                {
                  while ( 1 )
                  {
                    while ( 1 )
                    {
                      while ( k > 504275913 )
                      {
                        sprintf(v56, "/data/data/%s/.hide/%s", v55, v58);
                        vm = (JavaVM *)remove(v56);
                        v57 = (int)vm;
                        k = 308794308;
                      }
                      if ( k <= 308794307 )
                        break;
                      if ( v57 )
                        k = -158042328;
                      else
                        k = -1095053525;
                    }
                    if ( k <= -158042329 )
                      break;
                    v9 = k == -158042328;
                    k = -1095053525;
                    if ( !v9 )
                    {
                      while ( 1 )
                        ;
                    }
                  }
                  if ( k > -1499369114 )
                    break;
                  v18 = (crazy *)memset(v54, 0, 0x100u);
                  crazy::GetPackageName(v18);
                  for ( l = -1458226292; l == -1458226292; l = -1943834868 )
                    v59 = (JavaVM *)&v53;
                  v55 = (const char *)*v59;
                  crazy::String::~String((crazy::String *)&v53);
                  k = -1499369113;
                }
                if ( k != -1499369113 )
                  break;
                v56 = (char *)&v60;
                vm = (JavaVM *)sub_2E728();
                v58 = (const char *)vm;
                k = 504275914;
              }
              if ( k != -1119912898 )
                break;
              v54 = &v60;
            }
            v3 = -853626539;
          }
          else
          {
            if ( v3 > -1719305537 )
            {
              v3 = 1873022921;
              v2 = v27;
              goto LABEL_2;
            }
            v3 = -139557227;
            if ( v4 != -1782315966 )
            {
              if ( v4 == -1781762611 )
              {
                v40 = v31;
                fscanf(v43, "%s", v31);
                fclose(v43);
                vm = (JavaVM *)strchr(v40, 58);
                if ( vm )
                  v3 = 2071858716;
                else
                  v3 = 117134185;
              }
              else
              {
                v49 = v52;
                v3 = 585706881;
              }
            }
          }
        }
      }
    }
    else if ( v50 )
    {
      v3 = 117134185;
    }
    else
    {
      v3 = -1974907953;
    }
  }
}

反混淆后的代码

jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
  int v2; // w9
  _JNIEnv *v3; // x1
  _BOOL4 v5; // w8
  crazy *v6; // x0
  int v7; // w8
  crazy *v8; // x0
  _JNIEnv *v9; // x1
  const char *v10; // x0
  _JNIEnv *v12; // x1
  crazy *v13; // x0
  crazy *v14; // x0
  const char *v15; // x0
  crazy *v16; // x0
  _JNIEnv *v17; // x1
  int v18; // w0
  crazy *v19; // x8
  unsigned int v20; // w0
  crazy *v21; // x0
  __int64 v23; // [xsp-FD0h] [xbp-1240h]
  __int64 v24; // [xsp-FC0h] [xbp-1230h]
  __int64 v25; // [xsp-FA0h] [xbp-1210h]
  __int64 v26; // [xsp-7D0h] [xbp-A40h]
  char *v27; // [xsp+8h] [xbp-268h]
  void *v28; // [xsp+10h] [xbp-260h]
  int v29; // [xsp+18h] [xbp-258h]
  int v30; // [xsp+1Ch] [xbp-254h]
  JavaVM *v31; // [xsp+20h] [xbp-250h]
  char *v32; // [xsp+28h] [xbp-248h]
  char *v33; // [xsp+30h] [xbp-240h]
  crazy::String *v34; // [xsp+38h] [xbp-238h]
  void (__fastcall **v35)(JavaVM *, void *); // [xsp+40h] [xbp-230h]
  const char *v36; // [xsp+48h] [xbp-228h]
  int v37; // [xsp+54h] [xbp-21Ch]
  int v38; // [xsp+58h] [xbp-218h]
  int v39; // [xsp+5Ch] [xbp-214h]
  const char *v40; // [xsp+60h] [xbp-210h]
  char *v41; // [xsp+68h] [xbp-208h]
  const char *v42; // [xsp+70h] [xbp-200h]
  int v43; // [xsp+7Ch] [xbp-1F4h]
  char *v44; // [xsp+80h] [xbp-1F0h]
  FILE *v45; // [xsp+88h] [xbp-1E8h]
  int v46; // [xsp+94h] [xbp-1DCh]
  crazy *v47; // [xsp+98h] [xbp-1D8h]
  __int64 v48; // [xsp+A0h] [xbp-1D0h]
  int v49; // [xsp+A8h] [xbp-1C8h]
  int v50; // [xsp+ACh] [xbp-1C4h]
  crazy *v51; // [xsp+B0h] [xbp-1C0h]
  char *v52; // [xsp+B8h] [xbp-1B8h]
  crazy *v53; // [xsp+C0h] [xbp-1B0h]
  crazy *v54; // [xsp+C8h] [xbp-1A8h]
  jint (**v55)(JavaVM *, void **, jint); // [xsp+D0h] [xbp-1A0h]
  crazy::String **v56; // [xsp+E8h] [xbp-188h]
  const char *v57; // [xsp+F0h] [xbp-180h]
  char *v58; // [xsp+F8h] [xbp-178h]
  int v59; // [xsp+104h] [xbp-16Ch]
  const char *v60; // [xsp+108h] [xbp-168h]
  JavaVM *v61; // [xsp+110h] [xbp-160h]
  crazy::String *v62; // [xsp+118h] [xbp-158h]
  __int64 v63; // [xsp+218h] [xbp-58h]

  v28 = reserved;
  v31 = vm;
  v63 = *(_QWORD *)off_DFF90;
  v29 = v2;
  v30 = v2;
  v32 = (char *)&v26;
  v33 = (char *)&v25;
  v34 = (crazy::String *)&v24;
  v35 = (void (__fastcall **)(JavaVM *, void *))&v23;
  v54 = 0LL;
  v61 = vm;
  v55 = &(*vm)->GetEnv;
  v62 = (crazy::String *)*v55;
  if ( ((unsigned int (__fastcall *)(JavaVM *, crazy **, __int64))v62)(vm, &v54, 65540LL) != 0 )
    return -1;
  v60 = (const char *)v54;
  v61 = *(JavaVM **)v54;
  v55 = (jint (**)(JavaVM *, void **, jint))(v61 + 219);
  v62 = (crazy::String *)v61[219];
  ((void (*)(void))v62)();
  v16 = v54;
  *off_DFFF8 = (__int64)v54;
  v18 = crazy::GetApiLevel(v16, v17);
  v19 = v54;
  *off_DFF18 = v18;
  v47 = v19;
  v10 = (const char *)crazy::GetPlatformVersion(v19, v9);
  if ( strchr(v10, 77) != 0LL )
    *off_DFF18 = 23;
  v38 = *off_DFF18;
  if ( v38 > 23 )
    *off_DFEE8 = 1;
  v49 = sub_2E738();
  if ( v49 == 2 )
  {
    v53 = v54;
    v7 = sub_76F60(v53) & 1 ? -1618151004 : -990688990;
    if ( v7 > -990688991 )
      return -1;
  }
  v44 = v32;
  memset(v32, 0, 0x7D0u);
  v27 = v32;
  v20 = getpid();
  sprintf(v27, "/proc/%d/cmdline", v20);
  v45 = fopen(v27, "r");
  if ( v45 != 0LL )
  {
    v41 = v33;
    memset(v33, 0, 0x7D0u);
    v42 = v33;
    fscanf(v45, "%s", v33);
    fclose(v45);
    v5 = strchr(v42, 58) == 0LL;
    if ( v5 || (v52 = strstr(v42, "sg.bigo.enterprise.live:service"), v52 != 0LL) )
      anti_debug_start();
  }
  v43 = *off_DFF18;
  if ( v43 == 15 )
    j_aop_init();
  anti_section_hook();
  v13 = (crazy *)crazy::checkSignature_1(v54, v12);
  if ( ((unsigned __int8)v13 & 1) == 0 )
    crazy::AbortProcess(v13);
  v14 = (crazy *)sub_2E998();
  v40 = (const char *)v14;
  if ( *(_BYTE *)v14 )
  {
    crazy::GetPackageName(v14);
    v62 = v34;
    v36 = *(const char **)v34;
    v6 = (crazy *)strcmp(v36, v40);
    v37 = (int)v6;
    if ( v37 != 0 )
      crazy::AbortProcess(v6);
    crazy::String::~String(v34);
  }
  v46 = sub_2E738();
  if ( v46 == 1 )
  {
    v50 = sub_F688();
    if ( v50 == 0 )
      return -1;
  }
  v51 = v54;
  v8 = (crazy *)crazy::checkdex_1(v54, v3);
  if ( ((unsigned __int8)v8 & 1) == 0 )
    crazy::AbortProcess(v8);
  v39 = sub_E7EC(*off_DFE98[0], "JNI_OnLoad", v35);
  if ( v39 != 0 )
    (*v35)(v31, v28);
  v15 = (const char *)sub_2E728();
  v48 = strlen(v15);
  if ( v48 != 0 )
  {
    v56 = &v62;
    v21 = (crazy *)memset(&v62, 0, 0x100u);
    crazy::GetPackageName(v21);
    v61 = (JavaVM *)&v55;
    v57 = (const char *)v55;
    crazy::String::~String((crazy::String *)&v55);
    v58 = (char *)&v62;
    v60 = (const char *)sub_2E728();
    sprintf(v58, "/data/data/%s/.hide/%s", v57, v60);
    v59 = remove(v58);
  }
  return 65540;
}

参考资源

ollvm-breaker's People

Contributors

amimo avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.