CTF-RE-tar_tar_binks

题目给出了两个文件,一个是已经损坏的.tar文件,一个是.dylib的动态链接库
首先尝试解压.tar压缩包

supergate@ubuntu:~/Desktop/task1$ tar -xf flag.tar
tar: This does not look like a tar archive
tar: Skipping to next header
tar: Exiting with failure status due to previous errors

解压失败,但是可以得到一个flag.txt文件,看一下内容

supergate@ubuntu:~/Desktop/task1$ cat flag.txt
F5D1,4D6B,ED6A,08A6,38DD,F7FA,609E,EBC4,E55F,E6D1,7C89,ED5B,0871,1A69,5D58,72DE,224B,3AA6,0845,7DD6,58FB,E9CC,0A2D,76B8,ED60,251A,1F6B,32CC,E78D,12FA,201A,E889,2D25,922A,4BC5,F5FF,F8E5,C79B,3A77,4BDB,EA11,5941,58BD,3A95,F5C9,A225,AD40,F8BD,095D,70B6,458C,E7A9,EA68,252F,094B,5E41,0969,6015,5ED5,F6E5,59B9,7CAF,66DF,265B,7837,57B4,7CAF,AED9,F707,6A3C,F8E5,F509,7C8B,0915,2235,336F,33E9,2D14,7C91,5804,83E5,E78D,F4EA,0874,ED6B,4B35,E839,57B4,E77C,EA68,2525,AD41,ED6F,3A4A,4BCC,6015,F440,0858,3AA6,7809,671D,0874,EA77,63AF,2E91,5845,F6C4,086D,7795,3939,57B4,7C89,82DC,32ED,B994,C7AF,9135,0E65,1B66,ED5B,3235,6577,5A80,3AD3,E776,1EE5,AD41,ED59,864C,70B4,3876,ED67,64D6,F8E5,F505,EAD9,7C9C,32ED,B994,B4EF,0C6C,F665,F5F5,9047,521A,E99E,EA68,252F,9D09,76B7,E776,1ED0,095D,0D4D,5D5A,087B,2005,1526,7E76,85AD,78B9,E8B6,782C,251C,32ED,7F68,EBE3,EA41,57FD,ED59,846D,7A05,B994,BB78,ED6A,08A6,38DD,3B5D,7E45,E839,738C,E9CC,0A2D,764A,609E,E8B6,EA68,2524,E6BB,7C9C,639F,3A95,0895,F40F,8328,EA69,7EE5,F8BD,7F7D,0D6D,70B6,458C,E8B6,EA68,251C,6065,B35F,C789,5845,7F7D,6D89,4C6E,A20E,60B5,7E45,ED59,F707,69EF,922A,4BC5,F6EF,8635,F4B9,57B4,7CF8,ED60,2510,095D,20AF,3545,F40F,8328,EA41,58A4,225D,7E7C,4BDB,F8BD,082C,EAE7,5D57,5D50,0914,E7C7,8624,7CF8,ED60,2511,7C8E,7159,8416,7EF9,E7E5,774A,3895,1EC9,7C90,09B9,58BD,5FF5,E99E,EA68,250A,224C,EA3D,73F5,7C89,53A6,3190,3B5D,1526,7DD5,666A,0919,225F,CDEF,79E1,7E7B,7E6B,082C,A277,E885,E8BB,E775,5FF7,EA68,251B,7FDF,589D,7A05,779A,8A5A,7C91,5D5C,32ED,F628,2195,F49A,0C77,EAE1,59B9,58BD,E570,E99E,EA3D,73F9,13AD,2BF5,225D,7F7D,70B6,4A9C,337A,1EC9,4D05,7E75,2578,ED59,38E5,1ECA,A210,3B5D,779A,8A6F,C790,2518,4B41,7C89,5D49,4D05,152D,73C5,79F9,4BED,913C,37C9,5D4D,53C8,0941,7C97,5D5B,346A,82D8,5F36,801F,C800,

猜测是加密后的flag。因此相关的函数应该在另外一个动态链接库文件中。
ida打开这个动态链接库文件,查看字符串,发现有一个%04X,,这正好是上面的flag.txt文件输出的格式,因此我们找到了逆向的入口。查看交叉引用后发现如下函数

