buuctf/re/近日总结/rome,pyre等(详细解释)

rome:

检测到无壳,32位

直接用IDA打开,转到main函数

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

看到最前面的v12字符串,就知道大概是最后用来检验的key串,然后输入v2串

 

看到最前面把"字符串"v2给临时变量四个字节的result,不太合理

再看看上面的对于变量的定义,这实际上是将字符串存储到了以v2作为首地址开头的栈中

并且由高地址向着低地址存储(注意这是栈)

一直是存到了v11,数一数,一共是22个字节,因为上面那张图表示v11正好存储了“}”

 而且上面那几个连续的if都仅仅表示了括号外的东西,没用,仅仅作为标识、

扫描二维码关注公众号,回复: 16890671 查看本文章

下面直接看最核心的部分

 重点来了,*(_DWORD *)&v12[17]表示取v12(最上面的定义的char类型的,占一个字节)的首地址然后强行转化为dd类型的指针,然后再以指针形式赋予这四个字节为一个整数0(也就是

int v12=0)

所有这里可以把*(_DWORD *)&v12[17]这一串东西看作就是一个临时变量,作为index

 这里也不要看花眼了

实际上是把int类型的v1并以它为首地址转化为byte类型,此时还是指针,然后指针加上我上述的index,最后才*然后变为一个实际值,实际上就是一个字符串数组

知道了这些以后,下面程序的操作就异常简单,也就是简单的针对大写字母与小写字母做了一个移位,分别是向后移位14位和向后移位18位

这道题的脚本有两种写法

第一种是逆向移位写出脚本

这里推荐用python,因为python是取模运算(C/java是取余运算),取模运算更方便负数情况的移位(你懂的)

下面就是类凯撒加密解密固定脚本

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码

第二种是正向爆破(就是爆破原flag或者未中间值)

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)

得到flag{Cae3ar_th4_Gre@t}

easyre

有壳先脱壳,UPX壳

来到主函数

简单看一下,就是把flag的核心部分强制转化为byte类型然后asiic码值减一再花生为索引值再与v4逐个比较

写出脚本

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逆向)

是一个pyc文件

拿到在线网站上去反编译

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

写出脚本(正逆向,方便对比)

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

刮开有奖

无壳打开IDA搜搜main函数搜不到然后搜索字符串查看敏感字符串来到下图

sub_4010F0可正向复盘

下面两个函数有base64有关的敏感字符串

下面两个字符串拿去解码,然后正向复盘得到v7,v10

复盘代码:

#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:原始IDA中的4*i为什么要变为i?

A:i可以当作是一个index,这些奇奇怪怪的玩意都是数组的变形

得到flag

 flag{UJWP1jMp}

猜你喜欢

转载自blog.csdn.net/weixin_51681694/article/details/127201430