[ctf.show.reverse] 吃瓜杯 签层饼,Tea_tube_pot

签层饼

真有一千层函数呀,沿着输入存入的两个变量找,找到3个函数:

主函数给出了flag的组织方式,

check1说number2<882408,

check2说number1 = number2^333509

check_n说返回的条件,但是由于这个数是个随机数不能确定,而且number2很小可以爆破。

int __cdecl main_0(int argc, const char **argv, const char **envp)
{
  int v3; // eax

  printf("Hello!Welcome to ctfshow,You need to input two numbers\n");
  printf("number1:");
  scanf("%d", &number1);
  printf("\n");
  printf("number2:");
  scanf("%d", &number2);
  v3 = time(0);
  sub_4B9370(v3);
  dword_528DC0 = (rand() - 999) % 500;
  if ( dword_528DC0 > 9999999 )
    printf("提示:这里的R是想写成任意范围的,但是因为运算溢出");        // 提示:这里的R是想写成任意范围的
  if ( number1 > 0 && number2 > 0 )
  {
    sub_40431D();
    if ( dword_525A30 )
    {
      printf("%d", dword_528DC0);
      printf("Key Error");
    }
    else
    {
      printf("yeah!Your flag:ctfshow{c52e1e1a33%d0e%dc}", number1, number2);
    }
  }
  else
  {
    printf("Error");
  }
  ......
}

int check1()
{
  int result; // eax

  result = sub_4015B4(881778, 666);             // a1^a2
  if ( number2 <= result )                      // <882408
    result = sub_4098EA();
  return result;
}
int check2()
{
  int result; // eax

  result = sub_4015B4(number2, 333509);         // number1 = number2 ^333509
  if ( number1 == result )
    result = sub_40C63A();
  return result;
}
int check_n()
{
  dword_525A30 = 1;
  if ( dword_528DC0 * dword_528DC0 * number2 - 1877 * dword_528DC0 + 1 < 0
    || dword_528DC0 * dword_528DC0 * number2 - 1877 * dword_528DC0 != -1 )
  {
    dword_525A30 ^= 1u;
  }
  return sub_408724();
}

一般情况下实际的数应该在给定数比较近,所以一般不从0开始爆,而是从大向小爆。大概率少用时。

import subprocess

for n2 in range(882408,-1,-1):
    n1 = n2^333509
    
    p = subprocess.Popen('./千层饼.exe', stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    p.stdin.write(f"{n1}\n{n2}".encode())
    p.stdin.close()

    data = p.stdout.read()
    p.stdout.close()
    if b'flag' in data:
        print(data)
        break

#b'Hello!Welcome to ctfshow,You need to input two numbers\r\nnumber1:\r\nnumber2:
#yeah!Your flag:ctfshow{c52e1e1a335489030e882402c}'

Tea_tube_pot

看名字就是tea加密,而且用了3次,不过都不难,直接逆回即可。第2段在中间变的v5所以处理v4时与v3时v5差1个。第3段虽然用了判断两种情况,但参数是固定的,所以只需看一半。

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  if ( check_c11() && (unsigned int)check_CA5(a1, a2) && (unsigned int)check_D45() )
    puts("Congrts!Your Flag is 'ctfshow{'+PART1+PART2+PART3+'}'!");
  return 0LL;
}
__int64 __fastcall sub_71A(unsigned int *input, _DWORD *a2)
{
  __int64 result; // rax
  unsigned int v3; // [rsp+1Ch] [rbp-24h]
  unsigned int v4; // [rsp+20h] [rbp-20h]
  int v5; // [rsp+24h] [rbp-1Ch]
  unsigned int i; // [rsp+28h] [rbp-18h]

  v3 = *input;                                  // input,'This_is_teatube!'
  v4 = input[1];
  v5 = 0;
  for ( i = 0; i <= 0x1F; ++i )
  {
    v5 -= 0x61C88647;
    v3 += (v4 + v5) ^ (16 * v4 + *a2) ^ ((v4 >> 5) + a2[1]);
    v4 += (v3 + v5) ^ (16 * v3 + a2[2]) ^ ((v3 >> 5) + a2[3]);
  }
  *input = v3;
  result = v4;
  input[1] = v4;
  return result;
}
__int64 __fastcall sub_7F8(unsigned int a1, unsigned int *a2, __int64 a3)
{
  __int64 result; // rax
  unsigned int i; // [rsp+24h] [rbp-14h]
  unsigned int v3; // [rsp+28h] [rbp-10h]
  unsigned int v4; // [rsp+2Ch] [rbp-Ch]
  unsigned int v5; // [rsp+30h] [rbp-8h]

  v3 = *a2;
  v4 = a2[1];
  v5 = 0;
  for ( i = 0; i < a1; ++i )
  {
    v3 += (((v4 >> 5) ^ (16 * v4)) + v4) ^ (*(_DWORD *)(4LL * (v5 & 3) + a3) + v5);
    v5 -= 0x61C88647;
    v4 += (((v3 >> 5) ^ (16 * v3)) + v3) ^ (*(_DWORD *)(4LL * ((v5 >> 11) & 3) + a3) + v5);
  }
  *a2 = v3;
  result = v4;
  a2[1] = v4;
  return result;
}
__int64 __fastcall sub_8D3(unsigned int *a1, int a2, __int64 a3)
{
  unsigned int *v3; // rax
  unsigned int *v4; // rax
  __int64 result; // rax
  unsigned int *v6; // rax
  int v7; // [rsp+Ch] [rbp-2Ch]
  unsigned int v8; // [rsp+20h] [rbp-18h]
  unsigned int v9; // [rsp+20h] [rbp-18h]
  unsigned int v10; // [rsp+24h] [rbp-14h]
  unsigned int v11; // [rsp+24h] [rbp-14h]
  unsigned int v12; // [rsp+24h] [rbp-14h]
  unsigned int v13; // [rsp+28h] [rbp-10h]
  unsigned int v14; // [rsp+28h] [rbp-10h]
  unsigned int j; // [rsp+2Ch] [rbp-Ch]
  int i; // [rsp+2Ch] [rbp-Ch]
  int v17; // [rsp+30h] [rbp-8h]
  int v18; // [rsp+30h] [rbp-8h]
  int v19; // [rsp+34h] [rbp-4h]
  unsigned int v20; // [rsp+34h] [rbp-4h]

  if ( a2 <= 1 )
  {
    if ( a2 < -1 )
    {
      v7 = -a2;
      v18 = 52 / -a2 + 6;
      v14 = -1640531527 * v18;
      v9 = *a1;
      do
      {
        v20 = (v14 >> 2) & 3;
        for ( i = v7 - 1; i; --i )
        {
          v11 = a1[i - 1];
          v6 = &a1[i];
          *v6 -= ((v9 ^ v14) + (v11 ^ *(_DWORD *)(4LL * (v20 ^ i & 3) + a3))) ^ (((4 * v9) ^ (v11 >> 5))
                                                                               + ((v9 >> 3) ^ (16 * v11)));
          v9 = *v6;
        }
        v12 = a1[v7 - 1];
        *a1 -= (((4 * v9) ^ (v12 >> 5)) + ((v9 >> 3) ^ (16 * v12))) ^ ((v9 ^ v14) + (v12 ^ *(_DWORD *)(4LL * v20 + a3)));
        result = *a1;
        v9 = *a1;
        v14 += 1640531527;
        --v18;
      }
      while ( v18 );
    }
  }
  else
  {
    v17 = 52 / a2 + 6;                          // 32
    v13 = 0;
    v10 = a1[a2 - 1];                           // v10 = a1[1]
    do
    {
      v13 -= 0x61C88647;
      v19 = (v13 >> 2) & 3;
      for ( j = 0; j < a2 - 1; ++j )
      {
        v8 = a1[j + 1];
        v3 = &a1[j];
        *v3 += ((v8 ^ v13) + (v10 ^ *(_DWORD *)(4LL * (v19 ^ j & 3) + a3))) ^ (((4 * v8) ^ (v10 >> 5))
                                                                             + ((v8 >> 3) ^ (16 * v10)));
        v10 = *v3;
      }
      v4 = &a1[a2 - 1];
      *v4 += ((*a1 ^ v13) + (v10 ^ *(_DWORD *)(4LL * (v19 ^ j & 3) + a3))) ^ (((4 * *a1) ^ (v10 >> 5))
                                                                            + ((*a1 >> 3) ^ (16 * v10)));
      result = *v4;
      v10 = result;
      --v17;
    }
    while ( v17 );
  }
  return result;
}

