做了点简单的题目。

【春节】解题领红包之一

扫码关注即可。

【春节】解题领红包之二

查壳是 upx,ESP 定律法找到 OEP 脱壳。然后放进 ida 里:

HWND main_func()
{
  HWND result; // eax
  char *input; // esi
  char *key; // edi
  int enc_1; // [esp+0h] [ebp-14h]
  int enc_2; // [esp+4h] [ebp-10h]
  int enc_3; // [esp+8h] [ebp-Ch]
  int enc_4; // [esp+Ch] [ebp-8h]
  char v7; // [esp+10h] [ebp-4h]

  result = GetDlgItem(0, 1000);
  if ( result )
  {
    if ( GetWindowTextLengthA(result) == 16 )
    {
      input = (char *)malloc(0x11u);
      key = (char *)malloc(0x11u);
      *(_DWORD *)input = 0;
      *((_DWORD *)input + 1) = 0;
      *((_DWORD *)input + 2) = 0;
      *((_DWORD *)input + 3) = 0;
      input[16] = 0;
      *(_DWORD *)key = 0;
      *((_DWORD *)key + 1) = 0;
      *((_DWORD *)key + 2) = 0;
      *((_DWORD *)key + 3) = 0;
      key[16] = 0;
      GetDlgItemTextA(0, 1000, input, 17);
      enc_3 = 'udhY';
      enc_1 = 'ssdH';
      enc_2 = 'zhNb';
      enc_4 = '9102';
      v7 = 0;
      encrypt((const char *)&enc_1, (int)key, 3);
      if ( !strcmp(key, input) )
        result = (HWND)MessageBoxA(0, aOye, Caption, 0);
      else
        result = (HWND)MessageBoxA(0, aAuey, Caption, 0);
    }
    else
    {
      result = (HWND)MessageBoxA(0, &Text, Caption, 0);
    }
  }
  return result;
}

看下来应该就是把 16 位的 enc 加密了一下,然后和 input 比较。看看 encrypt() 函数:

signed int __cdecl encrypt(const char *enc, int key, int num_3)
{
  const char *enc_0; // edx
  unsigned int length; // kr04_4
  int v5; // esi
  int i; // edi
  char c; // al
  char alphabet[29]; // [esp+Bh] [ebp-1Dh]
  char tmp; // [esp+30h] [ebp+8h]

  strcpy(&alphabet[1], "abcdefghijklmnopqrstuvwxyz");
  if ( !key )
    return -1;
  enc_0 = enc;
  if ( !enc )
    return -1;
  if ( num_3 <= 0 )
    return -1;
  length = strlen(enc) + 1;
  if ( (signed int)(length - 1) <= 0 )
    return -1;
  v5 = key - (_DWORD)enc;
  tmp = alphabet[num_3 + 1];
  i = length - 1;
  do
  {
    c = *enc_0;
    if ( *enc_0 < tmp || c > 122 )
    {
      if ( c >= 97 && c <= alphabet[num_3] )
        c = c - num_3 + 26;
    }
    else
    {
      c -= num_3;
    }
    (enc_0++)[v5] = c;
    --i;
  }
  while ( i );
  return 0;
}

就是对字符串判断是否为字母,然后根据字母表 alphabet 做映射和加减。正向实现一下脚本就得到口令了:

#!/usr/bin/env python
enc = ('9102' + 'udhY' + 'zhNb' + 'ssdH')[::-1]
print enc
alpha = 'abcdefghijklmnopqrstuvwxyz'
num = 3
t = alpha[num + 1]
i = len(enc)
j = 0
res = ''
while i != 0:
    c = enc[j]
    if ord(c) < ord(t) or ord(c) > 122:
        if ord(c) >= 97 and ord(c) <= ord(alpha[num]):
            c = chr(ord(c) - num + 26)
            if ord(c) > ord(alpha[-1]):
                c = chr(ord(c) - 26)
    else:
        c = chr(ord(c) - num)
    res += c
    j += 1
    i -= 1
print res
# HappyNewYear2019

【春节】解题领红包之三

这道题我查了壳然后不会脱就一直没做。看了 writeup 居然是直接进 ida 就分析了。搜索到 main 函数:

