REVERSE-PRACTICE-BUUCTF-21

[SCTF2019]babyre

elf文件,无壳,用ida分析
在start函数中看到main函数的字样,但是左侧函数窗没有找到main函数
原因是main函数中加了花指令,导致ida不能正确地分析main函数
main函数中有三处类似这样的花指令,把jb,jnb,loope三条指令都nop掉,创建函数,F5反编译
babyre-fakecode
main函数中要求输入三个password,三个pwd都正确才能得到flag
先看第一个password的部分,是个走迷宫的逻辑
v28~v44是迷宫的map,长度为125,起点为’s’
往下走,switch case语句是由输入pwd1的字符决定方向,w-上,s-下,d-右,a-左,x-下一块,y-上一块,由此可以知道,长度为125的map,每25分为一个块,每个块又是5x5排列,路线只能走’.’,终点为’#’,要求最短的路线

  v28 = '********';                             // 注意小端序
  v29 = '*.******';
  v30 = '.s**.***';
  v31 = '****..*.';
  v32 = '.****.**';
  v33 = '********';
  v34 = '***..***';
  v35 = '*#..**..';
  v36 = '*..***..';
  v37 = '*****.**';
  v38 = '********';
  v39 = '.*******';
  v40 = '****..**';
  v41 = '.**..***';
  v42 = '*.*..*..';
  v43 = '.**.';
  v44 = '*';
  v10 = 0LL;
  v11 = 0LL;
  v12 = 0;
  v7 = (char *)&v30 + 6;                        // 起点为's'
  v8 = '019_ftcs';                              // v8='sctf_9102'
  v9 = '2';
  puts((const char *)(unsigned int)"plz tell me the shortest password1:");
  scanf("%s", &pwd1);
  v6 = 1;
  while ( v6 )
  {
    v4 = *((_BYTE *)&pwd1 + v5);
    switch ( v4 )
    {
      case 'w':
        v7 -= 5;
        break;
      case 's':
        v7 += 5;
        break;
      case 'd':
        ++v7;
        break;
      case 'a':
        --v7;
        break;
      case 'x':
        v7 += 25;
        break;
      case 'y':
        v7 -= 25;
        break;
      default:
        v6 = 0;
        break;
    }
    ++v5;
    if ( *v7 != '.' && *v7 != '#' )             // 只能走'.'
      v6 = 0;
    if ( *v7 == '#' )                           // 最后到'#'
    {
      puts("good!you find the right way!\nBut there is another challenge!");
      break;
    }
  }

