re刷题记录

目录

tea

  1. 打开师傅所给的题目,发现是让输入flag,并且没有回显,典型的ctf题目

  2. 拖进怕pe查壳,无壳的GCC编译的64位程序
    tap1

  3. 拖进IDA64位,查看字符串,发现right,wrong,双击跟进

  4. F5反汇编如下,接着对代码进行分析

    按r键直接将LOBYTE,BYTE,HIBYTE转为字符是flag{}
    tap2
    tap3

  5. 分析main代码,发现最重要的还是加密encrypt()函数

    scanf(“%38s”, v9);               // 输入38位的flag到v9中
    strncpy(Destination, (const char *)v9 + 5, 0x20ui64)                         // 从第v9+6个字符开始复制,复制32位到Destination中

    for ( i = 0; i <= 31; i += 8 )			// 总体来说循环4次
        {
          v4[0] = *(_DWORD *)&Destination[i];		// 将flag从v9[5+4k]到v[8+4k]赋予v4[0]
          v4[1] = *(_DWORD *)&Destination[i + 4];		// 将flag从v9[5+5k]到v[8+8k]赋予v4[1]
    // 先加密8位,逐步进行
          encrypt(v4, &::k);			// 对输入的flag进行加密,加密内容下面展示
          for ( j = 0; j <= 1; ++j )	// 两次循环
    // 仔细观察,可以知道是分别对两次传入的字符进行比较
    
          {
            for ( k = 0; k <= 3; ++k )	
    // 此处for循环是对每一个字符进行比较
            {
              if ( (unsigned __int8)v4[j] != str2[4 * j + i + k] )		// flag加密后的字符就在str2中,若加密后v4与str2不等,wrong!
              {
                printf("Wrong!");
                return 0;
              }
              v4[j] = (unsigned int)v4[j] >> 8;		// 将每四个字符按照8位也就是一个字节进行右移,此时可以让v4[j]对比后几个字符,接着重复对比
            }
          }
        }
        printf("Right!");
    
  6. 接着分析encrypt函数

    _DWORD *__fastcall encrypt(unsigned int *a1, _DWORD *a2)
    {
      _DWORD *result; // rax
      int i; // [rsp+10h] [rbp-10h]
      int v4; // [rsp+14h] [rbp-Ch]
      unsigned int v5; // [rsp+18h] [rbp-8h]
      unsigned int v6; // [rsp+1Ch] [rbp-4h]
    
      v6 = *a1;		// 将flag依次传入的前四个字符赋予v6;(此处是将a1地址直接给v6)
      v5 = a1[1];		// 将flag依次传入的后四个字符赋予v5;(此处是以数组的形式传参给v5
      v4 = 0;			// v4等0
      for ( i = 0; i <= 31; ++i )
      {
    // a为密钥,包含4个int型
        v4 += 221492336;
        v6 += (v5 + v4) ^ (*a2 + 16 * v5) ^ ((v5 >> 5) + a2[1]);		// 对v5进行操作赋予v6
        v5 += (v6 + v4) ^ (a2[2] + 16 * v6) ^ ((v6 >> 5) + a2[3]);	// 对v6进行操作赋予v5
    
      }
      *a1 = v6;		// 将传进的字符串首地址还给v6,加密完成
      result = a1 + 1;
      a1[1] = v5;
      return result;
    }
    
  7. 代码分析完毕,接着对str2,k进行分析提取

    tap4
    tap5
    str2是以字节存储的,强制转为4字节存储,小端存储,读取时倒序,即
    str2 = 0x5d9aa22e,0x4d7577d8,0x45507ce0,0x5df8a572,0x14620e6d,0x5bd85f66,0xc8c45d8a,0x65fd2074,k = 1,2,3,4;

  8. 经搜索为tea加密,得到其是极小加密算法,,脚本实际不是太会,问了一位佬才搞出来

    #include <stdio.h>
    #define DELTA 0xD33B470
    
    void encrypt(unsigned int* a, unsigned int* a2) {
        unsigned int v3, v4;
        int j,i;
        for (j = 0; j <= 7; j += 2) {
            v3 = a[j];
            v4 = a[j + 1];
            unsigned sum = 0;
            for (i = 0; i <= 31; ++i) {
                sum += DELTA;
                v3 += (v4 + sum) ^ (*a2 + 16 * v4) ^ ((v4 >> 5) + a2[1]);
                v4 += (v3 + sum) ^ (a2[2] + 16 * v3) ^ ((v3 >> 5) + a2[3]);
            }
            a[j] = v3;
            a[j + 1] = v4;
        }
    }
    
    void decrypt(unsigned int* a, unsigned int* a2) {
        unsigned int v3, v4;
        int j,i;
        for (j = 0; j <= 7; j += 2) {
            v3 = a[j];
            v4 = a[j + 1];
            unsigned int sum = 0xA6768E00;
            for (i = 0; i <= 31; ++i) {
                v4 -= (v3 + sum) ^ (a2[2] + 16 * v3) ^ ((v3 >> 5) + a2[3]);
                v3 -= (v4 + sum) ^ (*a2 + 16 * v4) ^ ((v4 >> 5) + a2[1]);
                sum -= DELTA;
            }
            a[j] = v3;
            a[j + 1] = v4;
        }
    }
    
    int main()
    {
      /*int a[] = {0x2E,0xA2,0x9A,0x5D,0xD8,0x77,0x75,0x4D,
            0xE0,0x7C,0x50,0x45,0x72,0xA5,0xF8,0x5D,
            0x6D,0x0E,0x62,0x14,0x66,0x5F,0xD8,0x5B,
            0x8A,0x5D,0xC4,0xC8,0x74,0x20,0xFD,0x65 };*/
        unsigned int a[] = {0x5d9aa22e,0x4d7577d8,0x45507ce0,0x5df8a572,0x14620e6d,0x5bd85f66,0xc8c45d8a,0x65fd2074};
        unsigned int a2[4] = { 1,2,3,4};
        int i;
        decrypt(a,a2);
        for (i = 0; i < 8; ++i) {
            printf("%x ", a[i]);
        }
        encrypt(a, a2);
        puts("\n");
        for (i = 0; i < 8; ++i) {
            printf("%x ", a[i]);
        }
    
    }
    