int main_main()
{
  int v0; // ST04_4
  _DWORD *v1; // ST04_4
  _DWORD *v2; // ST04_4
  int v3; // ST04_4
  _DWORD *v4; // ST04_4
  int v5; // ST10_4
  int v6; // ST14_4
  int base64_check; // ST18_4
  int v8; // ST04_4
  int result; // eax
  char v10; // ST0C_1
  int v11; // [esp+0h] [ebp-7Ch]
  int v12; // [esp+4h] [ebp-78h]
  int v13; // [esp+4h] [ebp-78h]
  int v14; // [esp+8h] [ebp-74h]
  int v15; // [esp+Ch] [ebp-70h]
  int v16; // [esp+Ch] [ebp-70h]
  int v17; // [esp+Ch] [ebp-70h]
  char v18; // [esp+Ch] [ebp-70h]
  int v19; // [esp+10h] [ebp-6Ch]
  int v20; // [esp+10h] [ebp-6Ch]
  int v21; // [esp+10h] [ebp-6Ch]
  int v22; // [esp+14h] [ebp-68h]
  int v23; // [esp+14h] [ebp-68h]
  int v24; // [esp+14h] [ebp-68h]
  int v25; // [esp+14h] [ebp-68h]
  unsigned int v26; // [esp+18h] [ebp-64h]
  int v27; // [esp+18h] [ebp-64h]
  int v28; // [esp+1Ch] [ebp-60h]
  int v29; // [esp+1Ch] [ebp-60h]
  int v30; // [esp+20h] [ebp-5Ch]
  int aes_check; // [esp+24h] [ebp-58h]
  int v32; // [esp+28h] [ebp-54h]
  int v33; // [esp+2Ch] [ebp-50h]
  int v34; // [esp+2Ch] [ebp-50h]
  _DWORD *v35; // [esp+30h] [ebp-4Ch]
  _DWORD *v36; // [esp+34h] [ebp-48h]
  _DWORD *v37; // [esp+38h] [ebp-44h]
  int *v38; // [esp+3Ch] [ebp-40h]
  int v39; // [esp+40h] [ebp-3Ch]
  int *v40; // [esp+44h] [ebp-38h]
  void *v41; // [esp+48h] [ebp-34h]
  int *v42; // [esp+4Ch] [ebp-30h]
  void *v43; // [esp+50h] [ebp-2Ch]
  int *key; // [esp+54h] [ebp-28h]
  _DWORD *v45; // [esp+58h] [ebp-24h]
  int *v46; // [esp+5Ch] [ebp-20h]
  void *v47; // [esp+60h] [ebp-1Ch]
  int *uid; // [esp+64h] [ebp-18h]
  _DWORD *v49; // [esp+68h] [ebp-14h]
  int *v50; // [esp+6Ch] [ebp-10h]
  void *v51; // [esp+70h] [ebp-Ch]
  int *v52; // [esp+74h] [ebp-8h]
  void *v53; // [esp+78h] [ebp-4h]
  void *retaddr; // [esp+7Ch] [ebp+0h]

  if ( (unsigned int)&retaddr <= *(_DWORD *)(*(_DWORD *)__readfsdword(0x14u) + 8) )
    runtime_morestack_noctxt();
  v52 = dword_4A04E0;
  v53 = &main_statictmp_0;
  fmt_Println(&v52, 1, 1);
  runtime_newobject(dword_4A04E0, v0);
  v36 = v1;
  runtime_newobject(dword_4A04E0, v1);
  v37 = v2;
  v50 = dword_4A04E0;
  v51 = &main_statictmp_1;
  fmt_Print(&v50, 1, 1);
  uid = dword_498EE0;
  v49 = v36;
  fmt_Scanln(&uid, 1, 1);                       // input uid
  v46 = dword_4A04E0;
  v47 = &main_statictmp_2;
  fmt_Print(&v46, 1, 1);
  key = dword_498EE0;
  v45 = v37;
  fmt_Scanln(&key, 1, 1);                       // input key
  runtime_newobject(dword_4A90C0, v3);
  v35 = v4;
  *v4 = 0x67452301;
  v4[1] = 0xEFCDAB89;
  v4[2] = 0x98BADCFE;
  v4[3] = 0x10325476;
  v4[4] = 0xC3D2E1F0;
  v4[21] = 0;
  v4[22] = 0;
  v4[23] = 0;
  runtime_stringtoslicebyte(0, *v36, v36[1]);
  crypto_sha1___digest__Write(v35, v15, v19, v22, v19, v22);
  crypto_sha1___digest__Sum(v35, 0, 0, 0, v5, v6);// get uid's sha1 digest
  if ( v26 < 0x10 )
    runtime_panicslice(
      v11,
      v12,
      v14,
      v16,
      v20,
      v23,
      v26,
      v28,
      v30,
      aes_check,
      v32,
      v33,
      v35,
      v36,
      v37,
      v38,
      v39,
      v40,
      v41,
      v42,
      v43,
      key,
      v45,
      v46,
      v47,
      uid,
      v49,
      v50,
      v51,
      v52,
      v53);
  v34 = v20;
  encoding_base64___Encoding__DecodeString(encoding_base64_StdEncoding, *v37, v37[1], v16, v20, v23, v26);
  if ( base64_check )
  {
    v42 = dword_4A04E0;
    v43 = &main_statictmp_3;
    result = fmt_Println(&v42, 1, 1);
  }
  else
  {
    main_AesDecrypt(v17, v21, v24, v34, 16, 16, 0, v28);
    if ( aes_check )
    {
      v40 = dword_4A04E0;
      v41 = &main_statictmp_4;
      result = fmt_Println(&v40, 1, 1);
    }
    else
    {
      if ( v29 == 26 && (runtime_memequal(v27, MEMORY[0x4B8A80], 26, v18), v10) )
        fmt_Printf(aSuccess, 73, 0, 0, 0, v25, v27, 26);
      else
        fmt_Printf(&aFailed, 24, 0, 0, 0, v25, v27, v29);
      runtime_newobject(dword_4A04E0, v13);
      v38 = dword_498EE0;
      v39 = v8;
      result = fmt_Scanln(&v38, 1, 1);
    }
  }
  return result;
}

大概看了一遍之后,可以推测,先分别输入 uid 和 key,然后先进行 base64 解密(如果解密失败则报错),然后用 uid 的 sha1 摘要作为 key 来进行 aes 解密(如果解密失败则报错),最后和数据段中一串长度为 26 的字符串比较。具体字符串我们可以 dump 出来:

data = [0x48, 0x61, 0x70, 0x70, 0x79, 0x4E, 0x65, 0x77, 0x59, 0x65, 0x61, 0x72, 0x46, 0x72, 0x6F, 0x6D, 0x35, 0x32, 0x50, 0x6F, 0x4A, 0x69, 0x65, 0x2E, 0x43, 0x6E, 0x4C, 0x69, 0x6E, 0x65, 0x20, 0x49, 0x73, 0x6C, 0x61, 0x6E, 0x64, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6E, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6D, 0x65, 0x4E, 0x65, 0x77, 0x66, 0x6F, 0x75, 0x6E, 0x64, 0x6C, 0x61, 0x6E, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6E, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69]
output = ''
for i in range(26):
  output += chr(data[i])
print output
# HappyNewYearFrom52PoJie.Cn

可以使用 IDA 进行动态调试来验证 AES 的密钥。先输入 uid 和一个可以被成功解码的 base64 字符串,然后在 AES 函数中设下断点,可以看到密钥即为 uid 的 sha1 摘要:

调试中可以从内存里 dump 得到 3f2481363378f23964b9977ab8bad974de108eee 其实这一串数据就是 uid 对应的 sha1 散列值,取前 16 位作为 AES 的密钥。 AES 加密方式为 CBCmain_AesDecrypt() 函数中可以直接看出),补码方式为 PKCS5Padding(AES 解密错误时,会退出程序,但是有异常信息一闪而过,给报错函数下断点即可查看异常信息)。只需要把密钥转化成字节数组,使用 AES/CBC/PKCS5Padding 方式加密 HappyNewYearFrom52PoJie.Cn,最后进行 base64 加密就可得到口令。go 语言实现代码:

package main

import (
    "fmt"
    "bytes"
    "crypto/cipher"
    "crypto/sha1"
    "crypto/aes"
    "encoding/base64"
)

