dota2 局域网联机软件开发过程中遇到了 一个逆向难题,请求帮助
本帖最后由 maxism 于 2021-2-16 16:08 编辑大家过年好,
最近几个朋友在开发dota2局域网联机的软件,但是遇到了一个难题,特向大佬们请教。
dota2中,当一个用户建立房间,另一个用户进行连接的时候,dota会请求一个“证书”,验证通过后,两台电脑才能开始联机,使用软件进行转储后得到的信息如下:
cert = 080112202B39DF35AAB3E009269D5FBF57A0AC8D8059BAFA7C4E1001EE8D54062DAAEAEF2108E41494763F4001453518F75F4D35BBF95F50BA045A0A810108E41494763F40016219737465616D69643A3930313431373731303730343937383030
ca_key_id = 18220590129359924542
ca_signature = E1FA9B6E43521BDA3DA6F5C579AB10A31913AA538D6FAFE4C813CF6321E43F66D2C3D913C96A86423DC8A2A24B73F237D4E30A5BE6A85536B1E042938B1A450B
现在的问题是,我们无法还原这个加密的算法,但是dota本身是要进行验证的,目前想到的办法是对steamnetworkingsockets.dll进行逆向,将证书验证的函数修改了,或者是发送一个自签名的证书,但是这些我们都不会,希望各位大佬不吝指教,万分感谢。下面是搜到的一个相关的帖子,希望有用。
dll文件地址
https://wwa.lanzouj.com/i7Z7Tlq6zdg
V社source游戏现在使用steamnetworkingsockets.dll进行客户端/服务器通信。它需要一个“证书”,该“证书”实际上是一个已签名的协议,
由应用程序通过使用EMsgClientNetworkingCertRequest通过蒸汽向cmserver请求,并响应EMsgClientNetworkingCertRequestResponse
,游戏会发送一个appid和一个“密钥”,服务器返回一个“证书” “,由CA签名(由ID标识)
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中进行连接:
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; // @58
char v53; // @26
char v54; // @82
char v55; // @80
char v56; // @94
char v57; // @95
void *v58; // @86
int v59; // @86
int v60; // @39
int v61; // @39
int v62; // @38
int v63; // @38
int v64; // @7
int v65; // @7
int v66; // @7
char v67; // @7
int v68; // @1
int v69; // @69
int v70; // @69
int v71; // @69
char v72; // @69
int v73; // @84
int v74; // @84
int v75; // @84
int v76; // @84
size_t v77; // @84
int v78; // @84
int v79; // @84
int v80; // @84
int v81; // @80
int v82; // @80
int v83; // @80
int v84; // @80
void *v85; // @84
char *v86; // @84
_BYTE *v87; // @84
_BYTE *v88; // @84
int v89; // @84
int v90; // @84
int v91; // @7
char *v92; // @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) )
goto LABEL_42;
v60 = v4->dword3220;
v61 = v4->dword3224;
v12 = sub_10086E60(&v4->gap2C);
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);
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 )
{
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;
v88 = &v4->gap330A;
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;
v88 = &v4->gap330A;
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;
}
原帖地址(请注册登录查看):https://cs.rin.ru/forum/viewtopic.php?f=20&t=85859
兄弟可以研究一下逃离塔科夫{:1_918:}现在有放出单人服务器可以研究研究改个多人的 那游戏可玩性非常高 1002373873 发表于 2021-2-16 18:29
兄弟可以研究一下逃离塔科夫现在有放出单人服务器可以研究研究改个多人的 那游戏可玩性非常高
麻烦发我看看
页:
[1]