BUUCTF之reverse(持续更新中)

easyre

拖入ida打开,反汇编直接看到flag

flag{this_Is_a_EaSyRe}
image-20220226181831713

reverse1

ida打开看看

shift+f12查看字符串

image-20220226184137718

看到flag的字符串,双击进去看看

image-20220226184234505

发现在数据段上,调用的函数是sub_1400118C0,再双击函数进去看看,发现是汇编代码,反汇编一下,得到函数的代码

__int64 sub_1400118C0()
{
  char *v0; // rdi
  __int64 i; // rcx
  size_t v2; // rax
  size_t v3; // rax
  char v5[36]; // [rsp+0h] [rbp-20h] BYREF
  int j; // [rsp+24h] [rbp+4h]
  char Str1[224]; // [rsp+48h] [rbp+28h] BYREF
  unsigned __int64 v8; // [rsp+128h] [rbp+108h]

  v0 = v5;
  for ( i = 82i64; i; --i )
  {
    *(_DWORD *)v0 = -858993460;
    v0 += 4;
  }
  for ( j = 0; ; ++j )
  {
    v8 = j;
    v2 = j_strlen(Str2);
    if ( v8 > v2 )
      break;
    if ( Str2[j] == 111 )
      Str2[j] = 48;
  }
  sub_1400111D1("input the flag:");
  sub_14001128F("%20s", Str1);
  v3 = j_strlen(Str2);
  if ( !strncmp(Str1, Str2, v3) )
    sub_1400111D1("this is the right flag!\n");
  else
    sub_1400111D1("wrong flag\n");
  sub_14001113B(v5, &unk_140019D00);
  return 0i64;
}
image-20220226191323158

分析代码可以看到,字符串str1就是输入的字符串,str2是我们刚刚看到的字符串{hello_world},然后接下来是比较str1和str2,直到完全匹配才会输出你得到flag,这里还有一个坑,就是前面的一个语句块

if ( Str2[j] == 111 )
      Str2[j] = 48;

可以看到如果str2的字符串中的字符的ASCII值为111,会被换成48,查一下ASCII表,便知道约束的条件是'o' -> '0'

所以来说,最后需要与str1匹配的字符串为{hell0_w0rld},得到flag

reverse2

这题目跟上面的有点相似,用exeinfo PE查看一下

image-20220304081414303

64位elf文件,用ida64打开,f5反汇编一下

image-20220304081532892

大意就是输入字符串s2,如果输入的字符串和字符串flag一样,输出"this is the right flag!"

在比较之前,有一个语句

for ( i = 0; i <= strlen(&flag); ++i )
    {
      if ( *(&flag + i) == 105 || *(&flag + i) == 114 )
        *(&flag + i) = 49;
    }

就是在字符串中,如果有ASCII值为105('i')或者问114('r'),转换为49('1')

在数据段看一下

image-20220304082027893

则经过转换后的字符串为"hack1ing_fo1_fun"

得到flagflag{hack1ing_fo1_fun}

2022/03/04

内涵的软件

ida反汇编看一下

image-20220304083241599

看到v5就是flag

得到flag

flag{49d3c93df25caad81232130f3d2ebfad}

2022/03/04

新年快乐

查看有无壳

image-20220304083944368

发现带了一个upx的壳,先手工脱壳一下

f2下断点

image-20220304092142665

f9运行到这里,再f8,

一般就到了OEP

image-20220304092330130

点击脱壳保存一下

检查是否已经脱壳

image-20220304092631803

扔到ida看看

反汇编查看主函数

image-20220304092758600

跟上一题类似,比较输入字符串和已有的字符串,在上面可以看见

strcpy(Str2, "HappyNewYear!");

显然str2为flag,得到flag

xor

查壳

image-20220305084708612

无壳,用ida打开看看

image-20220305085206344

分析代码

首先必须满足长度为33位,后一位与前一位进行异或运算,而后和global字符串比较,匹配即为flag

写一个脚本

s = ['f', 0x0A, 'k', 0x0C, 'w','&','O','.','@', 0x11, 'x', 0x0D, 'Z',';','U', 0x11, 'p', 0x19, 'F', 0x1F, 'v','"','M','#','D', 0x0E, 'g', 0x6, 'h',
     0x0F, 'G','2','O', 0x0]
# 因为含有数字,首先转换成字符
for i in range(len(s)):
    if type(s[i]) == int:
        s[i] = chr(s[i])
flag = 'f'
for i in range(1, len(s)):
    flag += chr(ord(s[i]) ^ ord(s[i - 1]))

print(flag)s = ['f', 0x0A, 'k', 0x0C, 'w','&','O','.','@', 0x11, 'x', 0x0D, 'Z',';','U', 0x11, 'p', 0x19, 'F', 0x1F, 'v','"','M','#','D', 0x0E, 'g', 0x6, 'h',
     0x0F, 'G','2','O', 0x0]
# 因为含有数字,首先转换成字符
for i in range(len(s)):
    if type(s[i]) == int:
        s[i] = chr(s[i])
flag = 'f'
for i in range(1, len(s)):
    flag += chr(ord(s[i]) ^ ord(s[i - 1]))

print(flag)

得到flag

2022/03/05

helloword

直接扔到ida查看

shift+f12查看字符串,右击选择过滤查看,得到flag

image-20220305091649651
flag{7631a988259a00816deda84afb29430a}

reverse3

查壳,没有壳

image-20220305092748231

ida查看main()函数

int __cdecl main_0(int argc, const char **argv, const char **envp)
{
  size_t v3; // eax
  const char *v4; // eax
  size_t v5; // eax
  char v7; // [esp+0h] [ebp-188h]
  char v8; // [esp+0h] [ebp-188h]
  signed int j; // [esp+DCh] [ebp-ACh]
  int i; // [esp+E8h] [ebp-A0h]
  signed int v11; // [esp+E8h] [ebp-A0h]
  char Destination[108]; // [esp+F4h] [ebp-94h] BYREF
  char Str[28]; // [esp+160h] [ebp-28h] BYREF
  char v14[8]; // [esp+17Ch] [ebp-Ch] BYREF

  for ( i = 0; i < 100; ++i )
  {
    if ( (unsigned int)i >= 0x64 )
      j____report_rangecheckfailure();
    Destination[i] = 0;
  }
  sub_41132F("please enter the flag:", v7);
  sub_411375("%20s", (char)Str);
  v3 = j_strlen(Str);
  v4 = (const char *)sub_4110BE(Str, v3, v14);
  strncpy(Destination, v4, 0x28u);
  v11 = j_strlen(Destination);
  for ( j = 0; j < v11; ++j )
    Destination[j] += j;
  v5 = j_strlen(Destination);
  if ( !strncmp(Destination, Str2, v5) )
    sub_41132F("rigth flag!\n", v8);
  else
    sub_41132F("wrong flag!\n", v8);
  return 0;
}