func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
    padding := blockSize - len(ciphertext)%blockSize
    padtext := bytes.Repeat([]byte{byte(padding)}, padding)
    return append(ciphertext, padtext...)
}

func PKCS5UnPadding(origData []byte) []byte {
    length := len(origData)
    unpadding := int(origData[length-1])
    return origData[:(length - unpadding)]
}

func AesEncrypt(origData, key []byte) ([]byte, error) {
    block, err := aes.NewCipher(key)
    if err != nil {
        return nil, err
    }
    blockSize := block.BlockSize()
    origData = PKCS5Padding(origData, blockSize)
    blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
    crypted := make([]byte, len(origData))
    blockMode.CryptBlocks(crypted, origData)
    return crypted, nil
}

func AesDecrypt(crypted, key []byte) ([]byte, error) {
    block, err := aes.NewCipher(key)
    if err != nil {
        return nil, err
    }
    blockSize := block.BlockSize()
    blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
    origData := make([]byte, len(crypted))
    blockMode.CryptBlocks(origData, crypted)
    origData = PKCS5UnPadding(origData)
    return origData, nil
}

func main() {
    uid := "975446"
    h := sha1.New()
    h.Write([]byte(uid))
    bs := h.Sum(nil)
    var aeskey = bs[0:16]
    fmt.Println("AES Key: ", aeskey)
    pass := []byte("HappyNewYearFrom52PoJie.Cn")
    xpass, err := AesEncrypt(pass, aeskey)
    if err != nil {
        fmt.Println(err)
        return
    }
    pass64 := base64.StdEncoding.EncodeToString(xpass)
    fmt.Printf("Ciphertext: %v\n",pass64)
    bytesPass, err := base64.StdEncoding.DecodeString(pass64)
    if err != nil {
        fmt.Println(err)
        return
    }
    tpass, err := AesDecrypt(bytesPass, aeskey)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Printf("Plaintext: %s\n", tpass)
}

【春节】解题领红包之番外篇

番外篇个人感觉应该算是一道 ctf 里的 misc 题了。压缩包里给了一个大部分文字被加密的 md 文件:

# ȐĆŅƃȓƇńƃȒċƝÞɌÇńßɌĉŇƅŕƇŃbȒȼȵßȒĆȵƁȓĉnƁɌćǸß

ƦćƝƁȓĉnƅȓčƞÞɌćÑbȒČŃbȒċÑbŕƇŃþȒČNƃȒĈÑƄȓĊÑƄŕƇņÞȓčƞÞɌćÑbȒċƝÞŘcǸÞȐĆŅBƦĊȵþřÇȵƅȐċŇbɌcńþȓČŇƁŕƇNƀȒČŃBɌćÑBɌċnƄȓĈƝbŗƇƞÞŗčnBŕƇnþȒȻŃBȓĉnƅȒČNƅȒƈŇþŕčȠßŕƇŃƃřčȠbřċȵƀ

ȐčNƄŕƇņƃɌcŅƄɌċnþŕƇŇƁȓƇńƁŕƇńþɌcńƄŕƇńþɌCňƀƦȻƝƃŕƇńþɌCňƀȐĉņþŗcŅƅȒĈÑƄȓĊǸƅȓĈȵþɌćƞßŕƇņÞȒȻŃþɌCňƀɌćǸbȒȼǹßȓĈƝB

