buuctf/re/resumo recente/roma, pira, etc. (explicação detalhada)

Roma:

Shellless detectado, 32 bits

Abra-o diretamente com IDA e vá para a função principal

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;
}

Ao ver a string v12 na frente, você sabe que provavelmente é a string chave usada para verificação no final e, em seguida, insira a string v2.

 

Vendo que a "string" v2 é dada à variável temporária como um resultado de quatro bytes no início, isso não é razoável.

Veja a definição de variáveis ​​acima. Na verdade, isso armazena a string na pilha começando com v2 como o primeiro endereço.

E armazene do endereço alto para o endereço baixo (observe que isso é uma pilha)

Ele foi armazenado até a v11. Conte, são 22 bytes no total, porque a imagem acima mostra que a v11 armazena "}"

 Além disso, os ifs consecutivos acima representam apenas coisas fora dos colchetes e são inúteis. Eles são usados ​​apenas como identificadores.

Vejamos diretamente a parte central

 Aqui está o ponto principal, *(_DWORD *)&v12[17] significa pegar o primeiro endereço de v12 (o tipo char definido na parte superior, ocupando um byte) e, em seguida, convertê-lo à força em um ponteiro do tipo dd e, em seguida, atribuí-lo em a forma de um ponteiro Quatro bytes são um número inteiro 0 (ou seja,

int v12=0)

Todas as coisas aqui *(_DWORD *)&v12[17] podem ser consideradas como uma variável temporária, como índice

 Não fique cego aqui também.

Na verdade, o tipo int v1 e seu endereço inicial são convertidos em tipo byte. Neste momento, ainda é um ponteiro, e então o ponteiro é adicionado ao índice que mencionei acima e, finalmente, * então se torna um valor real, que é na verdade uma matriz de strings.

Depois de saber disso, o funcionamento do programa a seguir é extremamente simples, ou seja, é feito um simples deslocamento para letras maiúsculas e minúsculas, retrocedendo 14 bits e retrocedendo 18 bits respectivamente.

Existem duas maneiras de escrever o script para esta pergunta:

A primeira é inverter o turno e escrever o script

É recomendado usar python aqui, porque python é uma operação de módulo (C/java é uma operação de resto), e a operação de módulo é mais conveniente para mudar números negativos (você sabe)

A seguir está um script fixo para criptografia e descriptografia do tipo César

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码

O segundo tipo é a explosão direta (ou seja, a explosão da bandeira original ou valor não intermediário)

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)

obter bandeira{Cae3ar_th4_Gre@t}

fácil

Se houver um shell, remova-o primeiro, shell UPX

Venha para a função principal

Uma breve olhada nisso é forçar a conversão da parte central do sinalizador para o tipo de byte, depois diminuir o valor do código asiic e defini-lo como o valor do índice e, em seguida, compará-lo com a v4, um por um.

escrever um roteiro

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)

 sinalizar{U9X_1S_W6@T?}

pira (python reverso)

é um arquivo pyc

Obtenha-o em um site online e descompile-o

#!/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']

Escreva o script (avançar e retroceder para facilitar a comparação)

#!/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)

sinalizador{Just_Re_1s_Ha66y!}

Raspe e ganhe prêmios

Abra o IDA sem shell. Se a função principal não puder ser encontrada, procure por strings para visualizar strings sensíveis e veja a imagem abaixo.

sub_4010F0 pode ser revisado posteriormente

As duas funções a seguir possuem strings confidenciais relacionadas a base64

As duas strings a seguir são decodificadas e, em seguida, reproduzidas para obter v7, v10

Código de revisão:

#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;
}

P: Por que 4*i no IDA original muda para i?

R: Posso ser considerado um índice. Essas coisas estranhas são todas transformações de arrays.

obter bandeira

 sinalizador{UJWP1jMp}

Acho que você gosta

Origin blog.csdn.net/weixin_51681694/article/details/127201430
Recomendado
Clasificación