将长度为125的map按照每25一块,每块5x5排列的方式,按w-上,s-下,d-右,a-左,x-下一块,y-上一块的规定,得到最短的路线为sxss,验证正确
babyre-route
往下走,看第二个password的部分
pwd2和v17作为参数传入loc_C22逻辑段的函数,过程中v17被赋值,函数返回后v17和v8比较,已知v8是字符串"sctf_9102"

  if ( v6 )
  {
    puts((const char *)(unsigned int)"plz tell me the password2:");
    scanf("%s", &pwd2);
    ((void (__fastcall *)(__int64 *, __int64 *))loc_C22)(&pwd2, &v17);
    if ( (unsigned int)sub_F67((const char *)&v17, (const char *)&v8) == 1 )// v17和v8比较,v8='sctf_9102'
    {
      puts("Congratulation!");

loc_C22逻辑段的代码也被插入了花指令,jb和jnb直接nop掉,“in"指令的第一个字节改成0x90
下面未被识别成代码的数据按d转成一个一个字节的形式,把前两个值为0的字节改成0x90
创建函数,F5反编译
babyre-fakecode
进入sub_C22函数,来到给v17赋值的部分
0x3f的二进制为0b00111111,v7又被v7<<6赋值,v9等于4时才会进入if语句给v17赋值,由6x4=8x3,猜测是base64的反编码过程,反编码的结果为v8的字符串"sctf_9102”,于是pwd2为v8的base64编码,即为"c2N0Zl85MTAy",验证正确
babyre-sub_C22
往下走,看第三个password的部分
pwd3进入sub_FFA函数进行验证,返回1验证成功

      puts((const char *)(unsigned int)"Now,this is the last!");
      puts("plz tell me the password3:");
      scanf("%s", &pwd3);
      if ( (unsigned int)sub_FFA(&pwd3) == 1 )
      {
        puts("Congratulation!Here is your flag!:");
        printf("sctf{%s-%s(%s)}", &pwd1, &pwd2, &pwd3);
      }

进入sub_FFA函数,将输入的pwd3按大端序规则,16个byte转成4个int,do循环体中的sub_143B进行变换和赋值,最后四次循环赋值给v44~v47,v44到v47的4个int按大端序规则,转成16个byte,与v8比较验证

signed __int64 __fastcall sub_FFA(char *pwd3)
{
  int v1; // ST24_4
  int v2; // ST28_4
  int v3; // ST2C_4
  signed int v5; // [rsp+18h] [rbp-158h]
  signed int i; // [rsp+18h] [rbp-158h]
  int v7; // [rsp+1Ch] [rbp-154h]
  int v8; // [rsp+30h] [rbp-140h]
  int v9; // [rsp+34h] [rbp-13Ch]
  int v10; // [rsp+38h] [rbp-138h]
  int v11; // [rsp+3Ch] [rbp-134h]
  int v12; // [rsp+40h] [rbp-130h]
  int v13; // [rsp+44h] [rbp-12Ch]
  int v14; // [rsp+48h] [rbp-128h]
  int v15; // [rsp+4Ch] [rbp-124h]
  int v16; // [rsp+50h] [rbp-120h]
  int v17; // [rsp+54h] [rbp-11Ch]
  int v18; // [rsp+58h] [rbp-118h]
  int v19; // [rsp+5Ch] [rbp-114h]
  int v20; // [rsp+60h] [rbp-110h]
  int v21; // [rsp+64h] [rbp-10Ch]
  int v22; // [rsp+68h] [rbp-108h]
  int v23; // [rsp+6Ch] [rbp-104h]
  unsigned int v24; // [rsp+70h] [rbp-100h]
  int v25; // [rsp+74h] [rbp-FCh]
  int v26; // [rsp+78h] [rbp-F8h]
  int v27; // [rsp+7Ch] [rbp-F4h]
  unsigned int v28; // [rsp+80h] [rbp-F0h]
  int v29; // [rsp+84h] [rbp-ECh]
  int v30; // [rsp+88h] [rbp-E8h]
  int v31; // [rsp+8Ch] [rbp-E4h]
  unsigned int v32; // [rsp+90h] [rbp-E0h]
  int v33; // [rsp+94h] [rbp-DCh]
  int v34; // [rsp+98h] [rbp-D8h]
  int v35; // [rsp+9Ch] [rbp-D4h]
  unsigned int v36; // [rsp+A0h] [rbp-D0h]
  int v37; // [rsp+A4h] [rbp-CCh]
  int v38; // [rsp+A8h] [rbp-C8h]
  int v39; // [rsp+ACh] [rbp-C4h]
  int v40; // [rsp+B0h] [rbp-C0h]
  int v41; // [rsp+B4h] [rbp-BCh]
  int v42; // [rsp+B8h] [rbp-B8h]
  int v43; // [rsp+BCh] [rbp-B4h]
  unsigned int v44; // [rsp+118h] [rbp-58h]
  unsigned int v45; // [rsp+11Ch] [rbp-54h]
  unsigned int v46; // [rsp+120h] [rbp-50h]
  unsigned int v47; // [rsp+124h] [rbp-4Ch]
  unsigned __int64 v48; // [rsp+168h] [rbp-8h]

  v48 = __readfsqword(0x28u);
  v8 = 0xBE;
  v9 = 4;
  v10 = 6;
  v11 = 0x80;
  v12 = 0xC5;
  v13 = 0xAF;
  v14 = 0x76;
  v15 = 0x47;
  v16 = 0x9F;
  v17 = 0xCC;
  v18 = 0x40;
  v19 = 0x1F;
  v20 = 0xD8;
  v21 = 0xBF;
  v22 = 0x92;
  v23 = 0xEF;
  v1 = (pwd3[6] << 8) | (pwd3[5] << 16) | (pwd3[4] << 24) | pwd3[7];// 大端序
  v2 = (pwd3[10] << 8) | (pwd3[9] << 16) | (pwd3[8] << 24) | pwd3[11];
  v3 = (pwd3[14] << 8) | (pwd3[13] << 16) | (pwd3[12] << 24) | pwd3[15];
  v7 = 0;
  v5 = 4;
  v40 = sub_78A((pwd3[2] << 8) | (pwd3[1] << 16) | (*pwd3 << 24) | (unsigned int)pwd3[3]);// 大端序
  v41 = sub_78A(v1);
  v42 = sub_78A(v2);
  v43 = sub_78A(v3);                            // v40~v43被pwd3赋值,按大端序规则,16个byte转成4个int
  do
  {
    *(&v40 + v5) = sub_143B(*(&v40 + v7), *(&v40 + v7 + 1), *(&v40 + v7 + 2), *(&v40 + v7 + 3));// 变换
    ++v7;
    ++v5;
  }
  while ( v5 <= 29 );
  v24 = v44 >> 24;                              // do循环体填充v43~v44之间的地址,v44~v47是最后四次循环被赋值
  v25 = BYTE2(v44);
  v26 = BYTE1(v44);
  v27 = (unsigned __int8)v44;
  v28 = v45 >> 24;
  v29 = BYTE2(v45);
  v30 = BYTE1(v45);
  v31 = (unsigned __int8)v45;
  v32 = v46 >> 24;
  v33 = BYTE2(v46);
  v34 = BYTE1(v46);
  v35 = (unsigned __int8)v46;
  v36 = v47 >> 24;
  v37 = BYTE2(v47);
  v38 = BYTE1(v47);
  v39 = (unsigned __int8)v47;
  for ( i = 0; i <= 15; ++i )
  {
    if ( *(&v24 + i) != *(&v8 + i) )            // v44~v47的4个int分成16个byte,与v8比较
      return 0xFFFFFFFFLL;
  }
  return 1LL;
}

sub_143B函数,异或运算

__int64 __fastcall sub_143B(int a1, int a2, int a3, unsigned int a4)
{
  return a1 ^ (unsigned int)sub_1464(a2 ^ a3 ^ a4);
}

sub_1464函数,主要也是异或运算

__int64 __fastcall sub_1464(unsigned int a1)
{
  int v1; // ST18_4
  int v3[290]; // [rsp+20h] [rbp-490h]
  unsigned __int64 v4; // [rsp+4A8h] [rbp-8h]

  v4 = __readfsqword(0x28u);
  qmemcpy(v3, &off_1940, 1152uLL);
  v1 = (v3[BYTE2(a1)] << 16) | v3[(unsigned __int8)a1] | (v3[BYTE1(a1)] << 8) | (v3[a1 >> 24] << 24);
  return __ROL4__(v1, 12) ^ (unsigned int)(__ROL4__(v1, 8) ^ __ROR4__(v1, 2)) ^ __ROR4__(v1, 6);
}

于是do循环体中的变换赋值主要是异或运算,直接可逆,sub_1464函数的代码直接用,写脚本即可解出pwd3

#include <stdio.h>
#include "ida_defs.h"
unsigned int off_1940[288] = {
	0xD6, 0x90, 0xE9, 0xFE, 0xCC, 0xE1, 0x3D, 0xB7,
	0x16, 0xB6, 0x14, 0xC2, 0x28, 0xFB, 0x2C, 0x05,
	0x2B, 0x67, 0x9A, 0x76, 0x2A, 0xBE, 0x04, 0xC3,
	0xAA, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,
	0x9C, 0x42, 0x50, 0xF4, 0x91, 0xEF, 0x98, 0x7A,
	0x33, 0x54, 0x0B, 0x43, 0xED, 0xCF, 0xAC, 0x62,
	0xE4, 0xB3, 0x1C, 0xA9, 0xC9, 0x08, 0xE8, 0x95,
	0x80, 0xDF, 0x94, 0xFA, 0x75, 0x8F, 0x3F, 0xA6,
	0x47, 0x07, 0xA7, 0xFC, 0xF3, 0x73, 0x17, 0xBA,
	0x83, 0x59, 0x3C, 0x19, 0xE6, 0x85, 0x4F, 0xA8,
	0x68, 0x6B, 0x81, 0xB2, 0x71, 0x64, 0xDA, 0x8B,
	0xF8, 0xEB, 0x0F, 0x4B, 0x70, 0x56, 0x9D, 0x35,
	0x1E, 0x24, 0x0E, 0x5E, 0x63, 0x58, 0xD1, 0xA2,
	0x25, 0x22, 0x7C, 0x3B, 0x01, 0x21, 0x78, 0x87,
	0xD4, 0x00, 0x46, 0x57, 0x9F, 0xD3, 0x27, 0x52,
	0x4C, 0x36, 0x02, 0xE7, 0xA0, 0xC4, 0xC8, 0x9E,
	0xEA, 0xBF, 0x8A, 0xD2, 0x40, 0xC7, 0x38, 0xB5,
	0xA3, 0xF7, 0xF2, 0xCE, 0xF9, 0x61, 0x15, 0xA1,
	0xE0, 0xAE, 0x5D, 0xA4, 0x9B, 0x34, 0x1A, 0x55,
	0xAD, 0x93, 0x32, 0x30, 0xF5, 0x8C, 0xB1, 0xE3,
	0x1D, 0xF6, 0xE2, 0x2E, 0x82, 0x66, 0xCA, 0x60,
	0xC0, 0x29, 0x23, 0xAB, 0x0D, 0x53, 0x4E, 0x6F,
	0xD5, 0xDB, 0x37, 0x45, 0xDE, 0xFD, 0x8E, 0x2F,
	0x03, 0xFF, 0x6A, 0x72, 0x6D, 0x6C, 0x5B, 0x51,
	0x8D, 0x1B, 0xAF, 0x92, 0xBB, 0xDD, 0xBC, 0x7F,
	0x11, 0xD9, 0x5C, 0x41, 0x1F, 0x10, 0x5A, 0xD8,
	0x0A, 0xC1, 0x31, 0x88, 0xA5, 0xCD, 0x7B, 0xBD,
	0x2D, 0x74, 0xD0, 0x12, 0xB8, 0xE5, 0xB4, 0xB0,
	0x89, 0x69, 0x97, 0x4A, 0x0C, 0x96, 0x77, 0x7E,
	0x65, 0xB9, 0xF1, 0x09, 0xC5, 0x6E, 0xC6, 0x84,
	0x18, 0xF0, 0x7D, 0xEC, 0x3A, 0xDC, 0x4D, 0x20,
	0x79, 0xEE, 0x5F, 0x3E, 0xD7, 0xCB, 0x39, 0x48,
	0xC6, 0xBA, 0xB1, 0xA3, 0x50, 0x33, 0xAA, 0x56,
	0x97, 0x91, 0x7D, 0x67, 0xDC, 0x22, 0x70, 0xB2,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

unsigned int sub_1464(unsigned int a1)
{
	int v1;
	v1 = (off_1940[BYTE2(a1)] << 16) | off_1940[(unsigned __int8)a1] | (off_1940[BYTE1(a1)] << 8) | (off_1940[a1 >> 24] << 24);
	return __ROL4__(v1, 12) ^ (unsigned int)(__ROL4__(v1, 8) ^ __ROR4__(v1, 2)) ^ __ROR4__(v1, 6);
}

int main()
{
	unsigned int v40[30] = { 0 };
	v40[26] = 0xBE040680;
	v40[27] = 0xC5AF7647;
	v40[28] = 0x9FCC401F;
	v40[29] = 0xD8BF92EF;
	int i;
	for (i = 25; i >= 0; i--)
		v40[i] = sub_1464(v40[i + 1] ^ v40[i + 2] ^ v40[i + 3]) ^ v40[i + 4];
	for (i = 0; i < 4; i++)
		printf("%c%c%c%c", ((char*)&v40[i])[0], ((char*)&v40[i])[1], ((char*)&v40[i])[2], ((char*)&v40[i])[3]);
	return 0;
//fl4g_is_s0_ug1y!
}

将三个password输入,得到flag
但是提交失败,看里别的师傅的wp,第一个password走迷宫出错了
正确的pwd1为ddwwxxssxaxwwaasasyywwdd
于是flag为sctf{ddwwxxssxaxwwaasasyywwdd-c2N0Zl85MTAy(fl4g_is_s0_ug1y!)}
babyre-flag

[MRCTF2020]EasyCpp

elf文件,无壳,ida分析
main函数,读取输入,输入赋到v21,利用迭代器将v21从头到尾全部异或1
easycpp-part1
异或1后的输入进入depart函数,将输入分解成其因子,各因子间用空格分隔,结果放到v15,v15进入func进行替换,数字变字符,空格变等号,替换后的结果进入check与已知比较
easycpp-part2
depart函数
easycpp-depart
写逆运算脚本即可得到正确的输入

#coding:utf-8
res=['=zqE=z=z=z','=lzzE','=ll=T=s=s=E','=zATT',
     '=s=s=s=E=E=E','=EOll=E','=lE=T=E=E=E',
     '=EsE=s=z','=AT=lE=ll']
for s in res:
    ss=s.replace('O','0').replace('l','1').replace('z','2').replace('E','3').replace('A','4').replace('s','5').replace('G','6').replace('T','7').replace('B','8').replace('q','9').replace('=',' ')
    data=ss.split(' ')[1:] #第0个均为空格 故从第1个开始
    sum=1
    for i in data:         #乘回去
        sum*=int(i,10)
    sum^=1                  #异或1
    print(sum),
#2345 1222 5774 2476 3374 9032 2456 3531 6720

将数字串取32位大写md5散列即可提交成功
easycpp-flag

[GUET-CTF2019]encrypt

elf文件,无壳,ida分析
main函数,逻辑清晰,读取输入,对输入进行RC4加密,再进行很像base64的变换,只是没有从表中取值,变换后的输入与已知的数据比较,验证输入

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  int v3; // eax
  int v4; // eax
  char v6; // [rsp+4h] [rbp-93Ch]
  int i; // [rsp+8h] [rbp-938h]
  int v8; // [rsp+Ch] [rbp-934h]
  char v9; // [rsp+10h] [rbp-930h]
  char v10; // [rsp+420h] [rbp-520h]
  char v11; // [rsp+421h] [rbp-51Fh]
  char v12; // [rsp+422h] [rbp-51Eh]
  char v13; // [rsp+423h] [rbp-51Dh]
  char v14; // [rsp+424h] [rbp-51Ch]
  char v15; // [rsp+425h] [rbp-51Bh]
  char v16; // [rsp+426h] [rbp-51Ah]
  char v17; // [rsp+427h] [rbp-519h]
  char input; // [rsp+430h] [rbp-510h]
  char v19[1032]; // [rsp+530h] [rbp-410h]
  unsigned __int64 v20; // [rsp+938h] [rbp-8h]

  v20 = __readfsqword(0x28u);
  v10 = 16;
  v11 = 32;
  v12 = 48;
  v13 = 48;
  v14 = 32;
  v15 = 32;
  v16 = 16;
  v17 = 64;
  memset(&input, 0, 0x100uLL);
  v8 = strlen(&input);
  memset(v19, 0, 0x400uLL);
  printf("please input your flag:", a2, v19);
  scanf("%s", &input);                          // 获取输入
  memset(&v9, 0, 1032uLL);
  RC4_S(&v9, (__int64)&v10, 8);                 // RC4加密算法,生成S盒,打乱S盒,密钥为v10~17的8个字节
  v3 = strlen(&input);
  RC4_encrypt(&v9, (__int64)&input, v3);        // RC4加密算法,对输入进行异或加密
  v4 = strlen(&input);
  base64_like((__int64)&input, v4, v19, &v6);   // 对加密后的输入进行变换,变换结构很像base64,变换的结果放到v19
  for ( i = 0; i <= 50; ++i )
  {
    if ( v19[i] != res[i] )                     // v19与res比较,验证输入
    {
      puts("Wrong");
      return 0LL;
    }
  }
  puts("Good");
  return 0LL;
}

由最后要比较的数据,逆很像base64的变换,得到输入经RC4加密后的密文

res="Z`TzzTrD|fQP[_VVL|yneURyUmFklVJgLasJroZpHRxIUlH\\vZE="
data=[]
for i in range(len(res)-1):
    data.append(ord(res[i])-61)
data.append(ord('='))
cipher=[]
for i in range(0,len(data),4):
    tmp=bin(data[i]).replace('0b','').zfill(6)+bin(data[i+1]).replace('0b','').zfill(6)+bin(data[i+2]).replace('0b','').zfill(6)+bin(data[i+3]).replace('0b','').zfill(6)
    a=int('0b'+tmp[0:8],2)
    b=int('0b'+tmp[8:16],2)
    c=int('0b'+tmp[16:24],2)
    cipher.append(a)
    cipher.append(b)
    cipher.append(c)
print(cipher)
#[118, 53, 253, 245, 125, 71, 254, 149, 19, 122, 38, 89, 63, 255, 49, 161, 133, 124, 99, 2, 110, 189, 147, 106, 62, 77, 141, 215, 39, 115, 45, 94, 204, 98, 242, 223, 229, 210, 61]

由已知的密钥(v10~v17的8个字节)和密文cipher,解密RC4,即可得到flag

#include<stdio.h>
void rc4_init(unsigned char* s, unsigned char* key, unsigned long Len_k) //初始化函数
{
	int i = 0, j = 0;
	char k[256] = { 0 };
	unsigned char tmp = 0;
	for (i = 0; i < 256; i++) {
		s[i] = i;
		k[i] = key[i % Len_k];
	}
	for (i = 0; i < 256; i++) {
		j = (j + s[i] + k[i]) % 256;
		tmp = s[i];
		s[i] = s[j]; 
		s[j] = tmp;
	}
}

/*
RC4加解密函数
unsigned char* Data     加解密的数据
unsigned long Len_D     加解密数据的长度
unsigned char* key      密钥
unsigned long Len_k     密钥长度
*/
void rc4_crypt(unsigned char* Data, unsigned long Len_D, unsigned char* key, unsigned long Len_k) //加解密
{
	unsigned char s[256];
	rc4_init(s, key, Len_k);
	int i = 0, j = 0, t = 0;
	unsigned long k = 0;
	unsigned char tmp;
	for (k = 0; k < Len_D; k++) {
		i = (i + 1) % 256;
		j = (j + s[i]) % 256;
		tmp = s[i];
		s[i] = s[j]; 
		s[j] = tmp;
		t = (s[i] + s[j]) % 256;
		Data[k] = Data[k] ^ s[t];
	}
}
void main()
{
	//密钥
	unsigned char key[] = {16,32,48,48,32,32,16,64};
	//密钥长度 
	unsigned long key_len = sizeof(key);
	//密文
	unsigned char data[] = { 118, 53, 253, 245, 125, 71, 254, 149, 19, 122, 38, 89, 63, 255, 49, 161, 133, 124, 99, 2, 110, 189, 147, 106, 62, 77, 141, 215, 39, 115, 45, 94, 204, 98, 242, 223, 229, 210, 61 };
	//解密
	rc4_crypt(data, sizeof(data), key, key_len);
	for (int i = 0; i < sizeof(data); i++)
	{
		printf("%c", data[i]);
	}
}
//flag{e10adc3949ba59abbe56e057f20f883e}

[QCTF2018]Xman-babymips

mips文件,无壳,用ida7.5打开(其他版本的ida可能不能反编译mips)
main函数,读取输入,长度为32,先进行input[i]^=32-i的变换,变换后的input的前5个字符与"Q|j{g"比较,相同时进入sub_4007F0函数,对后27个字符再进行变换
xmanmips-main
sub_4007F0函数,不考虑前5个字符,下标从5开始,分奇偶数对输入进行移位变换,变换后与已知数据比较
xmanmips-sub_4007F0
写逆脚本即可得到flag

#coding:utf-8
s="Q|j{g"
off_410D04=[0,0,0,0,0,0x52, 0xFD, 0x16, 0xA4, 0x89, 0xBD, 0x92, 0x80, 0x13, 0x41,
  0x54, 0xA0, 0x8D, 0x45, 0x18, 0x81, 0xDE, 0xFC, 0x95, 0xF0,
  0x16, 0x79, 0x1A, 0x15, 0x5B, 0x75, 0x1F] #前面补5个0,保持下标一致
flag=[0]*32
for i in range(len(s)):
    flag[i]=ord(s[i])
for i in range(5,len(off_410D04)):
    if i&1:
        flag[i]=(off_410D04[i]<<2)&0xfc|(off_410D04[i]>>6)&0x03
    else:
        flag[i]=(off_410D04[i]>>2)&0x3f|(off_410D04[i]<<6)&0xc0
for i in range(len(flag)):
    flag[i]^=32-i
print(''.join(chr(i) for i in flag))
#qctf{ReA11y_4_B@89_mlp5_4_XmAn_}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

P1umH0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值