Impl get contacts
This commit is contained in:
parent
48091b8526
commit
3042de5183
19
Rpc/rpc.idl
19
Rpc/rpc.idl
@ -23,13 +23,26 @@ interface ISpy
|
|||||||
int key;
|
int key;
|
||||||
BSTR value;
|
BSTR value;
|
||||||
} RpcIntBstrPair_t;
|
} RpcIntBstrPair_t;
|
||||||
typedef RpcIntBstrPair_t* PRpcIntBstrPair_t;
|
typedef RpcIntBstrPair_t* PRpcIntBstrPair;
|
||||||
typedef RpcIntBstrPair_t** PPRpcIntBstrPair_t;
|
typedef RpcIntBstrPair_t** PPRpcIntBstrPair;
|
||||||
|
|
||||||
|
typedef struct RpcContact {
|
||||||
|
BSTR wxId;
|
||||||
|
BSTR wxCode;
|
||||||
|
BSTR wxName;
|
||||||
|
BSTR wxCountry;
|
||||||
|
BSTR wxProvince;
|
||||||
|
BSTR wxCity;
|
||||||
|
BSTR wxGender;
|
||||||
|
} RpcContact_t;
|
||||||
|
typedef RpcContact_t *PRpcContact;
|
||||||
|
typedef RpcContact_t **PPRpcContact;
|
||||||
|
|
||||||
int IsLogin();
|
int IsLogin();
|
||||||
int SendTextMsg([ in, string ] const wchar_t *wxid, [ in, string ] const wchar_t *at_wxid, [ in, string ] const wchar_t *msg);
|
int SendTextMsg([ in, string ] const wchar_t *wxid, [ in, string ] const wchar_t *at_wxid, [ in, string ] const wchar_t *msg);
|
||||||
int SendImageMsg([ in, string ] const wchar_t *wxid, [ in, string ] const wchar_t *path);
|
int SendImageMsg([ in, string ] const wchar_t *wxid, [ in, string ] const wchar_t *path);
|
||||||
int GetMsgTypes([ out ] int *pNum, [ out, size_is(, *pNum) ] PPRpcIntBstrPair_t *msgTypes);
|
int GetMsgTypes([ out ] int *pNum, [ out, size_is(, *pNum) ] PPRpcIntBstrPair *msgTypes);
|
||||||
|
int GetContacts([ out ] int *pNum, [ out, size_is(, *pNum) ] PPRpcContact *contacts);
|
||||||
|
|
||||||
void EnableReceiveMsg();
|
void EnableReceiveMsg();
|
||||||
[callback] int ReceiveMsg([ in ] RpcMessage_t rpcMsg);
|
[callback] int ReceiveMsg([ in ] RpcMessage_t rpcMsg);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "sdk.h"
|
#include "rpc_client.h"
|
||||||
|
#include "sdk.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "rpc_client.h"
|
|
||||||
|
|
||||||
#pragma comment(lib, "Rpcrt4.lib")
|
#pragma comment(lib, "Rpcrt4.lib")
|
||||||
|
|
||||||
@ -113,13 +113,13 @@ int RpcSendImageMsg(const wchar_t *wxid, const wchar_t *path)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
PPRpcIntBstrPair_t RpcGetMsgTypes(int *pNum)
|
PPRpcIntBstrPair RpcGetMsgTypes(int *pNum)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
unsigned long ulCode = 0;
|
unsigned long ulCode = 0;
|
||||||
PPRpcIntBstrPair_t ppRpcMsgTypes = NULL;
|
PPRpcIntBstrPair ppRpcMsgTypes = NULL;
|
||||||
|
|
||||||
RpcTryExcept{ ret = client_GetMsgTypes(pNum, &ppRpcMsgTypes); }
|
RpcTryExcept { ret = client_GetMsgTypes(pNum, &ppRpcMsgTypes); }
|
||||||
RpcExcept(1)
|
RpcExcept(1)
|
||||||
{
|
{
|
||||||
ulCode = RpcExceptionCode();
|
ulCode = RpcExceptionCode();
|
||||||
@ -134,6 +134,27 @@ PPRpcIntBstrPair_t RpcGetMsgTypes(int *pNum)
|
|||||||
return ppRpcMsgTypes;
|
return ppRpcMsgTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PPRpcContact RpcGetContacts(int *pNum)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
unsigned long ulCode = 0;
|
||||||
|
PPRpcContact ppRpcContacts = NULL;
|
||||||
|
|
||||||
|
RpcTryExcept { ret = client_GetContacts(pNum, &ppRpcContacts); }
|
||||||
|
RpcExcept(1)
|
||||||
|
{
|
||||||
|
ulCode = RpcExceptionCode();
|
||||||
|
printf("RpcGetContacts exception 0x%lx = %ld\n", ulCode, ulCode);
|
||||||
|
}
|
||||||
|
RpcEndExcept;
|
||||||
|
if (ret != 0) {
|
||||||
|
printf("GetContacts Failed: %d\n", ret);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ppRpcContacts;
|
||||||
|
}
|
||||||
|
|
||||||
int server_ReceiveMsg(RpcMessage_t rpcMsg)
|
int server_ReceiveMsg(RpcMessage_t rpcMsg)
|
||||||
{
|
{
|
||||||
WxMessage_t msg;
|
WxMessage_t msg;
|
||||||
|
@ -9,4 +9,5 @@ unsigned int __stdcall RpcSetTextMsgCb(void *p);
|
|||||||
int RpcIsLogin();
|
int RpcIsLogin();
|
||||||
int RpcSendTextMsg(const wchar_t *wxid, const wchar_t *at_wxid, const wchar_t *msg);
|
int RpcSendTextMsg(const wchar_t *wxid, const wchar_t *at_wxid, const wchar_t *msg);
|
||||||
int RpcSendImageMsg(const wchar_t *wxid, const wchar_t *path);
|
int RpcSendImageMsg(const wchar_t *wxid, const wchar_t *path);
|
||||||
RpcIntBstrPair_t** RpcGetMsgTypes(int *pNum);
|
PPRpcIntBstrPair RpcGetMsgTypes(int *pNum);
|
||||||
|
PPRpcContact RpcGetContacts(int *pNum);
|
||||||
|
74
SDK/sdk.cpp
74
SDK/sdk.cpp
@ -128,60 +128,46 @@ static int getAddrHandle(DWORD *addr, HANDLE *handle)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ContactMap_t WxGetContacts()
|
|
||||||
{
|
|
||||||
ContactMap_t mContact;
|
|
||||||
DWORD moduleBaseAddress;
|
|
||||||
HANDLE hProcess;
|
|
||||||
|
|
||||||
if (getAddrHandle(&moduleBaseAddress, &hProcess) != 0) {
|
|
||||||
return mContact;
|
|
||||||
}
|
|
||||||
printf("WxGetContacts\n");
|
|
||||||
DWORD baseAddr = moduleBaseAddress + 0x23638F4;
|
|
||||||
DWORD tempAddr = GetMemoryIntByAddress(hProcess, baseAddr);
|
|
||||||
DWORD head = GetMemoryIntByAddress(hProcess, tempAddr + 0x4C);
|
|
||||||
DWORD node = GetMemoryIntByAddress(hProcess, head);
|
|
||||||
|
|
||||||
while (node != head) {
|
|
||||||
WxContact_t contactItem;
|
|
||||||
contactItem.wxId = GetUnicodeInfoByAddress(hProcess, node + 0x30);
|
|
||||||
contactItem.wxCode = GetUnicodeInfoByAddress(hProcess, node + 0x44);
|
|
||||||
contactItem.wxName = GetUnicodeInfoByAddress(hProcess, node + 0x8C);
|
|
||||||
contactItem.wxCountry = GetUnicodeInfoByAddress(hProcess, node + 0x1D0);
|
|
||||||
contactItem.wxProvince = GetUnicodeInfoByAddress(hProcess, node + 0x1E4);
|
|
||||||
contactItem.wxCity = GetUnicodeInfoByAddress(hProcess, node + 0x1F8);
|
|
||||||
DWORD gender = GetMemoryIntByAddress(hProcess, node + 0x184);
|
|
||||||
|
|
||||||
if (gender == 1)
|
|
||||||
contactItem.wxGender = L"男";
|
|
||||||
else if (gender == 2)
|
|
||||||
contactItem.wxGender = L"女";
|
|
||||||
else
|
|
||||||
contactItem.wxGender = L"未知";
|
|
||||||
|
|
||||||
mContact.insert(make_pair(contactItem.wxId, contactItem));
|
|
||||||
node = GetMemoryIntByAddress(hProcess, node);
|
|
||||||
}
|
|
||||||
|
|
||||||
CloseHandle(hProcess);
|
|
||||||
|
|
||||||
return mContact;
|
|
||||||
}
|
|
||||||
|
|
||||||
MsgTypesMap_t WxGetMsgTypes()
|
MsgTypesMap_t WxGetMsgTypes()
|
||||||
{
|
{
|
||||||
static MsgTypesMap_t WxMsgTypes;
|
static MsgTypesMap_t WxMsgTypes;
|
||||||
if (WxMsgTypes.empty()) {
|
if (WxMsgTypes.empty()) {
|
||||||
int size = 0;
|
int size = 0;
|
||||||
PPRpcIntBstrPair_t pp = RpcGetMsgTypes(&size);
|
PPRpcIntBstrPair pp = RpcGetMsgTypes(&size);
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
WxMsgTypes.insert(make_pair(pp[i]->key, GetWstringFromBstr(pp[i]->value)));
|
WxMsgTypes.insert(make_pair(pp[i]->key, GetWstringFromBstr(pp[i]->value)));
|
||||||
midl_user_free(pp[i]);
|
midl_user_free(pp[i]);
|
||||||
}
|
}
|
||||||
midl_user_free(pp);
|
if (pp) {
|
||||||
|
midl_user_free(pp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return WxMsgTypes;
|
return WxMsgTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ContactMap_t WxGetContacts()
|
||||||
|
{
|
||||||
|
ContactMap_t mContact;
|
||||||
|
int size = 0;
|
||||||
|
PPRpcContact pp = RpcGetContacts(&size);
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
WxContact_t contact;
|
||||||
|
contact.wxId = GetWstringFromBstr(pp[i]->wxId);
|
||||||
|
contact.wxCode = GetWstringFromBstr(pp[i]->wxCode);
|
||||||
|
contact.wxName = GetWstringFromBstr(pp[i]->wxName);
|
||||||
|
contact.wxCountry = GetWstringFromBstr(pp[i]->wxCountry);
|
||||||
|
contact.wxProvince = GetWstringFromBstr(pp[i]->wxProvince);
|
||||||
|
contact.wxCity = GetWstringFromBstr(pp[i]->wxCity);
|
||||||
|
contact.wxGender = GetWstringFromBstr(pp[i]->wxGender);
|
||||||
|
|
||||||
|
mContact.insert(make_pair(contact.wxId, contact));
|
||||||
|
midl_user_free(pp[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pp) {
|
||||||
|
midl_user_free(pp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mContact;
|
||||||
|
}
|
||||||
|
12
SDK/util.cpp
12
SDK/util.cpp
@ -167,12 +167,20 @@ int GetWstringByAddress(DWORD address, wchar_t *buffer, DWORD buffer_size)
|
|||||||
return strLength;
|
return strLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
BSTR GetBstrByAddress(DWORD address) { return SysAllocStringLen(GET_WSTRING(address), GET_DWORD(address + 4)); }
|
BSTR GetBstrByAddress(DWORD address)
|
||||||
|
{
|
||||||
|
wchar_t *p = GET_WSTRING(address);
|
||||||
|
if (p == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SysAllocStringLen(GET_WSTRING(address), GET_DWORD(address + 4));
|
||||||
|
}
|
||||||
|
|
||||||
wstring GetWstringFromBstr(BSTR p)
|
wstring GetWstringFromBstr(BSTR p)
|
||||||
{
|
{
|
||||||
wstring ws = L"";
|
wstring ws = L"";
|
||||||
if (p != nullptr) {
|
if (p != NULL) {
|
||||||
ws = wstring(p);
|
ws = wstring(p);
|
||||||
SysFreeString(p);
|
SysFreeString(p);
|
||||||
}
|
}
|
||||||
|
@ -166,6 +166,7 @@
|
|||||||
<ClInclude Include="..\Rpc\rpc_h.h" />
|
<ClInclude Include="..\Rpc\rpc_h.h" />
|
||||||
<ClInclude Include="..\SDK\util.h" />
|
<ClInclude Include="..\SDK\util.h" />
|
||||||
<ClInclude Include="framework.h" />
|
<ClInclude Include="framework.h" />
|
||||||
|
<ClInclude Include="get_contacts.h" />
|
||||||
<ClInclude Include="load_calls.h" />
|
<ClInclude Include="load_calls.h" />
|
||||||
<ClInclude Include="monitor.h" />
|
<ClInclude Include="monitor.h" />
|
||||||
<ClInclude Include="receive_msg.h" />
|
<ClInclude Include="receive_msg.h" />
|
||||||
@ -178,6 +179,7 @@
|
|||||||
<ClCompile Include="..\Rpc\rpc_s.c" />
|
<ClCompile Include="..\Rpc\rpc_s.c" />
|
||||||
<ClCompile Include="..\SDK\util.cpp" />
|
<ClCompile Include="..\SDK\util.cpp" />
|
||||||
<ClCompile Include="dllmain.cpp" />
|
<ClCompile Include="dllmain.cpp" />
|
||||||
|
<ClCompile Include="get_contacts.cpp" />
|
||||||
<ClCompile Include="load_calls.cpp" />
|
<ClCompile Include="load_calls.cpp" />
|
||||||
<ClCompile Include="monitor.cpp" />
|
<ClCompile Include="monitor.cpp" />
|
||||||
<ClCompile Include="receive_msg.cpp" />
|
<ClCompile Include="receive_msg.cpp" />
|
||||||
|
@ -45,6 +45,9 @@
|
|||||||
<ClInclude Include="spy_types.h">
|
<ClInclude Include="spy_types.h">
|
||||||
<Filter>头文件</Filter>
|
<Filter>头文件</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="get_contacts.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="dllmain.cpp">
|
<ClCompile Include="dllmain.cpp">
|
||||||
@ -74,6 +77,9 @@
|
|||||||
<ClCompile Include="send_msg.cpp">
|
<ClCompile Include="send_msg.cpp">
|
||||||
<Filter>源文件</Filter>
|
<Filter>源文件</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="get_contacts.cpp">
|
||||||
|
<Filter>源文件</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Midl Include="..\Rpc\rpc.idl">
|
<Midl Include="..\Rpc\rpc.idl">
|
||||||
|
39
Spy/get_contacts.cpp
Normal file
39
Spy/get_contacts.cpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#include "get_contacts.h"
|
||||||
|
#include "load_calls.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
extern WxCalls_t g_WxCalls;
|
||||||
|
extern DWORD g_WeChatWinDllAddr;
|
||||||
|
|
||||||
|
std::vector<RpcContact_t> GetContacts()
|
||||||
|
{
|
||||||
|
int gender = 0;
|
||||||
|
vector<RpcContact_t> vContacts;
|
||||||
|
DWORD baseAddr = g_WeChatWinDllAddr + 0x23638F4;
|
||||||
|
DWORD tempAddr = GET_DWORD(baseAddr);
|
||||||
|
DWORD head = GET_DWORD(tempAddr + 0x4C);
|
||||||
|
DWORD node = GET_DWORD(head);
|
||||||
|
|
||||||
|
while (node != head) {
|
||||||
|
RpcContact_t rpcContact = { 0 };
|
||||||
|
rpcContact.wxId = GetBstrByAddress(node + 0x30);
|
||||||
|
rpcContact.wxCode = GetBstrByAddress(node + 0x44);
|
||||||
|
rpcContact.wxName = GetBstrByAddress(node + 0x8C);
|
||||||
|
rpcContact.wxCountry = GetBstrByAddress(node + 0x1D0);
|
||||||
|
rpcContact.wxProvince = GetBstrByAddress(node + 0x1E4);
|
||||||
|
rpcContact.wxCity = GetBstrByAddress(node + 0x1F8);
|
||||||
|
|
||||||
|
gender = GET_DWORD(node + 0x184);
|
||||||
|
if (gender == 1)
|
||||||
|
rpcContact.wxGender = SysAllocString(L"男");
|
||||||
|
else if (gender == 2)
|
||||||
|
rpcContact.wxGender = SysAllocString(L"女");
|
||||||
|
else
|
||||||
|
rpcContact.wxGender = SysAllocString(L"未知");
|
||||||
|
|
||||||
|
vContacts.push_back(rpcContact);
|
||||||
|
node = GET_DWORD(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
return vContacts;
|
||||||
|
}
|
7
Spy/get_contacts.h
Normal file
7
Spy/get_contacts.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "rpc_h.h"
|
||||||
|
|
||||||
|
std::vector<RpcContact_t> GetContacts();
|
@ -1,11 +1,12 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "get_contacts.h"
|
||||||
#include "monitor.h"
|
#include "monitor.h"
|
||||||
#include "rpc_server.h"
|
#include "rpc_server.h"
|
||||||
|
#include "sdk.h"
|
||||||
#include "send_msg.h"
|
#include "send_msg.h"
|
||||||
#include "spy_types.h"
|
#include "spy_types.h"
|
||||||
#include "sdk.h"
|
|
||||||
|
|
||||||
#include "rpc_h.h"
|
#include "rpc_h.h"
|
||||||
#pragma comment(lib, "Rpcrt4.lib")
|
#pragma comment(lib, "Rpcrt4.lib")
|
||||||
@ -55,24 +56,24 @@ int server_SendImageMsg(const wchar_t *wxid, const wchar_t *path)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int server_GetMsgTypes(int *pNum, PPRpcIntBstrPair_t *msgTypes)
|
int server_GetMsgTypes(int *pNum, PPRpcIntBstrPair *msgTypes)
|
||||||
{
|
{
|
||||||
*pNum = g_WxMsgTypes.size();
|
*pNum = g_WxMsgTypes.size();
|
||||||
PPRpcIntBstrPair_t pp = (PPRpcIntBstrPair_t)midl_user_allocate(*pNum * sizeof(RpcIntBstrPair_t));
|
PPRpcIntBstrPair pp = (PPRpcIntBstrPair)midl_user_allocate(*pNum * sizeof(RpcIntBstrPair_t));
|
||||||
if (pp == NULL) {
|
if (pp == NULL) {
|
||||||
printf("server_GetMsgTypes midl_user_allocate Failed for pp\n");
|
printf("server_GetMsgTypes midl_user_allocate Failed for pp\n");
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (auto it = g_WxMsgTypes.begin(); it != g_WxMsgTypes.end(); ++it) {
|
for (auto it = g_WxMsgTypes.begin(); it != g_WxMsgTypes.end(); it++) {
|
||||||
PRpcIntBstrPair_t p = (PRpcIntBstrPair_t)midl_user_allocate(sizeof(RpcIntBstrPair_t));
|
PRpcIntBstrPair p = (PRpcIntBstrPair)midl_user_allocate(sizeof(RpcIntBstrPair_t));
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
printf("server_GetMsgTypes midl_user_allocate Failed for p\n");
|
printf("server_GetMsgTypes midl_user_allocate Failed for p\n");
|
||||||
return -3;
|
return -3;
|
||||||
}
|
}
|
||||||
|
|
||||||
p->key = it->first;
|
p->key = it->first;
|
||||||
p->value = SysAllocString(it->second.c_str());
|
p->value = SysAllocString(it->second.c_str());
|
||||||
pp[index++] = p;
|
pp[index++] = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,6 +82,41 @@ int server_GetMsgTypes(int *pNum, PPRpcIntBstrPair_t *msgTypes)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int server_GetContacts(int *pNum, PPRpcContact *contacts)
|
||||||
|
{
|
||||||
|
std::vector<RpcContact_t> vContacts = GetContacts();
|
||||||
|
|
||||||
|
*pNum = vContacts.size();
|
||||||
|
PPRpcContact pp = (PPRpcContact)midl_user_allocate(*pNum * sizeof(RpcContact_t));
|
||||||
|
if (pp == NULL) {
|
||||||
|
printf("server_GetMsgTypes midl_user_allocate Failed for pp\n");
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
for (auto it = vContacts.begin(); it != vContacts.end(); it++) {
|
||||||
|
PRpcContact p = (PRpcContact)midl_user_allocate(sizeof(RpcContact_t));
|
||||||
|
if (p == NULL) {
|
||||||
|
printf("server_GetMsgTypes midl_user_allocate Failed for p\n");
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
p->wxId = it->wxId;
|
||||||
|
p->wxCode = it->wxCode;
|
||||||
|
p->wxName = it->wxName;
|
||||||
|
p->wxCountry = it->wxCountry;
|
||||||
|
p->wxProvince = it->wxProvince;
|
||||||
|
p->wxCity = it->wxCity;
|
||||||
|
p->wxGender = it->wxGender;
|
||||||
|
|
||||||
|
pp[index++] = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
*contacts = pp;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
RPC_STATUS CALLBACK SecurityCallback(RPC_IF_HANDLE /*hInterface*/, void * /*pBindingHandle*/)
|
RPC_STATUS CALLBACK SecurityCallback(RPC_IF_HANDLE /*hInterface*/, void * /*pBindingHandle*/)
|
||||||
{
|
{
|
||||||
return RPC_S_OK; // Always allow anyone.
|
return RPC_S_OK; // Always allow anyone.
|
||||||
|
Loading…
Reference in New Issue
Block a user