BUUCTF_[V&N2020 公开赛]strangeCpp

本文分析了一个名为strangeCpp的比赛题目,通过逆向工程揭示了其内部逻辑并使用Python脚本破解了关键数值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


BUUCTF_[V&N2020 公开赛]strangeCpp


照例打开IDA,翻了翻函数没有找到main函数,那就shift + F12 查找字符串,看看有没什么敏感字符,如图:

在这里插入图片描述
点进去查看字符串的交叉引用(按 x ),如图:

在这里插入图片描述
找到sub_140013AA0用F5,如图:

__int64 __fastcall sub_140013AA0(__int64 a1, __int64 a2, __int64 *a3)
{
  char *v3; // rdi
  signed __int64 i; // rcx
  __int64 v5; // rax
  __int64 v6; // rax
  __int64 v7; // rax
  __int64 v8; // rax
  char v10; // [rsp+0h] [rbp-20h]
  struct _SYSTEM_INFO SystemInfo; // [rsp+28h] [rbp+8h]
  __int64 *j; // [rsp+78h] [rbp+58h]
  __int64 v13; // [rsp+98h] [rbp+78h]
  __int64 *v14; // [rsp+1A0h] [rbp+180h]

  v14 = a3;
  v3 = &v10;
  for ( i = 94i64; i; --i )
  {
    *(_DWORD *)v3 = -858993460;
    v3 += 4;
  }
  sub_1400110AA((__int64)&unk_140027033);
  GetSystemInfo(&SystemInfo);
  putchar(byte_140021004);
  putchar(byte_140021005);
  putchar(byte_140021006);
  putchar(byte_140021007);
  putchar(byte_140021019);
  putchar(byte_14002101A);
  putchar(byte_140021005);
  putchar(10);
  puts("Let me have a look at your computer...");
  for ( j = v14; *j; ++j )
  {
    v13 = *j;
    sub_140011226((__int64)"%s\n", v13);
  }
  std::basic_ostream<char,std::char_traits<char>>::operator<<(std::cout, sub_140011127);
  dword_140021190 = SystemInfo.dwNumberOfProcessors;
  sub_140011226((__int64)"now system cpu num is %d\n", SystemInfo.dwNumberOfProcessors);
  if ( dword_140021190 < 8 )
  {
    puts("Are you in VM?");
    _exit(0);
  }
  if ( GetUserNameA(Str1, &pcbBuffer) )
  {
    v5 = sub_140011172(std::cout, "this is useful");
    std::basic_ostream<char,std::char_traits<char>>::operator<<(v5, sub_140011127);
  }
  v6 = std::basic_ostream<char,std::char_traits<char>>::operator<<(std::cout, sub_140011127);
  v7 = sub_140011172(v6, "ok,I am checking...");
  std::basic_ostream<char,std::char_traits<char>>::operator<<(v7, sub_140011127);
  if ( !j_strcmp(Str1, "cxx") )
  {
    v8 = sub_140011172(std::cout, "flag{where_is_my_true_flag?}");
    std::basic_ostream<char,std::char_traits<char>>::operator<<(v8, sub_140011127);
    _exit(0);
  }
  system("pause");
  sub_1400113E3((__int64)&v10, (__int64)&unk_14001DE50);
  return 0i64;
}

好复杂,不过点进各种字符串查看交叉引用都没有其他的交叉引用,唯有下图有点东西:

在这里插入图片描述
点进去看,很奇怪的发现中间那段有点不太一样.

在这里插入图片描述
按x查看一下交叉引用.

在这里插入图片描述
来到sub_140013580用F5大法,发现关键函数!!!

在这里插入图片描述
红框的语句为关键函数,进入sub_140011384看看.

在这里插入图片描述
到现在为止已经将整个程序的逻辑看完了,现在来理一下逻辑sub_140011384 把 dword_140021190 当成实参传进去,也就是说a1就是dword_140021190,接着 a1 又给了 v8 ,接下来v8进行移位操作等于 v7 , v7 又乘与 291,接下来就返回 result ,也就是说 dword_140021190 -> a1 ->v8 -> v7 ->result,接下来要求result = 607052314 ,dword_140021190 <= 14549743,进入 if 后将 dword_140021190 与 byte_140021008 异或,那么现在只要爆破出 dword_140021190 的值,再进行异或就结束了.

分析完了,开始写python脚本

str = [0x26,0x2C,0x21,0x27,0x3B,0x0D,0x04,0x75,0x68,0x34,0x28,0x25,0x0E,0x35,0x2D,0x69,0x3D]
result = 607052314
flag = ''
num = 0

for i in range(14549743):
    v7 = (i << 8) ^ (i >> 12)
    v7 *= 291
    v7 = v7 & 0xFFFFFFFF
    if v7 ==  result:
        num = i
        print(i)
        break

for i in str:
    flag += chr((num ^ i) &0xFF)

print(flag)

在这里插入图片描述答案还要对爆破的值进行MD5加密,那直接上脚本:

import hashlib
def getMd5(str):
    #获取一个MD5的加密算法对象
    md5_value = hashlib.md5()
    #得到MD5消息摘要
    md5_value.update(str.encode('utf-8'))
    #以16进制返回消息
    print(md5_value.hexdigest())
if __name__=="__main__":
    getMd5('123456')

在这里插入图片描述至此,程序分析结束!!!

小结:

①再亿次提醒自己看字符串要再Hew View里面看,在 IDA View真的很容易漏!!!
②python需要对字符串进行截断 unsigned int 就是4个字节,不截断就如下图一样,没有爆破出来.

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值