好久没写代码了,花了几个小时写了这个程序。因为易游强制推送广告方面更新了,朋友找我更新一下之前那个程序。这次易游生成的路径规则改变了,负责广告推送的DLL没变,只是随机路径,随机文件夹,随机文件名。虽然有个文件夹文件名最后有tmp三个字母是确定,但是为了防止它再次更新文件生成的方式,导致程序失效,这次利用了杀毒软件的特征码查杀机制,去定位该文件。这样即使以后易游再次改变路径规则也一样能找到。这方式有个缺点就是若日后易游出现大幅度更新该DLL(修改浏览器主页的DLL)就会导致特征码不匹配。现在这个程序是应急的,下次若是有时间,就改成把特征码外置到配置文件中,在配置文件中可以修改扫描路径、修改特征码等关键参数,这样即使易更新了DLL,那就只需要重新提取特征码(几分钟的事)就能让程序根据新的特征码锁定新的文件,至于锁定机制还是和以前一样,采用独占方式打开文件的方法来锁定该文件,让其无法被加载。
这和杀毒软件与病毒变种之间的对抗很像啊。。。好怀念和小凡以前与杀毒软件对抗的日子,哈哈。。。
个人最讨厌强制推送广告了,给出完整的源码,以供日后复习,这次写的代码不是很满意,还有很多地方可以提升性能,初步估计,预计至少速度上能提升50%,其实现在不慢了,不过明天要上班了,朋友又急用,就暂时这样吧。
// KEyoo.cpp : Defines the entry point for the console application.
//
//
/************************************************************************/
/* 设计者:【L、】QQ:1007566569 */
/************************************************************************/
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
// 特征码地址
int TZM_Addr[9] = {0x00014C49,
0x00014D65,
0x00014EB2,
0x0001511E,
0x000151CA,
0x000153DA,
0x000155F5,
0x000157F8,
0x00016E10};
// 特征码 考虑到网吧文件的多样性,这里取9处特征码 均取该DLL 相关HOOK代码
unsigned char TZM_Code_0[] = {0x68, 0x44, 0xE3, 0x03, 0x10, 0xE8, 0xBD, 0x21, 0x00, 0x00};
unsigned char TZM_Code_1[] = {0x68, 0x68, 0xE3, 0x03, 0x10, 0xE8, 0xA1, 0x20, 0x00, 0x00};
unsigned char TZM_Code_2[] = {0x51, 0x68, 0x84, 0xE3, 0x03, 0x10, 0xE8, 0x53, 0x1F, 0x00};
unsigned char TZM_Code_3[] = {0x68, 0x98, 0xE3, 0x03, 0x10, 0xE8, 0xE8, 0x1C, 0x00, 0x00};
unsigned char TZM_Code_4[] = {0x68, 0xAC, 0xE3, 0x03, 0x10, 0xE8, 0x3C, 0x1C, 0x00, 0x00};
unsigned char TZM_Code_5[] = {0x68, 0xF8, 0xE3, 0x03, 0x10, 0xE8, 0x2C, 0x1A, 0x00, 0x00};
unsigned char TZM_Code_6[] = {0x68, 0xC4, 0xE3, 0x03, 0x10, 0xE8, 0x11, 0x18, 0x00, 0x00};
unsigned char TZM_Code_7[] = {0x68, 0x4C, 0xE4, 0x03, 0x10, 0xE8, 0x0E, 0x16, 0x00, 0x00};
unsigned char TZM_Code_8[] = {0x55, 0x8B, 0xEC, 0xB8, 0x01, 0x00, 0x00, 0x00, 0x5D, 0xC3};
// 指针,将所有特征码关联在一起 方便比对
unsigned char *TZM_Code[9];
// 锁定文件
BOOL OccupyFile( LPCTSTR lpFileName );
// 锁定文件数累加 这里只是用来判断是否找到文件
BOOL KillFileCout = 0;
// 遍历文件
int viewfiles(char *directory);
// 特征码匹配
DWORD WINAPI ScanKill_ttsB( LPVOID lpParam )
{
char *File = new char[MAX_PATH];
strcpy(File, (char*)lpParam);// 尽早取出参数
char Code[10] = {0};
FILE *fhand = fopen(File, "rb");
if (fhand == NULL)// 如果无法打开文件则退出
return 1;
// 特征码一一匹配
for (int i=0; i<9; i++)
{
fseek(fhand, (long)TZM_Addr[i], SEEK_SET);// 移动文件指针到指定位置
fread(Code, 1, 10, fhand);// 取10字节
// 比较
if (memcmp(TZM_Code[i], Code, 10) == 0)
continue;
else
break;// 如果不同则跳出
}
fclose(fhand);
if (i==9)// 如果已经完成了9次比对 说明该文件就是自己要寻找文件。
{
OccupyFile(File);// 将文件锁定
KillFileCout++;// 累计
}
delete []File;
return 1;
}
// 权限提升
void RaiseToDebugP()
{
HANDLE hToken;
HANDLE hProcess = GetCurrentProcess();
if ( OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken) )
{
TOKEN_PRIVILEGES tkp;
if ( LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tkp.Privileges[0].Luid) )
{
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
BOOL bREt = AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, NULL, 0) ;
}
CloseHandle(hToken);
}
}
// 这个函数是为了把文件句柄复制到 System 进程 这样本程序即使退出 被锁定的文件也不会失效
BOOL OccupyFile( LPCTSTR lpFileName )
{
BOOL bRet;
RaiseToDebugP();
// 打开System进程
HANDLE hProcess = OpenProcess( PROCESS_DUP_HANDLE, FALSE, 4); // 4为system进程号
if ( hProcess == NULL )
{
hProcess = OpenProcess( PROCESS_DUP_HANDLE, FALSE, 8);
if ( hProcess == NULL )
return FALSE;
}
HANDLE hFile;
HANDLE hTargetHandle;
// 独占方式打开文件 网上的不是打开
hFile =CreateFile(lpFileName,GENERIC_READ,0,NULL,OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS,0);
if ( hFile == INVALID_HANDLE_VALUE )
{
CloseHandle( hProcess );
return FALSE;
}
// 禁止内核关闭该句柄 一般情况下如果在内核关闭该句柄会蓝屏
SetHandleInformation(hFile,HANDLE_FLAG_PROTECT_FROM_CLOSE,HANDLE_FLAG_PROTECT_FROM_CLOSE);
// 这步是关键 从当前进程复制文件句柄到System进程空间 这样本程序即使退出 但是句柄在System进程内仍有效
bRet = DuplicateHandle( GetCurrentProcess(), hFile, hProcess, &hTargetHandle,
0, FALSE, DUPLICATE_SAME_ACCESS|DUPLICATE_CLOSE_SOURCE);
CloseHandle( hProcess );
return bRet;
}
// 遍历指定文件夹
int viewfiles(char *directory)
{
WIN32_FIND_DATA fdFindData;
HANDLE hFind, hFile;
char *filename;
int count=0;
BOOL done;
DWORD FileSize ;
filename=new char[strlen(directory)+5];
strcpy(filename,directory);
strcat(filename,"\\*.*");
hFind=FindFirstFile(filename,&fdFindData);
delete[] filename;
done=hFind!=INVALID_HANDLE_VALUE;
while(done)
{
if(strcmp(fdFindData.cFileName,".") && strcmp(fdFindData.cFileName,".."))
{
filename=new char[strlen(directory)+strlen(fdFindData.cFileName)+2];
strcpy(filename,directory);
strcat(filename,"\\");
strcat(filename,fdFindData.cFileName);
if((fdFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY )
{
viewfiles(filename);// 如果是文件夹则递归遍历
}
else if (strstr(filename, ".dll"))// 第一次过滤 简单从文件中判断是否为DLL
{
hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL,OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
FileSize = GetFileSize(hFile, NULL);
CloseHandle(hFile);
if (FileSize > 340000 && FileSize < 350000)// 第二次过滤 只要指定文件大小范围的DLL文件
{
CreateThread(NULL, NULL, ScanKill_ttsB, (LPVOID)filename, NULL, NULL);
Sleep(10); // 保证线程参数传递完毕 其实应该采用互斥量的形式,这样能提升性能和稳定性
}
}
delete[] filename;
}
done=FindNextFile(hFind,&fdFindData);
}
FindClose(hFind);
return(count);
}
void Scan()
{
while(1)
{
viewfiles("C:");// 扫描C盘
Sleep(1000);
if (KillFileCout)// 如果已经锁定了文件则退出
exit(1);
}
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// 运行时 去除鼠标指针漏斗
GetInputState();
PostThreadMessage(GetCurrentThreadId(), NULL, NULL, NULL);
MSG msg;
GetMessage(&msg, NULL, NULL, NULL);
printf("用于解决易游锁定IE广告主页 2013.9.21 更新 【L、】1007566569\n");
// 将所有特征码关联
TZM_Code[0] = TZM_Code_0;
TZM_Code[1] = TZM_Code_1;
TZM_Code[2] = TZM_Code_2;
TZM_Code[3] = TZM_Code_3;
TZM_Code[4] = TZM_Code_4;
TZM_Code[5] = TZM_Code_5;
TZM_Code[6] = TZM_Code_6;
TZM_Code[7] = TZM_Code_7;
TZM_Code[8] = TZM_Code_8;
// 以线程的形式去扫描
CreateThread(NULL, NULL,(LPTHREAD_START_ROUTINE)Scan, NULL, NULL, NULL);
Sleep(120000); // 如果 两分钟后还没有找到文件 那么就退出
return 0;
}
|