wxhelper/src/hook_img.cc
2022-12-21 20:30:44 +08:00

231 lines
6.6 KiB
C++

#include "pch.h"
#include "hook_img.h"
#include "common.h"
// #define WX_HOOK_IMG_OFFSET 0xd7eaa5
// #define WX_HOOK_IMG_NEXT_OFFSET 0xda56e0
#define WX_HOOK_IMG_OFFSET 0xc63ebc
#define WX_HOOK_IMG_NEXT_OFFSET 0xd7e9e0
#define WX_SELF_ID_OFFSET 0x2BEE08C
#define BUFSIZE 1024
#define JPEG0 0xFF
#define JPEG1 0xD8
#define JPEG2 0xFF
#define PNG0 0x89
#define PNG1 0x50
#define PNG2 0x4E
#define BMP0 0x42
#define BMP1 0x4D
#define GIF0 0x47
#define GIF1 0x49
#define GIF2 0x46
static wstring kImgStorePath = L"";
static int kImgHooked = FALSE;
static DWORD kWeChatWinBase = GetWeChatWinBase();
static char kOriginImgAsmCode[5] = {0};
static DWORD kHookImgNextAddress = kWeChatWinBase + WX_HOOK_IMG_NEXT_OFFSET;
static DWORD kHookImgJmpBackAddress = kWeChatWinBase + WX_HOOK_IMG_OFFSET + 0x5;
void OnHookImg(DWORD obj_addr) {
DWORD wxid_addr = GetWeChatWinBase() + WX_SELF_ID_OFFSET;
string wxid = string(*(char **)wxid_addr, *(DWORD *)(wxid_addr + 0x10));
wstring self_id = String2Wstring(wxid);
wstring save_path = kImgStorePath + self_id;
if (!FindOrCreateDirectoryW(save_path.c_str())) {
return;
}
wchar_t *origin_file_path = *(wchar_t **)obj_addr;
wstring img_path(origin_file_path);
if (img_path.find(L"_t.dat") != wstring::npos) {
return;
}
int pos_begin = img_path.find_last_of(L"\\") + 1;
int pos_end = img_path.find_last_of(L".");
wstring file_name = img_path.substr(pos_begin, pos_end - pos_begin);
char buffer[BUFSIZE] = {0};
DWORD bytes_read = 0;
DWORD bytes_write = 0;
unsigned char magic_head[4] = {0};
wchar_t suffix[5] = {0};
HANDLE h_origin_file =
CreateFileW(origin_file_path, GENERIC_READ, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if (h_origin_file == INVALID_HANDLE_VALUE) {
return;
}
if (ReadFile(h_origin_file, buffer, BUFSIZE, &bytes_read, NULL)) {
memcpy(magic_head, buffer, 3);
}
if (magic_head[0] == PNG0 && magic_head[1] == PNG1 && magic_head[2] == PNG2) {
lstrcpyW(suffix, L".png");
} else if (magic_head[0] == GIF0 && magic_head[1] == GIF1 &&
magic_head[2] == GIF2) {
lstrcpyW(suffix, L".gif");
} else if (magic_head[0] == JPEG0 && magic_head[1] == JPEG1 &&
magic_head[2] == JPEG2) {
lstrcpyW(suffix, L".jpg");
} else {
lstrcpyW(suffix, L"");
}
wstring save_img_path = save_path + L"\\" + file_name + suffix;
HANDLE save_file = CreateFileW(save_img_path.c_str(), GENERIC_ALL, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (save_file == INVALID_HANDLE_VALUE) {
return;
}
if (!WriteFile(save_file, (LPCVOID)buffer, bytes_read, &bytes_write, 0)) {
CloseHandle(h_origin_file);
CloseHandle(save_file);
return;
}
do {
if (ReadFile(h_origin_file, buffer, BUFSIZE, &bytes_read, NULL)) {
if (!WriteFile(save_file, (LPCVOID)buffer, bytes_read, &bytes_write, 0)) {
CloseHandle(h_origin_file);
CloseHandle(save_file);
return;
}
}
} while (bytes_read == BUFSIZE);
CloseHandle(h_origin_file);
CloseHandle(save_file);
}
/// @brief hook img implement
_declspec(naked) void handle_img() {
__asm {
PUSHAD
PUSHFD
PUSH ECX
CALL OnHookImg
ADD ESP, 0x4
POPFD
POPAD
CALL kHookImgNextAddress
JMP kHookImgJmpBackAddress
}
}
/// @brief hook image
/// @param save_path image save dir
/// @return
int HookImg(wstring save_path) {
kWeChatWinBase = GetWeChatWinBase();
if (!kWeChatWinBase) {
return -1;
}
if (kImgHooked) {
return 2;
}
kImgStorePath = save_path;
if (kImgStorePath.back() != '\\') {
kImgStorePath += L"\\";
}
wstring createpath = kImgStorePath.substr(0, kImgStorePath.length() - 1);
if (!FindOrCreateDirectoryW(createpath.c_str())) {
return -2;
}
DWORD hook_img_addr = kWeChatWinBase + WX_HOOK_IMG_OFFSET;
kHookImgNextAddress = kWeChatWinBase + WX_HOOK_IMG_NEXT_OFFSET;
static DWORD kHookImgJmpBackAddress = hook_img_addr + 0x5;
HookAnyAddress(hook_img_addr, (LPVOID)handle_img, kOriginImgAsmCode);
kImgHooked = TRUE;
return 1;
}
int UnHookImg() {
if (!kImgHooked) return 1;
DWORD hook_img_addr = kWeChatWinBase + WX_HOOK_IMG_OFFSET;
UnHookAnyAddress(hook_img_addr, kOriginImgAsmCode);
kImgHooked = FALSE;
return 1;
}
int GetImgByName(wchar_t* file_path,wchar_t* save_dir) {
wstring save_path(save_dir);
wstring orign_file_path(file_path);
if (!FindOrCreateDirectoryW(save_path.c_str())) {
return 0;
}
int pos_begin = orign_file_path.find_last_of(L"\\") + 1;
int pos_end = orign_file_path.find_last_of(L".");
wstring file_name = orign_file_path.substr(pos_begin, pos_end - pos_begin);
HANDLE h_origin_file =
CreateFileW(file_path, GENERIC_READ, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
char buffer[BUFSIZE] = {0};
DWORD bytes_read = 0;
DWORD bytes_write = 0;
unsigned char magic_head[4] = {0};
wstring suffix;
short key = 0;
if (ReadFile(h_origin_file, buffer, BUFSIZE, &bytes_read, NULL)) {
memcpy(magic_head, buffer, 3);
} else {
CloseHandle(h_origin_file);
return 0;
}
if ((magic_head[0] ^ JPEG0) == (magic_head[1] ^ JPEG1)) {
key = magic_head[0] ^ JPEG0;
suffix = L".jpg";
} else if ((magic_head[0] ^ PNG1) == (magic_head[1] ^ PNG2)) {
key = magic_head[0] ^ PNG1;
suffix = L".png";
} else if ((magic_head[0] ^ GIF0) == (magic_head[1] ^ GIF1)) {
key = magic_head[0] ^ GIF0;
suffix = L".gif";
} else if ((magic_head[0] ^ BMP0) == (magic_head[1] ^ BMP1)) {
key = magic_head[0] ^ BMP0;
suffix = L".bmp";
} else {
key = -1;
suffix = L".dat";
}
wstring save_img_path = save_path + L"\\" + file_name + suffix;
HANDLE save_img = CreateFileW(save_img_path.c_str(), GENERIC_ALL, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (save_img == INVALID_HANDLE_VALUE) {
return 0;
}
if (key > 0) {
for (unsigned int i = 0; i < bytes_read; i++) {
buffer[i]^=key;
}
}
if (!WriteFile(save_img, (LPCVOID)buffer, bytes_read, &bytes_write, 0)) {
CloseHandle(h_origin_file);
CloseHandle(save_img);
return 0;
}
do {
if (ReadFile(h_origin_file, buffer, BUFSIZE, &bytes_read, NULL)) {
if (key > 0) {
for (unsigned int i = 0; i < bytes_read; i++) {
buffer[i] ^= key;
}
}
if (!WriteFile(save_img, (LPCVOID)buffer, bytes_read, &bytes_write, 0)) {
CloseHandle(h_origin_file);
CloseHandle(save_img);
return 0;
}
}
} while (bytes_read == BUFSIZE);
CloseHandle(h_origin_file);
CloseHandle(save_img);
return 1;
}