分析代码,注意最后的这几行

sub_41132F("please enter the flag:", v7);
  sub_411375("%20s", (char)Str);
  v3 = j_strlen(Str);
  v4 = (const char *)sub_4110BE(Str, v3, v14);
  strncpy(Destination, v4, 0x28u);
  v11 = j_strlen(Destination);
  for ( j = 0; j < v11; ++j )
    Destination[j] += j;
  v5 = j_strlen(Destination);
  if ( !strncmp(Destination, Str2, v5) )
    sub_41132F("rigth flag!\n", v8);
  else
    sub_41132F("wrong flag!\n", v8);

其中

  v4 = (const char *)sub_4110BE(Str, v3, v14);

是一个加密的函数,追踪看了半天的代码,没看懂,上网找了找WP才知道是base64加密

看一下加密字符串里面的字符串的内容,点进去

image-20220305095054521 image-20220305095126617

确实是base64

查看str2字符串

image-20220305095608444

写一个脚本

import base64

str2='e3nifIH9b_C@n@dH'
flag=''

for i in range(0,len(str2)):
    flag+=chr(ord(str2[i])-i)

print("加密:{}".format(flag))
print("解密:{}".format(base64.b64decode(flag).decode('utf-8')))

得到flag

image-20220305100244966

不一样的flag

查壳

image-20220310141943582

无壳,32位

ida打开看看

int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  char v3[29]; // [esp+17h] [ebp-35h] BYREF
  int v4; // [esp+34h] [ebp-18h]
  int v5; // [esp+38h] [ebp-14h] BYREF
  int i; // [esp+3Ch] [ebp-10h]
  _BYTE v7[12]; // [esp+40h] [ebp-Ch] BYREF

  __main();
  v4 = 0;
  strcpy(v3, "*11110100001010000101111#");
  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", &v5);
    if ( v5 == 2 )
    {
      ++*(_DWORD *)&v3[25];
    }
    else if ( v5 > 2 )
    {
      if ( v5 == 3 )
      {
        --v4;
      }
      else
      {
        if ( v5 != 4 )
LABEL_13:
          exit(1);
        ++v4;
      }
    }
    else
    {
      if ( v5 != 1 )
        goto LABEL_13;
      --*(_DWORD *)&v3[25];
    }
    for ( i = 0; i <= 1; ++i )
    {
      if ( *(int *)&v3[4 * i + 25] < 0 || *(int *)&v3[4 * i + 25] > 4 )
        exit(1);
    }
    if ( v7[5 * *(_DWORD *)&v3[25] - 41 + v4] == 49 )
      exit(1);
    if ( v7[5 * *(_DWORD *)&v3[25] - 41 + v4] == 35 )
    {
      puts("\nok, the order you enter is the flag!");
      exit(0);
    }
  }
}

分析代码,是一个走迷宫的问题

*1111
01000
01010
00010
1111#

*代表起点,#代表终点

222441144222

试了半天最后才知道路径是flag。。。

2022/03/10

SimpleRev

查壳

image-20220310151759427

发现是64位程序

ida打开看看

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: ");
      v4 = getchar();
      if ( v4 != 'd' && v4 != 'D' )
        break;
      Decry();
    }
    if ( v4 == 'q' || v4 == 'Q' )
      Exit("Welcome to CTF game!\nPlease input d/D to start or input q/Q to quit this program: ", argv);
    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] BYREF
  __int64 v7; // [rsp+28h] [rbp-38h]
  int v8; // [rsp+30h] [rbp-30h]
  __int64 v9[2]; // [rsp+40h] [rbp-20h] BYREF
  int v10; // [rsp+50h] [rbp-10h]
  unsigned __int64 v11; // [rsp+58h] [rbp-8h]

  v11 = __readfsqword(0x28u);
  *(_QWORD *)src = 0x534C43444ELL;
  v7 = 0LL;
  v8 = 0;
  v9[0] = 0x776F646168LL;
  v9[1] = 0LL;
  v10 = 0;
  text = (char *)join(key3, v9);
  strcpy(key, key1);
  strcat(key, src);
  v2 = 0;
  v3 = 0;
  getchar();
  v5 = strlen(key);
  for ( i = 0; i < v5; ++i )
  {
    if ( key[v3 % v5] > 64 && key[v3 % v5] <= 90 )
      key[i] = key[v3 % v5] + 32;
    ++v3;
  }
  printf("Please input your flag:");
  while ( 1 )
  {
    v1 = getchar();
    if ( v1 == 10 )
      break;
    if ( v1 == 32 )
    {
      ++v2;
    }
    else
    {
      if ( v1 <= 96 || v1 > 122 )
      {
        if ( v1 > 64 && v1 <= 90 )
        {
          str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97;
          ++v3;
        }
      }
      else
      {
        str2[v2] = (v1 - 39 - key[v3 % v5] + 97) % 26 + 97;
        ++v3;
      }
      if ( !(v3 % v5) )
        putchar(32);
      ++v2;
    }
  }
  if ( !strcmp(text, str2) )
    puts("Congratulation!\n");
  else
    puts("Try again!\n");
  return __readfsqword(0x28u) ^ v11;
}

自己分析了半天代码,头晕乎乎的,看了一些WP