逆程序

from pwn import u32,p32

'''
  for ( i = 0; i <= 0x1F; ++i )
  {
    v5 -= 0x61C88647;
    v3 += (v4 + v5) ^ (16 * v4 + *a2) ^ ((v4 >> 5) + a2[1]);
    v4 += (v3 + v5) ^ (16 * v3 + a2[2]) ^ ((v3 >> 5) + a2[3]);
  }
'''
a2 = [u32(b'This'), u32(b'_is_'), u32(b'teat'), u32(b'ube!')]
v5 = [0]*0x20
t = 0 
for i in range(0x20):
    t = (t - 0x61C88647) & 0xffffffff
    v5[i] = t 
    #print(hex(t))

v3 = 0x5FD744F6
v4 = 0x95832046
for i in range(0x1f,-1,-1):
    v4 -= (v3 + v5[i])^(16 * v3 + a2[2]) ^ ((v3>>5) + a2[3])
    v4 = v4&0xffffffff
    v3 -= (v4 + v5[i])^(16 * v4 + a2[0]) ^ ((v4>>5) + a2[1])
    v3 = v3&0xffffffff
flag = b'ctfshow{'+p32(v3)+p32(v4)

#v3 += (((v4 >> 5) ^ (16 * v4)) + v4) ^ (*(_DWORD *)(4LL * (v5 & 3) + a3) + v5);
#v4 += (((v3 >> 5) ^ (16 * v3)) + v3) ^ (*(_DWORD *)(4LL * ((v5 >> 11) & 3) + a3) + v5);

v3 = 0xFD731313
v4 = 0x6662CB90
v5 = [0] + v5
for i in range(0x1f,-1,-1):
    v4 -= (((v3 >> 5) ^ (16 * v3)) + v3) ^ (a2[(v5[i+1] >> 11) & 3] + v5[i+1])
    v4 &= 0xffffffff
    v3 -= (((v4 >> 5) ^ (16 * v4)) + v4) ^ (a2[v5[i]         & 3] + v5[i])
    v3 &= 0xffffffff
flag += p32(v3)+p32(v4)

v3 = 0x4B136C82
v4 = 0x1A6E9613
v5 = v5[1:]
for i in range(0x1f,-1,-1):
    v4 -= ((v3 ^ v5[i]) + (v3 ^ a2[(((v5[i]>>2)&3)^1)&3])) ^ (((4 * v3) ^ (v3 >> 5))+ ((v3 >> 3) ^ (16 * v3)))
    v4 &= 0xffffffff
    v3 -= ((v4 ^ v5[i]) + (v4 ^ a2[(((v5[i]>>2)&3)^0)&3])) ^ (((4 * v4) ^ (v4 >> 5))+ ((v4 >> 3) ^ (16 * v4)))
    v3 &= 0xffffffff
flag += p32(v3)+p32(v4)+b'}'
print(flag)
    
#ctfshow{T1nyENCryPti0nA19ori7hM!}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值