zoukankan      html  css  js  c++  java
  • BUUOJ 第二弹

    1.Java逆向解密

    工具:jd-gui

    拖入jd-gui得到加密函数 public static void Encrypt(char[] arr)

    易得出是将用户输入加上‘@’^0x20的值再与KEY比较是否相等。

    0x20为16进制,异或时要转换为10进制即32

    可写出脚本:

    key=[180, 136, 137, 147, 191, 137, 147, 191, 148, 136, 133, 191, 134, 140, 129, 135, 191, 65]
    a=''
    for i in key:
        a += chr(i - ord('@')^32)
    print (a)
    

    解得 This_is_the_flag_!

    2.[BJDCTF2020]BJD hamburger competition

    工具:dnSpy,C#在线ide

    下载打开压缩包,发现是以unity为框架的小游戏,直接搜索Assembly-CSharp.dll文件,拖入dnspy进行反编译,找到关键类函数 ButtonSpawnFruit .发现关键代码

    找个网站解密哈希值得:

    接着就是进行MD5加密,跟进函数。

    一开始看不太懂,直接就用c#在线ide把这段代码搬上去。

    后来查到是调用系统md5加密函数后将字母全部转换为大写,再取前20个字符作为结果返回.得到md5加密后的结果,注意是用flag{}包上,而不是BJDCTF{} 。

    3.[HDCTF2019]Maze

    工具:Exeinfo pe,upx,IDA

    拖入Exeinfo pe,发现是一个加了upx壳的32位程序,走个流程脱壳。

    拖入IDA中寻找start函数,跟进main。

    发现main没有被ida识别成函数,看样子是被加花指令了。

    注意到_mian中有个jnz跳转,前面有个cmp,且跳转地址和与指令相邻的下一地址相同,所以相当于没跳转,把他nop掉。

    因为下面call另一个不是地址的地址,所以将反编译代码转换成机器码来看看。

    其中
    E8 对应指令为 call
    58 对应指令为 pop

    当ida把E8识别为call时,58 C7 45 EC便会被看作地址,此地址不存在便会无法反汇编,因此真正的指令应该是pop,所以把db 0E8hnop掉后,IDA就可以自动转换出汇编指令了

    接着按p将_mian转换为函数再进行反汇编。跟进 dword_408078和 dword_40807C查看到初始状态:dword_408078=7 dword_40807C=0,然后经过14次移动后要使 dword_408078=5 dword_40807C=-4才能解出答案。

    结合代码和题目名字Maze可得是一道迷宫题,但是程序好像没有判断迷宫。只要满足两个a和四个s就可以得到Congratulations!

    用ida搜索一下字符串,处理一下得到数据

    整理一下

    *******+**
    ******* **
    ****    **
    **   *****
    ** **F****
    **    ****
    **********
    

    因为dword_408078=7 dword_40807C=0,所以是+为起点,F为中点,且ad控制左右,ws控制上下。又因为

    a --dword_408078
    d ++dword_408078
    s --dword_40807C
    w ++dword_40807C
    

    所以s是上,w是下,a是右,d是左。

    若迷宫为正向,则行走路径为wwdddwddwwaaas;若迷宫为反向,则行走路径为ssaaasaassdddw。

    先验证一下.

    排除正向迷宫,提交一下:flag{ssaaasaassdddw}

    4.[GKCTF2020]BabyDriver

    工具:IDA

    根据题目描述,拖入IDA64中。看来看去没有头绪,搜下字符串,估计是个迷宫题

    跟进字符串,发现一共有224个字符,猜测是16*14 或 14*16,写个脚本验证一下

    list = '****************o.*..*......*..**.**...**.*.*.***.****.**.*.*.***...**....*.*.*****..***.**.*..**.**.***.**.**.**.**.******.**.**.**....***.**.**.*****.***....**...***.**********..***......#****.***************************** '
    a = 0
    for i in range(len(list)):
        a = a + 1
        print(list[i], end='')
        if a % 16 == 0:
            print('
    ', end='')
    

    得到

    ****************
    o.*..*......*..*
    *.**...**.*.*.**
    *.****.**.*.*.**
    *...**....*.*.**
    ***..***.**.*..*
    *.**.***.**.**.*
    *.**.******.**.*
    *.**....***.**.*
    *.*****.***....*
    *...***.********
    **..***......#**
    **.*************
    ****************
    

    跟进a0,并查看交叉引用列表。

    跟进sub_140001380进行反编译。得到关键代码,先分析好分析。

          v9 = aO[v5];
          if ( v9 == '*' )
          {
            v10 = "failed!
    ";
          }
          else
          {
            if ( v9 != '#' )
            {
    LABEL_27:
              aO[v5] = 'o';                   //更新位置
              goto LABEL_28;
            }
            v10 = "success! flag is flag{md5(input)}
    ";
          }
          dword_1400030E4 = 16;
          DbgPrint(v10);
          v5 = dword_1400030E4;
          goto LABEL_27;
        }
      }
    

    可知当碰到*时结束。碰到#时,你所输入的值md5加密后就是flag。

    再来分析输入判断。由于是驱动文件,所以输入比较的是16进制的键盘码

    LABEL_28:
            v6 += 6;
            if ( !--v7 )
              goto LABEL_29;
          }
          aO[v5] = 46;
          v8 = *v6;
          if ( *v6 == 0x17 )                 // I
          {
            if ( v5 & 0xFFFFFFF0 )           // 当V5>16,条件成立,因为是向上。所以不用考虑208这倒数第二层的边界
            {
              v5 -= 16;                      //上移
              goto LABEL_21;
            }
            v5 += 208;                       // 当V5<16也就是在第一层,强制碰到最后一层墙壁结束
            dword_1400030E4 = v5;
          }
          if ( v8 == 0x25 )                  // K
          {
            if ( (v5 & 0xFFFFFFF0) != 208 )  // 当V5>16且不等于208,条件成立,因为是向下。所以要考虑208这倒数第二层的边界
            {
              v5 += 16;                      //下移
              goto LABEL_21;
            }
            v5 -= 208;                       // 当v5=208,强制碰到第一层墙壁结束
            dword_1400030E4 = v5;
          }
          if ( v8 == 0x24 )                  // J
          {
            if ( v5 & 15 )                   //当v5不等于16的倍数时,即不在每一层的左边界,条件成立
            {
              --v5;                          //左移
              goto LABEL_21;
            }
            v5 += 15;                        //当v5等于16的倍数时,即在某一层的左边界 ,向右移15位,即移动到这一层的右边界
            dword_1400030E4 = v5;
          }
          if ( v8 != 0x26 )                   // L
            goto LABEL_22;
          if ( (v5 & 15) == 15 )              //当v5等于16的倍数-1时,即在某一层的右边界,条件成立      
            v5 -= 15;                         //向左移15位,即移动到这一层的左边界
          else
            ++v5;                             //右移
    LABEL_21:
          dword_1400030E4 = v5;
    

    所以,根据上面的迷宫和代码的分析:
    若为正向迷宫,则行走路径为 LKKKLLKLKKKLLLKKKLLLLLL;
    若为反向迷宫,则行走路径为 JIIIJJIJIIIJJJIIIJJJJJJ。

    然后进行md5 32位小写加密,进行验证,可得到只有正向才是对的,即flag{403950a6f64f7fc4b655dea696997851} 。

  • 相关阅读:
    shell数组
    Apache HTTP Server 与 Tomcat 的三种连接方式介绍
    实现Java动态类载入机制
    Tomcat 阀
    MYSQL 常用命令
    MYSQL字符数字转换
    主题:MySQL数据库操作实战
    日本手机三大代理商的UA
    Java解析XML文档——dom解析xml (转载)
    MS sql server和mysql中update多条数据的例子
  • 原文地址:https://www.cnblogs.com/b1ank/p/13466772.html
Copyright © 2011-2022 走看看