看到有大佬写的代码转换,就懂了点(ಥ _ ಥ)

 1 #include <bits/stdc++.h>
 2 
 3 #pragma warning(disable:4996)
 4 
 5 int main(void)
 6 {
 7     int i, j, n = 0, v5 = 10, v3 = 0, v2 = 0;
 8     char v1;
 9     char flag[11] = { 0 };
10     char str2[104] = { 0 };
11     char key[] = "ADSFKNDCLS";
12     char text[] = "killshadow";
13 
14 
15     for (i = 0; i < v5; ++i)
16     {
17         if (key[v3 % v5] > 64 && key[v3 % v5] <= 90)
18             key[i] = key[v3 % v5] + 32;
19         ++v3;
20     }
21     printf("Please input your flag:");
22     while (1)
23     {
24         v1 = getchar();
25         printf("v1:%c\nv2:%d\n\n", v1, v2);
26         if (v1 == 10) {
27             printf("进入1\n");
28             break;
29         }
30         if (v1 == 32)
31         {
32             printf("进入2\n");
33             ++v2;
34         }
35         else
36         {
37             if (v1 <= 96 || v1 > 122)
38             {
39                 if (v1 > 64 && v1 <= 90) {
40                     str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;
41                     printf("计算1\n");
42                 }
43             }
44             else
45             {
46                 str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;
47                 printf("计算1\n");
48             }
49             if (!(v3 % v5))
50                 putchar(' ');
51             ++v2;
52         }
53     }
54     if (!strcmp(text, str2))
55         puts("Congratulation!\n");
56     else {
57         printf("str2:%s\n", str2);
58         puts("Try again!\n");
59     }
60 
61     system("PAUSE");
62     return 0;
63 }

第30~35行代码的实际作用是将大写字母转换为小写。

第37~61行代码实际上就是遍历输入的字符(flag),进行str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;运算,最后与text比较。

因此我们只要反向就能求出输入的v1

编写一个脚本

i, j, n = 0, 0, 0
v5 = 10
v3 = 0
v2 = 0
v1 = ''
flag = ['0' for data in range(10)]
str = ''
key = 'ADSFKNDCLS'
text = 'killshadow'

for i in range(v5):
    if 90 >= ord(key[v3 % v5]) > 64:
        key = key[:i] + chr(ord(key[v3 % v5]) + 32) + key[i + 1:]
    v3 += 1
for j in range(10):
    for v2 in range(10):
        v1 = chr(ord(text[v2]) - 97 + 26 * j - 97 + ord(key[v3 % v5]) + 39)
        v3 += 1
        if 90 >= ord(v1) >= 65 or 122 >= ord(v1) >= 97:
            flag[v2] = v1
            n += 1
            if n == 10:
                s = ''
                for i in flag:
                    s += i
                print(s)
                exit(0)

跑一下得到flag

image-20220310172928178

Java逆向解密

.class文件

用jd-gui打开看看

import java.util.ArrayList;
import java.util.Scanner;

