攻防世界 REVERSE 新手区/getit

攻防世界 REVERSE 新手区/getit

在这里插入图片描述

下载得到附件,拖入Exeinfo PE中查一下壳

在这里插入图片描述

用IDA64bit打开,找到main函数按f5查看伪代码

在这里插入图片描述

下面开始分析代码

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v3; // al
  __int64 v5; // [rsp+0h] [rbp-40h]
  int i; // [rsp+4h] [rbp-3Ch]
  FILE *stream; // [rsp+8h] [rbp-38h]
  char filename[8]; // [rsp+10h] [rbp-30h]
  unsigned __int64 v9; // [rsp+28h] [rbp-18h]

  v9 = __readfsqword(0x28u);
  LODWORD(v5) = 0;
  while ( (signed int)v5 < strlen(s) )
  {
    if ( v5 & 1 )
      v3 = 1;
    else
      v3 = -1;
    *(&t + (signed int)v5 + 10) = s[(signed int)v5] + v3;
    LODWORD(v5) = v5 + 1;
  }
  strcpy(filename, "/tmp/flag.txt");
  stream = fopen(filename, "w");
  fprintf(stream, "%s\n", u, v5);
  for ( i = 0; i < strlen(&t); ++i )
  {
    fseek(stream, p[i], 0);
    fputc(*(&t + p[i]), stream);
    fseek(stream, 0LL, 0);
    fprintf(stream, "%s\n", u);
  }
  fclose(stream);
  remove(filename);
  return 0;
}

这一段是定义一个变量v5=0,然后while循环将s加到t偏移地址为10的后面,然后再加v3

  LODWORD(v5) = 0;
  while ( (signed int)v5 < strlen(s) )
  {
    if ( v5 & 1 )
      v3 = 1;
    else
      v3 = -1;
    *(&t + (signed int)v5 + 10) = s[(signed int)v5] + v3;
    LODWORD(v5) = v5 + 1;
  }

查看s和t的字符串,s=c61b68366edeb7bdce3c6820314b7498

在这里插入图片描述

t = harifCTF{???} 看来t就是输出的flag了

在这里插入图片描述

  strcpy(filename, "/tmp/flag.txt");
  stream = fopen(filename, "w");
  fprintf(stream, "%s\n", u, v5);

这里是进行文件操作,先将flag.txt复制给filename,然后以写方式打开filename, stream为fopen()函数的返回值,如果打开失败则返回NULL

fopen()的函数原型为:FILE *fopen(char *filename, *type);

type的形式参数类型:
“r” 打开文字文件只读
“w” 打开只写,如果不存在则新建,如果存在则清空
“a” 增补, 如果文件不存在则创建一个
“r+” 打开一个文字文件读/写
“w+” 创建一个文字文件读/写
“a+” 打开或创建一个文件增补
“b” 二进制文件(可以和上面每一项合用)
“t” 文这文件(默认项)

fprintf()为标准输出函数,用于按指定格式向文件写数据,
函数原型为: int fprintf(FILE *fp ,conse char *format,…),
这里是输出一排星号,可以不用管

在这里插入图片描述

  for ( i = 0; i < strlen(&t); ++i )
  {
    fseek(stream, p[i], 0);
    fputc(*(&t + p[i]), stream);
    fseek(stream, 0LL, 0);
    fprintf(stream, "%s\n", u);
  }

fseek()的函数原型int fseek(FILE *stream, long offset, int fromwhere);
函数设置文件指针stream的位置。如果执行成功,stream将指向以fromwhere(偏移起始位置:文件头0(SEEK_SET),当前位置1(SEEK_CUR),文件尾2(SEEK_END))为基准,偏移offset(指针偏移量)个字节的位置。如果执行失败(比如offset超过文件自身大小),则不改变stream指向的位置。

fput()的函数原型为:int fputs(const char *s,FILE *p),向文件指针p的位置写入一个字符

这里将文件指针指向离文件头偏移p[i]的位置,然后将t偏移p[i]的字符输入。其实就是输出的顺序不一样而已,比如我要输出123,我可以先输出2,然后在2的左边输出1,在2的右边输出3,和我直接输出123的结果是一样的。

这里是p[]的值,为16进制的数组,每隔3个0是一个16进制

在这里插入图片描述

知道了算法就可以编写脚本来解码了

#include<stdio.h>
#include<stdlib.h>
#include <string.h>
int main()
{
   char s[] = "c61b68366edeb7bdce3c6820314b7498";
   int p[] = {0x18,0x19,0x20,0x28,0x24,0x1C,0x11,0x22,0x27,0x10,0x21,0x13,0x1A,5,3,0x1D,0x1B,0x1F,4,8,0x0F,0x25,0x2A,0x0E,0x29,2,0x17,0x15,0,0x0A,0x14,7,0x0B,1,0x0D,6,0x26,0x12,0x23,0x0C,0x16,9};
   char t[] = "harifCTF{????????????????????????????????}";
   int v5 = 0;
   int v3;
   while(v5 < strlen(s))
   {
       if(v5 & 1)
          v3 = 1;
       else
          v3 = -1;
       t[v5 + 10] = s[v5] + v3;
       v5 ++;
   }
   for ( int i = 0; i < strlen(t) ; i++)
   {
       printf("%c",t[i]);
   }
   return 0;

}

然后输出结果为在这里插入图片描述

这不对呀,倒回去看下,这里确实是t之后偏移10啊

  *(&t + (signed int)v5 + 10) = s[(signed int)v5] + v3;

然后我看了下t的值

在这里插入图片描述

然后发现在t后面还有一个 db 53h 转字符后刚好是字符S

在这里插入图片描述

将S加到t前面,输出结果,得到flag:SharifCTF{b70c59275fcfa8aebf2d5911223c6589}

#include<stdio.h>
#include<stdlib.h>
#include <string.h>
int main()
{
   char s[] = "c61b68366edeb7bdce3c6820314b7498";
   int p[] = {0x18,0x19,0x20,0x28,0x24,0x1C,0x11,0x22,0x27,0x10,0x21,0x13,0x1A,5,3,0x1D,0x1B,0x1F,4,8,0x0F,0x25,0x2A,0x0E,0x29,2,0x17,0x15,0,0x0A,0x14,7,0x0B,1,0x0D,6,0x26,0x12,0x23,0x0C,0x16,9};
   char t[] = "SharifCTF{????????????????????????????????}";
   int v5 = 0;
   int v3;
   while(v5 < strlen(s))
   {
       if(v5 & 1)
          v3 = 1;
       else
          v3 = -1;
       t[v5 + 10] = s[v5] + v3;
       v5 ++;
   }
   for ( int i = 0; i < strlen(t) ; i++)
   {
       printf("%c",t[i]);
   }
   return 0;

}

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ofo300

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

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

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

打赏作者

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

抵扣说明:

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

余额充值