• HECTFreverse部分writeup


    因为期中考试(寄)所以很多题目没来得及复现,汇编也没学,感觉自己又变菜了qwq

    hard

    直接扔进Ida64查字符串/查汇编/查代码都可以得到flag:HECTF{HElLo_RRRRe}

    baby_upx

    尝试用指令脱壳失败,本来打算手动脱壳,但是后来偶然发现了upx-3.9.6封装好的一个脱壳软件,居然给脱出来了。

    反编译得到源代码:

    int __cdecl main(int argc, const char **argv, const char **envp)
    {
      unsigned int v3; // eax
      char String[26]; // [esp+1Eh] [ebp-46h] BYREF
      int v6; // [esp+38h] [ebp-2Ch]
      _DWORD v7[5]; // [esp+3Ch] [ebp-28h] BYREF
      char *v8; // [esp+50h] [ebp-14h]
      const char *v9; // [esp+54h] [ebp-10h]
      char i; // [esp+5Bh] [ebp-9h]
      int v11; // [esp+5Ch] [ebp-8h]
    
      sub_401AD0();
      v7[0] = 2099915543;
      v7[1] = 120201498;
      v7[2] = 269490557;
      v7[3] = 67837461;
      v7[4] = 271401;
      v9 = (const char *)v7;
      puts("Similarly, this is also a challenge for beginners");
      *(_DWORD *)String = 0;
      v6 = 0;
      v3 = 0;
      do
      {
        *(_DWORD *)&String[v3 + 2] = 0;
        v3 += 4;
      }
      while ( v3 < ((String - &String[2] + 30) & 0xFFFFFFFC) );
      printf("Now, please enter your flag: ");
      scanf("%30s", String);
      v11 = 0;
      v8 = strtok(String, "{");
      if ( strcmp(v8, "HECTF") )
        goto LABEL_10;
      v8 = strtok(0, "}");
      if ( !v8 )
        goto LABEL_10;
      for ( i = v8[v11]; i; i = v8[v11] )
      {
        i ^= String[(v11 ^ (rand() + 10086)) % 5];
        v8[v11++] = i;
      }
      if ( !strcmp(v8, v9) )
        puts("Success!");
      else
    LABEL_10:
        puts("Wrong!");
      return 0;
    }
    

    首先查询strtok函数的用法,发现是把HECTF{}这几个字符给去掉。
    发现输入语句之前的都是初始化,可以不用管,关键代码如下:

    for ( i = v8[v11]; i; i = v8[v11] )
      {
        i ^= String[(v11 ^ (rand() + 10086)) % 5];
        v8[v11++] = i;
      }
    

    我们发现v11是递增的

    i ^= String[(v11 ^ (rand() + 10086)) % 5];
    v8[v11++] = i;
    

    其实就是v9[v11]=v8[v11]^string(v11^(rand()+10086))%5]
    那么v8[v11]=v9[v11]^string(v11^(rand()+10086))%5]
    可以发现有个rand()函数,这是一个假随机数,只要种子是一样的rand出来的数就是一样的,可以预处理出rand数组。
    然后发现v8数组在通过这个循环结构后变成了v9,而v9直接copy源代码即可得到,由此得出exp:

    #include<bits/stdc++.h>
    #define I inline
    using namespace std;
    unsigned int v7[6];
    const char *v9;
    char *v8;
    char hectf[7]="HECTF{";
    char flag[30];
    int random[55];
    int len;
    
    I void make_rand(){for(int i=0;i<=50;i++)random[i]=rand();}
    
    int main()
    {
        v7[0]=2099915543;
        v7[1]=120201498;
        v7[2]=269490557;
        v7[3]=67837461;
        v7[4]=271401;
        v9=(const char *)v7;
        make_rand();
        for(int i=0;i<=18;i++)
        {
            flag[i]=v9[i]^hectf[(i^(random[i]+10086))%5];
        }
        for(int i=0;i<=18;i++)cout<<flag[i];
    }
    

    得到flag:
    HECTF{Thi5_iiS5_UUPX_LalA}

    baby_pp

    查壳发现用python打包的。

    用pyinstxtractor进行解包:

    得到main.pyc,用uncompyle6反编译(在线反编译出锅,比赛的时候反编译出来少了很多东西,后来用uncompyle6就可以了)

    查看python源代码:

    # uncompyle6 version 3.8.0
    # Python bytecode 3.8.0 (3413)
    # Decompiled from: Python 3.8.0 (tags/v3.8.0:fa919fd, Oct 14 2019, 19:37:50) [MSC v.1916 64 bit (AMD64)]
    # Embedded file name: main.py
    import random
    ens = '742641edefb6770733ab5932325106b3a5fa75222791d09e451161c46f15504402b32737362443d4df7d136145cd970b54116669c230'
    
    def encode(s, nuum):
        step = len(s) // nuum
        ens = ''
        for i in range(step):
            ens += s[i::step]
        else:
            return ens
    
    
    def main():
        random.seed(10085)
        u_input = input(': ')
        t = ''
        for i in u_input:
            t += '%02x' % (ord(i) ^ random.randint(0, 127))
        else:
            eni = encode(t, 6)
            if eni == ens:
                print('Success!')
            else:
                print('Failed!')
    
    
    if __name__ == '__main__':
        main()
    

    首先分析encode函数:

    ens = '742641edefb6770733ab5932325106b3a5fa75222791d09e451161c46f15504402b32737362443d4df7d136145cd970b54116669c230'
    def encode(s, nuum):
        step = len(s) // nuum #ens长度为108,返回值得到eni=ens,同时该函数并没有对字符串长度进行改变,推出len(s)=108,nuum=6,step=18
        ens = ''
        for i in range(step):
            ens += s[i::step] #每隔18位从s中选一个值(这里的ens和全局变量ens应该不是一个),那么也就相当于ens中的
                              #前0-5分别对应s中的0,0+18-1,0+2*18-1...
                              #前6-11分别对应s中的1,1+18-1,1+2*18-1...
        else:
            return ens
    

    由此可以有ens(全局)decode出eni:

    str = '742641edefb6770733ab5932325106b3a5fa75222791d09e451161c46f15504402b32737362443d4df7d136145cd970b54116669c230'
    eni= ''
    for i in range(0,6):
        eni+= str[i::6]
    print("eni="+eni)
    

    得到eni=7e7a3b794c5b3d1c564d7b23515403643d492e055a2d16422d691c6f7915201f474f17124b330f29610347406316326a7e15273d5b60
    注意到源代码中这一句:

    for i in u_input:
            t += '%02x' % (ord(i) ^ random.randint(0, 127))
    

    '%02x'是把t转成两位16进制之后进行异或运算,最后得到eni,再encode得到ens。
    此时我们已经得到了eni,应该是一个两位16进制数,手动转码之后异或写出exp:

    import random
    random.seed(10085)
    ens = [0x7e,0x7a,0x3b,0x79,0x4c,0x5b,0x3d,0x1c,0x56,0x4d,0x7b,0x23,0x51,0x54,0x03,0x64,0x3d,0x49,0x2e,0x05,0x5a,0x2d,0x16,0x42,0x2d,0x69,0x1c,0x6f,0x79,0x15,0x20,0x1f,0x47,0x4f,0x17,0x12,0x4b,0x33,0x0f,0x29,0x61,0x03,0x47,0x40,0x63,0x16,0x32,0x6a,0x7e,0x15,0x27,0x3d,0x5b,0x60]
    t = ''
    for i in range(len(ens)):
        t +=chr(ens[i] ^ random.randint(0, 127))
    else:
        print(t)
    

    得到虚假的flag:HECTF{decrypt(80410840840842108808881088408084210842)}
    最后是某crypto大佬一眼看出云影密码(01248密码),当场学习一波(白嫖一份解密脚本)

    a="80410840840842108808881088408084210842"
    a=a.split("0")
    flag=''
    for i in range(0,len(a)):
         str = a[i]
         list=[]
         sum=0
         for j in str:
            list.append(j)
            length = len(list)
         for k in range(0,length):
            sum+=int(list[k])
         flag+=chr(sum+64)
    print(flag)
    

    运行得到flag:HELLOPYTHON

  • 相关阅读:
    Daily Scrumming 2015.10.20(Day 1)
    Buaaclubs项目介绍
    [转载] Linux创建用户后,切换用户报This account is currently not available
    NetFPGA-1G-CML从零开始环境配置
    Digilent Xilinx USB Jtag cable
    OVS流表table之间的跳转
    Linux换源
    Scapy安装以及简单使用
    Do in SDN
    KMP算法
  • 原文地址:https://www.cnblogs.com/THRANDUil/p/15591486.html
Copyright © 2020-2023  润新知