FindQQByProcess
看网上有许多通过进程寻找QQ号的例子,看了一下,里面涉及的知识点还是比较多,但网上的兼容性不太好,而且没有给出匹配字符的来源,所以自己动手写了一下,顺便给出一些我调试的结果。
#include "stdafx.h"
#include <windows.h>
#include <TlHelp32.h> DWORD FindByPID(WCHAR* ProcessName);
int ReadMemory(DWORD PID);
int SearchStr(char* MemoryString, int StrLength, char* Special); int main()
{ WCHAR MyQQ[] = L"QQ.exe";
DWORD QQID = FindByPID(MyQQ);
return 0;
} DWORD FindByPID(WCHAR* ProcessName)
{
DWORD ProcessID = 0;
HANDLE ProcessSnapHANDLE;
PROCESSENTRY32 pe32; ProcessSnapHANDLE = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (ProcessSnapHANDLE == INVALID_HANDLE_VALUE)
{
return 0;
}
pe32.dwSize = sizeof(PROCESSENTRY32);
if (!Process32First(ProcessSnapHANDLE, &pe32))
{
CloseHandle(ProcessSnapHANDLE);
return 0;
}
do
{
//找到QQ进程
if (wcscmp(ProcessName, pe32.szExeFile) == 0)
{
ProcessID = pe32.th32ProcessID;
printf("ProcessID = %d \r\n", ProcessID);
//开始内存搜索
ReadMemory(ProcessID); }
}while (Process32Next(ProcessSnapHANDLE, &pe32));//继续找下一个进程
CloseHandle(ProcessSnapHANDLE);
return ProcessID;
} int ReadMemory(DWORD PID)
{
//要搜索的特征码
char Special[] = "User uin=";
//特征码出现的位置
int Pos = 0;
HANDLE ProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, 0, PID);
if (ProcessHandle == NULL)
{
return 0;
}
SYSTEM_INFO si;
GetSystemInfo(&si); MEMORY_BASIC_INFORMATION mbi;
DWORD Address = (DWORD)si.lpMinimumApplicationAddress; //可申请的最小值
while (Address < (DWORD)si.lpMaximumApplicationAddress)
{
if (VirtualQueryEx(ProcessHandle, (LPVOID)Address, &mbi, sizeof(mbi)) != sizeof(mbi))
{
return 0;
} if ((mbi.State == MEM_COMMIT) && (mbi.Protect == PAGE_READWRITE)) //限制条件,缩小范围
{
DWORD BaseAddress = Address;
int ReadSize = mbi.RegionSize; if (ReadSize >= 1024)
{
DWORD Bytes = 0;
char* MemBuffer = (char *)malloc(ReadSize * sizeof(char)); if (ReadProcessMemory(ProcessHandle, (LPCVOID)BaseAddress, MemBuffer, ReadSize, &Bytes))
{
//开始搜索特征码
Pos = SearchStr(MemBuffer, Bytes, Special);
if (Pos)
{
printf("Address: 0x%08X\n", BaseAddress + Pos * sizeof(char));
//指向QQ号码的第一个字符
char *ptsQQ = &MemBuffer[Pos + strlen(Special)];
printf("QQ: ");
//利用指针来打印出当前QQ进程的QQ号码,
//QQ号码之后的字符是'"'
for (*ptsQQ++; *ptsQQ != '"'; *ptsQQ++)
{
//注意这里是循环打印出QQ号码的每个字符,而不是整个字符串
printf("%c", *ptsQQ);
}
printf("\r\n");
//找到1个就OK了,去除break可继续找
break;
}
}
free(MemBuffer);
}
}
//从下一块内存块继续找
Address = (DWORD)mbi.BaseAddress + mbi.RegionSize;
}
return Pos;
} int SearchStr(char* MemoryString, int StrLength, char* Special)
{
int i = 0;
int SpecialLength = strlen(Special); while ((i + SpecialLength) <= StrLength)
{
int n = 0;
//先匹配两个字串的第一个字符
if (Special[0] == MemoryString[i])
{
//若相等,则开始逐字符匹配
for (int j = 0; j < SpecialLength; j++)
{
//相同位置字符匹配
if (Special[j] == MemoryString[i + j])
{
//若相同位置字符匹配成功,则计数器加1
n++;
}
else //相同位置字符匹配失败
{
//源字符串位置跳过匹配相同的n个字符
i = i + n;
//跳出当前匹配循环,开始新位置的匹配
break;
}
}
//若匹配成功,计数和目标字符串长度相等,则找到目标
if (SpecialLength == n)
{
//i为找到的目标字符串在源字符串中的起点位置, return i;
}
}
else //若两字符串的第一个字符不同
{
//开始反向找源字符串相对目标字符串的后一个字符是否在目标字符串内
for (int j = SpecialLength - 1; j >= 0; j--)
{
//找到存在紧跟其后的那个字符
if (Special[j] == MemoryString[i + SpecialLength])
{
//该字符出现在目标字符串中的位置
n = j;
//只需知道排在倒数第一那个位置,跳出循环开始移动位置
break;
}
}
i = i + SpecialLength - n;
}
}
return 0;
}
代码虽然比较简单,但是其中还是有一些需要注意的地方。
首先,为了方便从内存中粘出来内存数据,我都是用ASCII的单字符,而不是宽字符,因为宽字符的内存中会在每个字节后加上一个 00 ,看到的就是一个黑点。但是在进程查找匹配过程中,发现怎么也匹配不到 "QQ.exe",好像strcmp中用了强制类型转换就不行了,无奈只好把这个地方换成宽字节,但对于最后的结果没有影响。
还有就是由于操作系统不同,特征码"index?uin="我在运行时没有找到,我就换了一种思路,将我QQ号的前5位作为特征码来匹配,此时要注意代码中的结束字符,可能是&或者",自己多尝试一下。
我就找到了第一个符合条件的
/*
"1.0" encoding="utf-8"?>.<NewsFeed>.???<User uin="2294
800094"><minifeed appid="1" apptitle="title" showarea=
*/
可以看出我们要匹配的字符是 User uin=" ,但是两个双引号连在一起就视为空,又不会处理了,也没法用单引号代替,只能少一个引号,而在for循环的时候,用
*ptsQQ++ 来跳过第一个字符。
下面是我找到的第二个:
/*
...........down?..€.)'PE?'P).*[???wp??w?8?v?].w?].w_ER
ROR_CODE_OK, status-code=200, url=http://s.url.cn/qqwe
b/qunactivity/img/icon_qq_2014.png.1546250318/15462503
18-3167137263-CEE4381B4D81CC2812670D031D808E69/0?vuin=
2294800094&term=1&srvver=26650&rf=naio.i.p.....???L???
L???L???L???L???L???L?R?L?M?L?s?L?n?L?.?L?.?L?.?L?:?L?
*/
可以看出 uin= 在两个里面都出现了,应该是兼容性较好的一个特征码了,如果使用 uin= ,那么刚刚for循环一定改成这样:
for (; *ptsQQ != '&'; *ptsQQ++)
就可以找到QQ号码了。
FindQQByProcess的更多相关文章
随机推荐
- C/S结构 B/S结构
[1]C/S 结构,即大家熟知的客户机和服务器结构.它是软件系统体系结构,通过它可以充分利用两端硬件环境的优势,将任务合理分配到Client端和Server端来实现,降低了系统的通讯开销.目前大多数应 ...
- [OS] 多线程--第一次亲密接触CreateThread与_beginthreadex本质区别
转自:http://blog.csdn.net/morewindows/article/details/7421759 本文将带领你与多线程作第一次亲密接触,并深入分析CreateThread与_be ...
- java从远程服务器获取PDF文件并后台打印(使用pdfFox)
一.java原生方式打印PDF文件 正反面都打印,还未研究出只打印单面的方法,待解决 public static void printFile(String path) throws Exceptio ...
- hdu 1281 棋盘游戏 (二分匹配)
棋盘游戏 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- P4035 [JSOI2008]球形空间产生器
题目描述 有一个球形空间产生器能够在 nn 维空间中产生一个坚硬的球体.现在,你被困在了这个 nn 维球体中,你只知道球面上 n+1n+1 个点的坐标,你需要以最快的速度确定这个 nn 维球体的球心坐 ...
- POJ3678:Katu Puzzle——题解
http://poj.org/problem?id=3678 总觉得这题比例题简单. 设a为x取0的点,a+n为x取1的点. 我们还是定义a到b表示取a必须取b. 那么我们有: 当AND: 1.当c= ...
- HDOJ.2072 单词数(map)
单词数 点我挑战题目 点我一起学习STL-MAP 题意分析 给出一行单词,判断这行有不同种的单词多少个,用map可以轻松解决. 代码总览 /* Title:HDOJ.2072 Author:pengw ...
- warning: React does not recognize the xxx prop on a DOM element
这是React不能识别dom元素上的非标准attribute报出的警告,最终的渲染结果中React会移除这些非标准的attribute. 通常{...this.props}和cloneElement( ...
- PowerDesigner 技巧【1】
Name与Code同步的问题: PowerDesigner中,修改了某个字段的name,其code也跟着修改,这个问题很讨厌,因为一般来说,name是中文的,code是字段名. 解决方法如下: 1.选 ...
- mybatis逆向工程生成mapper报错
Result Maps collection already contains value for xxxMapper.BaseResultMap错误解决办法一.问题描述今天在做项目时,遇到一个错误: ...