[ƦĉņƃŖċŅþŕƇŅƀȒCŅƀȒƈŇþɌcŅƄɌĉŇßŕƇņÞȓčƞÞȒƈňþŕƇńþȓĉnþȓČŇBŗcŅƅɌćƞƁȓćŅƁŕƇņÞȒȻŃþɌCňƁ](//rcnb.xyz)

řĊÑbȒĉȠƀɌćÑbȒċƝÞȓćŅƁɌƈȠƃŕƇŃþȒȻŃþȒĈƞÞȑÇǹƄɌCȠƄƦȻŇƅɌćƞBȐčnÞŗÇÑBřĊÑbɌĆnþŗÇǹb

ȐȼŃßɌćÑbŕƇņÞȒȻŃƄŕƇņÞɌcńþȒCŅbŕȻ

ŘĈÑƀƝƄŘȻŖĊǸƀrcnƃňßɍĉƞƀRČņbRÇrcnbrcnbrcnbŖĊƝƃrcnbrcnbrcnbrČNþȓĉƞƁnƅŔƇńÞrćǹƁȓĆÑƅŔȼŕÇƞƅƞßȐCŅƁȐƇŖĆňƁɌƇȵƃȑĈȠƃNƃƦčƝƄȓĉŕČňƃŇbȐĆȑćnƅŘȼȵßƞßRĆǸƄɌCƞBȑĊŅÞŗĊɌȼŃßŇƁŔcŔƈǹÞȠƁɌĆńƅɍĉƝÞŖÇɌcŇƅŖĆnþńƁȓČňƄŘȻȓȻnƃǸƁɌCȒćȵƁȵƄɌCŅƅȐčŃƀřCřƇŇƁǸþřÇƞbƦČnbRCƝßȐćǹƁŔȻřȻņBǹBȑċŗÇƞƃȠBɌĆÑƃŕčņƃȓƇńbŖčÑbɌĊŗƈÑBRcƞƁȑƇńÞƦČǹƀǸƀŘcŘȻnƅRCņƃŅƄȐĉNÞŘĈÑƄŕčȐćǹbŇÞȓćǹßɌĈŔȻňƀƝbȐÇrCǹÞȓȻŃBńƄɍċńbɌČŗƇnƅȵƀŗċņßRCŇbřČřćÑƀȐĊŃbǸƅɍcȑCȵbǸßȑƇȑCǹƅŘȻŃƃřċŃþnƄRċǹBrƇńƃŖĈȑĉņbƞƅƦĆrCƝÞƦĆÑBņƄrćȑƇÑƅńƄƦƇŗĆnƀŔĆȠƄȐćNƀÑƅƦȼȓĉŇƄȵßȑCǹƄȐȼŗćȠƃŅBȓCȠƁŔċƝßřcŘčŅbƦĊƝƃɌċƞƀnƁŘȻÑbŖčŗCnþȒȻÑƅNþřȼrƈNƁŕĆƝBȐÇňƅȐCŃßŅƄrćƞƀȓĊńƃŖƇǸƁřċŘćŃƁŘȼÑƅȑċȵƀŃþrƇŃßŕĉrćNþȒȻƝƁɌƈȠbƦĊNƅŔCƝßȓČńÞƦċŇbŖƈņƃŖĉȵþnƃɍĉɌƈňÞřčǹBȠbŕĉřċńþņƄȑÇƞƁȒcŘĉǸƅňƃȒcŔĈńßǹƁƦćȓȼǹƁÑƁƦCȑċŇƄȓƈnƄȵƄrcŘčnƃȵßRčȑcNƁrĊNƅȐÇŇƁņƁȒčnƀɌČňbɌĆrȼƞÞŇƃɌCřÇnþňƅȒȼƝBȑcȐȻnBňƁȑċȓcȠbǹþȑƇǹƁrĈŖƈňƁŗcȵbňþřȼƦĈŃƅňßŗcŃƀƦĊŔcńÞŖĉȠƅŃƁȑĊȐÇȠþƞÞɌƇȵƅȐȼɍĉÑBrƇŇƅŔčƞßnƅŗĈɍĆȵƅŖČņbŖĆȠÞȒċÑƃŗċNƃŕȻŃÞNÞŔčŕĆƞƃNƃRČȐĆņƁŃƀřċŃbȓčƝƃȑcŔĆNþȑčȠbŗĆNþŇƁȓčrčŃƄȑĉnþŅþȓȻřcÑƄŖƇÑßȐĆńbŅbŕĊŃßŕČŇÞȒcÑƁȑĆŘÇńƃRƈǸƅŕcȠbņÞȑċRƈŇƀȐcňþńÞƦĈɍCȠƀÑBRĉǸƁŗȼȑƇnƁȵßŕƇŖċƞƅřƇǹþŇƄŖÇȠƃRĈǸƅŕƇņþŔĊřƈňbƝßrƈŕÇǸþŃÞȐĆnbȑĉȑȻǸƃǹƀRƇrƈNbnƄrċrĉŅBƦcňþRċňƁnBŗȼÑƁŕċƞßɍĈŗćņƀǹƁȑĈŅþŔƇňƅŗƇrĊǹƄǸßȒƈǹßŕȻȠBŔćƝþŔȻÑBȓĆǸÞȑċŕĉŃþŃƀŘcřȻÑBŅƀɌƈńƄŔĊÑÞƦĈƞƃȓȼņƁŘȻnƄŔćŖċǸƄŅBŖÇȓĉŅBňƄȐȼŖÇņbǹƅrȻÑÞŔČŅßŔĊNþɌƇȠÞRĉnþřčŕċNþȠþƦȼȠƅRĆÑƄŗćŘčŃƄŖÇÑƄǹbȑĆŖÇǹþƞƄȓcƞƁRCǸƄɍćȒČNƅȓȻňÞņBRĆƞbřƇŖcȠbřȻńƄŗĆŃÞŃBƦĉŗĊNþřĊņßȒĆȠƁȑĊŅBȐƈȵBǹƁřcrĉƞbnƀƦċŘȼÑƀȒÇńƁŗCȠƁƝßrĊǹþŗȻŃƀȒȻɍċNßŖĉǸßŃÞrƇȒȼȠƃřƇŃƃNbŘċƦČňƅŔČnBŗČƞbƞßŔȼŔĊȠƀnƅŖċŕčŇƄǹBŔCřċǹƅȐČňƀƝƀřĈŖČȵßńÞɌCǹƃŔćȓċÑþŕȼƝƄȒcńbǹbȓƈƝƅɌĆȠƄŖćǹBŖƈŘÇƝƅƦĉŃƁŃßŖĉNƃŔĉÑƄŖĈƞþȑČȑČnBŃƁŔČnƃȒĈȓĈNBǸßȐCȠßȐčŅbɍĉƞþƦĉrȻŅBŇßȒȻǸƁŘȼŘċńBňbŘčnƄŘÇȒƈŇƅǹÞřćȐćŅÞƦċŇƄŇbɌƇƦƇńƀňƁrČRČņbȑÇŅßȵƅřȼŖĆǸƀŔCƝƀņÞȓƇrĊŇþňbŕÇŃƄŔƈńÞŘČȐĊƝbřȻǹƃɌČȠBńƄȒƇNþřĊɌćņBŕȼȠƃŖƇňþÑßȓȼȑČÑƅnƄɍĉnÞŗcŘƈňßȓĉȵƄȑcNbȠßƦÇŅƃɍĈƦĊnƁŖÇŅBŔcŃƁńƁɌċňÞŕĉƦCņƅƦȻȵƅȓÇǹƃȓĆȠƃRȻňƃřćǸƀŗƈǹßřĉňbȐČńƁɍĈŇÞÑÞŘćŗÇNbŗȻÑÞRƈǸƃǹƀŕȻRĉƞBńþŘȻŔĆƝƁņBŕȻNBRĉņƃȓČƝƁȐċÑƀRČŕƈňƀrčŇƅȐĊŅÞƦȼǹƁňƃȓĊnþřĈŘCnþȠƀȒcƞƃɌćɌĊȵƅŕƇňƃnƄŔčńÞRČřȼńbŇßŕĊňþŘCǹbŔĈnbŕĊńþȑcŃƄŔĈŔčńbȐčȠBřĉŅƃņƃŘƈɌÇÑÞŇƄȓĉɍċňƅńþŗCřČƝƄRCņÞƝƁŔĈRȼNƅȒCnƃɌƇǹßńÞŕƈŇBŘCŕȼÑBȒÇŃÞǸƁȓȼŕČȠþȵƁȑƈńƀŔcȑƇÑßrƈǸÞrcŃÞŇƅȓćɌćńƀɍćňƀȠƅŘȼǸƁɍĊřčƞÞņƃrĊǸƀŗcȓƈńƀŇƀȐcrĊŅBȓĈȠƁɍćnƁnÞɌƇÑƃȐȼƞßŔCɍćƞbƝBȒcņƁrċnBŗƈȓȻńƃɌCÑBƞƀȒČňßŔƇřƇǹbŖcņƃŕĆňþŕČņƅȒĉŇƅȐĈŇƁȠƃRĉŔƇǸþŘĊȵßŔȼńbȑƈȠBǹBɌčȵƃrčǹƄŔȻƞƅŗȼȒĆƞƀŖĉȵbŕcƝÞȒȼńBrċǸƅŘcȠÞȐčƝbȓĊŅbŘCȠƀɍĆȠƅŕĉNƀȠÞŖćřċńƁńþȓĉȠƁƦȻnƀȓÇɍĈŅƅǸƀȓčȒȻņƀǹÞɍcȑĆȵƃrȻƝƀɌCŃþɍĈȵþŖČņßňƅŗĉÑÞŕƈȑcŃƁǸßȒƇȐÇƞßńbŕƈȵBŕƇnƄȓċȑȼȠBɍċŅÞŗċŅƃƦčńƄňÞRÇrcŅƄȐÇȠÞřčȠÞƞBɌȼɍĈŇþɍĉÑƅǸBrĆňƃŖȻŕčȵbņßŘĊƞƀȐƈnþŘčȓȻÑÞŕcńþņbŔȼɌČÑBɌčȵbȑĈŅBŕĉƞƄÑþȒÇȓȻNƀÑßŘĈÑƀȐȼƝBŔĈȵþɍĊÑßŕĉȒȼnþŕÇņbńþɍĆŅÞŗĊŃƃRċņƅŘcNþȑĆŅƁrƈǸƄȒCƝþŖȻrÇŇbřĊŅƅȑƈŃBƦċnßňƅƦĉÑþȓĈřȼŃƀɍcŃƄȵþɌCřĆNƄǹƄƦȻŔčŅƃnƅrċrCǸƄȓƈŃƀrÇnƁrCÑƅrCȵƀrƈǹßrƈȵƁRĆƞƁrÇŇÞȵßƦČȑȼǸƁǹBȑcɌƈƝÞȒĆŅÞrĆňƃRćŇƁȠƅȓcrc

这里给了一个网站,上面可以解密,得到明文 md 文件:

# Prove your Niubility

Hello there, Welcome to the 52PoJiE Spring Festival 2019 Challenge - RCNB.

To prove you are as NB as RC, complete this trial!

[It's dangerous to go alone, take this!](//rcnb.xyz)

And the key: Which_is_N0t_Th3_Answ3r

With the trial:

7z��'�G�֐'�l×v����2!���!$�x�Z�ˤ�XЂY�=��W�K�ï�z���������r�$]�I��q�Ib��iԎ�2C���Z�`�3��EW�w3X�� ��*2� ']�Kz�,<` ��5�&�
QT�~�z�rq+�I�1԰����r?�R���Y�5X�<rA���U��[���G��^*�O- GP���l��
��.:�7�3��:*J(v��]��,�h����nOˁ��X�&�6�=Z\����g�h�y6I��nNJ�)�&���yCE��A��#�
8��ȍr'�M\?o:��W��Va�)����D��.�5V��Gi��A��)�,~� H¬?���&��V�����~*;�P|�(
\$�e00"�� 荈{�����8�]�-1��_Z��G=�)oPd�
�)���w;����8zOi��|&���]à�'�C�q�����SD>��!��b��*� |�F�
-�'����-�ڷ��� 畢{�ٙ�� �ti��E��ޕ;��
���['��Yl�י*b����G�1�B�����~�:�و��׉��Aenqd�)ü#�EG-:�S/�ACb*[�V�H�l=Vg�-
�۴�b7&���ihCz��KLE0��)��H 咣 BT�0(k����m�"�`��b�ĥq�<IU�1������\��[� k��%���"ɡ� 菽 a8��H��gb��Q J��ZLL�� �*�\$�|�ɡ����R�E�wu��t7#)S�\�����;{l�W�����I�*Y��}��GN�p�k\*�?�2�@�S�}���33���v ���/���^Ӈ��!�R�N��F��5[�2�bvX ��ߍ�E؞%���d��� ��T�@��dy��r��B� ��?aHx�����"�g���� 呴^+��|t$}�x�C.���bp �X�lU|��&׶��}(���O�eq8s=店 �C�#^�c�Q��>�8��^���֙���b6&��i�5FT�m$5�|�X�tA���s��}��.h���Y��r�}�(�,�<W���V�����`�V08K�� -V�CV��}�~d��� 0�y��
q����wWxZe��#q"�״�=�%��h�!��_�������#��ᷫDA8^kJqɊ�=E�{%�m>��k� p
\$�
SL˓`��]y
b
v
��

最后面给出的 trial 看开头显然是个 7z,那上面的 key 应该就是密码了。我把它存为一个新文件,然而这个字符严重干扰了我好几个小时,让懵逼的我一度以为这是题目设计的加密。一开始我 xxd 了一下文件,发现有三个字节 efbfbd 频繁出现 505 次:

根据 7z 文件头 377a bcaf 271c 0004 尝试过替换,一度以为掉进了脑洞的陷阱。直到我看到这篇文章,才知道这串字节就是那个字符。

后来在 github 上找到了 rcnb 的源码,修改 js,将明文每个字节以 int 的形式输出,再用 python 一跑拿到压缩包:

function printRes(str) {
  var res = rcnb.decode(str);
  for (var i = 0; i < res.length; i++) {
    console.log(res[i]);
  }
  // console.log(res)
}

printRes("ŘĈÑƀƝƄŘȻŖĊǸƀrcnƃňßɍĉƞƀRČņbRÇrcnbrcnbrcnbŖĊƝƃrcnbrcnbrcnbrČNþȓĉƞƁnƅŔƇńÞrćǹƁȓĆÑƅŔȼŕÇƞƅƞßȐCŅƁȐƇŖĆňƁɌƇȵƃȑĈȠƃNƃƦčƝƄȓĉŕČňƃŇbȐĆȑćnƅŘȼȵßƞßRĆǸƄɌCƞBȑĊŅÞŗĊɌȼŃßŇƁŔcŔƈǹÞȠƁɌĆńƅɍĉƝÞŖÇɌcŇƅŖĆnþńƁȓČňƄŘȻȓȻnƃǸƁɌCȒćȵƁȵƄɌCŅƅȐčŃƀřCřƇŇƁǸþřÇƞbƦČnbRCƝßȐćǹƁŔȻřȻņBǹBȑċŗÇƞƃȠBɌĆÑƃŕčņƃȓƇńbŖčÑbɌĊŗƈÑBRcƞƁȑƇńÞƦČǹƀǸƀŘcŘȻnƅRCņƃŅƄȐĉNÞŘĈÑƄŕčȐćǹbŇÞȓćǹßɌĈŔȻňƀƝbȐÇrCǹÞȓȻŃBńƄɍċńbɌČŗƇnƅȵƀŗċņßRCŇbřČřćÑƀȐĊŃbǸƅɍcȑCȵbǸßȑƇȑCǹƅŘȻŃƃřċŃþnƄRċǹBrƇńƃŖĈȑĉņbƞƅƦĆrCƝÞƦĆÑBņƄrćȑƇÑƅńƄƦƇŗĆnƀŔĆȠƄȐćNƀÑƅƦȼȓĉŇƄȵßȑCǹƄȐȼŗćȠƃŅBȓCȠƁŔċƝßřcŘčŅbƦĊƝƃɌċƞƀnƁŘȻÑbŖčŗCnþȒȻÑƅNþřȼrƈNƁŕĆƝBȐÇňƅȐCŃßŅƄrćƞƀȓĊńƃŖƇǸƁřċŘćŃƁŘȼÑƅȑċȵƀŃþrƇŃßŕĉrćNþȒȻƝƁɌƈȠbƦĊNƅŔCƝßȓČńÞƦċŇbŖƈņƃŖĉȵþnƃɍĉɌƈňÞřčǹBȠbŕĉřċńþņƄȑÇƞƁȒcŘĉǸƅňƃȒcŔĈńßǹƁƦćȓȼǹƁÑƁƦCȑċŇƄȓƈnƄȵƄrcŘčnƃȵßRčȑcNƁrĊNƅȐÇŇƁņƁȒčnƀɌČňbɌĆrȼƞÞŇƃɌCřÇnþňƅȒȼƝBȑcȐȻnBňƁȑċȓcȠbǹþȑƇǹƁrĈŖƈňƁŗcȵbňþřȼƦĈŃƅňßŗcŃƀƦĊŔcńÞŖĉȠƅŃƁȑĊȐÇȠþƞÞɌƇȵƅȐȼɍĉÑBrƇŇƅŔčƞßnƅŗĈɍĆȵƅŖČņbŖĆȠÞȒċÑƃŗċNƃŕȻŃÞNÞŔčŕĆƞƃNƃRČȐĆņƁŃƀřċŃbȓčƝƃȑcŔĆNþȑčȠbŗĆNþŇƁȓčrčŃƄȑĉnþŅþȓȻřcÑƄŖƇÑßȐĆńbŅbŕĊŃßŕČŇÞȒcÑƁȑĆŘÇńƃRƈǸƅŕcȠbņÞȑċRƈŇƀȐcňþńÞƦĈɍCȠƀÑBRĉǸƁŗȼȑƇnƁȵßŕƇŖċƞƅřƇǹþŇƄŖÇȠƃRĈǸƅŕƇņþŔĊřƈňbƝßrƈŕÇǸþŃÞȐĆnbȑĉȑȻǸƃǹƀRƇrƈNbnƄrċrĉŅBƦcňþRċňƁnBŗȼÑƁŕċƞßɍĈŗćņƀǹƁȑĈŅþŔƇňƅŗƇrĊǹƄǸßȒƈǹßŕȻȠBŔćƝþŔȻÑBȓĆǸÞȑċŕĉŃþŃƀŘcřȻÑBŅƀɌƈńƄŔĊÑÞƦĈƞƃȓȼņƁŘȻnƄŔćŖċǸƄŅBŖÇȓĉŅBňƄȐȼŖÇņbǹƅrȻÑÞŔČŅßŔĊNþɌƇȠÞRĉnþřčŕċNþȠþƦȼȠƅRĆÑƄŗćŘčŃƄŖÇÑƄǹbȑĆŖÇǹþƞƄȓcƞƁRCǸƄɍćȒČNƅȓȻňÞņBRĆƞbřƇŖcȠbřȻńƄŗĆŃÞŃBƦĉŗĊNþřĊņßȒĆȠƁȑĊŅBȐƈȵBǹƁřcrĉƞbnƀƦċŘȼÑƀȒÇńƁŗCȠƁƝßrĊǹþŗȻŃƀȒȻɍċNßŖĉǸßŃÞrƇȒȼȠƃřƇŃƃNbŘċƦČňƅŔČnBŗČƞbƞßŔȼŔĊȠƀnƅŖċŕčŇƄǹBŔCřċǹƅȐČňƀƝƀřĈŖČȵßńÞɌCǹƃŔćȓċÑþŕȼƝƄȒcńbǹbȓƈƝƅɌĆȠƄŖćǹBŖƈŘÇƝƅƦĉŃƁŃßŖĉNƃŔĉÑƄŖĈƞþȑČȑČnBŃƁŔČnƃȒĈȓĈNBǸßȐCȠßȐčŅbɍĉƞþƦĉrȻŅBŇßȒȻǸƁŘȼŘċńBňbŘčnƄŘÇȒƈŇƅǹÞřćȐćŅÞƦċŇƄŇbɌƇƦƇńƀňƁrČRČņbȑÇŅßȵƅřȼŖĆǸƀŔCƝƀņÞȓƇrĊŇþňbŕÇŃƄŔƈńÞŘČȐĊƝbřȻǹƃɌČȠBńƄȒƇNþřĊɌćņBŕȼȠƃŖƇňþÑßȓȼȑČÑƅnƄɍĉnÞŗcŘƈňßȓĉȵƄȑcNbȠßƦÇŅƃɍĈƦĊnƁŖÇŅBŔcŃƁńƁɌċňÞŕĉƦCņƅƦȻȵƅȓÇǹƃȓĆȠƃRȻňƃřćǸƀŗƈǹßřĉňbȐČńƁɍĈŇÞÑÞŘćŗÇNbŗȻÑÞRƈǸƃǹƀŕȻRĉƞBńþŘȻŔĆƝƁņBŕȻNBRĉņƃȓČƝƁȐċÑƀRČŕƈňƀrčŇƅȐĊŅÞƦȼǹƁňƃȓĊnþřĈŘCnþȠƀȒcƞƃɌćɌĊȵƅŕƇňƃnƄŔčńÞRČřȼńbŇßŕĊňþŘCǹbŔĈnbŕĊńþȑcŃƄŔĈŔčńbȐčȠBřĉŅƃņƃŘƈɌÇÑÞŇƄȓĉɍċňƅńþŗCřČƝƄRCņÞƝƁŔĈRȼNƅȒCnƃɌƇǹßńÞŕƈŇBŘCŕȼÑBȒÇŃÞǸƁȓȼŕČȠþȵƁȑƈńƀŔcȑƇÑßrƈǸÞrcŃÞŇƅȓćɌćńƀɍćňƀȠƅŘȼǸƁɍĊřčƞÞņƃrĊǸƀŗcȓƈńƀŇƀȐcrĊŅBȓĈȠƁɍćnƁnÞɌƇÑƃȐȼƞßŔCɍćƞbƝBȒcņƁrċnBŗƈȓȻńƃɌCÑBƞƀȒČňßŔƇřƇǹbŖcņƃŕĆňþŕČņƅȒĉŇƅȐĈŇƁȠƃRĉŔƇǸþŘĊȵßŔȼńbȑƈȠBǹBɌčȵƃrčǹƄŔȻƞƅŗȼȒĆƞƀŖĉȵbŕcƝÞȒȼńBrċǸƅŘcȠÞȐčƝbȓĊŅbŘCȠƀɍĆȠƅŕĉNƀȠÞŖćřċńƁńþȓĉȠƁƦȻnƀȓÇɍĈŅƅǸƀȓčȒȻņƀǹÞɍcȑĆȵƃrȻƝƀɌCŃþɍĈȵþŖČņßňƅŗĉÑÞŕƈȑcŃƁǸßȒƇȐÇƞßńbŕƈȵBŕƇnƄȓċȑȼȠBɍċŅÞŗċŅƃƦčńƄňÞRÇrcŅƄȐÇȠÞřčȠÞƞBɌȼɍĈŇþɍĉÑƅǸBrĆňƃŖȻŕčȵbņßŘĊƞƀȐƈnþŘčȓȻÑÞŕcńþņbŔȼɌČÑBɌčȵbȑĈŅBŕĉƞƄÑþȒÇȓȻNƀÑßŘĈÑƀȐȼƝBŔĈȵþɍĊÑßŕĉȒȼnþŕÇņbńþɍĆŅÞŗĊŃƃRċņƅŘcNþȑĆŅƁrƈǸƄȒCƝþŖȻrÇŇbřĊŅƅȑƈŃBƦċnßňƅƦĉÑþȓĈřȼŃƀɍcŃƄȵþɌCřĆNƄǹƄƦȻŔčŅƃnƅrċrCǸƄȓƈŃƀrÇnƁrCÑƅrCȵƀrƈǹßrƈȵƁRĆƞƁrÇŇÞȵßƦČȑȼǸƁǹBȑcɌƈƝÞȒĆŅÞrĆňƃRćŇƁȠƅȓcrc");
#!/usr/bin/env python
f = open('plain_array.txt', 'rb')
t = f.read()
f.close()
data = t.split('\n')[:-1]
print len(data)
# print data
f = open('trial.7z', 'wb')
for i in range(len(data)):
    f.write(chr(int(data[i])))
f.close()

解压后拿到一个新文件 nb,还是被加密了的:

ȐȼŃƁȓĉnƅŕƇŅƀȓƇŃƅȒċƝþŕƇNƄɌćŃÞɌCȵBȒČNƄɌCňƀɌćÑbȒCŅÞŕƇŇƁȓƇńƁŕƇŅƅȒCņbȒċƝÞȒƈƝƀȒČnƁɌćŃÞȓƈȠƅȓƇNþɌcńBȓĊǸƁȒȼȵbȒƈnbɌCȵßȒȼȠÞȓĉNƁŗćƝƅRćŇbƞƅRȻÑßŘȻŇƁrĊńßŕčȠþRĉNƁƦĈņBƦcǹÞƦćŃbƦĈNƁƦĈȒćƝÞnƅŔĆņÞrȼȒćƝþǸßRĊńþrȻNþrČńßŕčǸÞRĊȵÞrȼȵbŕƇŇÞrĊnÞŔĆnBŘÇƝƃrĉǹþƦćņƅƦcȵƀƦćņBƦcǹÞƦćŃbƦĈNƁƦĈȒćƝÞnƃŔĆǸþRĊƝƃrĉňÞƦĉřƇƞþȵƅrȼņbrCnƃŔĆņßRćńßrȻńßŕčŃBRĊƞƅřȻƞƀřƇǹþƦćȵÞřƈƞþřȻŅþƦcǸƁřȻņƄƦcƞÞřȻŇbřƇǹÞƦćNþƦĈƞƄřȻņƀƦcǸƁřȻņƄƦcƞßřȻņƁƦcǹþƦćņƄƦcƞƄřȻņBƦcǹÞƦćŃbƦĈȵƀƦćȒćƝÞŃƄŔCƞÞřȻŅþƦcňÞƦĉřƇƞþȵƅrȼņbrCŃƄŔCƞßřȻŅÞƦcǹÞƦćȵƄřƈȵƀƦćŅÞƦcňÞƦĉȵƁřƈŅßřƇȒćƝþŃBRĊƞßřȻņƀƦcňÞƦĉȵƄřƈƞÞřȻņƀƦcǹÞƦćNþƦĈƞƅřȻņƀƦcňÞƦĉȵƄřƈƞþřȻŇbřƇǸƁřȻņƄƦcƞÞřȻŇbřƇǹÞƦćNþƦĈƞƄřȻņƀƦcǸƁřȻņƄƦcƞƄřȻȒćƝÞnƃŔĆǸþRĊŇƅrĊŃBrČŃƃŔċńþrȻŅbrċǹÞƦćȵÞřƈȓčnÞnƅrćǸƃŔćÑþŘȻȠBŘĊȵƅŕċRćņßƝƃŔƇȵƅrƇŅÞƦcǹÞƦćȵƁřƈȓčnƄNþřĆŃƃŔċÑƀrÇƞƀřƇǹþƦćņƄƦcƞƅřȻņƁƦcňÞƦĉņƄƦcňßƦcņƀƦcǸßřȻȵƃřƈňßƦcŇBřƇǸƄřȻņƄƦcȵƀƦćȒćƝÞǸbŔćňÞRČNƅŘCǹÞƦćŃbƦĈňÞƦcƞƀřƇǸƄřȻȒĉŅBǹÞrčȠbrčŅÞŔcÑƃRCȵbŕƇnƅrćŃƄŔCƞßřȻŅÞƦcňÞƦĉȵƁřƈƞƄřȻŇbřƇňÞƦĉȵƁřƈŅßřƇŇBřƇǸƁřȻņƄƦcƞßřȻƞƀřƇǹþƦćȵÞřƈÑbřȻřČȵßǸÞRĊǸþRĊǹÞrčȠbrčǸbŔćņþRćȠƃŘĊŃƄrČŃBRĊƞƅřȻņƀƦcǸƁřȻņƄƦcƞƅřȻƞƀřƇǹÞƦćȵƀřƈNƁƦĈƞƀřƇňÞƦĉȵƄřƈƞþřȻŇbřƇǸƁřȻņƄƦcƞƄřȻņBƦcǸßřȻȵþřƈȵƀƦćȒćƝƄȵƅŔȻNƅRĉǸƅŘCņbrCȠBŔĆŅßřƇřČȵƁȵƅŔȻńþrȻƝƃrĉǸƃřȻȵÞřƈNƁƦĈņBƦcňÞƦĉȵƁřƈŇbƦĆŅÞƦcǹþƦćņƅƦcȵƀƦćŇBřƇǸƅřȻȵþřƈƞßřȻņƀƦcǸƄřȻȵƄřƈȵƀƦćņƀƦcǹÞƦćŃbƦĈNƁƦĈņƁƦcǹÞƦćNþƦĈƞßřȻřČȵƅnƃŔĆƝƃrƈǹƀŕĉŇÞrĊnƃŔĆȵƁrȼņbŔcŃƃrČǸbŔćņßRćÑƀrƇǸßřȻņƄƦcƦȼŇƅnßrćǹbRĊŅbrȻǹÞŕĊňÞƦĉřƇÑbǸþŕĉńƅŕčƞƀRȻÑBRCƝBrƈŃbřĆŃÞŖĊnƀŘÇǹƀŕĉŇƄrĊƝƃŔƇȵƄrȼŃƀrČņBrCȠþRĉňßƦcřċÑƅRĆŇþŖƇŃÞǹƅƦćȒĉŅBȵƁrȼňßŕċȠßŔčƞßřȻņƁƦcǹÞƦćřƇƞþǹÞrčņbrCnƃŔĆÑƃRCȵbŕƇņbrCnÞŔĆnBŘÇŇƅrĊŃƄrČŃBRĊƞƅřȻņƀƦcǸƃřȻȵßřƈƞßřȻƞƀřƇǸƁřȻņƄƦcƞÞřȻŇbřƇǹÞƦćNþƦĈƞƄřȻņƀƦcǸƁřȻņƄƦcƞßřȻƞƀřƇǹÞƦćȵÞřƈƞƄřȻŇBřƇǸƅřȻȵþřƈƞƅřȻȒćƝƅŃÞŖĊnBŘÇŅbrȻȠBrčǸÞRĊǸßRĊŅßŔcŃƁřĆǹbRĊȵßrȼƞbŘČŇþrĊǸÞRĊÑBRCǹƄrčńƅŕčŃƄŔCƞßřȻņƁƦcǹÞƦćȵÞřƈȓČŃƅƝƅƦcNþƦĈňßƦcņBƦcǹßƦćńßřƇňßƦcņƀƦcǸƅřȻřčȠbŅþƦcǹƅƦćȵƄřƈƞÞřȻƞƀřƇ

然后一层层解密拿到 key:

Well done! It seems that you have great programming skills.

ȐȼŃßɌCȵƃȒȼȵbȒƈnbɌÇńßɌĈȠƃȒȻŃBȓƈȠƃȒȼȵbȒČŃBɌCňƀȒĊŇßɌcńþȓČŇƁŕƇņÞȒȻŃƄŕƇŅƅȓƇŃƃȒȼȠbȒCņƁɌCňƀȒCŅƀȒĉȠƀɌćÑbɌcŅƄɌĉņƄȒȻńƄɌĉŇÞŕƇņÞȒȻŃƄŕƇŃbȒČŃƄŕƇńBȒČnƁȓȼǸß

ŗĆnƀȒćnþŕƇnþȓƇńƅɌƇƝƄřĈƝßŗƇȠbȓčȵbȒȼƞþŗcŅƅȑĉȠƁȒCŅƀɌćŃÞɌćÑßŕƇŅþȓČňBɌČŅƅȓĊǸƄɌcńƄŕƇńþȒĆȵþɌĉŇÞŕƇŃƃřčȠbřċȵƀȓCÑBřćŃBŖČȵƃɌćǸƀȓƈȠßŘčŅƄŗĉȠƄȒȼȵƅȒȻŅBȒĆƝƃȒĈÑƄȓĊņBřƇNƁɌƇƞbɌCƝßȐĉņþƦȻƝƃŗĈńƀɌCƝB

;) ȐcňÞŗcŅƅȒCŅƀȒĉȠƀȒȻŃƄɌcńƄŖċŅþŕƇņÞȒȻŃƄŕƇŅþȒČŃßŘčńbƦȻŇƅɌČÑþɌƈǹƃɌĉŅßȒCŅƅȒČnBƦȻƝƃȑÇƝƄŘCNƁȐĉņþ
Well done! It seems that you have great programming skills.

Wishing you happiness during the holidays and throughout the New Year!

- by Coxxs@52PoJiE, [Want to know more about RCNB.js?](https://github.com/Coxxs/RCNB.js)

;) Oh, and here's the key: N0w_y0u_are_NB_A5_RC

感谢的话

最后感谢吾爱破解大佬们的辛勤付出!

参考网站

https://github.com/Coxxs/RCNB.js
https://travis-ci.com/Coxxs/RCNB.js
https://liudanking.com/golang/utf-8_replacement_character/
https://www.52pojie.cn/thread-873265-1-1.html


wp re

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!

【译】Radare2之旅-Part2:Exploitation
【译】Radare2之旅-Part1:Simple crackme