__int64 __fastcall archive_write_client_write(__int64 a1, __int64 a2, unsigned __int64 a3)
{
  size_t v3; // rax
  unsigned __int64 v5; // [rsp+10h] [rbp-D0h]
  unsigned __int64 i; // [rsp+68h] [rbp-78h]
  unsigned __int64 v7; // [rsp+70h] [rbp-70h]
  unsigned int v8; // [rsp+7Ch] [rbp-64h]
  char *v9; // [rsp+80h] [rbp-60h]
  char *v10; // [rsp+88h] [rbp-58h]
  __int64 v11; // [rsp+90h] [rbp-50h]
  __int64 v12; // [rsp+90h] [rbp-50h]
  __int64 v13; // [rsp+90h] [rbp-50h]
  signed __int64 v14; // [rsp+A0h] [rbp-40h]
  unsigned __int64 *v15; // [rsp+A8h] [rbp-38h]
  __int64 v16; // [rsp+B0h] [rbp-30h]
  char *v17; // [rsp+B8h] [rbp-28h]
  unsigned __int64 v18; // [rsp+C0h] [rbp-20h]
  unsigned int v19; // [rsp+DCh] [rbp-4h]

  v18 = a3;
  v16 = *(_QWORD *)(a1 + 8);
  v15 = *(unsigned __int64 **)(a1 + 64);
  v10 = (char *)malloc(0x2710uLL);
  __memcpy_chk(v10, a2, v18, -1LL);
  if ( v18 > 0x200 )
  {
    sub_1023457(v10, v18);
    v9 = (char *)malloc(0x2710uLL);
    __memset_chk(v10, 0LL, 10000LL, -1LL);
    v8 = 0;
    __memset_chk(v9, 0LL, 10000LL, -1LL);
    while ( v8 < posi )
    {
      v3 = strlen(v9);
      __sprintf_chk(&v9[v3], 0, 0xFFFFFFFFFFFFFFFFLL, "%04X,", sub_101[v8++]);
    }
    __memcpy_chk(v10, v9, v18, -1LL);
  }
  v17 = v10;
  v14 = v18;
  if ( *v15 )
  {
    if ( v15[1] >= *v15
      || (v18 <= v15[1] ? (v5 = v18) : (v5 = v15[1]),
          __memcpy_chk(v15[3], v10, v5, -1LL),
          v15[3] += v5,
          v15[1] -= v5,
          v17 = &v10[v5],
          v14 = v18 - v5,
          v15[1]) )
    {
LABEL_25:
      while ( v14 >= *v15 )
      {
        v13 = (*(__int64 (__fastcall **)(__int64, _QWORD, char *, unsigned __int64))(v16 + 208))(
                v16,
                *(_QWORD *)(v16 + 224),
                v17,
                *v15);
        if ( v13 <= 0 )
          return (unsigned int)-30;
        v17 += v13;
        v14 -= v13;
      }
      if ( v14 > 0 )
      {
        __memcpy_chk(v15[3], v17, v14, -1LL);
        v15[3] += v14;
        v15[1] -= v14;
      }
      v19 = 0;
    }
    else
    {
      v7 = v15[2];
      for ( i = *v15; ; i -= v12 )
      {
        if ( !i )
        {
          v15[3] = v15[2];
          v15[1] = *v15;
          goto LABEL_25;
        }
        v12 = (*(__int64 (__fastcall **)(__int64, _QWORD, unsigned __int64, unsigned __int64))(v16 + 208))(
                v16,
                *(_QWORD *)(v16 + 224),
                v7,
                i);
        if ( v12 <= 0 )
          return (unsigned int)-30;
        if ( v12 > i )
          break;
        v7 += v12;
      }
      archive_set_error(v16);
      v19 = -30;
    }
  }
  else
  {
    while ( v14 > 0 )
    {
      v11 = (*(__int64 (__fastcall **)(__int64, _QWORD, char *, signed __int64))(v16 + 208))(
              v16,
              *(_QWORD *)(v16 + 224),
              v17,
              v14);
      if ( v11 <= 0 )
        return (unsigned int)-30;
      v14 -= v11;
      v17 += v11;
    }
    v19 = 0;
  }
  return v19;
}

可以看到有一个对sub_101数组的输出,格式为%04X,
我们大概知道这个sub_101数组就是加密后的flag。因此查看sub_101的交叉引用,找到另外一个引用他的函数

