polar2024冬季个人挑战赛 re部分题解
1438911687251843 发表于 江西 CTF 91浏览 · 2024-12-08 12:47

L00K_at_h3r3

NSpark壳,直接手脱

x32dbg打开,按一次f9进入程序领空,一路f8,直到f4过两个loop

然后再按几次f8就可以跳出壳了,在这里dump就行

壳被脱掉了

ida打开

只有xor,直接上脚本

a = ['lfkmqw','nqT','kixS','ka9jR','h|>cQ','g<}<']

for i in range(len(a)):
    y = 0xa + i
    print(''.join([chr(ord(x)^y)for x in a[i]]),end='')

ezpack

这又来个ASpack,还是手脱,使用x32dbg

先一个f9进入程序领空,然后一路f7,直到跳到这里

双击jne,然后按f4跳到里面(这里需要手动跳进去)

跳到ret后再跳一次就到oep了,直接dump

这里查壳还是可以查到,但是不用管他,我们dump出来的可以直接用

ida打开后看到的就是start函数,shift+f12找字符串交叉引用进入main函数

主要加密逻辑

BOOL __cdecl sub_401738(int a1)
{
  char Str1[50]; // [esp+1Ah] [ebp-3Eh] BYREF
  int i; // [esp+4Ch] [ebp-Ch]

  if ( sub_40172E() )
  {
    sub_40160C(aDetectedDebugg);
    return 0;
  }
  else
  {
    for ( i = 0; i <= 31; ++i )
      Str1[i] = *(_BYTE *)(i + a1) ^ 0xC;
    Str1[32] = 0;
    return strcmp(Str1, &Str2) == 0;
  }
}

还是很简单的,只有一个异或,str1是已知的

脚本:

a = '>4i44oo4?i=n>:m;8m4=oo4i;>?4>h9m'
print(''.join([chr(ord(i)^0xc)for i in a]))

先脱upx,直接工具脱就行

主函数有两个加密,第一个加密flag,第二个加密str

str已知,为"hwGwg88Y

第一个加密就不多说了

第二个加密大概是重排字符串吧,但是好像没什么用

void __fastcall sub_140011820(const char *a1, int a2, __int64 a3)
{
  int v3; // [rsp+24h] [rbp+4h]
  _QWORD *Block; // [rsp+48h] [rbp+28h]
  int i; // [rsp+64h] [rbp+44h]
  int v6; // [rsp+84h] [rbp+64h]
  int v7; // [rsp+A4h] [rbp+84h]
  int j; // [rsp+C4h] [rbp+A4h]
  int v9; // [rsp+E4h] [rbp+C4h]
  int k; // [rsp+104h] [rbp+E4h]
  int m; // [rsp+124h] [rbp+104h]
  int n; // [rsp+144h] [rbp+124h]

  sub_1400113A2(&unk_140024014);
  v3 = j_strlen(a1);
  Block = malloc(saturated_mul(a2, 8ui64));
  for ( i = 0; i < a2; ++i )
  {
    Block[i] = malloc(v3);
    j_memset(Block[i], 0, v3);
  }
  v6 = 0;
  v7 = 1;
  for ( j = 0; j < v3; ++j )
  {
    *(Block[v6] + j) = a1[j];
    if ( v6 )
    {
      if ( v6 == a2 - 1 )
        v7 = -1;
    }
    else
    {
      v7 = 1;
    }
    v6 += v7;
  }
  v9 = 0;
  for ( k = 0; k < a2; ++k )
  {
    for ( m = 0; m < v3; ++m )
    {
      if ( *(Block[k] + m) )
        *(a3 + v9++) = *(Block[k] + m);
    }
  }
  *(a3 + v9) = 0;
  for ( n = 0; n < a2; ++n )
    free(Block[n]);
  free(Block);
}
enc = list('"hwGwg88Y')

for i in range(len(enc)):
    enc[i] = chr(ord(enc[i]) - i - 1)
enc.reverse()
print(''.join(enc))

P01arCtf!

然后md5加密一下就行

delf

ida反编译,找到加密逻辑

void __fastcall encrypt(const char *a1)
{
  char v1; // [rsp+13h] [rbp-Dh]
  int v2; // [rsp+14h] [rbp-Ch]
  int j; // [rsp+18h] [rbp-8h]
  int i; // [rsp+1Ch] [rbp-4h]

  v2 = strlen(a1);
  for ( i = 0; i < v2; ++i )
    a1[i] ^= 0x5Au;
  for ( j = 0; j < v2 - 1; j += 2 )
  {
    v1 = a1[j];
    a1[j] = a1[j + 1];
    a1[j + 1] = v1;
  }
}

异或,然后打乱顺序

解密:

a = [0x32,0x0e,0x05,0x3f,0x34,0x3f,0x05,0x3e,0x3c,0x35,0x2e,0x05,0x3f,0x32,0x2d,0x05,0x28,0x35,0x3e,0x36,0x33,0x05,0x05,0x29,0x33,0x38,0x3b,0x34,0x23,0x28]

for i in range(0,len(a)-1,2):
    v1 = a[i]
    a[i] = a[i+1]
    a[i+1] = v1

for i in range(len(a)):
    print(chr(a[i]^0x5a),end='')

o_O

MacOS的题目

