小白学逆向7.26笔记

BUUCTF

reverse3

查壳

 

 

 无壳的32位文件

用IDA打开,找到main_0函数,f5反编译得到代码

__int64 main_0()
{
  int v0; // eax
  const char *v1; // eax
  size_t v2; // eax
  int v3; // edx
  __int64 v4; // ST08_8
  signed int j; // [esp+DCh] [ebp-ACh]
  signed int i; // [esp+E8h] [ebp-A0h]
  signed int v8; // [esp+E8h] [ebp-A0h]
  char Dest[108]; // [esp+F4h] [ebp-94h]
  char Str; // [esp+160h] [ebp-28h]
  char v11; // [esp+17Ch] [ebp-Ch]

  for ( i = 0; i < 100; ++i )
  {
    if ( (unsigned int)i >= 0x64 )
      j____report_rangecheckfailure();
    Dest[i] = 0;
  }
  sub_41132F("please enter the flag:");
  sub_411375("%20s", &Str);
  v0 = j_strlen(&Str);
  v1 = (const char *)sub_4110BE((int)&Str, v0, (int)&v11);
  strncpy(Dest, v1, 0x28u);
  v8 = j_strlen(Dest);
  for ( j = 0; j < v8; ++j )
    Dest[j] += j;                  //对Dest进行列变换
  v2 = j_strlen(Dest);
  if ( !strncmp(Dest, Str2, v2) )  //str2中储存flag变换后的字符串
    sub_41132F("rigth flag!\n");
  else
    sub_41132F("wrong flag!\n");
  HIDWORD(v4) = v3;
  LODWORD(v4) = 0;
  return v4;
}

打开str2

Str2[]
.data:0041A034 Str2            db 'e3nifIH9b_C@n@dH',0 ; DATA XREF: _main_0+142↑o

我们只需要讲str2反向变换即可得到flag

打开24行代码的函数

void *__cdecl sub_411AB0(char *a1, unsigned int a2, int *a3)
{
  int v4; // STE0_4
  int v5; // STE0_4
  int v6; // STE0_4
  int v7; // [esp+D4h] [ebp-38h]
  signed int i; // [esp+E0h] [ebp-2Ch]
  unsigned int v9; // [esp+ECh] [ebp-20h]
  int v10; // [esp+ECh] [ebp-20h]
  signed int v11; // [esp+ECh] [ebp-20h]
  void *Dst; // [esp+F8h] [ebp-14h]
  char *v13; // [esp+104h] [ebp-8h]

  if ( !a1 || !a2 )
    return 0;
  v9 = a2 / 3;
  if ( (signed int)(a2 / 3) % 3 )
    ++v9;
  v10 = 4 * v9;
  *a3 = v10;
  Dst = malloc(v10 + 1);
  if ( !Dst )
    return 0;
  j_memset(Dst, 0, v10 + 1);
  v13 = a1;
  v11 = a2;
  v7 = 0;
  while ( v11 > 0 )
  {
    byte_41A144[2] = 0;
    byte_41A144[1] = 0;
    byte_41A144[0] = 0;
    for ( i = 0; i < 3 && v11 >= 1; ++i )
    {
      byte_41A144[i] = *v13;
      --v11;
      ++v13;
    }
    if ( !i )
      break;
    switch ( i )
    {
      case 1:
        *((_BYTE *)Dst + v7) = aAbcdefghijklmn[(signed int)(unsigned __int8)byte_41A144[0] >> 2];
        v4 = v7 + 1;
        *((_BYTE *)Dst + v4++) = aAbcdefghijklmn[((byte_41A144[1] & 0xF0) >> 4) | 16 * (byte_41A144[0] & 3)];
        *((_BYTE *)Dst + v4++) = aAbcdefghijklmn[64];
        *((_BYTE *)Dst + v4) = aAbcdefghijklmn[64];
        v7 = v4 + 1;
        break;
      case 2:
        *((_BYTE *)Dst + v7) = aAbcdefghijklmn[(signed int)(unsigned __int8)byte_41A144[0] >> 2];
        v5 = v7 + 1;
        *((_BYTE *)Dst + v5++) = aAbcdefghijklmn[((byte_41A144[1] & 0xF0) >> 4) | 16 * (byte_41A144[0] & 3)];
        *((_BYTE *)Dst + v5++) = aAbcdefghijklmn[((byte_41A144[2] & 0xC0) >> 6) | 4 * (byte_41A144[1] & 0xF)];
        *((_BYTE *)Dst + v5) = aAbcdefghijklmn[64];
        v7 = v5 + 1;
        break;
      case 3:
        *((_BYTE *)Dst + v7) = aAbcdefghijklmn[(signed int)(unsigned __int8)byte_41A144[0] >> 2];
        v6 = v7 + 1;
        *((_BYTE *)Dst + v6++) = aAbcdefghijklmn[((byte_41A144[1] & 0xF0) >> 4) | 16 * (byte_41A144[0] & 3)];
        *((_BYTE *)Dst + v6++) = aAbcdefghijklmn[((byte_41A144[2] & 0xC0) >> 6) | 4 * (byte_41A144[1] & 0xF)];
        *((_BYTE *)Dst + v6) = aAbcdefghijklmn[byte_41A144[2] & 0x3F];
        v7 = v6 + 1;
        break;    //Dst经过aAbcdefghijklmn[]数组的变换,打开这里
    }
  }
  *((_BYTE *)Dst + v7) = 0;
  return Dst;
}
efghijklmn db 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
.rdata:00417B30                                         ; DATA XREF: .text:004117E8↑o
.rdata:00417B30                                         ; .text:00411827↑o ...
.rdata:00417B30                 db 0
.rdata:00417B72                 align 4

