ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

强网拟态 2021 showyourflag Writeup

2021-10-26 06:00:07  阅读:221  来源: 互联网

标签:Writeup showyourflag len ptr output d1 d2 强网 dis


题目简介

题目给出程序 showyourflag 以及用该程序加密后的文件 yourflag

可以通过命令行执行:

showyourflag [infile] [outfile]

加密分析

字节变换

程序首先对输入文件的内容进行逐字节变换,位于函数 sub_401FC0

v8 = ~__ROL1__(v8, 1);

子串压缩

随后实现了一个类似于压缩的算法,位于函数 sub_4023D0

函数先对子串开头的三个字节进行哈希,随后在字典中查找之前是否出现过相同的哈希值。

若存在则求出两个子串相同部分长度的最大值,随后将两个子串相差的距离 dis 以及匹配的长度 len 进行编码,并将编码结果存储到输出文件中。

若不存在则直接将子串内容存储到输出文件中。

while ( 1 )
{
  tri_bytes = *now_ptr & 0xFFFFFF;
  hash = (0x9E3779B9 * tri_bytes) >> 18;
  last_pos = dict[hash];
  dict[hash] = now_ptr - a1;
  last_ptr = &a1[last_pos];
  dis = now_ptr - last_ptr;
  if ( (now_ptr - last_ptr) <= 0x1FFF )
  {
    if ( now_ptr >= tail_13 )
      goto LABEL_21;
    v10 = (now_ptr + 1);
    if ( tri_bytes != (*last_ptr & 0xFFFFFF) )
      goto LABEL_10;
    if ( tail_13 <= v10 )
      goto LABEL_21;
    if ( v9 < now_ptr )
      copy_raw(now_ptr - v9, v9, output_);
    len_d2 = len_prefix(last_ptr + 3, (now_ptr + 3), tail_4);
    dis_d1 = dis - 1;
    len_d2_remain = len_d2;                 // dis <= 0x1FFF
    for ( hi_dis_d1 = (dis - 1) >> 8; len_d2_remain > 0x106; *(output - 1) = dis - 1 )
    {                                       // loop n times
      *output = hi_dis_d1 - 0x20;           // high_byte(dis_d1) - 0x20
                                            //   0xE0 ~ 0xFF
      len_d2_remain -= 0x106;
      output += 3;
      *(output - 2) = 0xFD;                 // 0xFD
    }                                       // low_byte(dis_d1)
    if ( len_d2_remain > 6 )
    {                                       // case len_d2 : 7 ~ 0x106
      output[2] = dis_d1;
      output_ = output + 3;
      *output = hi_dis_d1 - 0x20;           // high_byte(dis_d1) - 0x20
                                            //   0xE0 ~ 0xFF
      output[1] = len_d2_remain - 7;        // len_d2 - n * 0x106 - 7
                                            //   0x0 ~ 0xFF
    }                                       // low_byte(dis_d1)
    else
    {
      output[1] = dis_d1;                   // case len_d2 : 1 ~ 6
      output_ = output + 2;
      *output = hi_dis_d1 + 0x20 * len_d2_remain;// 
                                            // high_byte(dis_d1) + 0x20 * len_d2
                                            //   0x20 ~ 0xDF
    }                                       // low_byte(dis_d1)
    v22 = (v18 + len_d2);
    v23 = *v22;
    now_ptr = (v22 + 2);
    dict[(0x9E3779B9 * (v23 & 0xFFFFFF)) >> 18] = v22 - a1;
    v9 = v22 + 2;
    dict[(0x9E3779B9 * (v23 >> 8)) >> 18] = v22 + 1 - a1;
    if ( tail_13 <= v22 + 2 )
      goto LABEL_21;
  }
  else
  {
    if ( now_ptr >= tail_13 )
      goto LABEL_21;
    v10 = (now_ptr + 1);
LABEL_10:
    now_ptr = v10;
  }
}
LABEL_21:
return result;

解密分析

提取子串相差的距离 dis 以及匹配的长度 len 后还原原串内容即可。

#include <cstdio>
#include <cstdlib>

int main(){
  FILE *pFile, *pFile2;
  long lSize;
  unsigned char *buffer,*buffer2;
  size_t result;

  pFile = fopen ( "yourflag" , "rb" );
  pFile2 = fopen ( "flag.png" , "wb+" );

  fseek (pFile , 0 , SEEK_END);
  lSize = ftell (pFile);
  rewind (pFile);

  buffer = (unsigned char*) malloc (sizeof(char)*lSize);
  buffer2 = (unsigned char*) malloc (sizeof(char)*lSize);
  result = fread (buffer,1,lSize,pFile);

  int i=0,dis=0,len,cnt=0;
  while(i<lSize-2){
    printf("%02X ",buffer[i]);
    if (0<=buffer[i]&&buffer[i]<0x20){
      for (int j=1;j<=buffer[i]+1;j++){
        buffer2[cnt++]=buffer[i+j];
      }
      i+=buffer[i]+2;
      dis=0;
      len=0;
    }
    else if (0x20<=buffer[i]&&buffer[i]<0xE0){
      len=(buffer[i]&0xE0)/0x20+2;
      dis=buffer[i+1]+((buffer[i]&0x1F)<<8)+1;
      i+=2;
    }
    else if (0xE0<=buffer[i]&&buffer[i]<0x100){
      len=buffer[i+1]+9;
      dis=((buffer[i]-0xE0)<<8)+buffer[i+2]+1;
      i+=3;
    }
    for (int j=0;j<len;j++){
      buffer2[cnt]=buffer2[cnt-dis];
      cnt++;
    }
  }

  for (int i=0;i<lSize;i++){
    int t=~buffer2[i];
    buffer2[i]=((t&0xFE)>>1)+((t&0x01)<<7);
  }
  fwrite(buffer2,1,lSize,pFile2);

  fclose (pFile);
  fclose (pFile2);
  free (buffer);
  return 0;
}

运行后得到解密的 flag.png,内容如下:

标签:Writeup,showyourflag,len,ptr,output,d1,d2,强网,dis
来源: https://www.cnblogs.com/algonote/p/15464076.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有