public class Reverse {
  public static void main(String[] args) {
    Scanner s = new Scanner(System.in);
    System.out.println("Please input the flag );
    String str = s.next();
    System.out.println("Your input is );
    System.out.println(str);
    char[] stringArr = str.toCharArray();
    Encrypt(stringArr);
  }
  
  public static void Encrypt(char[] arr) {
    ArrayList<Integer> Resultlist = new ArrayList<>();
    for (int i = 0; i < arr.length; i++) {
      int result = arr[i] + 64 ^ 0x20;
      Resultlist.add(Integer.valueOf(result));
    } 
    int[] KEY = { 
        180, 136, 137, 147, 191, 137, 147, 191, 148, 136, 
        133, 191, 134, 140, 129, 135, 191, 65 };
    ArrayList<Integer> KEYList = new ArrayList<>();
    for (int j = 0; j < KEY.length; j++)
      KEYList.add(Integer.valueOf(KEY[j])); 
    System.out.println("Result:");
    if (Resultlist.equals(KEYList)) {
      System.out.println("Congratulations);
    } else {
      System.err.println("Error);
    } 
  }
}

有一个加密函数Encrypt,分析是一个简单的异或操作

exp

KEY = [
    180, 136, 137, 147, 191, 137, 147, 191, 148, 136,
    133, 191, 134, 140, 129, 135, 191, 65]
for i in KEY:
    print(chr(i - 64 ^ 0x20), end='')

得到flag

image-20220313221304226

[GXYCTF2019]luck_guy

查壳

image-20220316073332315

64位,无壳,用ida打开

f5反汇编查看一下主函数

image-20220316081511236

没有注入点,追踪patch_me函数

image-20220316081608690

发现get_flag函数,基本上确定是flag了,继续点进去看看

unsigned __int64 get_flag()
{
  unsigned int v0; // eax
  int i; // [rsp+4h] [rbp-3Ch]
  int j; // [rsp+8h] [rbp-38h]
  __int64 s; // [rsp+10h] [rbp-30h] BYREF
  char v5; // [rsp+18h] [rbp-28h]
  unsigned __int64 v6; // [rsp+38h] [rbp-8h]

  v6 = __readfsqword(0x28u);
  v0 = time(0LL);
  srand(v0);
  for ( i = 0; i <= 4; ++i )
  {
    switch ( rand() % 200 )
    {
      case 1:
        puts("OK, it's flag:");
        memset(&s, 0, 0x28uLL);
        strcat((char *)&s, f1);
        strcat((char *)&s, &f2);
        printf("%s", (const char *)&s);
        break;
      case 2:
        printf("Solar not like you");
        break;
      case 3:
        printf("Solar want a girlfriend");
        break;
      case 4:
        s = 0x7F666F6067756369LL;
        v5 = 0;
        strcat(&f2, (const char *)&s);
        break;
      case 5:
        for ( j = 0; j <= 7; ++j )
        {
          if ( j % 2 == 1 )
            *(&f2 + j) -= 2;
          else
            --*(&f2 + j);
        }
        break;
      default:
        puts("emmm,you can't find flag 23333");
        break;
    }
  }
  return __readfsqword(0x28u) ^ v6;
}

使用了strcat函数进行字符串的拼接

先看一下f1和f2在数据段上的存储的内容

image-20220316082603963

得到一半,还差一半肯定是f2

继续分析代码,在case5代码中可以看到给s赋值了一串数字,然后转换类型为字符串复制给f2,继而通过一个if语句块进行改造

exp

flag = 'GXY{do_not_'
f2 = [0x7F, 0x66, 0x6F, 0x60, 0x67, 0x75, 0x63, 0x69]
# print(s)
for j in range(8):
    if j % 2 == 1:
        f2[j] -= 1
    else:
        f2[j] -= 2
    f2[j] = chr(f2[j])

s = ''.join(f2)
flag += s[::-1]
print(flag)
image-20220316083349763

附:需要注意端序的问题,先开始写的时候没有发现,直到输出的时候才知道后一半写反了。。。。

2022/03/16

刮开有奖

查壳

image-20220316162438824

无壳,32位exe程序

ida打开看看

image-20220319111015128

调用了函数DialogBoxParamA,不认识,百度查了一下,作用是创建一个模态的对话框

看到参数里面有一个功能函数,点进去看看

INT_PTR __stdcall DialogFunc(HWND hDlg, UINT a2, WPARAM a3, LPARAM a4)
{
  const char *v4; // esi
  const char *v5; // edi
  int v7[2]; // [esp+8h] [ebp-20030h] BYREF
  int v8; // [esp+10h] [ebp-20028h]
  int v9; // [esp+14h] [ebp-20024h]
  int v10; // [esp+18h] [ebp-20020h]
  int v11; // [esp+1Ch] [ebp-2001Ch]
  int v12; // [esp+20h] [ebp-20018h]
  int v13; // [esp+24h] [ebp-20014h]
  int v14; // [esp+28h] [ebp-20010h]
  int v15; // [esp+2Ch] [ebp-2000Ch]
  int v16; // [esp+30h] [ebp-20008h]
  CHAR String[65536]; // [esp+34h] [ebp-20004h] BYREF
  char v18[65536]; // [esp+10034h] [ebp-10004h] BYREF

  if ( a2 == 272 )
    return 1;
  if ( a2 != 273 )
    return 0;
  if ( (_WORD)a3 == 1001 )                      // a3=1001
  {
    memset(String, 0, 0xFFFFu);                 // 初始化为0
    GetDlgItemTextA(hDlg, 1000, String, 0xFFFF);
    if ( strlen(String) == 8 )                  // string的长度为8
    {
      v7[0] = 90;
      v7[1] = 74;
      v8 = 83;
      v9 = 69;
      v10 = 67;
      v11 = 97;
      v12 = 78;
      v13 = 72;
      v14 = 51;
      v15 = 110;
      v16 = 103;
      sub_4010F0(v7, 0, 10);                    // 升序算法
      memset(v18, 0, 0xFFFFu);
      v18[0] = String[5];
      v18[2] = String[7];
      v18[1] = String[6];
      v4 = (const char *)sub_401000(v18, strlen(v18));// base64加密,结果赋值给v4
      memset(v18, 0, 0xFFFFu);
      v18[1] = String[3];
      v18[0] = String[2];
      v18[2] = String[4];
      v5 = (const char *)sub_401000(v18, strlen(v18));
      if ( String[0] == v7[0] + 34              // 'U'
        && String[1] == v10                     // 'J'
        && 4 * String[2] - 141 == 3 * v8        // 'W'
        && String[3] / 4 == 2 * (v13 / 9)       // 'P'
        && !strcmp(v4, "ak1w")                  // 'ak1w'
        && !strcmp(                             // 'V1Ax'
              v5,
              "V1Ax") )
      {
        MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0);
      }
    }
    return 0;
  }
  if ( (_WORD)a3 != 1 && (_WORD)a3 != 2 )
    return 0;
  EndDialog(hDlg, (unsigned __int16)a3);
  return 1;
}

v4和v5解密一下,拼接起来得到flag

image-20220319144537846 image-20220319144635078
flag{UJWP1jMp}

[BJDCTF2020]JustRE

拿到exe先查壳

image-20220823203604341

32位,无壳

拖入ida查看

shift+f12查看字符串

image-20220823203745609

追踪一下调用它的函数

image-20220823203824639

显然的打印出来的flag

BJD{1999902069a45792d233ac}

2022/08/23

简单注册器

下载的文件是安卓类型的

用jadx打开

image-20220823222419610

很简单的一个加密

exp

x=['d','d','2','9','4','0','c','0','4','4','6','2','b','4','d','d','7','c','4','5','0','5','2','8','8','3','5','c','c','a','1','5']
x[2]=chr(ord(x[2])+ord(x[3])-50)
x[4]=chr(ord(x[2])+ord(x[5])-48)
x[30]=chr(ord(x[31])+ord(x[9])-48)
x[14]=chr(ord(x[27])+ord(x[28])-97)
for i in range(16):
	x[31-i],x[i]=x[i],x[31-i]

print('flag{',end='')
for i in x:
	print(i,end='')

print('}')

得到flag

flag{59acc538825054c7de4b26440c0999dd}

2022/08/23

[GWCTF 2019]pyre

下载的文件格式是pyc

找个在线网站反编译:https://tool.lu/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 = [
    "\x1f",
    "\x12",
    "\x1d",
    "(",
    "0",
    "4",
    "\x01",
    "\x06",
    "\x14",
    "4",
    ",",
    "\x1b",
    "U",
    "?",
    "o",
    "6",
    "*",
    ":",
    "\x01",
    "D",
    ";",
    "%",
    "\x13",
]

根据加密的代码写一个脚本跑一下

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(hex(ord(code[i])))

for i in range(len(code)):
    code[i]=chr((ord(code[i])+128-i)%128)
    print(code[i],end='')


得到flag

image-20220824092813509
flag{Just_Re_1s_Ha66y!}

2022/08/24

[ACTF新生赛2020]easyre

exe文件,查壳

image-20220824093134737

32位,upx加壳

直接在Ubuntu下脱壳

➜  re sudo apt install upx			# 安装upx
...
➜  re upx -d easyre.exe 
                       Ultimate Packer for eXecutables
                          Copyright (C) 1996 - 2018
UPX 3.95        Markus Oberhumer, Laszlo Molnar & John Reiser   Aug 26th 2018

        File size         Ratio      Format      Name
   --------------------   ------   -----------   -----------
     28123 <-     21467   76.33%    win32/pe     easyre.exe

Unpacked 1 file.

脱壳成功后,放入ida

image-20220824103057024

根据for循环编写exp

exp

v4_s='''*F'\"N,\"(I?+@'''

s_s=r"~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)(" + chr(0x27) + r'&%$# !"'

v6=[chr(65),chr(67),chr(84),chr(70),chr(123)]
v10=chr(125)


print('flag{',end='')
for i in v4_s:
	print(chr(s_s.find(i)+1),end='')
print('}')

2022/08/24

rsa

下载下来得是两个文件

image-20220824165109636

打开公钥文件

-----BEGIN PUBLIC KEY-----
MDwwDQYJKoZIhvcNAQEBBQADKwAwKAIhAMAzLFxkrkcYL2wch21CM2kQVFpY9+7+
/AvKr1rzQczdAgMBAAE=
-----END PUBLIC KEY-----

找一个在线网站解析:http://tool.chacuo.net/cryptrsakeyparse

image-20220824165312603

得到e=65537,n=0xC0332C5C64AE47182F6C1C876D42336910545A58F7EEFEFC0BCAAF5AF341CCDD

一开始使用yafu分解n,后来跑了半天没跑出来,找了在线网站分解出来了

在线网站:http://www.factordb.com/

image-20220824170143191

得到p和q

脚本跑一下

import gmpy2
import rsa

N = 0xC0332C5C64AE47182F6C1C876D42336910545A58F7EEFEFC0BCAAF5AF341CCDD
E = 65537
p = 285960468890451637935629440372639283459
q = 304008741604601924494328155975272418463
D = int(gmpy2.invert(E,(p-1)*(q-1)))
privkey = rsa.PrivateKey(N, E, D, p, q)
with open("flag.enc", "rb+") as file:
    text = file.read()
message = rsa.decrypt(text,privkey)
print(message)

得到flag

image-20220824170238271

2022/08/24

[ACTF新生赛2020]rome

查壳

image-20220824213111103

32位,未加壳

拖入ida

image-20220824220450779

直接看func函数

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;
                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];
              }
              result = printf("You are correct!");// 执行到这里成功
            }
          }
        }
      }
    }
  }
  return result;
}