这个函数位base64的加密函数,解密即可

import base64

str1 = 'e3nifIH9b_C@n@dH'
x = ''
flag = ''

for j in range(0, len(str1)):
    x += chr(ord(str1[j]) - j)

flag = base64.b64decode(x)
flag = flag.decode('ASCII')
print(flag)

运行脚本,得到flag{i_l0ve_you}

不一样的flag

查壳

 

 

 32位文件无壳

用IDA打开,f5查看main函数伪代码

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v3; // [esp+17h] [ebp-35h]
  int v4; // [esp+30h] [ebp-1Ch]
  int v5; // [esp+34h] [ebp-18h]
  signed int v6; // [esp+38h] [ebp-14h]
  int i; // [esp+3Ch] [ebp-10h]
  int v8; // [esp+40h] [ebp-Ch]

  __main();
  v4 = 0;
  v5 = 0;
  qmemcpy(&v3, _data_start__, 0x19u);
  while ( 1 )
  {
    puts("you can choose one action to execute");
    puts("1 up");
    puts("2 down");
    puts("3 left");
    printf("4 right\n:");
    scanf("%d", &v6);
    if ( v6 == 2 )
    {
      ++v4;
    }
    else if ( v6 > 2 )
    {
      if ( v6 == 3 )
      {
        --v5;
      }
      else
      {
        if ( v6 != 4 )
LABEL_13:
          exit(1);
        ++v5;
      }
    }
    else
    {
      if ( v6 != 1 )
        goto LABEL_13;
      --v4;
    }
    for ( i = 0; i <= 1; ++i )
    {
      if ( *(&v4 + i) < 0 || *(&v4 + i) > 4 )
        exit(1);
    }
    if ( *((_BYTE *)&v8 + 5 * v4 + v5 - 41) == 49 )
      exit(1);
    if ( *((_BYTE *)&v8 + 5 * v4 + v5 - 41) == 35 )
    {
      puts("\nok, the order you enter is the flag!");
      exit(0);
    }
  }
}

shift+f12查看字符串

.data:00402000    0000001A    C    *11110100001010000101111#

找到特殊的字符串

分析代码

if ( *((_BYTE *)&v8 + 5 * v4 + v5 - 41) == 49 )
      exit(1);
    if ( *((_BYTE *)&v8 + 5 * v4 + v5 - 41) == 35 )
    {
      puts("\nok, the order you enter is the flag!");
      exit(0);
    }

可以看出是5x5的迷宫,碰到1就结束

画出迷宫

 

 

 直接按照命令来走

得到字符串222441144222,则flag{222441144222}

SimpleRev

用IDA64打开,f5查看伪代码

int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  int v3; // eax
  char v4; // [rsp+Fh] [rbp-1h]

  while ( 1 )
  {
    while ( 1 )
    {
      printf("Welcome to CTF game!\nPlease input d/D to start or input q/Q to quit this program: ", argv, envp);
      v4 = getchar();
      if ( v4 != 100 && v4 != 68 )
        break;
      Decry();
    }
    if ( v4 == 113 || v4 == 81 )
      Exit();
    puts("Input fault format!");
    v3 = getchar();
    putchar(v3);
  }
}

打开Decry()函数

