鹏城杯2022 writeup

reverse

rota

rota

1.base64码表替换

2.自定义取码表字符,逆向回去。

code 1

 do                                            // 换表的base64
  {
    q0 = input[j];
    enc2 += 4;
    q1 = input[j + 1];
    *(enc2 - 4) = aXiizduaoglak6j[(unsigned __int64)q0 >> 2];
    qj = q0;
    q2 = (unsigned __int8)input[j + 2];
    j += 3i64;
    *(enc2 - 3) = aXiizduaoglak6j[(16i64 * (qj & 3)) | ((unsigned __int64)q1 >> 4)];
    *(enc2 - 2) = aXiizduaoglak6j[(4i64 * (q1 & 0xF)) | ((unsigned __int64)q2 >> 6)];
    *(enc2 - 1) = aXiizduaoglak6j[q2 & 0x3F];
  }
  while ( j < 30 );

code2

   i1 = 0;
    while ( (unsigned __int8)v4[offset - 1] != aXiizduaoglak6j[i1] )// enc[i] != aXiizduaoglak6j[ii]
    {
      if ( ++i1 >= 64 )
      {
        LOBYTE(i1) = 0;
        break;
      }
    }
    v11 = s2;
    v12 = (s2 + m[(s1 + (_BYTE)i1) & 63]) & 0x3F;// &63, m[0-63]中取第一个
    v13 = (s1 + 1) & 0x3F;
    // m[v12+64]  [64-128]区域取
    // m[xx+128]  [128-192]区域取
    v14 = (unsigned __int8)m[((s3 + m[v12 + 64]) & 0x3F) + 128];
    m[192] = v13;                               // s1 = v13
    *(v4 - 1) = aXiizduaoglak6j[v14];           // enc[i] 置换为 table[i]

base64table

XiIzDuAoGlaK6JcjM3g/9YQmHBOsxn1hLZ4w7Tt0PV5pNqUFC+rE2dSfyvWe8kRb=

爆破法1

patch rota,最后打印输出加密字符。进行爆破

main结尾处patch

  sub_7FF6477510E0((__int64)m);                 // v23未初始化--- 一堆0
  sub_7FF647751E10(m, (__int64)enc1, (__int64)tmp);
  sub_7FF647751020("%s\n", tmp);
# 取自qq群的朋友,不知道哪个战队
from itertools import product
from alive_progress import alive_bar
import os

table = "0123456789abcdef"
enc_flag = "ksPhS/34MXifj+Ibtjud2Tikj5HkA7iTpbaNELBebOaIm"
flag = ""
while len(flag) < 32:
    with alive_bar(len(table) ** 3) as bar:
        for i in product(table, repeat=3):
            s = "".join(i)
            tmp = os.popen(f"echo {(flag+s)[:32]}|.\\rota.exe").readlines()[0]
            n = len(flag) // 3
            l = n * 4
            r = (n + 1) * 4
            if tmp[l:r] == enc_flag[l:r]:
                flag += s
                flag = flag[:32]
                break
            bar()
    print(flag)

爆破法2 - WHT战队

不会弄GetModuleHandleA和compute 未定义 。有会的教我一下。


char p_base_table[] = "XiIzDuAoGlaK6JcjM3g/9YQmHBOsxn1hLZ4w7Tt0PV5pNqUFC+rE2dSfyvWe8kRb=";

