buu题解

打开题目,下载附件,拖入pe中查看有无壳

 无壳

拖入ida中

 shift+f12找到可疑的字符串,跟进查看

 找到如下代码,分析可知,当dword_4099F0的值达到19999时,会输出BJD{%d%d2069a45792d233ac}对应的字符串,其中%d%d会被替换成199990

sprintf的具体用法参考如下https://www.baidu.com/baidu?tn=monline_4_dg&ie=utf-8&wd=sprintf%E5%87%BD%E6%95%B0%E7%9A%84%E7%94%A8%E6%B3%95

所以得到flag 为flag{1999902069a45792d233ac}

学到的知识点:sprintf函数的含义

buu题解——luck_guy

打开题目,下载附件,解压缩

拖入PE中,发现无壳

 拖入ida中

shift+F12查看字符串,找到可疑字符串

 分别跟进,找到如下代码

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v4; // [rsp+14h] [rbp-Ch] BYREF
  unsigned __int64 v5; // [rsp+18h] [rbp-8h]

  v5 = __readfsqword(0x28u);
  welcome(argc, argv, envp);
  puts("_________________");
  puts("try to patch me and find flag");
  v4 = 0;
  puts("please input a lucky number");
  __isoc99_scanf("%d", &v4);
  patch_me(v4);
  puts("OK,see you again");
  return 0;
}

 此为主函数,进入patch_me即为如下函数

unsigned __int64 get_flag()
{
  unsigned int v0; // eax
  int i; // [rsp+4h] [rbp-3Ch]
  int j; // [rsp+8h] [rbp-38h]
  __int64 s; // [rsp+10h] [rbp-30h] BYREF
  char v5; // [rsp+18h] [rbp-28h]
  unsigned __int64 v6; // [rsp+38h] [rbp-8h]

  v6 = __readfsqword(0x28u);
  v0 = time(0LL);
  srand(v0);
  for ( i = 0; i <= 4; ++i )
  {
    switch ( rand() % 200 )
    {
      case 1:
        puts("OK, it's flag:");
        memset(&s, 0, 0x28uLL);                 // 将s字符串数组全部初始化为0
        strcat(&s, f1);
        strcat(&s, &f2);
        printf("%s", &s);
        break;
      case 2:
        printf("Solar not like you");
        break;
      case 3:
        printf("Solar want a girlfriend");
        break;
      case 4:
        s = 0x7F666F6067756369LL;
        v5 = 0;
        strcat(&f2, &s);
        break;
      case 5:
        for ( j = 0; j <= 7; ++j )
        {
          if ( j % 2 == 1 )
            *(&f2 + j) -= 2;
          else
            --*(&f2 + j);
        }
        break;
      default:
        puts("emmm,you can't find flag 23333");
        break;
    }
  }
  return __readfsqword(0x28u) ^ v6;
}

 对如上函数分析,主函数输入的v4字符串经过patch_me处理后得到flag

对patch_me函数分析

       代码中meset函数含义参考:https://baike.baidu.com/item/memset/4747579

       随机获取一个数,然后经过switch语句,可以看出flag 是s字符数组,而s由f1,f2组成。

跟进f1得到

 由代码知得到f2的过程为case 4->5->1

写脚本得到flag

#include<stdio.h>
int main(){
	int j;
	char f1[]="GXY{do_not_";
	char f2[9]="icug`of";
	f2[7]=0x7F;
	 for ( j = 0; j <= 7; ++j )
        {
          if ( j % 2 == 1 )
            *(f2 + j) -= 2;
          else
            --*(f2 + j);
        }printf("%s",f1);
    for(j=0;j<=7;j++){
    	printf("%c",f2[j]);
	}
	return 0;
}

学到的知识点:1.s在内存中的存储为小端存储,即s的字符串顺序应反过来

                          2.对于s字符串中的\符号不能直接写在字符串数组内部(不然会报错哦)而应该单独拿出来处理

                          3.meset函数含义(作用是将某一块内存中的内容全部设置为指定的值,通常初始化使用)

buu题解——rome

打开题目,下载附件,解压拖入PE中查看有壳无壳

 无壳,且为32位,拖入ida中查看

 主函数没发现什么,shift+f12找可疑的字符串,猜测flag就在贯标所在的字符串内,跟进

int func()
{
  int result; // eax
  int v1[4]; // [esp+14h] [ebp-44h]
  unsigned __int8 v2; // [esp+24h] [ebp-34h] BYREF
  unsigned __int8 v3; // [esp+25h] [ebp-33h]
  unsigned __int8 v4; // [esp+26h] [ebp-32h]
  unsigned __int8 v5; // [esp+27h] [ebp-31h]
  unsigned __int8 v6; // [esp+28h] [ebp-30h]
  int v7; // [esp+29h] [ebp-2Fh]
  int v8; // [esp+2Dh] [ebp-2Bh]
  int v9; // [esp+31h] [ebp-27h]
  int v10; // [esp+35h] [ebp-23h]
  unsigned __int8 v11; // [esp+39h] [ebp-1Fh]
  char v12[29]; // [esp+3Bh] [ebp-1Dh] BYREF

  strcpy(v12, "Qsw3sj_lz4_Ujw@l");
  printf("Please input:");
  scanf("%s", &v2);
  result = v2;
  if ( v2 == 'A' )
  {
    result = v3;
    if ( v3 == 'C' )
    {
      result = v4;
      if ( v4 == 'T' )
      {
        result = v5;
        if ( v5 == 'F' )
        {
          result = v6;
          if ( v6 == '{' )
          {
            result = v11;
            if ( v11 == '}' )
            {
              v1[0] = v7;
              v1[1] = v8;
              v1[2] = v9;
              v1[3] = v10;
              *&v12[17] = 0;
              while ( *&v12[17] <= 15 )
              {
                if ( *(v1 + *&v12[17]) > 64 && *(v1 + *&v12[17]) <= 90 )
                  *(v1 + *&v12[17]) = (*(v1 + *&v12[17]) - 51) % 26 + 65;
                if ( *(v1 + *&v12[17]) > 96 && *(v1 + *&v12[17]) <= 122 )
                  *(v1 + *&v12[17]) = (*(v1 + *&v12[17]) - 79) % 26 + 97;
                ++*&v12[17];
              }
              *&v12[17] = 0;
              while ( *&v12[17] <= 15 )
              {
                result = v12[*&v12[17]];
                if ( *(v1 + *&v12[17]) != result )
                  return result;
                ++*&v12[17];
              }
              return printf("You are correct!");
            }
          }
        }
      }
    }
  }
  return result;
}

 找到如上代码,中间的两个while 循环是加密运算,

当加密后 的值与v12相等时得到flag(即什么ascll码值经过加密运算后与v12相等,我们要找到就是这个ascll码值)

写脚本代码

#include<stdio.h>
int main(){
	char v12[29]="Qsw3sj_lz4_Ujw@l";
	int k,i,z;
	char flag[]={0};
	printf("ACTF{");
for(k=0;k<16;k++){
	for(i=0;i<127;i++){
		z=i;
		if ( i> 64 &&i <= 90 )
                 i = (i- 51) % 26 + 65;
        if ( i> 96 && i <= 122 )
                  i= (i - 79) % 26 + 97;
        if(i==v12[k])
                flag[k]=z;
           
	}printf("%c",flag[k]);
}
	printf("}");
	return 0;
}

 得到flag

flag{Cae3ar_th4_Gre@t}

学到的知识点:通过遍历所有ascll码值,判断经过加密后的值是否与要比较的值相等来找flag

称为暴力破解(后来发现此加密过程时凯撒+大小写转换)

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值