飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 3337|回复: 5

[求助] dota2 局域网联机软件开发过程中遇到了 一个逆向难题 请求帮助

[复制链接]
  • TA的每日心情
    开心
    2021-3-3 22:30
  • 签到天数: 5 天

    [LV.2]偶尔看看I

    发表于 2021-1-5 11:23:17 | 显示全部楼层 |阅读模式
    本帖最后由 maxism 于 2021-2-16 20:39 编辑

    大家好,最近几个朋友在开发dota2局域网联机的软件,但是遇到了一个难题,特向大佬们请教。
    dota2中,当一个用户建立房间,另一个用户进行连接的时候,dota会请求一个“证书”,验证通过后,两台电脑才能开始联机,使用软件进行转储后得到的信息如下:

    [C] 纯文本查看 复制代码
    cert = 080112202B39DF35AAB3E009269D5FBF57A0AC8D8059BAFA7C4E1001EE8D54062DAAEAEF2108E41494763F4001453518F75F4D35BBF95F50BA045A0A810108E41494763F40016219737465616D69643A3930313431373731303730343937383030
    ca_key_id = 18220590129359924542
    ca_signature = E1FA9B6E43521BDA3DA6F5C579AB10A31913AA538D6FAFE4C813CF6321E43F66D2C3D913C96A86423DC8A2A24B73F237D4E30A5BE6A85536B1E042938B1A450B



    目前想到的办法是对steamnetworkingsockets.dll进行逆向,动态调试,将证书验证的函数修改了,或者是发送一个自签名的证书,但是这些我们都不会,希望各位大佬不吝指教,万分感谢。下面是搜到的一个相关的帖子,希望有用。

    dll文件地址

    https://wwa.lanzous.com/i7Z7Tlq6zdg




    V社source游戏现在似乎使用steamnetworkingsockets.dll进行客户端/服务器通信。它需要一个“证书”,该“证书”实际上是一个已签名的协议,
    由应用程序通过使用EMsgClientNetworkingCertRequest通过蒸汽向cmserver请求,并响应EMsgClientNetworkingCertRequestResponse
    ,游戏会发送一个appid和一个“密钥”,服务器返回一个“证书” “,由CA签名(由ID标识)



    [C++] 纯文本查看 复制代码
            response->body_cert.set_key_type(CMsgSteamDatagramCertificate_EKeyType_ED25519);
            response->body_cert.set_key_data(msg->body.key_data());
            response->body_cert.set_steam_id(connection->getSteamGlobalId());
            response->body_cert.set_time_created(now);
            response->body_cert.set_time_expiry(now+2*24*60*60); // 2 days
            response->body_cert.set_app_id(msg->body.app_id());
    
            response->body.set_ca_key_id(1234);
            response->body.set_ca_signature(64 bytes signature);





    证书似乎存储在userdata / steamid / config / localconfig.vdf中,在“ nettickets”部分中  ,服务器似乎可以发送任何东西,它将被缓存,无论如何,当证书/ ca /​​签名被验证时,游戏服务器/客户端在steamnetworkingsockets.dll中进行连接:


    [C++] 纯文本查看 复制代码
    char __thiscall sub_10088EF0(int this, struct_a2 *a2, struct_a3 *a3, void *a4)
    {
      struct_v4 *v4; // edi@1
      bool v6; // zf@7
      int v7; // eax@9
      size_t v8; // ecx@9
      int v9; // ecx@25
      int v10; // eax@31
      int v11; // eax@38
      int v12; // ST28_4@39
      int v13; // eax@39
      HANDLE *v14; // esi@43
      int v15; // eax@46
      int v16; // ecx@49
      int v17; // edx@49
      int v18; // ecx@57
      int v19; // eax@58
      int v20; // esi@59
      int v21; // eax@59
      int v22; // eax@71
      size_t v23; // ecx@71
      char v24; // cl@75
      int v25; // edx@80
      int v26; // esi@80
      int v27; // eax@80
      int v28; // ecx@80
      char *v29; // eax@82
      signed int v30; // ecx@82
      int v31; // edx@84
      int v32; // esi@84
      int v33; // ebx@84
      int v34; // ecx@84
      int v35; // eax@85
      int v36; // eax@85
      int v37; // eax@85
      int *v38; // esi@89
      signed int v39; // ebx@89
      void *v40; // eax@90
      char *v41; // edi@93
      void *v42; // esi@93
      int v43; // eax@95
      _BYTE *v44; // ecx@95
      int i; // edi@95
      signed int v46; // ecx@97
      char *v47; // eax@97
      signed int v48; // ecx@99
      char *v49; // eax@99
      signed int v50; // ecx@101
      char *v51; // eax@101
      char v52; // [sp+4h] [bp-290h]@58
      char v53; // [sp+104h] [bp-190h]@26
      char v54; // [sp+184h] [bp-110h]@82
      char v55; // [sp+1A4h] [bp-F0h]@80
      char v56; // [sp+1C4h] [bp-D0h]@94
      char v57; // [sp+1E4h] [bp-B0h]@95
      void *v58; // [sp+1E8h] [bp-ACh]@86
      int v59; // [sp+1F8h] [bp-9Ch]@86
      int v60; // [sp+20Ch] [bp-88h]@39
      int v61; // [sp+210h] [bp-84h]@39
      int v62; // [sp+214h] [bp-80h]@38
      int v63; // [sp+218h] [bp-7Ch]@38
      int v64; // [sp+21Ch] [bp-78h]@7
      int v65; // [sp+220h] [bp-74h]@7
      int v66; // [sp+224h] [bp-70h]@7
      char v67; // [sp+228h] [bp-6Ch]@7
      int v68; // [sp+22Ch] [bp-68h]@1
      int v69; // [sp+230h] [bp-64h]@69
      int v70; // [sp+234h] [bp-60h]@69
      int v71; // [sp+238h] [bp-5Ch]@69
      char v72; // [sp+23Ch] [bp-58h]@69
      int v73; // [sp+240h] [bp-54h]@84
      int v74; // [sp+244h] [bp-50h]@84
      int v75; // [sp+248h] [bp-4Ch]@84
      int v76; // [sp+24Ch] [bp-48h]@84
      size_t v77; // [sp+250h] [bp-44h]@84
      int v78; // [sp+254h] [bp-40h]@84
      int v79; // [sp+258h] [bp-3Ch]@84
      int v80; // [sp+25Ch] [bp-38h]@84
      int v81; // [sp+260h] [bp-34h]@80
      int v82; // [sp+264h] [bp-30h]@80
      int v83; // [sp+268h] [bp-2Ch]@80
      int v84; // [sp+26Ch] [bp-28h]@80
      void *v85; // [sp+270h] [bp-24h]@84
      char *v86; // [sp+274h] [bp-20h]@84
      _BYTE *v87; // [sp+278h] [bp-1Ch]@84
      _BYTE *v88; // [sp+27Ch] [bp-18h]@84
      int v89; // [sp+280h] [bp-14h]@84
      int v90; // [sp+284h] [bp-10h]@84
      int v91; // [sp+290h] [bp-4h]@7
      char *v92; // [sp+2A4h] [bp+10h]@86
    
      v4 = (struct_v4 *)this;
      v68 = this;
      if ( *(_BYTE *)(this + 13032) )
        return 1;
      if ( !(a2->byte8 & 1) || !(a3->byte8 & 1) )
      {
        sub_1008A650(4002, "Crypto handshake missing cert or session data");
        return 0;
      }
      if ( !(unsigned __int8)sub_100C3130(a2->dword10) )
      {
        sub_1008A650(4002, "Cert failed protobuf decode");
        return 0;
      }
      v64 = 3;
      v66 = 0;
      v65 = 0;
      v67 = 0;
      v6 = v4->key_type == 1;
      v91 = 0;
      if ( !v6 )
      {
        sub_1008A650(4002, "Unsupported identity key type");
    LABEL_107:
        sub_10022270(&v64);
        return 0;
      }
      v7 = v4->dword3218;
      v8 = *(_DWORD *)(v7 + 16);
      if ( *(_DWORD *)(v7 + 20) >= 0x10u )
        v7 = *(_DWORD *)v7;
      if ( !(unsigned __int8)sub_10021860((void *)v7, v8) || !(unsigned __int8)sub_10021170(&v64) )
      {
        sub_1008A650(4002, "Cert has invalid identity key");
        goto LABEL_107;
      }
      if ( v4->byte32C8 & 1 )
      {
        if ( !((v4->fields_maps >> 2) & 1) )
          sub_1001CDE0(
            (int)"Assertion Failed: m_msgCryptLocal.has_nonce()",
            0,
            "steamnetworkingsockets_connections.cpp",
            802);
        if ( !((v4->fields_maps >> 1) & 1) )
          sub_1001CDE0(
            (int)"Assertion Failed: m_msgCryptLocal.has_key_data()",
            0,
            "steamnetworkingsockets_connections.cpp",
            803);
        if ( !(v4->fields_maps & 1) )
          sub_1001CDE0(
            (int)"Assertion Failed: m_msgCryptLocal.has_key_type()",
            0,
            "steamnetworkingsockets_connections.cpp",
            804);
      }
      else
      {
        if ( !(unsigned __int8)(*(int (__thiscall **)(struct_v4 *))(v4->dword0 + 56))(v4) && dword_10271D84 >= 4 )
          sprintf(
            (char *)4,
            "We don't have cert, and unsigned certs are not supposed to be allowed here.  Continuing anyway temporarily.");
        sub_1008B330(v4);
      }
      if ( (v4->dword3210 >> 6) & 1 )
      {
        v9 = v4->app_id;
        if ( v9 != v4->dword28->dword78 )
        {
          sub_10077AE0((int)&v53, "Cert is for AppID %u instead of %u", v9, v4->dword28->dword78);
          if ( dword_10271D84 >= 4 )
            sprintf((char *)4, "Cert failure: %s\n", &v53);
        }
      }
      if ( v4->steam_id <= 0 || !((*(_DWORD *)&a2->byte8 >> 2) & 1) )
      {
        if ( !((v4->dword3210 >> 2) & 1) && dword_10271D84 >= 4 )
          sprintf((char *)4, "Cert failure: %s\n", "Cert must be bound to a SteamID.");
        if ( !((v4->dword3210 >> 6) & 1) && dword_10271D84 >= 4 )
          sprintf((char *)4, "Cert failure: %s\n", "Cert must be bound to an AppID.");
        v11 = v4->dword3220;
        v63 = v4->dword3224;
        v62 = v11;
        if ( !(unsigned __int8)sub_10087AA0(&v4->gap2C[4]) )
          goto LABEL_42;
        v60 = v4->dword3220;
        v61 = v4->dword3224;
        v12 = sub_10086E60(&v4->gap2C[4]);
        v13 = sub_10086E60(&v60);
        sub_10077AE0((int)&v53, "Cert was issued to %s, not %s", v13, v12);
        goto LABEL_40;
      }
      if ( (v4->dword34 & 0xF00000) != 0x400000 )
      {
        v10 = sub_10086E60(&v4->gap2C[4]);
        sub_10077AE0((int)&v53, "Certs restricted data center are for anon GS only.  Not %s", v10);
    LABEL_40:
        if ( dword_10271D84 >= 4 )
          sprintf((char *)4, "Cert failure: %s\n", &v53);
      }
    LABEL_42:
      if ( (*(_DWORD *)&a2->byte8 >> 2) & 1 )
      {
        v14 = (HANDLE *)&unk_102562E0;
        do
        {
          if ( a2->ca_key_1 == *v14 && a2->ca_key_2 == v14[1] )
          {
            v15 = a2->dword20;
            if ( *(_DWORD *)(v15 + 16) == 64 )
            {
              if ( *(_DWORD *)(v15 + 20) >= 0x10u )
                v15 = *(_DWORD *)v15;
              v16 = a2->dword10;
              v17 = *(_DWORD *)(v16 + 16);
              if ( *(_DWORD *)(v16 + 20) >= 0x10u )
                v16 = *(_DWORD *)v16;
              if ( sub_100221F0(v16, v17, (int)(v14 + 2), v15) )
                goto LABEL_57;
            }
            if ( dword_10271D84 >= 4 )
              sprintf((char *)4, "Cert failure: %s\n", "Invalid cert signature");
          }
          v14 += 6;
        }
        while ( v14 != &hEvent );
        sub_10077AE0((int)&v53, "Cert signed with key %llu; not in trusted list", a2->ca_key_1, a2->ca_key_2);
        if ( dword_10271D84 >= 4 )
          sprintf((char *)4, "Cert failure: %s\n", &v53);
    LABEL_57:
        v18 = v4->dword28->dword6C;
        if ( v18 )
        {
          v20 = v4->dword323C;
          v21 = (*(int (**)(void))(*(_DWORD *)v18 + 12))();
          if ( v21 > v20 )
          {
            sub_10077AE0((int)&v53, "Cert expired %ld secs ago at %ld", v21 - v20, v20);
            if ( dword_10271D84 >= 4 )
              sprintf((char *)4, "Cert failure: %s\n", &v53);
          }
        }
        else
        {
          v19 = sub_1001D440(&v52, "Assertion Failed: %s", "No ISteamUtils?  Cannot check if cert expired!");
          sub_1001CDE0(v19, 0, "steamnetworkingsockets_connections.cpp", 899);
        }
        if ( !(unsigned __int8)(*(int (__thiscall **)(struct_v4 *))(v4->dword0 + 60))(v4) )
        {
          if ( v4->dword334C != 5 )
          {
            sub_1001CDE0(
              (int)"Assertion Failed: GetState() == k_ESteamNetworkingConnectionState_ProblemDetectedLocally",
              0,
              "steamnetworkingsockets_connections.cpp",
              920);
            sub_10022270(&v64);
            return 0;
          }
          goto LABEL_107;
        }
      }
      else if ( dword_10271D84 >= 5 )
      {
        sprintf((char *)5, "Remote host is using an unsigned cert.  Allowing connection, but it's not secure!\n");
      }
      if ( !(unsigned __int8)sub_100C3130(a3->dword10) )
      {
        sub_1008A650(4002, "Crypt info failed protobuf decode");
        goto LABEL_107;
      }
      v69 = 5;
      v71 = 0;
      v70 = 0;
      v72 = 0;
      v6 = v4->dword325C == 1;
      LOBYTE(v91) = 1;
      if ( !v6 )
      {
        sub_1008A650(4002, "Unsupported DH key type");
    LABEL_105:
        sub_10022270(&v69);
        sub_10022270(&v64);
        return 0;
      }
      v22 = v4->dword3258;
      v23 = *(_DWORD *)(v22 + 16);
      if ( *(_DWORD *)(v22 + 20) >= 0x10u )
        v22 = *(_DWORD *)v22;
      if ( !(unsigned __int8)sub_10021860((void *)v22, v23) || !(unsigned __int8)sub_10021130(&v69) )
      {
        sub_1008A650(4002, "Invalid DH key");
        goto LABEL_105;
      }
      v24 = v4->byte3260;
      if ( !v24 )
        goto LABEL_112;
      if ( !dword_10264930 )
      {
    LABEL_79:
        sub_1008A650(4002, "Incompatible protocol format (SNP)");
        goto LABEL_105;
      }
      if ( !v24 )
      {
    LABEL_112:
        if ( dword_10264930 )
          goto LABEL_79;
      }
      LOBYTE(v91) = 2;
      sub_10021640(v4->gap3270, &v69, &v55);
      sub_10022270(v4->gap3270);
      v25 = v4->dword3268;
      v26 = v4->dword326C;
      v27 = v4->dword32A0;
      v28 = v4->dword32A4;
      v81 = v4->dword3268;
      v82 = v26;
      v83 = v27;
      v84 = v28;
      if ( (_BYTE)a4 )
      {
        v81 = v27;
        v82 = v28;
        v83 = v25;
        v84 = v26;
      }
      LOBYTE(v91) = 3;
      sub_10020940(&v81, 0x10u, &v55, 0x20u, &v54);
      v29 = &v55;
      v30 = 32;
      do
      {
        *v29++ = 0;
        --v30;
      }
      while ( v30 );
      v31 = a2->dword10;
      v32 = v4->dword32D0;
      v33 = v4->dword32B8;
      v85 = &v4->char32E9;
      v86 = &v4->char3309;
      v87 = &v4->gap330A[31];
      v88 = &v4->gap330A[47];
      v77 = 32;
      v78 = 32;
      v34 = a3->dword10;
      v89 = v4->dword50;
      v90 = v4->dword54;
      v79 = 16;
      v80 = 16;
      v73 = v31;
      v74 = v32;
      v75 = v34;
      v76 = v33;
      if ( (_BYTE)a4 )
      {
        v85 = &v4->char3309;
        v86 = &v4->char32E9;
        v87 = &v4->gap330A[47];
        v88 = &v4->gap330A[31];
        v35 = v31;
        v31 = v32;
        v77 = 32;
        v32 = v35;
        v78 = 32;
        v36 = v34;
        v79 = 16;
        v34 = v33;
        v80 = 16;
        v33 = v36;
        v73 = v31;
        v89 = v4->dword54;
        v37 = v4->dword50;
        v74 = v32;
        v75 = v34;
        v76 = v33;
        v90 = v37;
      }
      sub_1001E020(
        0,
        *(_DWORD *)(v31 + 16) + *(_DWORD *)(v32 + 16) + *(_DWORD *)(v34 + 16) + 104 + *(_DWORD *)(v33 + 16),
        0);
      LOBYTE(v91) = 4;
      sub_1001EFD0(0, 32);
      v92 = (char *)v58 + v59;
      if ( v4->dword60 < 3u )
        sub_1001EAE0(&v89, 4u);
      else
        sub_1001EAE0(&v89, 8u);
      sub_1001EAE0("Steam datagram", 0xEu);
      v38 = &v73;
      v39 = 4;
      do
      {
        v40 = (void *)*v38;
        if ( *(_DWORD *)(*v38 + 20) >= 0x10u )
          v40 = *(void **)v40;
        sub_1001EAE0(v40, *(_DWORD *)(*v38 + 16));
        ++v38;
        --v39;
      }
      while ( v39 );
      v41 = (char *)v58 + v59;
      v42 = v92;
      do
      {
        *v41 = v39 + 1;
        sub_10020940(v42, v41 - (_BYTE *)v42 + 1, &v54, 0x20u, &v56);
        memmove_0(*(&v85 + v39), &v56, *(&v77 + v39));
        v42 = v58;
        memmove_0(v58, &v56, 0x20u);
        ++v39;
      }
      while ( v39 < 4 );
      v43 = sub_100B09D0(&v57);
      v44 = v58;
      for ( i = v68; v43; --v43 )
        *v44++ = 0;
      v46 = 32;
      v47 = &v56;
      do
      {
        *v47++ = 0;
        --v46;
      }
      while ( v46 );
      *(_BYTE *)(i + 13032) = 1;
      LOBYTE(v91) = 3;
      sub_1001F470(&v57);
      v48 = 32;
      v49 = &v54;
      do
      {
        *v49++ = 0;
        --v48;
      }
      while ( v48 );
      v50 = 32;
      v51 = &v55;
      do
      {
        *v51++ = 0;
        --v50;
      }
      while ( v50 );
      sub_10022270(&v69);
      sub_10022270(&v64);
      return 1;
    }










    PYG19周年生日快乐!
  • TA的每日心情
    难过
    前天 14:49
  • 签到天数: 11 天

    [LV.3]偶尔看看II

    发表于 2021-1-6 10:35:58 | 显示全部楼层
    "服务器似乎可以发送狗屎"

    啥玩意?
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    昨天 09:24
  • 签到天数: 2167 天

    [LV.Master]伴坛终老

    发表于 2021-1-6 12:03:29 | 显示全部楼层

    可能是打错字了吧
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情

    2024-3-19 22:28
  • 签到天数: 50 天

    [LV.5]常住居民I

    发表于 2021-1-9 19:47:50 | 显示全部楼层
    不懂这个,来围观一下啊
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2021-3-3 22:30
  • 签到天数: 5 天

    [LV.2]偶尔看看I

     楼主| 发表于 2021-2-16 20:44:34 | 显示全部楼层
    飘云 发表于 2021-1-6 10:35
    "服务器似乎可以发送狗屎"

    啥玩意?

    难得大哥回复
    能不能帮忙看看、、、、、、、、
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    擦汗
    前天 13:21
  • 签到天数: 506 天

    [LV.9]以坛为家II

    发表于 2021-5-7 20:38:41 | 显示全部楼层
    maxism 发表于 2021-2-16 20:44
    难得大哥回复
    能不能帮忙看看、、、、、、、、

    大哥不想理你,i并向你扔了一坨**
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

    快速回复 返回顶部 返回列表