char key[] =
{
    0x33, 0x34, 0x2C, 0x36, 0x1D, 0x12, 0x1E, 0x0C, 0x1A, 0x3C, 0x29, 0x10, 0x20, 0x14, 0x3D, 0x3B,
    0x19, 0x08, 0x0E, 0x1F, 0x30, 0x05, 0x38, 0x03, 0x11, 0x1B, 0x17, 0x21, 0x2E, 0x04, 0x18, 0x23,
    0x2B, 0x02, 0x27, 0x37, 0x1C, 0x24, 0x39, 0x3F, 0x35, 0x2D, 0x26, 0x13, 0x2A, 0x0A, 0x00, 0x07,
    0x3E, 0x01, 0x28, 0x2F, 0x32, 0x22, 0x0D, 0x06, 0x25, 0x3A, 0x09, 0x0F, 0x16, 0x0B, 0x15, 0x31,
    0x0C, 0x2C, 0x0D, 0x21, 0x22, 0x09, 0x02, 0x39, 0x31, 0x17, 0x1A, 0x33, 0x06, 0x24, 0x10, 0x04,
    0x1B, 0x0B, 0x34, 0x12, 0x38, 0x27, 0x0E, 0x20, 0x2B, 0x2E, 0x00, 0x13, 0x3E, 0x3A, 0x05, 0x1E,
    0x36, 0x08, 0x32, 0x29, 0x19, 0x23, 0x3D, 0x3B, 0x3C, 0x3F, 0x37, 0x30, 0x18, 0x16, 0x35, 0x25,
    0x0A, 0x2D, 0x28, 0x26, 0x15, 0x11, 0x07, 0x1D, 0x2A, 0x0F, 0x1F, 0x14, 0x01, 0x1C, 0x03, 0x2F,
    0x13, 0x0D, 0x35, 0x31, 0x07, 0x11, 0x1B, 0x23, 0x0B, 0x0C, 0x10, 0x25, 0x2B, 0x21, 0x33, 0x18,
    0x27, 0x29, 0x02, 0x2F, 0x28, 0x30, 0x0E, 0x19, 0x3C, 0x08, 0x34, 0x20, 0x3D, 0x2E, 0x05, 0x15,
    0x2C, 0x1C, 0x36, 0x22, 0x1E, 0x24, 0x38, 0x0A, 0x3F, 0x1A, 0x04, 0x26, 0x16, 0x2A, 0x3A, 0x1F,
    0x2D, 0x32, 0x06, 0x37, 0x03, 0x3B, 0x00, 0x17, 0x1D, 0x12, 0x09, 0x01, 0x3E, 0x39, 0x0F, 0x14,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

auto a = GetModuleHandleA("rota.exe");
compute func = (compute)((long long)a + 0x1E10);

char input[] = "6/GEJz9SXGXCXXXXXXXXXiPIXXXXXXXXXXXXXXXXXXX=";
char passwd[] = "ksPhS/34MXifj+Ibtjud2Tikj5HkA7iTpbaNELBebOaIm";

char result[256] = { 0 };

for (int i = 0; i < 45; ++i)
{
    for (int j = 0; j <= sizeof(p_base_table); ++j)
    {
        memcpy(input, result, i);
        input[i] = p_base_table[j];
        char out[256] = { 0 };
        char temp_key[sizeof(key)] = { 0 };
        memcpy(temp_key, key, sizeof(key));
        func(temp_key, input, out);
        if (0 == memcmp(passwd, out, i + 1))
        {
            result[i] = p_base_table[j];
            break;
        }
    }
}

printf("%s", result);

逆向法:

加密过程

Maps = bytearray(b'XiIzDuAoGlaK6JcjM3g/9YQmHBOsxn1hLZ4w7Tt0PV5pNqUFC+rE2dSfyvWe8kRb=')
sbox = [0x33, 0x34, 0x2C, 0x36, 0x1D, 0x12, 0x1E, 0x0C, 0x1A, 0x3C, 0x29, 0x10, 0x20, 0x14, 0x3D, 0x3B, 0x19, 0x08, 0x0E, 0x1F, 0x30, 0x05, 0x38, 0x03, 0x11, 0x1B, 0x17, 0x21, 0x2E, 0x04, 0x18, 0x23, 0x2B, 0x02, 0x27, 0x37, 0x1C, 0x24, 0x39, 0x3F, 0x35, 0x2D, 0x26, 0x13, 0x2A, 0x0A, 0x00, 0x07,
        0x3E, 0x01, 0x28, 0x2F, 0x32, 0x22, 0x0D, 0x06, 0x25, 0x3A, 0x09, 0x0F, 0x16, 0x0B, 0x15, 0x31, 0x0C, 0x2C, 0x0D, 0x21, 0x22, 0x09, 0x02, 0x39, 0x31, 0x17, 0x1A, 0x33, 0x06, 0x24, 0x10, 0x04, 0x1B, 0x0B, 0x34, 0x12, 0x38, 0x27, 0x0E, 0x20, 0x2B, 0x2E, 0x00, 0x13, 0x3E, 0x3A, 0x05, 0x1E,
        0x36, 0x08, 0x32, 0x29, 0x19, 0x23, 0x3D, 0x3B, 0x3C, 0x3F, 0x37, 0x30, 0x18, 0x16, 0x35, 0x25, 0x0A, 0x2D, 0x28, 0x26, 0x15, 0x11, 0x07, 0x1D, 0x2A, 0x0F, 0x1F, 0x14, 0x01, 0x1C, 0x03, 0x2F, 0x13, 0x0D, 0x35, 0x31, 0x07, 0x11, 0x1B, 0x23, 0x0B, 0x0C, 0x10, 0x25, 0x2B, 0x21, 0x33, 0x18,
        0x27, 0x29, 0x02, 0x2F, 0x28, 0x30, 0x0E, 0x19, 0x3C, 0x08, 0x34, 0x20, 0x3D, 0x2E, 0x05, 0x15, 0x2C, 0x1C, 0x36, 0x22, 0x1E, 0x24, 0x38, 0x0A, 0x3F, 0x1A, 0x04, 0x26, 0x16, 0x2A, 0x3A, 0x1F, 0x2D, 0x32, 0x06, 0x37, 0x03, 0x3B, 0x00, 0x17, 0x1D, 0x12, 0x09, 0x01, 0x3E, 0x39, 0x0F, 0x14,
        0x00, 0x00, 0x00, 0x3F, 0xFB, 0x7F, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0xFB, 0x7F, 0x00, 0x00, 0x6B, 0x73, 0x50, 0x68, 0x53, 0x2F, 0x33, 0x34, 0x4D, 0x58, 0x69, 0x66, 0x6A, 0x2B, 0x49, 0x62, 0x74, 0x6A, 0x75, 0x64, 0x32, 0x54, 0x69, 0x6B, 0x6A, 0x35, 0x48, 0x6B, 0x41, 0x37, 0x69, 0x54,
        0x70, 0x62, 0x61, 0x4E, 0x45, 0x4C, 0x42, 0x65, 0x62, 0x4F, 0x61, 0x49, 0x6D, 0x00, 0x00, 0x00]
box1 = sbox[0:64]
box2 = sbox[64:128]
box3 = sbox[128:192]
idx_1, idx_2, idx_3 = sbox[192], sbox[193], sbox[194]  # 0 0 0

inp = bytearray(b"XzD+6/D+6/D+6/D+6/D+6/D+6/D+6/D+6/D+6/D+6/D=\x00")
print(len(inp))
out = bytearray([0] * 45)

for i in range(45):
        idx = Maps.find(inp[i])
        if idx == -1:
            idx = 0
        v12 = (idx_2 + box1[(idx_1 + idx) & 0x3f]) & 0x3f
        v14 = box3[(idx_3 + box2[v12]) & 0x3f]
        out[i] = Maps[v14]

        idx_1 = (idx_1 + 1) & 0x3F
print(idx_1)

print(out)

逆向回去

Maps = bytearray(b'XiIzDuAoGlaK6JcjM3g/9YQmHBOsxn1hLZ4w7Tt0PV5pNqUFC+rE2dSfyvWe8kRb=')
sbox = [0x33, 0x34, 0x2C, 0x36, 0x1D, 0x12, 0x1E, 0x0C, 0x1A, 0x3C, 0x29, 0x10, 0x20, 0x14, 0x3D, 0x3B, 0x19, 0x08, 0x0E, 0x1F, 0x30, 0x05, 0x38, 0x03, 0x11, 0x1B, 0x17, 0x21, 0x2E, 0x04, 0x18, 0x23, 0x2B, 0x02, 0x27, 0x37, 0x1C, 0x24, 0x39, 0x3F, 0x35, 0x2D, 0x26, 0x13, 0x2A, 0x0A, 0x00, 0x07,
        0x3E, 0x01, 0x28, 0x2F, 0x32, 0x22, 0x0D, 0x06, 0x25, 0x3A, 0x09, 0x0F, 0x16, 0x0B, 0x15, 0x31, 0x0C, 0x2C, 0x0D, 0x21, 0x22, 0x09, 0x02, 0x39, 0x31, 0x17, 0x1A, 0x33, 0x06, 0x24, 0x10, 0x04, 0x1B, 0x0B, 0x34, 0x12, 0x38, 0x27, 0x0E, 0x20, 0x2B, 0x2E, 0x00, 0x13, 0x3E, 0x3A, 0x05, 0x1E,
        0x36, 0x08, 0x32, 0x29, 0x19, 0x23, 0x3D, 0x3B, 0x3C, 0x3F, 0x37, 0x30, 0x18, 0x16, 0x35, 0x25, 0x0A, 0x2D, 0x28, 0x26, 0x15, 0x11, 0x07, 0x1D, 0x2A, 0x0F, 0x1F, 0x14, 0x01, 0x1C, 0x03, 0x2F, 0x13, 0x0D, 0x35, 0x31, 0x07, 0x11, 0x1B, 0x23, 0x0B, 0x0C, 0x10, 0x25, 0x2B, 0x21, 0x33, 0x18,
        0x27, 0x29, 0x02, 0x2F, 0x28, 0x30, 0x0E, 0x19, 0x3C, 0x08, 0x34, 0x20, 0x3D, 0x2E, 0x05, 0x15, 0x2C, 0x1C, 0x36, 0x22, 0x1E, 0x24, 0x38, 0x0A, 0x3F, 0x1A, 0x04, 0x26, 0x16, 0x2A, 0x3A, 0x1F, 0x2D, 0x32, 0x06, 0x37, 0x03, 0x3B, 0x00, 0x17, 0x1D, 0x12, 0x09, 0x01, 0x3E, 0x39, 0x0F, 0x14,
        0x00, 0x00, 0x00, 0x3F, 0xFB, 0x7F, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0xFB, 0x7F, 0x00, 0x00, 0x6B, 0x73, 0x50, 0x68, 0x53, 0x2F, 0x33, 0x34, 0x4D, 0x58, 0x69, 0x66, 0x6A, 0x2B, 0x49, 0x62, 0x74, 0x6A, 0x75, 0x64, 0x32, 0x54, 0x69, 0x6B, 0x6A, 0x35, 0x48, 0x6B, 0x41, 0x37, 0x69, 0x54,
        0x70, 0x62, 0x61, 0x4E, 0x45, 0x4C, 0x42, 0x65, 0x62, 0x4F, 0x61, 0x49, 0x6D, 0x00, 0x00, 0x00]
box1 = sbox[0:64]
box2 = sbox[64:128]
box3 = sbox[128:192]

inp = bytearray(b"ksPhS/34MXifj+Ibtjud2Tikj5HkA7iTpbaNELBebOaIm")
# inp = bytearray(b'yl3bWT94MekETq0yejDlqVN/jmtXV+iWmbHM+4vTbEpIm')

print(len(inp))
out = bytearray([0] * 45)

for index in range(44, -1 , -1):
    v14 = Maps.find(inp[index])
    v12 = box2.index(box3.index(v14))
    idx = (box1.index(v12) - index) & 0x3f

    out[index] = Maps[idx]

print(out)

换表解码:

# base64 自定义变化码表
import base64

cipher = 'cAJ7BzX+6zHrHwnTc/i7Bz6f6t6EBQDvc/xfHt9d6S9=='
my_base64chars = "XiIzDuAoGlaK6JcjM3g/9YQmHBOsxn1hLZ4w7Tt0PV5pNqUFC+rE2dSfyvWe8kRb"
STD_BASE64CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

cipher = cipher.translate(str.maketrans(my_base64chars, STD_BASE64CHARS))
data = base64.b64decode(cipher)
print(data)

# 8cdd01062b7e90dd372c3ea9977be53e

baby_re

jadx打开

onCreate里有

        setContentView(inflate.getRoot());
        ((Button) _$_findCachedViewById(R.id.btn)).setOnClickListener(new MainActivity$$ExternalSyntheticLambda0(this, 
        new int[]{119, 9, 40, 44, 106, 83, 126, 123, 33, 87, 113, 123, 112, 93, 125, 127, 41, 82, 44, 127, 39, 3, 126, 125, 119, 87, 47, 125, 33, 6, 44, 127, 112, 0, 126, 123, 115, 24}));
    }
    
        /* renamed from: onCreate$lambda-0  reason: not valid java name */
        public static final void m20onCreate$lambda0(MainActivity this$0, int[] $c, View it) {
            Intrinsics.checkNotNullParameter(this$0, "this$0");
            Intrinsics.checkNotNullParameter($c, "$c");
            int[] array = ((EditText) this$0._$_findCachedViewById(R.id.input)).getText().toString().chars().toArray();
            Intrinsics.checkNotNullExpressionValue(array, "flag.toArray()");
            if (Arrays.equals(this$0.baby_xor(array), $c)) { // 关键比较
                Toast.makeText(this$0, "Success", 1).show();
            } else {
                Toast.makeText(this$0, "Failed", 0).show();
            }
        }
        public final native int[] baby_xor(int[] iArr); // native在so中