关键的部分加密

image-20220824221321770

exp

import string
s='Qsw3sj_lz4_Ujw@l'
t_low=string.ascii_lowercase
t_upp=string.ascii_uppercase

flag=''

for i in s:
	if 64<ord(i)<=90:
		flag+=t_upp[ord(i)-14-65]
	elif 96<ord(i)<=122:
		flag+=t_low[ord(i)-18-97]
	else:
		flag+=i

print('flag{'+flag+'}')

得到flag

flag{Cae3ar_th4_Gre@t}

2022/08/24

CrackRTF

查壳

image-20220825101013630

32位,无壳

拖入ida

int __cdecl main_0(int argc, const char **argv, const char **envp)
{
  DWORD v3; // eax
  DWORD v4; // eax
  char Str[260]; // [esp+4Ch] [ebp-310h] BYREF
  int v7; // [esp+150h] [ebp-20Ch]
  char String1[260]; // [esp+154h] [ebp-208h] BYREF
  char Destination[260]; // [esp+258h] [ebp-104h] BYREF

  memset(Destination, 0, sizeof(Destination));
  memset(String1, 0, sizeof(String1));
  v7 = 0;
  printf("pls input the first passwd(1): ");
  scanf("%s", Destination);
  if ( strlen(Destination) != 6 )
  {
    printf("Must be 6 characters!\n");
    ExitProcess(0);
  }
  v7 = atoi(Destination);
  if ( v7 < 100000 )
    ExitProcess(0);
  strcat(Destination, "@DBApp");	//第一次输入的和'@DBApp'拼接
  v3 = strlen(Destination);
  sub_40100A((BYTE *)Destination, v3, String1);//加密验证
  if ( !_strcmpi(String1, "6E32D0943418C2C33385BC35A1470250DD8923A9") )
  {
    printf("continue...\n\n");
    printf("pls input the first passwd(2): ");
    memset(Str, 0, sizeof(Str));
    scanf("%s", Str);
    if ( strlen(Str) != 6 )
    {
      printf("Must be 6 characters!\n");
      ExitProcess(0);
    }
    strcat(Str, Destination);
    memset(String1, 0, sizeof(String1));
    v4 = strlen(Str);
    sub_401019((BYTE *)Str, v4, String1);
    if ( !_strcmpi("27019e688a4e62a649fd99cadaafdb4e", String1) )
    {
      if ( !(unsigned __int8)sub_40100F(Str) )
      {
        printf("Error!!\n");
        ExitProcess(0);
      }
      printf("bye ~~\n");
    }
  }
  return 0;
}

可以看到两次密码验证

第一次中的加密函数

int __cdecl sub_401230(BYTE *pbData, DWORD dwDataLen, LPSTR lpString1)
{
  int result; // eax
  DWORD i; // [esp+4Ch] [ebp-28h]
  CHAR String2[4]; // [esp+50h] [ebp-24h] BYREF
  BYTE v6[20]; // [esp+54h] [ebp-20h] BYREF
  DWORD pdwDataLen; // [esp+68h] [ebp-Ch] BYREF
  HCRYPTHASH phHash; // [esp+6Ch] [ebp-8h] BYREF
  HCRYPTPROV phProv; // [esp+70h] [ebp-4h] BYREF

  if ( !CryptAcquireContextA(&phProv, 0, 0, 1u, 0xF0000000) )
    return 0;
  if ( CryptCreateHash(phProv, 0x8004u, 0, 0, &phHash) )
  {
    if ( CryptHashData(phHash, pbData, dwDataLen, 0) )
    {
      CryptGetHashParam(phHash, 2u, v6, &pdwDataLen, 0);
      *lpString1 = 0;
      for ( i = 0; i < pdwDataLen; ++i )
      {
        wsprintfA(String2, "%02X", v6[i]);
        lstrcatA(lpString1, String2);
      }
      CryptDestroyHash(phHash);
      CryptReleaseContext(phProv, 0);
      result = 1;
    }
    else
    {
      CryptDestroyHash(phHash);
      CryptReleaseContext(phProv, 0);
      result = 0;
    }
  }
  else
  {
    CryptReleaseContext(phProv, 0);
    result = 0;
  }
  return result;
}

脚本爆破

import hashlib
string='@DBApp'
for i in range(100000,999999):
    flag=str(i)+string
    x = hashlib.sha1(flag.encode("utf8"))
    y = x.hexdigest()
    if "6e32d0943418c2c33385bc35a1470250dd8923a9" == y:
            print(flag)
            break

得到密码1

123321

密码2

rtf = '{\\rtf1' \\需要注意,\r需要转义,变成\\r
A = [0x05, 0x7D, 0x41, 0x15, 0x26, 0x01]
password=''
for i in range(len(rtf)):
    x = ord(rtf[i]) ^ A[i]
    password+=chr(x)
print(password)

生成的rtf中有flag

得到flag