unsigned int *__fastcall sub_1023458(_DWORD *a1)
{
  unsigned int *result; // rax
  int v2; // ST04_4
  int v3; // esi

  result = sub_101;
  v2 = *a1 + 40 * a1[1] + 1600 * a1[2];
  v3 = posi++;
  sub_101[v3] = v2;
  return result;
}

这个函数是对sub_101进行了一个比较简单的压缩,再看一下对这个函数的引用

__int64 __fastcall sub_1023457(char *a1, int a2)
{
  int v2; // eax
  char *v3; // rax
  int v5; // [rsp+4h] [rbp-2Ch]
  signed int v6; // [rsp+8h] [rbp-28h]
  int v7; // [rsp+Ch] [rbp-24h]
  char *v8; // [rsp+10h] [rbp-20h]
  int v9[3]; // [rsp+1Ch] [rbp-14h]

  v8 = a1;
  v7 = a2;
  v6 = 3;
  while ( 1 )
  {
    v2 = v7--;
    if ( !v2 )
      break;
    v3 = v8++;
    v5 = *v3;
    pending = 1;
    while ( pending )
    {
      v9[--v6] = sub_1023456(v5);
      if ( !v6 )
      {
        change_sub101(v9);
        v6 = 3;
      }
    }
  }
  if ( v6 != 3 )
  {
    while ( v6 != -1 )
      v9[--v6] = 0;
    change_sub101(v9);
  }
  return __stack_chk_guard;
}

最后,点入sub_1023456函数,理清程序的逻辑,就可以写脚本了

__int64 __fastcall sub_1023456(int a1)
{
  int v1; // ST04_4
  int i; // [rsp+0h] [rbp-Ch]
  int v4; // [rsp+4h] [rbp-8h]
  unsigned int v5; // [rsp+8h] [rbp-4h]

  v4 = a1;
  if ( sub_1023456_shifted == -1 )
  {
    if ( a1 == '~' )
      v4 = 0;
    for ( i = 0; i < 39; ++i )
    {
      if ( ctable[i] == v4 )
      {
        pending = 0;
        return (unsigned int)i;
      }
      if ( ctable[i + 39] == v4 )
      {
        pending = 1;
        sub_1023456_shifted = i;
        return 39;
      }
    }
    pending = 0;
    v5 = 37;
  }
  else
  {
    v1 = sub_1023456_shifted;
    sub_1023456_shifted = -1;
    pending = 0;
    v5 = v1;
  }
  return v5;
}

其中

ctable="\x00abcdefghijklmnopqrstuvwxyz0123456789 \n\x00ABCDEFGHIJKLMNOPQRSTUVWXYZ(!@#,.?/*)<>"

所以这一坨就干了一个事,将原文的字符逐个取出,查询在ctable的上部分还是下部分,如果是下部分,就用两个数字来表示:39(下部分的偏移)和在上部分的偏移。如果在上部分就用一个数字——在上部分的偏移来表示。

solve.py :