解压用ida打开so文件

__int64 __fastcall Java_com_example_createso_MainActivity_baby_1xor(__int64 a1, __int64 a2, __int64 a3)
{
  int i; // [rsp+14h] [rbp-2Ch]
  __int64 IntArrayElements; // [rsp+18h] [rbp-28h]
  unsigned int ArrayLength; // [rsp+24h] [rbp-1Ch]

  ArrayLength = _JNIEnv::GetArrayLength(a1, a3);
  IntArrayElements = _JNIEnv::GetIntArrayElements(a1, a3, 0LL);
  for ( i = 0; i < (int)ArrayLength; ++i )
    *(_DWORD *)(IntArrayElements + 4LL * i) ^= key[i % 4];
  _JNIEnv::SetIntArrayRegion(a1, a3, 0LL, ArrayLength, IntArrayElements);
  return a3;
}
双击看key  [56h, 57h ,58h, 59h]

解密。没解出来。翻了一下so里有个hidekey的函数。按x定位。它在init_array中。初始化时执行了。

_DWORD *hide_key(void)
{
  _DWORD *result; // rax

  result = key;
  key[0] ^= 0x47u;
  key[1] ^= 0x32u;
  key[2] ^= 0x11u;
  key[3] ^= 0x12u;
  return result;
}