flag{N0_M0re_Free_Bugs}

2022/08/25

[FlareOn4]login

html文件

打开源码看看

<!DOCTYPE Html />
<html>
    <head>
        <title>FLARE On 2017</title>
    </head>
    <body>
        <input type="text" name="flag" id="flag" value="Enter the flag" />
        <input type="button" id="prompt" value="Click to check the flag" />
        <script type="text/javascript">
            document.getElementById("prompt").onclick = function () {
                var flag = document.getElementById("flag").value;
                var rotFlag = flag.replace(/[a-zA-Z]/g, function(c){return String.fromCharCode((c <= "Z" ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26);});
                if ("PyvragFvqrYbtvafNerRnfl@syner-ba.pbz" == rotFlag) {
                    alert("Correct flag!");
                } else {
                    alert("Incorrect flag, rot again");
                }
            }
        </script>
    </body>
</html>

rot13加密的算法

wiki解释:

image-20220828095456571

直接把对比的字符串跑一下脚本

exp

import string
s='PyvragFvqrYbtvafNerRnfl@syner-ba.pbz'

for i in s:
	if i not in string.ascii_lowercase+string.ascii_uppercase:
		print(i,end='')
	else:
		if i<='Z':
			jud=ord('Z')
		else:
			jud=ord('z')
		tmp=ord(i)+13
		if jud>=tmp:
			print(chr(tmp),end='')
		else:
			print(chr(tmp-26),end='')

跑一下得到flag

2022/08/28

[2019红帽杯]easyRE

image-20220903170442819

elf64位文件

拖入ida看看

查看一下字符串,追踪第三个

image-20220903212108704 image-20220903220251369 image-20220903220310967

几个字符串异或操作

exp

s_1=[0x40,0x35,0x20,0x56,0x5D,0x18,0x22,0x45,0x17,0x2F,0x24,0x6E,0x62,0x3C,0x27,0x54,0x48,0x6C,0x24,0x6E,0x72,0x3C,0x32,0x45,0x5B]
s_2='flag'

s_4=[chr(ord(s_2[i])^(s_1[i])) for i in range(len(s_2))]

flag=[chr((s_1[i])^ord(s_4[i%4])) for i in range(25)]

print(''.join(flag))

得到flag

flag{Act1ve_Defen5e_Test}

2022/09/03

[GUET-CTF2019]re

image-20220904213130971

elf64位文件,加upx壳,直接拖入Linux脱掉

image-20220904213947163

拖入ida,shift+f12查看字符串

image-20220904214102500 image-20220904215944658

进入判断的函数看看

image-20220904220018255

写个脚本跑一下

import string
d_1=[166163712,731332800,357245568,1074393000,489211344,518971936,406741500,294236496,177305856,650683500,298351053,386348487,438258597,249527520,445362764,174988800,981182160,493042704,257493600,767478780,312840624,1404511500,316139670,619005024,372641472,373693320,498266640,452465676,208422720,515592000,719890500]

d_2=[1629056,6771600,3682944,10431000,3977328,5138336,7532250,5551632,3409728,13013670,6088797,7884663,8944053,5198490,4544518,3645600,10115280,9667504,5364450,13464540,5488432,14479500,6451830,6252576,7763364,7327320,8741520,8871876,4086720,9374400,5759124]

flag=''

for i in range(len(d_1)):
	flag=flag+(chr(d_1[i]//d_2[i]))

print('缺少a1[6]的字符串:  {}'.format(flag[:6]+' '+flag[6:]))

# 注意没有给a1[6],故需要爆破a1[6]
for i in (string.ascii_lowercase+string.ascii_uppercase+string.digits):
	print('fill with {} a1[6]=:{}'.format(i,flag[:6]+i+flag[6:]))


得到flag

flag{e165421110ba03099a1c039337}

2022/09/04

[WUSTCTF2020]level1

查看文件信息

image-20220905215017271

elf64位文件,未加壳

拖入ida查看,直接反汇编看主函数

image-20220905225749657

给的output.txt有输出的数据

直接脚本跑一下

exp

s=[198,
232,
816,
200,
1536,
300,
6144,
984,
51200,
570,
92160,
1200,
565248,
756,
1474560,
800,
6291456,
1782,
65536000]

flag=[]

for i in range(19):
	if (i+1)%2==1:
		flag.append(chr(s[i]>>(i+1)))
	else:
		flag.append(chr(s[i]//(i+1)))

print(''.join(flag))

得到flag

image-20220905230508375
flag{d9-dE6-20c}

2022/09/05

[SUCTF2019]SignIn

检查文件

image-20220905230835482

elf64位文件,未加壳

拖入ida

image-20220905233156725

看到65537和两串长长的字符串,当下知道是rsa算法

C=M^E mod N

根据程序知道

C=0xad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35
E=65537
N=103461035900816914121390101299049044413950405173712170434161686539878160984549

用在线或者yafu分离N为P和Q

image-20220905233806887

得到p和q

P=282164587459512124844245113950593348271
Q=366669102002966856876605669837014229419

脚本跑一下

exp

import gmpy2

C = 0xad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35
E = 65537
N = 103461035900816914121390101299049044413950405173712170434161686539878160984549

P = 282164587459512124844245113950593348271
Q = 366669102002966856876605669837014229419

d = gmpy2.invert(E, (P - 1) * (Q - 1))
m = gmpy2.powmod(C, d, N)

print(hex(m))
print(bytes.fromhex(hex(m)[2:]))

得到flag

suctf{Pwn_@_hundred_years}

2022/09/05

[MRCTF2020]Transform

检查文件

image-20220906215121676

exe64位程序,未加壳,拖入ida分析

image-20220906221717354

分别查看参与操作的比特流

image-20220906221802034 image-20220906221840476

简单的逆向操作,修改了字符串的顺序而已

exp

s_1=[0x67, 0x79, 0x7B, 0x7F, 0x75, 0x2B, 0x3C, 0x52, 0x53, 0x79, 0x57, 0x5E, 0x5D, 0x42, 0x7B, 0x2D, 0x2A, 0x66, 0x42, 0x7E, 0x4C, 0x57, 0x79, 0x41, 0x6B, 0x7E, 0x65, 0x3C, 0x5C, 0x45, 0x6F, 0x62, 0x4D]
# print(len(s_1))

s_2=[0x9, 0x0A, 0x0F, 0x17, 0x7, 0x18, 0x0C, 0x6, 0x1, 0x10, 0x3, 0x11, 0x20, 0x1D, 0x0B, 0x1E, 0x1B, 0x16, 0x4, 0x0D, 0x13, 0x14, 0x15, 0x2, 0x19, 0x5, 0x1F, 0x8, 0x12, 0x1A, 0x1C, 0x0E, 0x00]
# print(len(s_2))

flag=['' for i in range(len(s_1))]

for i in range(len(s_1)):
	tmp=s_1[i]^s_2[i]
	print(chr(tmp),end='')
	flag[s_2[i]]=chr(tmp)

print()
print(''.join(flag))

得到flag

MRCTF{Tr4nsp0sltiON_Clph3r_1s_3z}

2022/09/06

[WUSTCTF2020]level2

检查文件

image-20220906222120299

elf32位,加upx壳,直接在终端脱壳

image-20220906222327069

拖入ida查看

image-20220906222719809

签到题,直接拿到flag

2022/09/06

[ACTF新生赛2020]usualCrypt

检查文件

image-20220907090101341

pe32位文件,未加壳

拖入ida看看

主函数

image-20220907102855564

比较的字符串

image-20220907211226225

进入关键的加密函数看看

image-20220907210917000 image-20220907210931785

一开始调用的函数修改了字典的顺序

image-20220907213905438

修改的数据如下

image-20220907213934542

最后返回的函数功能是大小写转换

image-20220907211027001

程序运行思路

首先输入字符串,修改了base64表的位移,然后进行base64编码转换,最后进行大小写转换

exp

import base64

s='zMXHz3TIgnxLxJhFAdtZn2fFk3lYCrtPC2l9'.swapcase() # 大小写转换
# print(s)
d=dict()
offset=0x40E0AA-0x40E0A0

k='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
flag=''
for i in range(len(k)):
	d[k[i]]=k[i]

for i in range(6,15):
	d[k[i]],d[k[i+offset]]=d[k[i+offset]],d[k[i]]

for i in s:
	flag+=d[i]

flag=base64.b64decode(flag).decode('utf-8')
print(flag)

得到flag

flag{bAse64_h2s_a_Surprise}

2022/09/07

[HDCTF2019]Maze

看题目名字,感觉是一个迷宫题目

查看文件

image-20220907215048758

pe32位,加upx壳

直接在终端脱壳

image-20220907215303774

拖入ida

主函数

image-20220907220049970

可以看到限制输入的字符串的长度是14

看完后,没有思路,上网找了一些wp看了看,知道是花指令

借鉴的wp:https://blog.csdn.net/weixin_46009088/article/details/110204937

image-20220907221855835 image-20220907222025631

选中main的汇编部分按p可以生成对应的函数

image-20220907224228054

adsw,分别对应上下左右,根据最后的结果进行对比,如果相等说明成功crack

初始位置是(0,7),结果需要到(-4,5)

image-20220907225939142

找到迷宫

image-20220907225817028
*******+**
******* **
****    **
**   *****
** **F****
**    ****
**********

得到flag

flag{ssaaasaassdddw}

2022/09/07

Youngter-drive

检查文件

image-20220909161648647

pe32位文件,加upx壳

拖入终端脱壳

image-20220909161925262

拖入ida

image-20220909175454647

查看第一个线程,发现一个加密的操作

image-20220909181356756 image-20220909181550380

发现和输入的字符串同时操作的字符串有效长度只有29,而遍历的次数是30次,这里有点摸不着头脑

看看第二个线程

image-20220909181631404

exp

off_418004='TOiZiZtOrYaToUwPnToBsOaOapsyS'

off_418000='QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm'

flag=[]

for i in range(len(off_418004)):
	if(i%2==0):
		flag.append(off_418004[i])
	else:
		for j,k in enumerate(off_418000):
			if off_418004[i]==k:
				if chr(j+38).isupper():
					flag.append(chr(j+38))
				else:
					flag.append(chr(j+96))

print(''.join(flag))

得到flag

ThisisthreadofwindowshahaIsES

因为之前遍历的问题,缺少一位,所以最后一位需要自己去补齐,经过几次尝试,得到最后一位是E

2022/09/09

相册

检查文件

image-20220909182837428

apk文件,未加壳

用jeb打开

image-20220909191342681

邮箱加密的方式是base64,

jeb不太会用,把so文件提取出来,直接拖入ida查看字符串

image-20220909193153740

base64解码得到flag

 flag{18218465125@163.com}

2022/09/09

[MRCTF2020]Xor

检查文件

image-20220914083228060

pe32位,无壳

直接拖入ida

无法反汇编成c,那就直接看汇编

image-20220914085054829 image-20220914090008612

image-20220914085903073

查看存储的字符串

image-20220914090205791

简单的异或

exp

s=b'\x4dSAWB~FXZ:J:`tQJ"N@ bpdd}8g'

for i in range(len(s)):
    print(chr(i^s[i]),end='')

跑一下得到flag

MRCTF{@_R3@1ly_E2_R3verse!}

2022/09/14

[MRCTF2020]hello_world_go

检查文件

image-20220914090752509

elf64位,第一次碰到go语言写的程序,直接拖入ida尝试,f5反编译

image-20220914091042515

???直接送flag,试了一下,果然是这个。。。

2022/09/14

[WUSTCTF2020]level3

检查文件

image-20220914091212287

elf64位,未加壳,直接拖入ida

image-20220914091817150

看着一串很像base64的字符,尝试解一下

image-20220914091901571

有乱码,不对,但是有部分是对的,猜测是base64的变形

image-20220914093100107

之前做过修改base64表的题目,就是这个[ACTF新生赛2020]usualCrypt

思路:直接把编码后的字符串修改为正常的base64表的即可

exp

import base64

flag=''
table='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
s='d2G0ZjLwHjS7DmOzZAY0X2lzX3CoZV9zdNOydO9vZl9yZXZlcnGlfD==' 
d={}
for i in range(len(table)):
	d[table[i]]=table[i]

for i in range(0,9+1):
	d[table[i]],d[table[19-i]]=d[table[19-i]],d[table[i]]

for i in s:
	if i in table:
		flag+=d[i]
	else:
		flag+=i    # 问了避免填充的等于号带入运算报错

print(flag)
# flag+='=='
print(base64.b64decode(flag).decode('utf-8'))

得到flag

wctf2020{Base64_is_the_start_of_reverse}

2022/09/14

[GWCTF 2019]xxor

检查文件

image-20220914094917165

elf64位,未加壳,直接拖入ida

image-20220915081121440

关键函数中的宏定义可以在ida安装的文件夹中的defs.h里面找到

#define LODWORD(x) DWORDn(x,LOW_IND(x,_DWORD))
#define HIDWORD(x) DWORDn(x,HIGH_IND(x,_DWORD))

看一下加密的函数以及传入的参数

image-20220915081957691 image-20220915082013889

再看一下校验的函数

image-20220915082058817

一堆数据关系,不知道怎么下手,找了一下wp看了一下,知道了使用z3约束器

from z3 import *

a0, a1, a2, a3, a4, a5 = Ints('a0 a1 a2 a3 a4 a5')
s = Solver()
s.add(a2 - a3 == 0x84A236FF)
s.add(a3 + a4 == 0xFA6CB703)
s.add(a2 - a4 == 0x42D731A8)
s.add(a0 == 0xDF48EF7E)
s.add(a5 == 0x84F30420)
s.add(a1 == 0x20CAACF4)

if s.check() == sat:
    print(s.model())

得到

a2 = 3774025685
a1 = 550153460
a5 = 2230518816
a0 = 3746099070
a3 = 1548802262
a4 = 2652626477

对于异或操作,涉及到端序和异或问题,用python写了半天没弄出来,看了网上的wp用的是c写的,代码如下

#include <stdio.h>
int main()
{
    int a1[6] = { 3746099070,550153460,3774025685,1548802262,2652626477,2230518816 };
    unsigned int a2[4] = { 2,2,3,4 };
    unsigned int v3;
    unsigned int v4;
    int v5;
    for (unsigned int j = 0; j < 5; j += 2)
    {
        v3 = a1[j];
        v4 = a1[j + 1];
        v5 = 1166789954 * 64;
        for (unsigned int i = 0; i < 64; i++)
        {
            v4 -= (v3 + v5 + 20) ^ ((v3 << 6) + a2[2]) ^ ((v3 >> 9) + a2[3]) ^ 0x10;
            v3 -= (v4 + v5 + 11) ^ ((v4 << 6) + *a2) ^ ((v4 >> 9) + a2[1]) ^ 0x20;
            v5 -= 1166789954;
        }
        a1[j] = v3;
        a1[j + 1] = v4;
    }//小端序
    for (unsigned int i = 0; i < 6; i++)
        printf("%c%c%c", *((char*)&a1[i] + 2), *((char*)&a1[i] + 1), *(char*)&a1[i]);
}

得到flag

image-20220915084839925
flag{re_is_great!}

2022/09/15

[FlareOn4]IgniteMe

检查文件

image-20220915085859991

pe32位,未加壳,直接拖入ida

image-20220921191650595 image-20220921192124570

程序的运行思路:最后一个字符xor 0x4,然后之后按位和前一个异或,最后和403000比较

exp

byte_403000=[0x0D,0x26,0x49, 0x45, 0x2A, 0x17, 0x78, 0x44, 0x2B, 0x6C, 0x5D,0x5E, 0x45, 0x12, 0x2F, 0x17, 0x2B, 0x44, 0x6F, 0x6E, 0x56, 0x9,0x5F, 0x45, 0x47, 0x73, 0x26, 0x0A, 0x0D, 0x13, 0x17, 0x48, 0x42,0x1, 0x40, 0x4D, 0x0C, 0x2, 0x69, 0x0]
flag=""
L=len(byte_403000)-1
for i in range(len(byte_403000)):
    if i==0:
       byte_403000[L-i]= byte_403000[L-i]^0x4
    byte_403000[L-i-1] = byte_403000[L-i-1]^byte_403000[L-i]
    flag+=chr(byte_403000[L-i])
print(byte_403000)
print(flag[::-1])


得到flag

R_y0u_H0t_3n0ugH_t0_1gn1t3@flare-on.com

2022/09/21

[WUSTCTF2020]Cr0ssfun

检查文件

image-20220921192619675

elf64位,无壳,扔进ida

image-20220921192747276

继续看看

image-20220921192920099

继续追踪

image-20220921193156099

继续

image-20220921193317353 image-20220921193517454 image-20220921193814744 image-20220921193833368 image-20220921193931585

exp

a1=['' for i in range(33)]

a1[10] = 'p' 
a1[13] = '@' 
a1[3] = 'f' 
a1[26] = 'r' 
a1[20] = 'e'

a1[7] = '0' 
a1[16] = '_' 
a1[11] = 'p' 
a1[23] = 'e' 
a1[30] = 'u'

a1[0] = 'w'
a1[6] = '2'
a1[22] = 's'
a1[31] = 'n'
a1[12] = '_'

a1[15] = 'd'
a1[8] = '{'
a1[18] = '3'
a1[28] = '_'
a1[21] = 'r'

a1[2] = 't'
a1[9] = 'c'
a1[32] = '}'
a1[19] = 'v'
a1[5] = '0'
a1[14] = 'n'

a1[4] = '2'
a1[17] = 'r'
a1[29] = 'f'
a1[17] = 'r'
a1[24] = '_'

a1[1] = 'c' 
a1[25] = '@' 
a1[27] = 'e'

print(''.join(a1))

得到

wctf2020{cpp_@nd_r3verse_@re_fun}

2022/09/21

[FlareOn6]Overlong

检查文件

image-20220922212706140

pe32位,未加壳,拖入ida

image-20220922214047438

瞅了半天没看懂逻辑,上网找了找相关的wp,知道了动调得到flag

用od打开(网上的师傅们写的有点简略,自己初学od,琢磨了半天才改成功QWQ)

image-20220922215813238

先给跳转的函数下一个断点(在地址那里双击即可),然后选中上面的运行自动运行到断点

注意右下角的栈的变化,双击第三个变量,并把1c修改为AF

image-20220922220124101

然后点击ok,运行得到flag

image-20220922220310189

2022/09/22

[UTCTF2020]basic-re

检查文件

image-20220922220648164

elf64位文件,未加壳,直接拖入ida

image-20220922220942074

送分的题。。。

2022/09/22

posted @ 2022-09-22 22:11  vi0let  阅读(103)  评论(0编辑  收藏  举报