Impl Functions_FUNC_GET_CONTACTS
This commit is contained in:
parent
9cdfb66bd4
commit
b34cdfd38e
@ -7,26 +7,86 @@
|
||||
extern WxCalls_t g_WxCalls;
|
||||
extern DWORD g_WeChatWinDllAddr;
|
||||
|
||||
#define FEAT_LEN 5
|
||||
static const uint8_t FEAT_COUNTRY[FEAT_LEN] = { 0xA4, 0xD9, 0x02, 0x4A, 0x18 };
|
||||
static const uint8_t FEAT_PROVINCE[FEAT_LEN] = { 0xE2, 0xEA, 0xA8, 0xD1, 0x18 };
|
||||
static const uint8_t FEAT_CITY[FEAT_LEN] = { 0x1D, 0x02, 0x5B, 0xBF, 0x18 };
|
||||
|
||||
static DWORD FindMem(DWORD start, DWORD end, const void *target, size_t len)
|
||||
{
|
||||
uint8_t *p = (uint8_t *)start;
|
||||
while ((DWORD)p < end) {
|
||||
if (memcmp((void *)p, target, len) == 0) {
|
||||
return (DWORD)p;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static string GetCntString(DWORD start, DWORD end, const uint8_t *feat, size_t len)
|
||||
{
|
||||
DWORD pfeat = FindMem(start, end, feat, len);
|
||||
if (pfeat == 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
DWORD lfeat = GET_DWORD(pfeat + len);
|
||||
if (lfeat <= 2) {
|
||||
return "";
|
||||
}
|
||||
|
||||
// DbgMsg("pfeat: %08X, lfeat: %d", pfeat, lfeat);
|
||||
return Wstring2String(wstring(GET_WSTRING_FROM_P(pfeat + FEAT_LEN + 4), lfeat));
|
||||
}
|
||||
|
||||
vector<RpcContact_t> GetContacts()
|
||||
{
|
||||
vector<RpcContact_t> contacts;
|
||||
DWORD baseAddr = g_WeChatWinDllAddr + g_WxCalls.contact.base;
|
||||
DWORD tempAddr = GET_DWORD(baseAddr);
|
||||
DWORD head = GET_DWORD(tempAddr + g_WxCalls.contact.head);
|
||||
DWORD node = GET_DWORD(head);
|
||||
DWORD call1 = g_WeChatWinDllAddr + g_WxCalls.contact.base;
|
||||
DWORD call2 = g_WeChatWinDllAddr + g_WxCalls.contact.head;
|
||||
|
||||
while (node != head) {
|
||||
int success = 0;
|
||||
DWORD *addr[3] = { 0, 0, 0 };
|
||||
__asm {
|
||||
pushad
|
||||
call call1
|
||||
lea ecx,addr
|
||||
push ecx
|
||||
mov ecx,eax
|
||||
call call2
|
||||
mov success,eax
|
||||
popad
|
||||
}
|
||||
|
||||
DWORD pstart = (DWORD)addr[0];
|
||||
DWORD pend = (DWORD)addr[2];
|
||||
|
||||
while (pstart < pend) {
|
||||
RpcContact_t cnt;
|
||||
cnt.wxid = GetStringByAddress(node + g_WxCalls.contact.wxId);
|
||||
cnt.code = GetStringByAddress(node + g_WxCalls.contact.wxCode);
|
||||
cnt.remark = GetStringByAddress(node + g_WxCalls.contact.wxRemark);
|
||||
cnt.name = GetStringByAddress(node + g_WxCalls.contact.wxName);
|
||||
cnt.country = GetStringByAddress(node + g_WxCalls.contact.wxCountry);
|
||||
cnt.province = GetStringByAddress(node + g_WxCalls.contact.wxProvince);
|
||||
cnt.city = GetStringByAddress(node + g_WxCalls.contact.wxCity);
|
||||
cnt.gender = GET_DWORD(node + g_WxCalls.contact.wxGender);
|
||||
DWORD pbin = GET_DWORD(pstart + 0x150);
|
||||
DWORD lenbin = GET_DWORD(pstart + 0x154);
|
||||
// DbgMsg("pstart: %08X, pbin: %08X, lenbin: %d", pstart, pbin, lenbin);
|
||||
|
||||
cnt.wxid = GetStringByAddress(pstart + g_WxCalls.contact.wxId);
|
||||
cnt.code = GetStringByAddress(pstart + g_WxCalls.contact.wxCode);
|
||||
cnt.remark = GetStringByAddress(pstart + g_WxCalls.contact.wxRemark);
|
||||
cnt.name = GetStringByAddress(pstart + g_WxCalls.contact.wxName);
|
||||
|
||||
cnt.country = GetCntString(pbin, pbin + lenbin, FEAT_COUNTRY, FEAT_LEN);
|
||||
cnt.province = GetCntString(pbin, pbin + lenbin, FEAT_PROVINCE, FEAT_LEN);
|
||||
cnt.city = GetCntString(pbin, pbin + lenbin, FEAT_CITY, FEAT_LEN);
|
||||
|
||||
if (pbin == 0) {
|
||||
cnt.gender = 0;
|
||||
} else {
|
||||
cnt.gender = (DWORD) * (uint8_t *)(pbin + g_WxCalls.contact.wxGender);
|
||||
}
|
||||
// DbgMsg("pstart: %08X, pbin: %08X, lenbin: %d, cnt.gender: %08X", pstart, pbin, lenbin, cnt.gender);
|
||||
|
||||
contacts.push_back(cnt);
|
||||
node = GET_DWORD(node);
|
||||
pstart += 0x438;
|
||||
}
|
||||
|
||||
return contacts;
|
||||
|
@ -16,8 +16,8 @@ WxCalls_t wxCalls = {
|
||||
{ 0xB8A70, 0x3ED5E0, 0x107F00, 0x3ED7B0, 0x2386FE4 }, // Send xml Message
|
||||
{ 0x771980, 0x4777E0, 0x239E888 }, // Send Emotion Message
|
||||
/* Get Contacts:
|
||||
Base, head, wxId, Code, Remark,Name, Gender, Country, Province, City*/
|
||||
{ 0x23668F4, 0x4C, 0x30, 0x44, 0x78, 0x8C, 0x184, 0x1D0, 0x1E4, 0x1F8 },
|
||||
call1, call2, wxId, Code, Remark,Name, Gender, Country, Province, City*/
|
||||
{ 0x75A4A0, 0xC089F0, 0x10, 0x24, 0x58, 0x6C, 0x0E, 0x00, 0x00, 0x00 },
|
||||
/* Exec Sql:
|
||||
Exec, base, start, end, slot, name*/
|
||||
{ 0x141BDF0, 0x2366934, 0x1428, 0x142C, 0x3C, 0x50 },
|
||||
|
@ -559,12 +559,12 @@ static bool dispatcher(uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len
|
||||
ret = func_get_msg_types(out, out_len);
|
||||
break;
|
||||
}
|
||||
#if 0
|
||||
case Functions_FUNC_GET_CONTACTS: {
|
||||
LOG_DEBUG("[Functions_FUNC_GET_CONTACTS]");
|
||||
ret = func_get_contacts(out, out_len);
|
||||
break;
|
||||
}
|
||||
#if 0
|
||||
case Functions_FUNC_GET_DB_NAMES: {
|
||||
LOG_DEBUG("[Functions_FUNC_GET_DB_NAMES]");
|
||||
ret = func_get_db_names(out, out_len);
|
||||
|
25
spy/util.cpp
25
spy/util.cpp
@ -5,6 +5,7 @@
|
||||
#include <string.h>
|
||||
#include <strsafe.h>
|
||||
#include <tlhelp32.h>
|
||||
#include <vector>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "util.h"
|
||||
@ -244,3 +245,27 @@ wstring GetUnicodeInfoByAddress(HANDLE hProcess, DWORD address)
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void DbgMsg(const char *zcFormat, ...)
|
||||
{
|
||||
// initialize use of the variable argument array
|
||||
va_list vaArgs;
|
||||
va_start(vaArgs, zcFormat);
|
||||
|
||||
// reliably acquire the size
|
||||
// from a copy of the variable argument array
|
||||
// and a functionally reliable call to mock the formatting
|
||||
va_list vaArgsCopy;
|
||||
va_copy(vaArgsCopy, vaArgs);
|
||||
const int iLen = std::vsnprintf(NULL, 0, zcFormat, vaArgsCopy);
|
||||
va_end(vaArgsCopy);
|
||||
|
||||
// return a formatted string without risking memory mismanagement
|
||||
// and without assuming any compiler or platform specific behavior
|
||||
std::vector<char> zc(iLen + 1);
|
||||
std::vsnprintf(zc.data(), zc.size(), zcFormat, vaArgs);
|
||||
va_end(vaArgs);
|
||||
std::string strText(zc.data(), iLen);
|
||||
|
||||
OutputDebugStringA(strText.c_str());
|
||||
}
|
||||
|
10
spy/util.h
10
spy/util.h
@ -8,10 +8,11 @@
|
||||
#define WECHATINJECTDLL L"spy.dll"
|
||||
#define WECHATINJECTDLL_DEBUG L"spy_debug.dll"
|
||||
|
||||
#define GET_DWORD(addr) ((DWORD) * (DWORD *)(addr))
|
||||
#define GET_STRING(addr) ((CHAR *)(*(DWORD *)(addr)))
|
||||
#define GET_WSTRING(addr) ((WCHAR *)(*(DWORD *)(addr)))
|
||||
#define GET_STRING_FROM_P(addr) ((CHAR *)(addr))
|
||||
#define GET_DWORD(addr) ((DWORD) * (DWORD *)(addr))
|
||||
#define GET_STRING(addr) ((CHAR *)(*(DWORD *)(addr)))
|
||||
#define GET_WSTRING(addr) ((WCHAR *)(*(DWORD *)(addr)))
|
||||
#define GET_STRING_FROM_P(addr) ((CHAR *)(addr))
|
||||
#define GET_WSTRING_FROM_P(addr) ((WCHAR *)(addr))
|
||||
|
||||
typedef struct PortPath {
|
||||
int port;
|
||||
@ -27,3 +28,4 @@ std::wstring GetUnicodeInfoByAddress(HANDLE hProcess, DWORD address);
|
||||
std::wstring String2Wstring(std::string s);
|
||||
std::string Wstring2String(std::wstring ws);
|
||||
std::string GetStringByAddress(DWORD address);
|
||||
void DbgMsg(const char *zcFormat, ...);
|
||||
|
Loading…
Reference in New Issue
Block a user