BUUCTF-逆向部分题解

533 阅读6分钟

第一题easyre

ida查壳直接看

flag{this_Is_a_EaSyRe}

第二题reverse1

定位到Str2{hello_world}

根据

 for ( j = 0; ; ++j )
  {
    v8 = j;
    v2 = j_strlen(Str2);
    if ( v8 > v2 )
      break;
    if ( Str2[j] == 'o' )
      Str2[j] = '0';
  }

把o换成0

flag{hell0_w0rld}

第三题reverse2

ELF即linux 下可执行文件

先用ida看看

找到{hacking_for_fun}

定位到关键代码

for ( i = 0; i <= strlen(&flag); ++i )
    {
      if ( *(&flag + i) == 'i' || *(&flag + i) == 'r' )
        *(&flag + i) = '1';
    }

把i或者r换成1

直接换flag{hack1ng_fo1_fun}

第四题内涵的软件

直接看

v6 = 5;
  v5 = "DBAPP{49d3c93df25caad81232130f3d2ebfad}";
  while ( v6 >= 0 )
  {
    printf("距离出现答案还有%d秒,请耐心等待!\n", v6);
    sub_40100A();
    --v6;
  }
  printf(
    "\n"
    "\n"
    "\n"
    "这里本来应该是答案的,但是粗心的程序员忘记把变量写进来了,你要不逆向试试看:(Y/N)\n");
  v4[0] = 1;
  scanf("%c", v4);
  if ( v4[0] == 'Y' )
  {
    printf("OD吾爱破解或者IDA这些逆向软件都挺好的!");
    result = sub_40100A();
  }
  else
  {
    if ( v4[0] == 'N' )
      printf("那没办法了,猜是猜不出的.");
    else
      printf(&byte_42501C);
    result = sub_40100A();
  }
  return result;

v5十分可疑,直接flag{49d3c93df25caad81232130f3d2ebfad}

第五题新年快乐

查壳,发现UPX,直接脱壳

定位关键

 __main();
  strcpy(Str2, "HappyNewYear!");
  Str1 = 0;
  memset(v6, 0, sizeof(v6));
  printf("please input the true flag:");
  scanf("%s", &Str1);
  if ( !strncmp((const char *)&Str1, Str2, strlen(Str2)) )
    result = puts("this is true flag!");
  else
    result = puts("wrong!");
  return result;

Str2就是flag

flag{HappyNewYear!}

第六题xor

mac 64位

ida进

定位关键的代码

 memset(__b, 0, 0x100uLL);
  printf("Input your flag:\n");
  get_line(__b, 256LL);
  if ( strlen(__b) != 33 )
    goto LABEL_7;
  for ( i = 1; i < 33; ++i )
    __b[i] ^= __b[i - 1];
  if ( !strncmp(__b, global, 0x21uLL) )
    printf("Success");
  else
LABEL_7:
    printf("Failed");
  return 0;

分析flag 33位,进入异或后和global相等

导出global

unsigned char aFK[] =
{
  102,  10, 107,  12, 119,  38,  79,  46,  64,  17, 
  120,  13,  90,  59,  85,  17, 112,  25,  70,  31, 
  118,  34,  77,  35,  68,  14, 103,   6, 104,  15, 
   71,  50,  79
};

写EXP

#include<stdio.h>
#include<windows.h>
#include<string.h>
int main(){
  char str[]={
  102,  10, 107,  12, 119,  38,  79,  46,  64,  17, 
  120,  13,  90,  59,  85,  17, 112,  25,  70,  31, 
  118,  34,  77,  35,  68,  14, 103,   6, 104,  15, 
   71,  50,  79
};
int i,len = 33;
for(i=len-1;i>=1;i--){str[i]^=str[i-1];}
puts(str);
}
//flag{QianQiuWanDai_YiTongJiangHu}

第七题helloword

apk逆向,准备工具jadx

定位到关键代码