到这里还没结束,最大的问题就是这,还需将得到的串在以4个字节逆序回来,才能得到原来正确输入的顺序,得到flag最后想要的32位4fe6818d59b8c6ca7cf055b2f12f8d27

RSA

下载出现pub.keyflag.enc两个文件
将pub.key文件的内容进行公钥解析
解析网站
得到e和n,对n进行分解因数求p,q
factordb解密传送


import rsa
import gmpy2
c = 1854183526100811878807183372982532818560316522978821358738967769534081571682
p = 285960468890451637935629440372639283459
q = 304008741604601924494328155975272418463
e = 65537
n = 86934482296048119190666062003494800588905656017203025617216654058378322103517
fn = (p-1)*(q-1)

d = int(gmpy2.invert(e,fn))
key = rsa.PrivateKey(n,e,d,q,p)
with open(r'c:\111\flag.enc','rb') as f:    #文件路径
    f = f.read()
    print(rsa.decrypt(f,key))

数字签名和数字证书

rome

  1. 查壳,32位,无壳
    int func()
    {
      int result; // eax
      int v1; // [esp+14h] [ebp-44h]
      int v2; // [esp+18h] [ebp-40h]
      int v3; // [esp+1Ch] [ebp-3Ch]
      int v4; // [esp+20h] [ebp-38h]
      unsigned __int8 v5; // [esp+24h] [ebp-34h]
      unsigned __int8 v6; // [esp+25h] [ebp-33h]
      unsigned __int8 v7; // [esp+26h] [ebp-32h]
      unsigned __int8 v8; // [esp+27h] [ebp-31h]
      unsigned __int8 v9; // [esp+28h] [ebp-30h]
      int v10; // [esp+29h] [ebp-2Fh]
      int v11; // [esp+2Dh] [ebp-2Bh]
      int v12; // [esp+31h] [ebp-27h]
      int v13; // [esp+35h] [ebp-23h]
      unsigned __int8 v14; // [esp+39h] [ebp-1Fh]
      char v15; // [esp+3Bh] [ebp-1Dh]
      char v16; // [esp+3Ch] [ebp-1Ch]
      char v17; // [esp+3Dh] [ebp-1Bh]
      char v18; // [esp+3Eh] [ebp-1Ah]
      char v19; // [esp+3Fh] [ebp-19h]
      char v20; // [esp+40h] [ebp-18h]
      char v21; // [esp+41h] [ebp-17h]
      char v22; // [esp+42h] [ebp-16h]
      char v23; // [esp+43h] [ebp-15h]
      char v24; // [esp+44h] [ebp-14h]
      char v25; // [esp+45h] [ebp-13h]
      char v26; // [esp+46h] [ebp-12h]
      char v27; // [esp+47h] [ebp-11h]
      char v28; // [esp+48h] [ebp-10h]
      char v29; // [esp+49h] [ebp-Fh]
      char v30; // [esp+4Ah] [ebp-Eh]
      char v31; // [esp+4Bh] [ebp-Dh]
      int i; // [esp+4Ch] [ebp-Ch]
    
      v15 = 81;
      v16 = 115;
      v17 = 119;
      v18 = 51;
      v19 = 115;
      v20 = 106;
      v21 = 95;
      v22 = 108;
      v23 = 122;
      v24 = 52;
      v25 = 95;
      v26 = 85;
      v27 = 106;
      v28 = 119;
      v29 = 64;
      v30 = 108;
      v31 = 0;
      printf("Please input:");
      scanf("%s", &v5);
      result = v5;
      if ( v5 == 'A' )
      {
        result = v6;
        if ( v6 == 'C' )
        {
          result = v7;
          if ( v7 == 'T' )
          {
            result = v8;
            if ( v8 == 'F' )
            {
              result = v9;
              if ( v9 == '{' )
              {
                result = v14;
                if ( v14 == '}' )
                {
                  v1 = v10;
                  v2 = v11;
                  v3 = v12;
                  v4 = v13;
                  for ( i = 0; i <= 15; ++i )
                  {
                    if ( *((_BYTE *)&v1 + i) > 64 && *((_BYTE *)&v1 + i) <= 90 )
                      *((_BYTE *)&v1 + i) = (*((char *)&v1 + i) - 51) % 26 + 65;
                    if ( *((_BYTE *)&v1 + i) > 96 && *((_BYTE *)&v1 + i) <= 122 )
                      *((_BYTE *)&v1 + i) = (*((char *)&v1 + i) - 79) % 26 + 97;
                  }
                  for ( i = 0; i <= 15; ++i )
                  {
                    result = (unsigned __int8)*(&v15 + i);
                    if ( *((_BYTE *)&v1 + i) != (_BYTE)result )
                      return result;
                  }
                  result = printf("You are correct!");
                }
              }
            }
          }
        }
      }
      return result;
    }
    
  2. 字符串操作
    if ( *((_BYTE *)&v1 + i) > 64 && *((_BYTE *)&v1 + i) <= 90 )
                      *((_BYTE *)&v1 + i) = (*((char *)&v1 + i) - 51) % 26 + 65;
                    if ( *((_BYTE *)&v1 + i) > 96 && *((_BYTE *)&v1 + i) <= 122 )
                      *((_BYTE *)&v1 + i) = (*((char *)&v1 + i) - 79) % 26 + 97;
    
    当其与上面v15相当后,得到结果,其中v15是连续的字符串
  3. 分析得到flag的python脚本
    v15 = [81,115,119,51,115,106,95,108,122,52,95,85,106,119,64,108]
    flag = ''
    for i in range(0,16):
         for j in range(0,127):
              f=j
              if j > 64 and j <= 90:
                   j = (j-51)%26 + 65
              if j > 96 and j <= 122:
                   j = (j-79)%26 + 97
              if(j == v15[i]):
                   flag += chr(f)
    print(flag)
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
青马易战是一款用于的在线教育平台,可以帮助学生提升编程能力。Python是一门强大的编程语言,具有简单易学、功能丰富的特点,可以用来实现青马易战的自动。 首先,我们可以使用Python的web自动化工具,如Selenium或Pyppeteer,来模拟用户在青马易战网站上的操作。通过编程方式,我们可以自动登录到青马易战网站,并进入目列表页面。 接下来,我们可以使用Python的数据处理和爬虫库,如BeautifulSoup或Scrapy,来提取目列表页面中的目信息,包括目名称、描述、输入输出样例等。 然后,我们可以使用Python的文本处理库,如re或pandas,来对目信息进行清洗和解析,将目描述和输入输出样例提取出来,并保存到相应的变量中,以便后续的处理和分析。 在获取目信息之后,我们可以使用Python的编程能力来编写算法来解。根据目的要求,我们可以使用Python的各种数据结构和算法进行求解,包括字符串处理、列表操作、循环、递归、排序、搜索等。通过编写相应的函数或方法,我们可以将解过程封装起来,以便于自动化。 最后,我们可以使用Python的自动化测试工具,如unittest或pytest,来对编写的解代码进行自动化测试。通过提供输入样例,我们可以自动调用解函数,并将输出结果与预期结果进行比较,以验证解代码的正确性。如果输出结果正确,我们可以将解代码保存,继续下一道流程。 通过以上步骤,就可以使用Python实现青马易战的自动。这样可以大大提高的效率,并帮助学生更好地学习和理解编程知识。同时,自动也可以帮助学生培养解思维和编程能力,提升竞赛的成绩。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值