BaseCTF-week3-UPX PRO

查壳后你会发现有壳,去壳的时候你会发现去不了壳,所以这里是有个overlay_offset变量被修改了

所以用010Editor打开,修改最后

可以参考吾爱上面的见解

UPX脱不了壳的问题

然后我们用ida打开

int __fastcall main(int argc, const char **argv, const char **envp)
{
  size_t v4; // rbx
  unsigned __int8 rright[18]; // [rsp+0h] [rbp-C0h] BYREF
  unsigned __int8 nss_array[40]; // [rsp+20h] [rbp-A0h]
  unsigned __int8 BUU[41]; // [rsp+50h] [rbp-70h] BYREF
  unsigned __int8 crypt[13]; // [rsp+83h] [rbp-3Dh] BYREF
  unsigned __int8 *encrypt; // [rsp+90h] [rbp-30h]
  int flag; // [rsp+9Ch] [rbp-24h]
  unsigned __int64 k_len; // [rsp+A0h] [rbp-20h]
  int i; // [rsp+ACh] [rbp-14h]

  puts("UPX shell is really fun, fun to play with");
  puts("Can you unpack?");
  memset(crypt, 0, sizeof(crypt));
  memset(BUU, 0, sizeof(BUU));
  k_len = 0LL;
  flag = 1;
  *(_QWORD *)nss_array = 0x364A65466C271216LL;
  *(_QWORD *)&nss_array[8] = 0x2447243568082139LL;
  *(_QWORD *)&nss_array[16] = 0x29323C0F5A1A7D60LL;
  *(_QWORD *)&nss_array[24] = 0x4D647C3C45531544LL;
  *(_QWORD *)&nss_array[32] = 0x74152339130F7024LL;
  strcpy((char *)rright, "BQ3SDnTj7vaKkMvur");
  if ( ptrace(__ptrace_request::PTRACE_TRACEME, 0LL, 1LL, 0LL) == -1 )
  {
    puts("nononono!!!");
    puts("plz close debugger");
  }
  else
  {
    puts("What is the key for unpacking:");
    scanf("%12s");
    encrypt = enc_obsfucate(crypt);
    if ( !strcmp((const char *)encrypt, (const char *)rright) )
    {
      puts("Unpacking successful!!!");
      puts("then, plz input your flag:");
      scanf(" %40s");
      if ( strlen((const char *)BUU) == 40 )
      {
        k_len = strlen((const char *)crypt);
        strlen((const char *)BUU);
        c4(BUU, crypt, k_len);
        for ( i = 0; ; ++i )
        {
          v4 = i;
          if ( v4 >= strlen((const char *)BUU) )
            break;
          if ( nss_array[i] != BUU[i] )
          {
            puts("Practice again!!!");
            flag = 0;
            return -1;
          }
        }
        if ( flag == 1 )
          printf("GOOD!");
      }
      else
      {
        puts("flag length wrong!!!!!");
      }
    }
    else
    {
      puts("cai-jiu-duo-lian!!!");
    }
    free(encrypt);
  }
  return 0;
}

发现主要就是个C4函数进行加密,加密后的数组BUU和已知数组相同,注意我们是小端存储。还原数组是反着来,所以是:

data=[0x16, 0x12, 0x27, 0x6c, 0x46, 0x65, 0x4a, 0x36, 0x39, 0x21,
    0x08, 0x68, 0x35, 0x24, 0x47, 0x24, 0x60, 0x7d, 0x1a, 0x5a,
           0x0f, 0x3c, 0x32, 0x29, 0x44, 0x15, 0x53, 0x45, 0x3c, 0x7c,
    0x64, 0x4d, 0x24, 0x70, 0xf, 0x13, 0x39, 0x23, 0x15, 0x74]

其实这这有一段rright,这段进行了base58加密

加密完它的位数是13位,(包括‘\0’)

这句代码其实就是要获取字符串的长度,就是12,当然你也可以点进去,就知道它 的位数了

接下来点开c4,发现就是RC4加密,解密的逻辑网上脚本一大堆,注意256换成了128

所以脚本非常简单的写出来

EXP


s=[0x16, 0x12, 0x27, 0x6c, 0x46, 0x65, 0x4a, 0x36, 0x39, 0x21,
    0x08, 0x68, 0x35, 0x24, 0x47, 0x24, 0x60, 0x7d, 0x1a, 0x5a,
           0x0f, 0x3c, 0x32, 0x29, 0x44, 0x15, 0x53, 0x45, 0x3c, 0x7c,
    0x64, 0x4d, 0x24, 0x70, 0xf, 0x13, 0x39, 0x23, 0x15, 0x74]
s1=[0]*129
i=0
k=[0]*129
for i in range(0,128):
    s1[i]=i
    k[i]= k[i % 12]
j=0
for i in range(0,128):
    j = (k[i] + j + s1[i]) % 128
    tmp = s1[i]
    s1[i] = s1[j]
    s1[j] = tmp
i=0
j=0
t=0
for k in range(0,40):
    i = (i + 1) % 128
    j = (j + s1[i]) % 128
    tmp = s1[i]
    s1[i] = s1[j]
    s1[j] = tmp
    t = (s1[i] + s1[j]) & 0x7F
    s[k] ^= s1[t]
for i in range(len(s)):
    print(chr(s[i]),end='')
#BaseCTF{Rc4_1$_@_G0od_3nCrypt!on_MethOd}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值