直接丢进ida

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v3; // w1
  _DWORD *v4; // x0
  _DWORD *v5; // x0
  _DWORD *v6; // x0
  __int64 v8; // [xsp+10h] [xbp-110h]
  __int64 v9; // [xsp+18h] [xbp-108h]
  int v10; // [xsp+2Ch] [xbp-F4h]
  int v11; // [xsp+3Ch] [xbp-E4h]
  int v12; // [xsp+48h] [xbp-D8h]
  int v13; // [xsp+4Ch] [xbp-D4h]
  int v14; // [xsp+5Ch] [xbp-C4h]
  __int64 v15; // [xsp+60h] [xbp-C0h]
  int m; // [xsp+6Ch] [xbp-B4h]
  int k; // [xsp+70h] [xbp-B0h]
  int j; // [xsp+78h] [xbp-A8h]
  int v19; // [xsp+7Ch] [xbp-A4h]
  int v20; // [xsp+80h] [xbp-A0h] BYREF
  char v21; // [xsp+87h] [xbp-99h]
  __int64 v22; // [xsp+88h] [xbp-98h] BYREF
  __int64 v23[2]; // [xsp+90h] [xbp-90h] BYREF
  char v24[24]; // [xsp+B0h] [xbp-70h] BYREF
  _QWORD v25[3]; // [xsp+C8h] [xbp-58h] BYREF
  unsigned int v26; // [xsp+E0h] [xbp-40h] BYREF
  int i; // [xsp+E4h] [xbp-3Ch]
  unsigned int v28; // [xsp+E8h] [xbp-38h]
  int v29; // [xsp+ECh] [xbp-34h]
  __int128 v30; // [xsp+F0h] [xbp-30h]
  __int64 v31; // [xsp+100h] [xbp-20h]

  v29 = 0;
  v30 = xmmword_100007C9C;
  v31 = 0x600000005LL;
  v28 = 0;
  for ( i = 0; i < 6; ++i )
  {
    if ( (ZDJD::O((ZDJD *)&o, (*((_DWORD *)&v30 + i) & 1) != 0) & 1) != 0 )
      ++v28;
  }
  v15 = std::ostream::operator<<(&std::cout, v28, envp);
  std::operator<<[abi:ne180100]<std::char_traits<char>>(v15, 10LL);
  std::istream::operator>>(&std::cin, &v26);
  std::vector<int>::vector[abi:ne180100](v25);
  std::to_string((std::__1 *)v26, v3);
  v23[1] = (__int64)v24;
  v23[0] = std::string::begin[abi:ne180100](v24);
  v22 = std::string::end[abi:ne180100](v24);
  while ( (std::operator!=[abi:ne180100]<char *>(v23, &v22) & 1) != 0 )
  {
    v21 = *(_BYTE *)std::__wrap_iter<char *>::operator*[abi:ne180100](v23);
    v20 = v21 - 48;
    std::vector<int>::push_back[abi:ne180100](v25, &v20);
    std::__wrap_iter<char *>::operator++[abi:ne180100](v23);
  }
  v19 = 2 * v28;
  for ( j = 0; j < (int)v28; ++j )
  {
    v12 = *(_DWORD *)std::vector<int>::operator[][abi:ne180100](v25, v19 - j);
    v4 = (_DWORD *)std::vector<int>::operator[][abi:ne180100](v25, j);
    *v4 ^= v12;
    v13 = *(_DWORD *)std::vector<int>::operator[][abi:ne180100](v25, j);
    v5 = (_DWORD *)std::vector<int>::operator[][abi:ne180100](v25, v19 - j);
    *v5 ^= v13;
    v14 = *(_DWORD *)std::vector<int>::operator[][abi:ne180100](v25, v19 - j);
    v6 = (_DWORD *)std::vector<int>::operator[][abi:ne180100](v25, j);
    *v6 ^= v14;
  }
  for ( k = 0; k < (unsigned __int64)std::vector<int>::size[abi:ne180100](v25); ++k )
  {
    v10 = *(_DWORD *)std::vector<int>::operator[][abi:ne180100](v25, k);
    v11 = 8 * *(_DWORD *)std::vector<int>::operator[][abi:ne180100](v25, k) + 2 * v10;
    *(_DWORD *)std::vector<int>::operator[][abi:ne180100](v25, k) = v11;
  }
  for ( m = 0; m < (unsigned __int64)std::vector<int>::size[abi:ne180100](v25); ++m )
  {
    if ( *(_DWORD *)std::vector<int>::operator[][abi:ne180100](v25, m) != arr[m] )
    {
      v9 = std::operator<<[abi:ne180100]<std::char_traits<char>>(&std::cout, "?o.O_O.o?");
      std::operator<<[abi:ne180100]<std::char_traits<char>>(v9, 10LL);
      std::operator<<[abi:ne180100]<std::char_traits<char>>(&std::cout, "flag{this_is_sample_flag}");
      v29 = 0;
      goto LABEL_21;
    }
  }
  v8 = std::operator<<[abi:ne180100]<std::char_traits<char>>(&std::cout, "!O.o_o.O!");
  std::operator<<[abi:ne180100]<std::char_traits<char>>(v8, 10LL);
  std::operator<<[abi:ne180100]<std::char_traits<char>>(&std::cout, "flag{md5(your_number)}");
  v29 = 0;
LABEL_21:
  std::string::~string(v24);
  std::vector<int>::~vector[abi:ne180100](v25);
  return v29;
}

是c++编写的

分析:

第一个循环(for)里面判断奇偶数,所以v28等于3

第二个循环(while)把每一位输入减48

第三个循环(for),v19=6

这个函数std::vector<int>::operator[][abi:ne180100](v25, v19 - j)的意思是v25[v19-j]

连续三个异或,a^=b,b^=a,a^=b,意思是交换a和b

这个循环的意思是给有7个元素的列表逆序

第四个循环(for),自己乘8加上自己乘2,相当于乘10

第五个循环,判断结果

a = [0x5A, 0x14, 0x0A, 0x32, 0x00, 0x00, 0x14]
for i in range(len(a)):
    a[i]//=10
a.reverse()
print(''.join([chr(i+48)for i in a]))

最后再md5加密一下即可

0 条评论
某人
表情
可输入 255
目录