package com.example.helloword;
​
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
​
public class MainActivity extends ActionBarActivity {
    /* access modifiers changed from: protected */
    @Override // android.support.v7.app.ActionBarActivity, android.support.v4.app.FragmentActivity
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        "flag{7631a988259a00816deda84afb29430a}".compareTo("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
    }
​
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
​
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

直接提取flag

flag{7631a988259a00816deda84afb29430a}

第八题reverse3

ida打开

定位到关键代码

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;

接着分享 flag给到了Str,进入了函数sub_4110BE(Str, v3, v14);处理

然后处理为v4,v4复制到Destination,Destination进行加操作,接着和Str2比较

我们发现sub_4110BE对字符串flag进行base64加密(字符特征)

Str2=“e3nifIH9b_C@n@dH

直接写EXP

#include<stdio.h>
#include<windows.h>
#include<string.h>
int main(){
  char str[]="e3nifIH9b_C@n@dH";
int i,len = strlen(str);
for(i=0;i<len;i++){str[i]-=i;}
puts(str);
}
//e2lfbDB2ZV95b3V9
//拿着e2lfbDB2ZV95b3V9进行常规base64解密
//flag{i_l0ve_you}

第九题不一样的flag

有点像游戏,用ida打开

f5直接看,定位到

 strcpy(v3, "*11110100001010000101111#");
 for ( i = 0; i <= 1; ++i )
    {
      if ( *(&v4 + i) < 0 || *(&v4 + i) > 4 )
        exit(1);
    }
    if ( v8[5 * v4 - 41 + v5] == '1' )
      exit(1);
    if ( v8[5 * v4 - 41 + v5] == '#' )
    {
      puts("\nok, the order you enter is the flag!");
      exit(0);
    }

首先

puts("1 up");
 puts("2 down");
 puts("3 left");
 printf("4 right\n:");

超出1到范围直接退出

其次在数组v3种遇到1或者#直接退出,但#提示我们输入的就是flag,这是一道典型的迷宫题

根据二维数组公式结合

 if ( v8[5 * v4 - 41 + v5] == '1' )
      exit(1);
    if ( v8[5 * v4 - 41 + v5] == '#' )

假设迷宫一列5位,v4是行,v5是列

*1111
01000
01010
00010
1111#

我们这种迷宫直接手写,如果是复杂的那种要用递归写。

flag{222441144222}

第十题SimpleRev

ELF文件

定位到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 = 'SLCDN';
  v7 = 0LL;
  v8 = 0;
  v9[0] = 'wodah';
  v9[1] = '\0';
  v10 = 0;
  text = (char *)join(key3, v9);                // key3="killshadow"
  strcpy(key, key1);
  strcat(key, src);                             // key="ADSFKNDCLS"
  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 <= '`' || v1 > 'z' )
      {
        if ( v1 > '@' && v1 <= 'Z' )
        {
          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;
}

text=str2 为key3,key经过变化后,与flag操作成为Str2

注意,大小端的问题,我们换成字符串的时候要注意顺序

我们直接写EXP

#include<stdio.h>
#include<windows.h>
#include<string.h>
int main(){
char key[]="adsfkndcls";
char str2[]="killshadow";
 int  v5 = strlen(key);
 char flag[v5+1];
 flag[v5] = '\0';
  int i;
  int j = 0;
  for( i = 0; i < v5; ++i ){
  j = 0;
    for( j = 0;j<10;j++) {
     flag[i]=str2[i]-97+26*j+39-97+key[i];
     if( flag[i]<='Z'&&flag[i]>='A'||flag[i]>='a'&&flag[i]<='z')
      break;
 }
    
 }
  puts(flag);
}

第十一题JAVA逆向

用jadx打开

package defpackage;
​
import java.util.ArrayList;
import java.util.Scanner;
​
/* renamed from: Reverse  reason: default package */
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);
        Encrypt(str.toCharArray());
    }
​
    public static void Encrypt(char[] arr) {
        int[] KEY;
        ArrayList<Integer> Resultlist = new ArrayList<>();
        for (char c : arr) {
            Resultlist.add(Integer.valueOf((c) +'@' ^ 32));
        }
        ArrayList<Integer> KEYList = new ArrayList<>();
        for (int i : new int[]{180, 136, 137, 147, 191, 137, 147, 191, 148, 136, 133, 191, 134, 140, 129, 135, 191, 65}) {
            KEYList.add(Integer.valueOf(i));
        }
        System.out.println("Result:");
        if (Resultlist.equals(KEYList)) {
            System.out.println("Congratulations!");
        } else {
            System.err.println("Error!");
        }
    }
}

显而易见,直接写EXP

#include<stdio.h>
#include<windows.h>
#include<string.h>
int main(){
char enflag[]={180, 136, 137, 147, 191, 137, 147, 191, 148, 136, 133, 191, 134, 140, 129, 135, 191, 65};
int len = strlen(enflag);
char flag[len + 1];
flag[len] = '\0';
int i;
for(i = 0; i < len; i++){
  flag[i] = enflag[i]-'@'^32;
}
puts(flag);
}
//flag{This_is_the_flag_!}