unsigned __int64 Decry()
{
  char v1; // [rsp+Fh] [rbp-51h]
  int v2; // [rsp+10h] [rbp-50h]
  int v3; // [rsp+14h] [rbp-4Ch]
  int i; // [rsp+18h] [rbp-48h]
  int v5; // [rsp+1Ch] [rbp-44h]
  char src[8]; // [rsp+20h] [rbp-40h]
  __int64 v7; // [rsp+28h] [rbp-38h]
  int v8; // [rsp+30h] [rbp-30h]
  __int64 v9; // [rsp+40h] [rbp-20h]
  __int64 v10; // [rsp+48h] [rbp-18h]
  int v11; // [rsp+50h] [rbp-10h]
  unsigned __int64 v12; // [rsp+58h] [rbp-8h]

  v12 = __readfsqword(0x28u);
  *(_QWORD *)src = 357761762382LL;
  v7 = 0LL;
  v8 = 0;
  v9 = 512969957736LL;
  v10 = 0LL;
  v11 = 0;
  text = (char *)join(key3, &v9);//让text等于key3+v9
                    //key3 = "kills" v9="hodow" text="killshadow" strcpy(key, key1); //将key1复制给key key="ADSFK" strcat(key, src);        //将src处的字符串接到key后
                   //key="ADSFKNDCLS"
v2
= 0; v3 = 0; getchar();              //获取输入 v5 = strlen(key);           //v5=key的长度 v5=10 for ( i = 0; i < v5; ++i ) { if ( key[v3 % v5] > 64 && key[v3 % v5] <= 90 )//if(key[v3]>64 && key[v3]<=90)
                              //key[v3] = key[v3]+32
key[i]
= key[v3 % v5] + 32;          //key = "adsfkndcls"         ++v3;         } printf("Please input your flag:", src); while ( 1 ) { v1 = getchar(); if ( v1 == 10 ) break;                  // 如果输入的为换行符,则退出 if ( v1 == 32 ) { ++v2;                    // 如果输入的为空格,则v2加一 } else { if ( v1 <= 96 || v1 > 122 )      // 如果输入的v1不为小写字母 { if ( v1 > 64 && v1 <= 90 )     // 如果v1为大写字母 str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;
                         // 对str2[v2]进行处理(v2为0每次加1)
                         // str1[v2] = (v1-key[v3]+58)%26 + 97 // 变换后str1[v2]存放小写字母
}
else                    // 如果输入的值v1为小写字母 {                     str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;// 做同样处理
                          // 如果不为大小写字母,则不进行处理
}
if ( !(v3 % v5) )             // 如果循环到key的最后一位 putchar(32);               // 打印出一个空格 ++v2; } } if ( !strcmp(text, str2) )         // 如果text和str2存储的相同,则成功
                           // text = "killshadow"
puts(
"Congratulation!\n"); else puts("Try again!\n"); return __readfsqword(0x28u) ^ v12; }

其中有一个自定义的join函数

//传入两个指针
//a1=key3
//a2=v9
char
*__fastcall join(const char *a1, const char *a2) { size_t v2; // rbx size_t v3; // rax char *dest; // [rsp+18h] [rbp-18h] v2 = strlen(a1);          //v2为key3的长度 v3 = strlen(a2);          //v3为v9的长度 dest = (char *)malloc(v2 + v3 + 1);//动态分配一个能存下v9和key3的空间dest if ( !dest ) exit(1); strcpy(dest, a1);           //将a1赋值给dest strcat(dest, a2);           //将a2拼接到dest后 return dest;              //返回dest }

写出脚本代码

#include <iostream>
using namespace std;
int main(void)
{
    int i, j, n = 0, v5 = 10, v3 = 0, v2 = 0;
    char v1;
    char flag[11] = { 0 };
    char str2[104] = { 0 };
    char key[] = "ADSFKNDCLS";
    char text[] = "killshadow";


    for (i = 0; i < v5; ++i)
    {
        if (key[v3 % v5] > 64 && key[v3 % v5] <= 90)
            key[i] = key[v3 % v5] + 32;
        ++v3;
    }
    for (j = 0; j < 10; ++j) {
        for (v2 = 0; v2 < 10; ++v2) {
            v1 = text[v2] - 97 + 26 * j - 97 + key[v3++ % v5] + 39;
            if ((v1 >= 65 && v1 <= 90) || (v1 >= 97 && v1 <= 122)) {
                flag[v2] = v1;
                if (++n == 10) {
                    printf("%s\n", flag);
                    system("PAUSE");
                    return 0;
                }
            }
        }
    }

    system("PAUSE");
    return 0;
}
 

 

 flag{KLDQCUDFZO}

posted @ 2020-07-27 09:58  英雄你个土豆  阅读(321)  评论(0)    收藏  举报