解密

enc =[ 0x77,0x9,0x28,0x2c,0x6a,0x53,0x7e,0x7b,0x21,0x57,0x71,0x7b,0x70,0x5d,0x7d,0x7f,0x29,0x52,0x2c,0x7f,0x27,0x3,0x7e,0x7d,0x77,0x57,0x2f,0x7d,0x21,0x6,0x2c,0x7f,0x70,0x0,0x7e,0x7b,0x73,0x18]
key = [0x56, 0x57, 0x58, 0x59]
key[0] ^= 0x47
key[1] ^= 0x32
key[2] ^= 0x11
key[3] ^= 0x12


print(len(enc))
lst = []
for i, c in enumerate(enc):
    print(chr(c ^ key[i % 4]), end='')
#  flag{6700280a84487e46f76f2f60ce4ae70b}

Maze

__int64 sub_40500A()
{
  _QWORD *v0; // rbp
  char v2; // [rsp+Fh] [rbp-29h] BYREF
  _QWORD *v3; // [rsp+10h] [rbp-28h] BYREF
  unsigned __int64 v4; // [rsp+18h] [rbp-20h]

  v4 = __readfsqword(0x28u);
  sub_404CD9();
  v0 = *(_QWORD **)(*(_QWORD *)(*(_QWORD *)(qword_5D3680 + 8) + 8LL) + 8LL);
  v3 = *(_QWORD **)(*(_QWORD *)(*(_QWORD *)(*(_QWORD *)(qword_5D36A0 + 8) + 8LL) + 8LL) + 8LL);
  *((_BYTE *)v3 + 27) = 1;
  print2(qword_5D45C0, "Welcome to Hexagonal maze\nplz enter the foot print\n");
  v2 = 0;
  do
  {
    printf(qword_5D45C0, (__int64)"> ", 2LL);
    scanf(qword_5D46E0, &v2);
    check_cur(&v3, v2); // 检查每一步
  }
  while ( v3 != v0 ); // 要v3要走到v0的位置才算结束
  printf(qword_5D45C0, (__int64)"flag is md5 your input", 22LL);
  sub_46D7E0(qword_5D45C0);
  if ( __readfsqword(0x28u) != v4 )
    sub_52CB40();
  return 0LL;
}
_QWORD *__fastcall check_cur(_QWORD **av3, char a2)
{
  _QWORD *v2; // rax
  _QWORD *v3; // rax
  _QWORD *result; // rax
  _QWORD *v5; // rax

  switch ( a2 )
  {
    case 'l':
      if ( *((_BYTE *)*av3 + 24) || (v3 = (_QWORD *)**av3) == 0LL ) // qword av3_addr+24=1时退出, 然后将av3的地址给av3作为新指针
        exit(0);
      *av3 = v3;
      break;
    case 'r':
      if ( *((_BYTE *)*av3 + 25) || (v5 = (_QWORD *)(*av3)[1]) == 0LL ) // qword av3_addr+25=1时退出, 然后将av3 + 8(qword长度为8)地址给av3作为新指针
        exit(0);
      *av3 = v5;
      break;
    case 't':
      if ( *((_BYTE *)*av3 + 26) || (v2 = (_QWORD *)(*av3)[2]) == 0LL ) // qword av3_addr+25=1时退出, 然后将av3 + 16(qword长度为8)地址给av3作为新指针
        exit(0);
      *av3 = v2;
      break;
    default:
      exit(0);
  }
  result = *av3;
  if ( *((_BYTE *)*av3 + 27) )
    exit(0);
  *((_BYTE *)result + 27) = 1;
  return result;
}