第十二题[GXYCTF2019]luck_guy

定位关键代码

 v5 = __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, sizeof(s));
        strcat((char *)s, f1);                  // GXY{do_not_
        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:
        strcpy((char *)s, "icug`of\x7F");
        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;
    }

逻辑简单,我们直接拿到上半部分GXY{do_not_

下半部分直接写EXP

#include<stdio.h>
#include<windows.h>
#include<string.h>
int main(){
char s[]="icug`of\x7F";
int j;
int len = strlen(s);
   for ( j = 0; j <= 7; ++j )
        {
          if ( j % 2 == 1 )
           s[j]-= 2;
          else
            s[j] -=1;
        }
        puts( s );
}
//hate_me}

flag{do_not_hate_me}

第十三题刮开有奖

定位到关键代码

INT_PTR __stdcall DialogFunc(HWND hDlg, UINT a2, WPARAM a3, LPARAM a4)
{
  const char *v4; // esi
  const char *v5; // edi
  int v7[10]; // [esp+8h] [ebp-20030h] BYREF
  int v8; // [esp+30h] [ebp-20008h]
  CHAR String[65536]; // [esp+34h] [ebp-20004h] BYREF
  char v10[65536]; // [esp+10034h] [ebp-10004h] BYREF
​
  if ( a2 == 272 )
    return 1;
  if ( a2 != 273 )
    return 0;
  if ( (_WORD)a3 == 1001 )
  {
    memset(String, 0, 0xFFFFu);
    GetDlgItemTextA(hDlg, 1000, String, 0xFFFF);
    if ( strlen(String) == 8 )
    {
      v7[0] = 90;
      v7[1] = 74;
      v7[2] = 83;
      v7[3] = 69;
      v7[4] = 67;
      v7[5] = 97;
      v7[6] = 78;
      v7[7] = 72;
      v7[8] = 51;
      v7[9] = 110;
      v8 = 103;
      sub_4010F0(v7, 0, 10);
      memset(v10, 0, 0xFFFFu);
      v10[0] = String[5];
      v10[2] = String[7];
      v10[1] = String[6];
      v4 = (const char *)sub_401000(v10, strlen(v10));
      memset(v10, 0, 0xFFFFu);
      v10[1] = String[3];
      v10[0] = String[2];
      v10[2] = String[4];
      v5 = (const char *)sub_401000(v10, strlen(v10));
      if ( String[0] == v7[0] + 34
        && String[1] == v7[4]
        && 4 * String[2] - 141 == 3 * v7[2]
        && String[3] / 4 == 2 * (v7[7] / 9)
        && !strcmp(v4, "ak1w")
        && !strcmp(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;
}

这道题让我学会了,如果动态调试调不了,可以把代码copy下来,自己跑。

先说说思路String的后6位很简单,解base64就出来了,但前2位是要进过sub_4010F0函数变化得到的,重点就到了加密上。太多太复杂,我动态调试,结果跑不到我的断点。看到大佬的WP让我感悟到可以直接copy代码,自己跑

我们得知道加密后的v7

#include<stdio.h> 
void sub_7310F0(int *v7, int a2, int a3)
{
  int v3; // eax
  int i; // esi
  int v5; // ecx
  int v6; // edx
​
  v3 = a3;
  for ( i = a2; i <= a3; a2 = i )
  {
    v5 = i;
    v6 = v7[i];
    if ( a2 < v3 && i < v3 )
    {
      do
      {
        if ( v6 > v7[v3] )
        {
          if ( i >= v3 )
            break;
          ++i;
          v7[v5] = v7[v3];
          if ( i >= v3 )
            break;
          while ( v7[i] <= v6 )
          {
            if ( ++i >= v3 )
              goto LABEL_13;
          }
          if ( i >= v3 )
            break;
          v5 = i;
          v7[v3] = v7[i];
        }
        --v3;
      }
      while ( i < v3 );
    }
LABEL_13:
    v7[v3] = v6;
    sub_7310F0(v7, a2, i - 1);
    v3 = a3;
    ++i;
  }
}
int main()
{
    int v7[11];
     v7[0] = 90;
      v7[1] = 74;
      v7[2] = 83;
      v7[3] = 69;
      v7[4] = 67;
      v7[5] = 97;
      v7[6] = 78;
      v7[7] = 72;
      v7[8] = 51;
      v7[9] = 110;
      v7[10] = 103;
      sub_7310F0(v7,0,10);
      for ( int i = 0; i <10;i++)
      {
          printf("%c",v7[i]);
      }
      //3CEHJNSZag
​
}
​

然后直接解

#include<stdio.h>
#include<windows.h>
#include<string.h>
int main(){
char v7[11]="3CEHJNSZag";
char String[9];
  String[0] = v7[0] + 34;
  String[1] = v7[4];
  String[5]='j';
  String[6]='M';
  String[7]='p';
  String[2]= 'W';
  String[3]='P';
  String[4]='1';
  String[8]='\0';
  puts(String);
//UJWP1jMp
}

第十四题[BJDCTF2020]JustRE

定位到关键代码

 sprintf(String, " BJD{%d%d2069a45792d233ac}", 19999, 0);

flag{1999902069a45792d233ac}

第十六题简单注册器

apk逆向

定位到关键代码

​
            public void onClick(View v) {
                int flag = 1;
                String xx = editview.getText().toString();
                if (!(xx.length() == 32 && xx.charAt(31) == 'a' && xx.charAt(1) == 'b' && (xx.charAt(0) + xx.charAt(2)) - 48 == 56)) {
                    flag = 0;
                }
                if (flag == 1) {
                    char[] x = "dd2940c04462b4dd7c450528835cca15".toCharArray();
                    x[2] = (char) ((x[2] + x[3]) - 50);
                    x[4] = (char) ((x[2] + x[5]) - 48);
                    x[30] = (char) ((x[31] + x[9]) - 48);
                    x[14] = (char) ((x[27] + x[28]) - 97);
                    for (int i = 0; i < 16; i++) {
                        char a = x[31 - i];
                        x[31 - i] = x[i];
                        x[i] = a;
                    }
                    textview.setText("flag{" + String.valueOf(x) + "}");
                    return;
                }
                textview.setText("输入注册码错误");
            }
        });
    }
​

写EXP

#include<stdio.h>
#include<windows.h>
#include<string.h>
int main(){
 char x[]= "dd2940c04462b4dd7c450528835cca15";
                   x[2] = (char) ((x[2] + x[3]) - 50);
                    x[4] = (char) ((x[2] + x[5]) - 48);
                    x[30] = (char) ((x[31] + x[9]) - 48);
                    x[14] = (char) ((x[27] + x[28]) - 97);
                    for (int i = 0; i < 16; i++) {
                        char a = x[31 - i];
                        x[31 - i] = x[i];
                        x[i] = a;
                    }
                    puts(x);
//59acc538825054c7de4b26440c0999dd

}

第十七题GWCTF 2019]pyre

pyc逆向

直接逆向

# uncompyle6 version 3.8.0
# Python bytecode 2.7 (62211)
# Decompiled from: Python 3.8.5 (tags/v3.8.5:580fbb0, Jul 20 2020, 15:57:54) [MSC v.1924 64 bit (AMD64)]
# Embedded file name: encode.py
# Compiled at: 2019-08-19 21:01:57
print 'Welcome to Re World!'
print 'Your input1 is your flag~'
l = len(input1)
for i in range(l):
    num = ((input1[i] + i) % 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']
# okay decompiling 1.pyc

直接写EXP

#include<stdio.h>
#include<windows.h>
#include<string.h>
int main(){
char code[]={'\x1f', '\x12', '\x1d', '(', '0', '4', '\x01', '\x06', '\x14', '4', ',', '\x1b', 'U', '?', 'o', '6', '*', ':', '\x01', 'D', ';', '%', '\x13'};
int i, len =strlen(code);
for(i=len-2; i>=0; i--){
 code[i] = code[i] ^ code[(i + 1)];
}
char flag[len+1];
flag[len] = '\0';
for(i=0; i<=len-1; i++){
  int j = 0;
  for(j = 0;j<2;j++)
  {
    flag[i] = code[i] -i+j*128;
  if(flag[i]<=126&&flag[i]>=0) break;
  }
 
}
puts(flag);
}
//GWHT{Just_Re_1s_Ha66y!}

flag{Just_Re_1s_Ha66y!}

第十八题[ACTF新生赛2020]easyre

UPX直接脱壳

关键部分

 __main();
  qmemcpy(v4, "*F'"N,"(I?+@", sizeof(v4));
  printf("Please input:");
  scanf("%s", v6);
  if ( v6[0] != 'A' || v6[1] != 'C' || v6[2] != 'T' || v6[3] != 'F' || v6[4] != '{' || v10 != '}' )//ACTF{*F'"N,"(I?+@}
    return 0;
  v5[0] = v7;
  v5[1] = v8;
  v5[2] = v9;
  for ( i = 0; i <= 11; ++i )
  {
    if ( v4[i] != _data_start__[*((char *)v5 + i) - 1] )
      return 0;
  }
  printf("You are correct!");
  return 0;
}
    if ( v4[i] != enflag[*((char *)v5 + i) - 1] )
    v4[i]=enflag[j];
    v5[i]=j+1;
这次上python脚本
code='''~}|{zyxwvutsrqponmlkjihgfedcba`_^][ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$# !"'''

v4='''*F'"N,"(I?+@''';

flag=""

for i in range(len(v4)):

  for j in range(len(code)):

​    if ord(v4[i]) == ord(code[j]):

​      flag+=chr(j+1)

print(flag)
#U9X_1S_W6@T?

第十九题RSA

提取公钥指数及模数信息:

模数:C0332C5C64AE47182F6C1C876D42336910545A58F7EEFEFC0BCAAF5AF341CCDD
指数:65537 (0x10001)

表示n=0xC0332C5C64AE47182F6C1C876D42336910545A58F7EEFEFC0BCAAF5AF341CCDD

e=65537

n=86934482296048119190666062003494800588905656017203025617216654058378322103517

q=285960468890451637935629440372639283459

p=304008741604601924494328155975272418463

然后就是rsa的使用了,

别人的wp

import gmpy2
import rsa
e = 65537
n = 86934482296048119190666062003494800588905656017203025617216654058378322103517
p = 285960468890451637935629440372639283459
q = 304008741604601924494328155975272418463

phin = (q-1)*(p-1)
d = gmpy2.invert(e, phin)

key = rsa.PrivateKey(n, e, int(d), p, q)

with open("flag.enc", "rb+") as f:
    f = f.read()
    print(rsa.decrypt(f, key))

第二十题rome

定位关键代码

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 == 'A' )
  {
    result = v3;
    if ( v3 == 'C' )
    {
      result = v4;
      if ( v4 == 'T' )
      {
        result = v5;
        if ( v5 == 'F' )
        {
          result = v6;
          if ( v6 == '{' )
          {
            result = v11;
            if ( v11 == '}' )
            {
              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]) > '@' && *((char *)v1 + *(_DWORD *)&v12[17]) <= 'Z' )
                  *((_BYTE *)v1 + *(_DWORD *)&v12[17]) = (*((char *)v1 + *(_DWORD *)&v12[17]) - 51) % 26 + 65;
                if ( *((char *)v1 + *(_DWORD *)&v12[17]) > '`' && *((char *)v1 + *(_DWORD *)&v12[17]) <= 'z' )
                  *((_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;
}

不好看,把关键部分化简一下

          j = 0;
              while ( j <= 15 )
              {
                if ( v1[j] > '@' && v1[j]  <= 'Z' )
                  v1[j]  = (v1[j]  - 51) % 26 + 65;
                if ( v1[j] > '`' && v1[j] <= 'z' )
                 v1[j]  = (v1[j]  - 79) % 26 + 97;
                ++j;
              }
             j = 0;
              while ( j <= 15 )
              {
               char result = (unsigned __int8)v12[j];
                if ( v1[j]  != result )
                  return result;
                ++j;
              }
              result = printf("You are correct!");

然后while化成for,主要我不习惯

for(j = 0;j<=15;j++)
{
                if ( v1[j] > '@' && v1[j]  <= 'Z' )
                  v1[j]  = (v1[j]  - 51) % 26 + 65;
                if ( v1[j] > '`' && v1[j] <= 'z' )
                 v1[j]  = (v1[j]  - 79) % 26 + 97;
}
for(j = 0;j<=15;j++)
{
 char result = (unsigned __int8)v12[j];
                if ( v1[j]  != result )
                  return result;

}
//v12="Qsw3sj_lz4_Ujw@l"

好了逻辑到这里就很清楚了

EXP

v1="Qsw3sj_lz4_Ujw@l"
flag=""
j = 0
for i in v1:
    if i > '`' and i <= 'z' :
        for k in range(10):
            z=chr(ord(i)-97+k*26+79)
            if z<='z'and z>'`':
               flag+=z
               print(flag)
               break;
    elif  i > '@' and i <= 'Z':
        for k in range(10):
            z=chr(ord(i)-65+k*26+51)
            if z<='Z'and z>'@':
               flag+=z
               print(flag)
               break;
    else: flag+=i
print(flag)
        

\