看网上有许多通过进程寻找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的更多相关文章

随机推荐

  1. [剑指Offer] 44.翻转单词顺序列

    题目描述 牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上.同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思.例如,“student ...

  2. MyBatis原理系列

    原理分析之一:从JDBC到Mybatis 原理分析之二:框架整体设计 原理分析之三:初始化(配置文件读取和解析) 原理分析之四:一次SQL查询的源码分析

  3. 异步执行任务SimpleAsyncTaskExecutor详解

    SimpleAsyncTaskExecutor 异步执行用户任务的SimpleAsyncTaskExecutor.每次执行客户提交给它的任务时,它会启动新的线程,并允许开发者控制并发线程的上限(con ...

  4. Python文件传输模块ftplib

    ftplib是基于FTP协议实现的一个Python模块 from ftplib import FTP # 创建一个FTP连接对象 ftp = FTP() #[ 当带有参数时,即:ftp = FTP(h ...

  5. dashboard and reporting Interface analysis

    dashboard and reporting Interface analysis > show system show system backup show system counters ...

  6. [CQOI2014]数三角形 组合数 + 容斥 + gcd

    推导过程 : 组合数+容斥原理+gcd 正确做法是暴力的一种优化,ans=所有情况 - 平行坐标轴的三点共线 - 斜线三点共线 如果快速求斜线三点共线: 首先要知道一个结论,对于点(a,b) (x,y ...

  7. Android中WebView的跨域漏洞分析和应用被克隆问题情景还原(免Root获取应用沙盒数据)

    一.前言 去年年底支付宝的被克隆漏洞被爆出,无独有偶就是腾讯干的,其实真正了解这个事件之后会发现,感觉是针对支付宝.因为这个漏洞找出肯定花费了很大劲,主要是因为支付宝的特殊业务需要开启了WebView ...

  8. [bzoj] 1040 骑士 || 基环外向树dp

    原题 给出n个点n条边和每个点的点权,一条边的两个断点不能同时选择,问最大可以选多少. //图是一张基环外向树森林 是不是很像舞会啊- 就是多了一条边. 所以我们考虑一下对于一棵基环外向树,拆掉一条在 ...

  9. 我的ACM参赛故事

    从我接触程序竞赛到现在应该有十多年了,单说ACM竞赛,从第一次非正式参赛到现在也差不多有7年多的样子.有太多的故事,想说的话,却一直没能有机会写下来.一方面是自己忙,一方面也是自己懒.所以很感谢能有人 ...

  10. 一些实用的JQuery代码片段收集

    本文将展示50个非常实用的JQuery代码片段,这些代码能够给你的JavaScript项目提供帮助.其中的一些代码段是从jQuery1.4.2才开始支持的做法,另一些则是真正有用的函数或方法,他们能够 ...