类似地下城选关卡的效果 。

Misc

Misc_water

题目提示:water -- 水印
文件名 ʍɐʇǝɹ‾dıɔʇnɹǝ 也提示是了这是water_picture倒过来的。

中间的一个文件就是16进制倒序。

png用010提取出3个文件。中间的文件16进制反序重组。

图2使用傅利叶变换得到密码(脚本或52pojie的水印工具)

ZC4#QaWbW

crc32恢复png。得到flag

PCL{f0b31d6f9abc59f34815678c31d79178}

简单取证

cmdscan提取到密码。

filescan恢复secret文件。是倒序的压缩包。逆序恢复。解压。

解压后用gnuplot画坐标。

#flag{a6b93e36-f097-11ec-a9b2-5254002d2b31}

babybit

用Misc_Windows Registry Recovery找到SYSTEM文件。再找ROOT\ControlSet001\Control\FVEStats下面的OsvEncryptInit和OsvEncryptComplete

按格式填写一下。

PCL{2022/6/13_15:17:39_2022/6/13_15:23:46}

what_is_log

1.sudo sysdig -r file.scap > 2.log
2. 看了一会儿,过滤出mysql, write, 长字符,搜索 mysql.*write.*\w{18,} 找到flag

# 1555a651a13ec074ce725383214fd7cc
posted @ 2022-07-02 16:32  wgf4242  阅读(408)  评论(0编辑  收藏  举报