BUUCTF 逆向工程(reverse)之[GXYCTF2019]luck_guy

用IDA64打开,进入到get_flag函数

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

  v7 = __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);
        strcat((char *)&s, f1);
        strcat((char *)&s, &f2);
        printf("%s", &s);
        break;
      case 2:
        printf("Solar not like you");
        break;
      case 3:
        printf("Solar want a girlfriend");
        break;
      case 4:
        v6 = 0;
        s = 0x7F666F6067756369LL;
        strcat(&f2, (const char *)&s);
        break;
      case 5:
        for ( j = 0; j <= 7; ++j )
        {
          if ( j % 2 == 1 )
            v1 = *(&f2 + j) - 2;
          else
            v1 = *(&f2 + j) - 1;
          *(&f2 + j) = v1;
        }
        break;
      default:
        puts("emmm,you can't find flag 23333");
        break;
    }
  }
  return __readfsqword(0x28u) ^ v7;
}

首先这里用到了随机数,但是想通过随机数来获取flag有点不现实,或者说是太难了。。。。

v0 = time(0LL);
srand(v0);
for ( i = 0; i <= 4; ++i )
	switch ( rand() % 200 )

所以主要的点在case 1 ~ case 5,但是case 2和case 3这两个是printf的输出语句,并没有什么用。所以可以不考虑。然后再进一步分析可以看出来具体步骤是case 4 —》 case 5 —》 case 1

case 4:

case 4:
v6 = 0;		// 这里的v6可以不考虑
s = 0x7F666F6067756369LL;	// 这里要把16进制转为字符串,并且是逆序的(之所以是逆序的应该是和stack的存储结构有关)
strcat(&f2, (const char *)&s);	// 把s的值赋值给f2(赋值前的f2是空字符)
break;

case 5

for ( j = 0; j <= 7; ++j )
{
	if ( j % 2 == 1 ) 	v1 = *(&f2 + j) - 2;
	else 				v1 = *(&f2 + j) - 1;	
	*(&f2 + j) = v1;
}
break;

如果看不懂上面的代码,可以把它改成这样下面的代码。它们是等价的:

for ( j = 0; j <= 7; ++j )
{
	if ( j % 2 == 1 ) 	v1 = f2[j] - 2;
	else 				v1 = f2[j] - 1;	
	f2[j] = v1;
}
break;

case 1

puts("OK, it's flag:");
memset(&s, 0, 0x28uLL);
strcat((char *)&s, f1);		// 这里的f1的值为:GXY{do_not_
strcat((char *)&s, &f2);	// 链接f1和f2的字符串就是flag(这个f2是我们逆向出来的)
printf("%s", &s);
break;

在这里插入图片描述

Python3代码

key1 = "GXY{do_not_"
# 这里的key2的值为:0x7F666F6067756369,以两个一组来分割。这是为将16进制转成对应的字符
key2 = [ 0x7F, 0x66, 0x6F, 0x60, 0x67, 0x75, 0x63, 0x69 ][::-1] # 注意要把这里的数组反过来
flag = key1

for i in range(0,len(key2)):
    x = key2[i]
    if i % 2 == 1: x = x - 2
    else:          x = x - 1
    flag = flag + chr(x)
print(flag)     # 输出的值为:GXY{do_not_hate_me},再把前面的GXY改成flag就是我们要的flag了

在这里插入图片描述
所以最终的flag为:flag{do_not_hate_me}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值