diff --git a/Rpc/rpc.idl b/Rpc/rpc.idl
index 2ec1d8d..3b55c2a 100644
--- a/Rpc/rpc.idl
+++ b/Rpc/rpc.idl
@@ -23,13 +23,26 @@ interface ISpy
int key;
BSTR value;
} RpcIntBstrPair_t;
- typedef RpcIntBstrPair_t* PRpcIntBstrPair_t;
- typedef RpcIntBstrPair_t** PPRpcIntBstrPair_t;
+ typedef RpcIntBstrPair_t* PRpcIntBstrPair;
+ 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 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 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();
[callback] int ReceiveMsg([ in ] RpcMessage_t rpcMsg);
diff --git a/SDK/rpc_client.cpp b/SDK/rpc_client.cpp
index c6d247d..06beb8f 100644
--- a/SDK/rpc_client.cpp
+++ b/SDK/rpc_client.cpp
@@ -1,6 +1,6 @@
-#include "sdk.h"
+#include "rpc_client.h"
+#include "sdk.h"
#include "util.h"
-#include "rpc_client.h"
#pragma comment(lib, "Rpcrt4.lib")
@@ -113,13 +113,13 @@ int RpcSendImageMsg(const wchar_t *wxid, const wchar_t *path)
return ret;
}
-PPRpcIntBstrPair_t RpcGetMsgTypes(int *pNum)
+PPRpcIntBstrPair RpcGetMsgTypes(int *pNum)
{
- int ret = 0;
- unsigned long ulCode = 0;
- PPRpcIntBstrPair_t ppRpcMsgTypes = NULL;
+ int ret = 0;
+ unsigned long ulCode = 0;
+ PPRpcIntBstrPair ppRpcMsgTypes = NULL;
- RpcTryExcept{ ret = client_GetMsgTypes(pNum, &ppRpcMsgTypes); }
+ RpcTryExcept { ret = client_GetMsgTypes(pNum, &ppRpcMsgTypes); }
RpcExcept(1)
{
ulCode = RpcExceptionCode();
@@ -134,6 +134,27 @@ PPRpcIntBstrPair_t RpcGetMsgTypes(int *pNum)
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)
{
WxMessage_t msg;
diff --git a/SDK/rpc_client.h b/SDK/rpc_client.h
index 5587f99..800d02c 100644
--- a/SDK/rpc_client.h
+++ b/SDK/rpc_client.h
@@ -9,4 +9,5 @@ unsigned int __stdcall RpcSetTextMsgCb(void *p);
int RpcIsLogin();
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);
-RpcIntBstrPair_t** RpcGetMsgTypes(int *pNum);
+PPRpcIntBstrPair RpcGetMsgTypes(int *pNum);
+PPRpcContact RpcGetContacts(int *pNum);
diff --git a/SDK/sdk.cpp b/SDK/sdk.cpp
index 0af3228..de7e39f 100644
--- a/SDK/sdk.cpp
+++ b/SDK/sdk.cpp
@@ -128,60 +128,46 @@ static int getAddrHandle(DWORD *addr, HANDLE *handle)
return 0;
}
+MsgTypesMap_t WxGetMsgTypes()
+{
+ static MsgTypesMap_t WxMsgTypes;
+ if (WxMsgTypes.empty()) {
+ int size = 0;
+ PPRpcIntBstrPair pp = RpcGetMsgTypes(&size);
+ for (int i = 0; i < size; i++) {
+ WxMsgTypes.insert(make_pair(pp[i]->key, GetWstringFromBstr(pp[i]->value)));
+ midl_user_free(pp[i]);
+ }
+ if (pp) {
+ midl_user_free(pp);
+ }
+ }
+
+ return WxMsgTypes;
+}
+
ContactMap_t WxGetContacts()
{
ContactMap_t mContact;
- DWORD moduleBaseAddress;
- HANDLE hProcess;
+ 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);
- 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);
+ mContact.insert(make_pair(contact.wxId, contact));
+ midl_user_free(pp[i]);
}
- CloseHandle(hProcess);
+ if (pp) {
+ midl_user_free(pp);
+ }
return mContact;
}
-
-MsgTypesMap_t WxGetMsgTypes()
-{
- static MsgTypesMap_t WxMsgTypes;
- if (WxMsgTypes.empty()) {
- int size = 0;
- PPRpcIntBstrPair_t pp = RpcGetMsgTypes(&size);
- for (int i = 0; i < size; i++) {
- WxMsgTypes.insert(make_pair(pp[i]->key, GetWstringFromBstr(pp[i]->value)));
- midl_user_free(pp[i]);
- }
- midl_user_free(pp);
- }
-
- return WxMsgTypes;
-}
-
diff --git a/SDK/util.cpp b/SDK/util.cpp
index e153ea8..61100be 100644
--- a/SDK/util.cpp
+++ b/SDK/util.cpp
@@ -167,12 +167,20 @@ int GetWstringByAddress(DWORD address, wchar_t *buffer, DWORD buffer_size)
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 ws = L"";
- if (p != nullptr) {
+ if (p != NULL) {
ws = wstring(p);
SysFreeString(p);
}
diff --git a/Spy/Spy.vcxproj b/Spy/Spy.vcxproj
index 28b3413..4ca44e3 100644
--- a/Spy/Spy.vcxproj
+++ b/Spy/Spy.vcxproj
@@ -166,6 +166,7 @@
+
@@ -178,6 +179,7 @@
+
diff --git a/Spy/Spy.vcxproj.filters b/Spy/Spy.vcxproj.filters
index d756e4f..be1f776 100644
--- a/Spy/Spy.vcxproj.filters
+++ b/Spy/Spy.vcxproj.filters
@@ -45,6 +45,9 @@
头文件
+
+ 头文件
+
@@ -74,6 +77,9 @@
源文件
+
+ 源文件
+
diff --git a/Spy/get_contacts.cpp b/Spy/get_contacts.cpp
new file mode 100644
index 0000000..5f43cc5
--- /dev/null
+++ b/Spy/get_contacts.cpp
@@ -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 GetContacts()
+{
+ int gender = 0;
+ vector 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;
+}
diff --git a/Spy/get_contacts.h b/Spy/get_contacts.h
new file mode 100644
index 0000000..5662225
--- /dev/null
+++ b/Spy/get_contacts.h
@@ -0,0 +1,7 @@
+#pragma once
+
+#include
+
+#include "rpc_h.h"
+
+std::vector GetContacts();
diff --git a/Spy/rpc_server.cpp b/Spy/rpc_server.cpp
index 9c340d8..344b34d 100644
--- a/Spy/rpc_server.cpp
+++ b/Spy/rpc_server.cpp
@@ -1,18 +1,19 @@
-#include
+#include
#include
+#include "get_contacts.h"
#include "monitor.h"
#include "rpc_server.h"
-#include "send_msg.h"
-#include "spy_types.h"
#include "sdk.h"
+#include "send_msg.h"
+#include "spy_types.h"
#include "rpc_h.h"
-#pragma comment(lib, "Rpcrt4.lib")
+#pragma comment(lib, "Rpcrt4.lib")
extern HANDLE g_hEvent;
extern MsgQueue_t g_MsgQueue;
-extern const MsgTypesMap_t g_WxMsgTypes;
+extern const MsgTypesMap_t g_WxMsgTypes;
int server_IsLogin() { return IsLogin(); }
@@ -54,32 +55,67 @@ int server_SendImageMsg(const wchar_t *wxid, const wchar_t *path)
return 0;
}
-
-int server_GetMsgTypes(int *pNum, PPRpcIntBstrPair_t *msgTypes)
+
+int server_GetMsgTypes(int *pNum, PPRpcIntBstrPair *msgTypes)
{
- *pNum = g_WxMsgTypes.size();
- PPRpcIntBstrPair_t pp = (PPRpcIntBstrPair_t)midl_user_allocate(*pNum * sizeof(RpcIntBstrPair_t));
+ *pNum = g_WxMsgTypes.size();
+ PPRpcIntBstrPair pp = (PPRpcIntBstrPair)midl_user_allocate(*pNum * sizeof(RpcIntBstrPair_t));
if (pp == NULL) {
printf("server_GetMsgTypes midl_user_allocate Failed for pp\n");
return -2;
- }
- int index = 0;
- for (auto it = g_WxMsgTypes.begin(); it != g_WxMsgTypes.end(); ++it) {
- PRpcIntBstrPair_t p = (PRpcIntBstrPair_t)midl_user_allocate(sizeof(RpcIntBstrPair_t));
+ }
+ int index = 0;
+ for (auto it = g_WxMsgTypes.begin(); it != g_WxMsgTypes.end(); it++) {
+ PRpcIntBstrPair p = (PRpcIntBstrPair)midl_user_allocate(sizeof(RpcIntBstrPair_t));
if (p == NULL) {
printf("server_GetMsgTypes midl_user_allocate Failed for p\n");
return -3;
- }
+ }
- p->key = it->first;
- p->value = SysAllocString(it->second.c_str());
+ p->key = it->first;
+ p->value = SysAllocString(it->second.c_str());
pp[index++] = p;
- }
-
- *msgTypes = pp;
-
+ }
+
+ *msgTypes = pp;
+
return 0;
-}
+}
+
+int server_GetContacts(int *pNum, PPRpcContact *contacts)
+{
+ std::vector 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*/)
{