buuctf/re/recent summary/rome, pyre, etc. (detailed explanation)

rome:

Shellless detected, 32-bit

Open it directly with IDA and go to the main function

int func()
{
  int result; // eax
  int v1[4]; // [esp+14h] [ebp-44h]
  unsigned __int8 v2; // [esp+24h] [ebp-34h] BYREF
  unsigned __int8 v3; // [esp+25h] [ebp-33h]
  unsigned __int8 v4; // [esp+26h] [ebp-32h]
  unsigned __int8 v5; // [esp+27h] [ebp-31h]
  unsigned __int8 v6; // [esp+28h] [ebp-30h]
  int v7; // [esp+29h] [ebp-2Fh]
  int v8; // [esp+2Dh] [ebp-2Bh]
  int v9; // [esp+31h] [ebp-27h]
  int v10; // [esp+35h] [ebp-23h]
  unsigned __int8 v11; // [esp+39h] [ebp-1Fh]
  char v12[29]; // [esp+3Bh] [ebp-1Dh] BYREF

  strcpy(v12, "Qsw3sj_lz4_Ujw@l");
  printf("Please input:");
  scanf("%s", &v2);
  result = v2;
  if ( v2 == 65 )
  {
    result = v3;
    if ( v3 == 67 )
    {
      result = v4;
      if ( v4 == 84 )
      {
        result = v5;
        if ( v5 == 70 )
        {
          result = v6;
          if ( v6 == 123 )
          {
            result = v11;
            if ( v11 == 125 )
            {
              v1[0] = v7;
              v1[1] = v8;
              v1[2] = v9;
              v1[3] = v10;
              *(_DWORD *)&v12[17] = 0;
              while ( *(int *)&v12[17] <= 15 )
              {
                if ( *((char *)v1 + *(_DWORD *)&v12[17]) > 64 && *((char *)v1 + *(_DWORD *)&v12[17]) <= 90 )
                  *((_BYTE *)v1 + *(_DWORD *)&v12[17]) = (*((char *)v1 + *(_DWORD *)&v12[17]) - 51) % 26 + 65;// A到O
                if ( *((char *)v1 + *(_DWORD *)&v12[17]) > 96 && *((char *)v1 + *(_DWORD *)&v12[17]) <= 122 )
                  *((_BYTE *)v1 + *(_DWORD *)&v12[17]) = (*((char *)v1 + *(_DWORD *)&v12[17]) - 79) % 26 + 97;
                ++*(_DWORD *)&v12[17];
              }
              *(_DWORD *)&v12[17] = 0;
              while ( *(int *)&v12[17] <= 15 )
              {
                result = (unsigned __int8)v12[*(_DWORD *)&v12[17]];
                if ( *((_BYTE *)v1 + *(_DWORD *)&v12[17]) != (_BYTE)result )
                  return result;
                ++*(_DWORD *)&v12[17];
              }
              return printf("You are correct!");
            }
          }
        }
      }
    }
  }
  return result;
}

When you see the v12 string at the front, you know that it is probably the key string used for verification at the end, and then enter the v2 string.

 

Seeing that the "string" v2 is given to the temporary variable as a four-byte result at the beginning, it is not reasonable.

Look at the definition of variables above. This actually stores the string in the stack starting with v2 as the first address.

And store from high address to low address (note that this is a stack)

It has been stored until v11. Count it, it is 22 bytes in total, because the picture above shows that v11 happens to store "}"

 Moreover, the consecutive ifs above only represent things outside the brackets and are useless. They are only used as identifiers.

Let’s look directly at the core part

 Here’s the key point, *(_DWORD *)&v12[17] means taking the first address of v12 (the char type defined at the top, occupying one byte) and then forcibly converting it into a dd type pointer, and then assigning it in the form of a pointer Four bytes are an integer 0 (that is,

int v12=0)

All the things here *(_DWORD *)&v12[17] can be regarded as a temporary variable, as index

 Don’t be blinded here either.

In fact, the int type v1 and its starting address are converted into byte type. At this time, it is still a pointer, and then the pointer is added to the index I mentioned above, and finally * then becomes an actual value, which is actually a string array.

After knowing this, the operation of the following program is extremely simple, that is, a simple shift is made for uppercase letters and lowercase letters, shifting backward by 14 bits and shifting backward by 18 bits respectively.

There are two ways to write the script for this question:

The first is to reverse shift and write the script

It is recommended to use python here, because python is a modulo operation (C/java is a remainder operation), and the modulo operation is more convenient for shifting negative numbers (you know)

The following is a fixed script for Caesar-like encryption and decryption

key="Qsw3sj_lz4_Ujw@l"
flag=""

for c in key:
    if c>='a' and c<='z':
        flag+=chr((ord(c)-18-97)%26+97) 
    elif c>='A' and c<='Z':
        flag+=chr((ord(c)-14-65)%26+65)
    else:
        flag+=c