last_ver=[0xF5D1,0x4D6B,0xED6A,0x08A6,0x38DD,0xF7FA,0x609E,0xEBC4,0xE55F,0xE6D1,0x7C89,0xED5B,0x0871,0x1A69,0x5D58,0x72DE,0x224B,0x3AA6,0x0845,0x7DD6,0x58FB,0xE9CC,0x0A2D,0x76B8,0xED60,0x251A,0x1F6B,0x32CC,0xE78D,0x12FA,0x201A,0xE889,0x2D25,0x922A,0x4BC5,0xF5FF,0xF8E5,0xC79B,0x3A77,0x4BDB,0xEA11,0x5941,0x58BD,0x3A95,0xF5C9,0xA225,0xAD40,0xF8BD,0x095D,0x70B6,0x458C,0xE7A9,0xEA68,0x252F,0x094B,0x5E41,0x0969,0x6015,0x5ED5,0xF6E5,0x59B9,0x7CAF,0x66DF,0x265B,0x7837,0x57B4,0x7CAF,0xAED9,0xF707,0x6A3C,0xF8E5,0xF509,0x7C8B,0x0915,0x2235,0x336F,0x33E9,0x2D14,0x7C91,0x5804,0x83E5,0xE78D,0xF4EA,0x0874,0xED6B,0x4B35,0xE839,0x57B4,0xE77C,0xEA68,0x2525,0xAD41,0xED6F,0x3A4A,0x4BCC,0x6015,0xF440,0x0858,0x3AA6,0x7809,0x671D,0x0874,0xEA77,0x63AF,0x2E91,0x5845,0xF6C4,0x086D,0x7795,0x3939,0x57B4,0x7C89,0x82DC,0x32ED,0xB994,0xC7AF,0x9135,0x0E65,0x1B66,0xED5B,0x3235,0x6577,0x5A80,0x3AD3,0xE776,0x1EE5,0xAD41,0xED59,0x864C,0x70B4,0x3876,0xED67,0x64D6,0xF8E5,0xF505,0xEAD9,0x7C9C,0x32ED,0xB994,0xB4EF,0x0C6C,0xF665,0xF5F5,0x9047,0x521A,0xE99E,0xEA68,0x252F,0x9D09,0x76B7,0xE776,0x1ED0,0x095D,0x0D4D,0x5D5A,0x087B,0x2005,0x1526,0x7E76,0x85AD,0x78B9,0xE8B6,0x782C,0x251C,0x32ED,0x7F68,0xEBE3,0xEA41,0x57FD,0xED59,0x846D,0x7A05,0xB994,0xBB78,0xED6A,0x08A6,0x38DD,0x3B5D,0x7E45,0xE839,0x738C,0xE9CC,0x0A2D,0x764A,0x609E,0xE8B6,0xEA68,0x2524,0xE6BB,0x7C9C,0x639F,0x3A95,0x0895,0xF40F,0x8328,0xEA69,0x7EE5,0xF8BD,0x7F7D,0x0D6D,0x70B6,0x458C,0xE8B6,0xEA68,0x251C,0x6065,0xB35F,0xC789,0x5845,0x7F7D,0x6D89,0x4C6E,0xA20E,0x60B5,0x7E45,0xED59,0xF707,0x69EF,0x922A,0x4BC5,0xF6EF,0x8635,0xF4B9,0x57B4,0x7CF8,0xED60,0x2510,0x095D,0x20AF,0x3545,0xF40F,0x8328,0xEA41,0x58A4,0x225D,0x7E7C,0x4BDB,0xF8BD,0x082C,0xEAE7,0x5D57,0x5D50,0x0914,0xE7C7,0x8624,0x7CF8,0xED60,0x2511,0x7C8E,0x7159,0x8416,0x7EF9,0xE7E5,0x774A,0x3895,0x1EC9,0x7C90,0x09B9,0x58BD,0x5FF5,0xE99E,0xEA68,0x250A,0x224C,0xEA3D,0x73F5,0x7C89,0x53A6,0x3190,0x3B5D,0x1526,0x7DD5,0x666A,0x0919,0x225F,0xCDEF,0x79E1,0x7E7B,0x7E6B,0x082C,0xA277,0xE885,0xE8BB,0xE775,0x5FF7,0xEA68,0x251B,0x7FDF,0x589D,0x7A05,0x779A,0x8A5A,0x7C91,0x5D5C,0x32ED,0xF628,0x2195,0xF49A,0x0C77,0xEAE1,0x59B9,0x58BD,0xE570,0xE99E,0xEA3D,0x73F9,0x13AD,0x2BF5,0x225D,0x7F7D,0x70B6,0x4A9C,0x337A,0x1EC9,0x4D05,0x7E75,0x2578,0xED59,0x38E5,0x1ECA,0xA210,0x3B5D,0x779A,0x8A6F,0xC790,0x2518,0x4B41,0x7C89,0x5D49,0x4D05,0x152D,0x73C5,0x79F9,0x4BED,0x913C,0x37C9,0x5D4D,0x53C8,0x0941,0x7C97,0x5D5B,0x346A,0x82D8,0x5F36,0x801F,0xC800]
t1=[]
t2=[]
flag=""
ctable="\x00abcdefghijklmnopqrstuvwxyz0123456789 \n\x00ABCDEFGHIJKLMNOPQRSTUVWXYZ(!@#,.?/*)<>"

for num in last_ver:
    a=num%40
    b=(num/40)%40
    c=num/1600
    t1+=[c,b,a]

i=0
while i<len(t1):
    if t1[i]==39:
        t2+=[t1[i]+t1[i+1]]
        i+=2
    else :
        t2+=[t1[i]]
        i+=1

for i in t2:
    if ctable[i]!='\x00':
        flag+=ctable[i]
print flag

最终原文的md5值就是flag

supergate@ubuntu:~/Desktop/task1$ python solve.py | md5sum | awk '{print $1}'
2c8cd31daeba8753815851f13e6370b3
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值