print(flag)

##原始数据加减移位值,-97或者是-65然后%26变为索引值,再加上97或者是65变为asiic码

The second type is forward blasting (that is, blasting the original flag or unintermediate value)

key="Qsw3sj_lz4_Ujw@l"
flag=""
for i in range(16):
    if key[i]<='Z' and key[i]>='A':
        for j in range(65,91,1):
            if ord(key[i]) == (j-51)%26+65:
                flag+=chr(j)
                break
    elif key[i]<='z' and key[i]>='a':
        for j in range(97, 123, 1):
            if ord(key[i]) == (j - 79) % 26 + 97:
                flag += chr(j)
                break
    else:
        flag+=key[i]

print(flag)

get flag{Cae3ar_th4_Gre@t}

easyre

If there is a shell, remove it first, UPX shell

Come to the main function

A brief look at it is to force the core part of the flag to be converted to byte type, then decrement the asiic code value and set it as the index value, and then compare it with v4 one by one.

write a script

key="*F'\"N,\"(I?+@"
flag=""
list=[]
data="~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$# !\""
for i in range(12):
    for j in range(len(data)):
        if key[i]==data[j]:
            list.append(j)
            break;

for i in range(12):
    flag += chr(list[i] + 1)

print(flag)

 flag{U9X_1S_W6@T?}

pyre (python reverse)

is a pyc file

Get it on an online website and decompile it

#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 2.7

print 'Welcome to Re World!'
print 'Your input1 is your flag~'
l = len(input1)
for i in range(l):
    num = ((input1[i] + i) % 128 + 128) % 128
    code += num

for i in range(l - 1):
    code[i] = code[i] ^ code[i + 1]

print code
code = [
    '%1f',
    '%12',
    '%1d',
    '(',
    '0',
    '4',
    '%01',
    '%06',
    '%14',
    '4',
    ',',
    '%1b',
    'U',
    '?',
    'o',
    '6',
    '*',
    ':',
    '%01',
    'D',
    ';',
    '%',
    '%13']

Write the script (forward and reverse for easy comparison)

#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 2.7


input1="flag{Just_Re_1s_Ha66y!}"

code=[]
l = len(input1)
for i in range(l):
    num = ((ord(input1[i]) + i) % 128 + 128) % 128
    code.append(num)

print(code)
for i in range(l - 1):
    code[i] = code[i] ^ code[i + 1]

code = [
    '\x1f',
    '\x12',
    '\x1d',
    '(',
    '0',
    '4',
    '\x01',
    '\x06',
    '\x14',
    '4',
    ',',
    '\x1b',
    'U',
    '?',
    'o',
    '6',
    '*',
    ':',
    '\x01',
    'D',
    ';',
    '%',
    '\x13']

for i in range(len(code)-2,-1,-1):
    code[i]=chr(ord(code[i])^ord(code[i+1]))

print(code)
flag=""

for i in range(len(code)):
    flag+=chr((ord(code[i])-i)%128)

print(flag)

flag{Just_Re_1s_Ha66y!}

Scratch off and win prizes

Open IDA without a shell. If the main function cannot be found, then search for strings to view sensitive strings and come to the picture below.

sub_4010F0 can be reviewed forward

The following two functions have sensitive strings related to base64

The following two strings are decoded, and then replayed forward to get v7, v10

Review code:

#include <iostream>
using namespace std;

void sub_4010F0(char *a1, int a2, int a3)
{
    int result; // eax
    int i; // esi
    int v5; // ecx
    int v6; // edx

    result = a3;
    for ( i = a2; i <= a3; a2 = i )
    {
        v5 = i;
        v6 = a1[i];
        if ( a2 < result && i < result )
        {
            do
            {
                if ( v6 > a1[result] )
                {
                    if ( i >= result )
                        break;
                    ++i;
                    a1[v5] = a1[result];
                    if ( i >= result )
                        break;
                    while ( a1[i] <= v6 )
                    {
                        if ( ++i >= result )
                            goto LABEL_13;
                    }
                    if ( i >= result )
                        break;
                    v5 = i;
                    a1[result] = a1[i];
                }
                --result;
            }
            while ( i < result );
        }
        LABEL_13:
        a1[result] = v6;
        sub_4010F0(a1, a2, i - 1);
        result = a3;
        ++i;
    }
}

int main(){
    char str[]="ZJSECaNH3ng";
    sub_4010F0(str,0,10);
    printf("%s\n",str);
    return 0;
}

Q: Why does 4*i in the original IDA change to i?

A: i can be regarded as an index. These strange things are all transformations of arrays.

get flag

 flag{UJWP1jMp}

Guess you like

Origin blog.csdn.net/weixin_51681694/article/details/127201430