动态修改窗口标题和类名

 

 反外挂会检测外挂标题和类名,所以我们要实现每次启动外挂都会修改标题和类名。具体方法如下还有自己写的API hook代码以供后来人参考


修改窗口标题字符串“无标题-Test”

   <1> 修改前半部分

  方法一:更改StringTable的IDR_MAINFRME的标题,将第一个\n之和第二个\n之间添加字符串fan为:
Test\nfan\nTest\n\n\nTest.Document\nTest.Document

  方法二:在 CEX041Doc::OnNewDocument()中添加SetTitle("我的程序");

BOOL CTestDoc::OnNewDocument()

{

    if (!CDocument::OnNewDocument())

        return FALSE;

    // TODO: 在此添加重新初始化代码

    SetTitle(L"fan");

    // (SDI 文档将重用该文档)

    return TRUE;

}

  方法三:重载虚函数SetTitle
void CTestDoc::SetTitle(LPCTSTR lpszTitle)

{

    // TODO: 在此添加专用代码和/或调用基类

    CDocument::SetTitle(L"fan");

}

运行结果如下:

 

   <2>修改后半部分

修改StringTable的IDR_MAINFRME的标题,将第一个\n之前的字符串Test替换为XJTU:XJTU\nfan\nEX041\n\n\nEX041.Document\nEX041.Document

运行结果如下:

 


 <3>去掉标题中间的“-”

方法一:可以通过利用CWnd::SetWindowText即:void SetWindowText( LPCTSTR lpszString );在C EX041App::InitInstance()中调用如下语句m_pMainWnd->SetWindowText(L"XJTU");或在其他地方用(AfxGetMainWnd())->SetWindowText(L"XJTU");也可以得到相同的结果。

  方法二:重载CFramWnd类的OnUpdateFrameTitle函数,这个函数在VC提供的帮助文件中找不到,利用类向导重写virtual void OnUpdateFrameTitle(BOOLbAddToTitle)

void CMainFrame::OnUpdateFrameTitle(BOOL bAddToTitle)

 

 

 

 

 

 

 

 

修改类名要的至少单文档的程序


BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
 if( !CFrameWnd::PreCreateWindow(cs) )
  return FALSE;
 // TODO: 在此处通过修改
 //  CREATESTRUCT cs 来修改窗口类或样式

 //cs.style = WS_OVERLAPPED | WS_CAPTION | FWS_ADDTOTITLE
 //  | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;

 
  WNDCLASS wndclass;  
 ::GetClassInfo(AfxGetInstanceHandle(),cs.lpszClass,&wndclass);  
 wndclass.lpszClassName=L"New566";  
 VERIFY(AfxRegisterClass(&wndclass));  
 cs.lpszClass=wndclass.lpszClassName;  
 m_strTitle = L"妈蛋";

 return TRUE;
}

 


 

 

我尝试API HOOK掉原先的RegisterClassW,在这个api里面写入五个字节jmp 自己函数的偏移地址  完后自己函数实现吧参数wndclass的最后一个类名改成自己的类名,这样在恢复原来的API内的前五个字节,调用这个api(此时参数是自己设计的类名)返回的结果存到变量里,完后在hook原来的api 以便下次用,最后返回那个变量

但是该死的mfc 基于对话框项目  貌似里面 要不 修改rc资源文件添加类名,要不 就是在对话框属性里修改类名  这样就是内定的了  你这边一hook  虽然成功,但是马上就报内存错误,说明对话框的类名"#32770"是已经注册好的,你再怎么hook  也不会跳转到你自己的api。在资源文件中添加的CLASS 类名虽然运行能跳转到 你自己的API,但是对话框的本身资源文件已经是固定类名,你如果在你自己的API里面动态修改成自己的类名,就会内存访问冲突,经过多天调试只能基于文档的才能动态修改类名,但是这几天我也学会了API hook和一些内存读写时候注意细节,大家可以看看互相学习,谁会动态修改类名,是基于对话框的项目的,可以发站内邮件给我或者email:liveforrevenge@qq.com。下面是app里面代码和dll代码,因为要hook  api的话必须自己的api也是全局的,不知道类成员函数可行否,反正自己尝试一堆错误,所以鉴于此只能用dll了,在里面写全局不会报错。下面的程序运行的时候,你们的项目属性里是unicode还是宽字节,是unicode就修改registerclassw否则就是registerclassA;下面dll的starthook是鸡肋,只是为了注入所有电脑里进程才会用到。这里只是修改自己程序的,所以直接loadlibrary就行了。程序一开始会健康运行,跳到我自己的API,完后我修改参数结构里的类名,最后在调用原来的API处理注册这个类名  最后返回结果,可是最后像上面说的  报内存访问冲突的错误,推断基于对话框的不能动态修改类名。

 

BOOL CCallAddApp::InitInstance()
{
	// 如果一个运行在 Windows XP 上的应用程序清单指定要
	// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
	//则需要 InitCommonControlsEx()。否则,将无法创建窗口。

	typedef BOOL (CALLBACK *inshook)(); //函数原型定义
	inshook insthook;

	 hinst=::LoadLibrary(_T("F:\\搜狗下载\\Add\\Debug\\Hook.dll"));//加载dll文件
	if(hinst==NULL)
	{
		AfxMessageBox(_T("no Hook.dll!"));
		return FALSE;
	}
	insthook=::GetProcAddress(hinst,"InstallHook");//获取函数地址
	if(insthook==NULL)
	{
		AfxMessageBox(_T("func not found!"));
		return FALSE;
	}
	insthook();

	WNDCLASS wc;
	// 获取窗口类信息。MFC默认的所有对话框的窗口类名为 #32770
	::GetClassInfo(AfxGetInstanceHandle(), _T("#32770"), &wc);
	// 改变窗口类名
	wc.lpszClassName = _T("666");
	// 注册新窗口类,使程序能使用它
	AfxRegisterClass(&wc);


	INITCOMMONCONTROLSEX InitCtrls;
	InitCtrls.dwSize = sizeof(InitCtrls);
	// 将它设置为包括所有要在应用程序中使用的
	// 公共控件类。
	InitCtrls.dwICC = ICC_WIN95_CLASSES;
	InitCommonControlsEx(&InitCtrls);

	CWinApp::InitInstance();

	AfxEnableControlContainer();

	// 标准初始化
	// 如果未使用这些功能并希望减小
	// 最终可执行文件的大小,则应移除下列
	// 不需要的特定初始化例程
	// 更改用于存储设置的注册表项
	// TODO: 应适当修改该字符串,
	// 例如修改为公司或组织名
	SetRegistryKey(_T("应用程序向导生成的本地应用程序"));

	CCallAddDlg dlg;
	m_pMainWnd = &dlg;
	INT_PTR nResponse = dlg.DoModal();
	if (nResponse == IDOK)
	{
		// TODO: 在此放置处理何时用
		//  “确定”来关闭对话框的代码
	}
	else if (nResponse == IDCANCEL)
	{
		// TODO: 在此放置处理何时用
		//  “取消”来关闭对话框的代码
	}

	// 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
	//  而不是启动应用程序的消息泵。
	return FALSE;
}


int CCallAddApp::ExitInstance()
{
	// TODO: 在此添加专用代码和/或调用基类

	if (hinst!=NULL)
	{
		
	
		typedef BOOL (CALLBACK *UnhookProc)(); //函数原型定义
		UnhookProc UninstallHook;

		UninstallHook=::GetProcAddress(hinst,"UninstallHook");//获取函数地址
		if(UninstallHook!=NULL) 
		{
			UninstallHook();
		}
		if (hinst!=NULL)
		{
			::FreeLibrary(hinst);
		}
		}
	return CWinApp::ExitInstance();
}


 

// Hook.cpp : 定义 DLL 的初始化例程。
//

#include "stdafx.h"
#include "Hook.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


//变量定义
//不同Instance共享的该变量
#pragma data_seg("SHARED")
static HHOOK  hhk=NULL; //鼠标钩子句柄
static HINSTANCE hinst=NULL; //本dll的实例句柄 (hook.dll)
#pragma data_seg()
#pragma comment(linker, "/section:SHARED,rws")
//以上的变量共享哦!

CString temp; //用于显示错误的临时变量
bool bHook=false; //是否Hook了函数
bool m_bInjected=false; //是否对API进行了Hook
BYTE OldCode[5]; //老的系统API入口代码
BYTE NewCode[5]; //要跳转的API代码 (jmp xxxx)
HANDLE hProcess=NULL; //所处进程的句柄
FARPROC pdadd1;  //指向user32.dll中的registerclassw函数的远指针
DWORD dwPid;  //所处进程ID
//end of 变量定义


//开启钩子的函数
void HookOn() 
{ 
	ASSERT(hProcess!=NULL);

	DWORD dwTemp=0;
	DWORD dwOldProtect;

	//将内存保护模式改为可写,老模式保存入dwOldProtect
	VirtualProtectEx(hProcess,pdadd1,5,PAGE_READWRITE,&dwOldProtect); 
	//将所属进程中add()的前5个字节改为Jmp Myadd 
	WriteProcessMemory(hProcess,pdadd1,NewCode,5,0);
	//将内存保护模式改回为dwOldProtect
	VirtualProtectEx(hProcess,pdadd1,5,dwOldProtect,&dwTemp);

	bHook=true; 
}
//关闭钩子的函数
void HookOff()//将所属进程中add()的入口代码恢复
{ 
	ASSERT(hProcess!=NULL);

	DWORD dwTemp=0;
	DWORD dwOldProtect;

	VirtualProtectEx(hProcess,pdadd1,5,PAGE_READWRITE,&dwOldProtect); 
	WriteProcessMemory(hProcess,pdadd1,OldCode,5,0); 
	VirtualProtectEx(hProcess,pdadd1,5,dwOldProtect,&dwTemp); 
	bHook=false; 
}

ATOM WINAPI MyRegisterClass1(__in  CONST WNDCLASSW * lpWndClass);//函数声明

//好,最重要的HOOK函数:
void Inject()
{

	if (m_bInjected==false)
	{ //保证只调用1次
		m_bInjected=true;

		//获取add.dll中的add()函数
		//HMODULE hmod=::LoadLibrary(_T("F:\\搜狗下载\\Add\\Debug\\Add1.dll"));
		HMODULE hmod=::LoadLibrary(_T("user32.dll"));
		pdadd1=::GetProcAddress(hmod,"RegisterClassW");
		//pdadd1=(FARPROC)registerAddr;

		if (pdadd1==NULL)
		{
			AfxMessageBox(L"cannot locate add()");
		}

		// 将add()中的入口代码保存入OldCode[]
		_asm 
		{ 
			push edi
			push  esi
			lea edi,OldCode 
				mov esi,pdadd1 
				cld 
				movsd 
				movsb 
			pop esi
			pop  edi
		}

		NewCode[0]=0xe9;//实际上0xe9就相当于jmp指令
		//获取Myadd()的相对地址
		_asm 
		{ 
			push eax
			push  ebx
			lea eax,MyRegisterClass1
				mov ebx,pdadd1 
				sub eax,ebx 
				sub eax,5 
				mov dword ptr [NewCode+1],eax 
			pop  ebx
			pop  eax
		} 
		//填充完毕,现在NewCode[]里的指令相当于Jmp Myadd
		HookOn(); //可以开启钩子了
	}
}

VOID GetRandClassTitleName(TCHAR pch[])
{
	srand((unsigned)time(NULL));
	for( int i = 0; i < 10; ++i )
	{
		INT iChar = 66 + rand() % 50;
		pch[i] =(TCHAR) iChar;

	}
	pch[49] = 0;
}
ATOM WINAPI MyRegisterClass1(__in  CONST WNDCLASSW * lpWndClass)
{

	BYTE nameByte[50];
	LONG wndAddr = (LONG)lpWndClass;
	ATOM result;
	CString className;
	DWORD tempAddr = 0;
	TCHAR name[4];
	//DWORD dwOldProtect;

	DWORD dwTemp=0;
	DWORD dwOldProtect;

		
	 

	ReadProcessMemory(hProcess,(LPCVOID)(wndAddr+0x24),(LPVOID)&tempAddr,4,0);//一定要注意这里tempAddr是传入的这个tempAddr的地址,不是里面存的指针,就是说读写内存遇到这些参数就是要读取这个地址里面的内容,你传入的参数就是地址,如果
	ReadProcessMemory(hProcess,(LPCVOID)tempAddr,nameByte,50,0);
	className.Format(L"%s",nameByte);
	if(className.Left(6)==L"666")
	{
		name[0] = _T('5');
		name[1] = _T('5');
		name[2] = _T('5');
		name[3] = _T('\0');
		SIZE_T si = sizeof(name);
		LONG nameAddr = (LONG)name;
		VirtualProtectEx(hProcess,(LPVOID)(tempAddr),4,PAGE_EXECUTE_READWRITE,&dwOldProtect);
		WriteProcessMemory(hProcess,(LPVOID)(tempAddr),(LPCVOID)name,8,&si);//这里要把类名字符串的数组地址覆盖掉原先的地址,可以传入&nameAddr,另外注意tchar一个是两字节,所以四个是八字结,传入8就对了,不然就出错,每次读写内存时候最好加上修改权限的API 
		VirtualProtectEx(hProcess,(LPVOID)(tempAddr),4,dwOldProtect,&dwTemp);

			}
	     
	HookOff();
	result =::RegisterClassW(lpWndClass);
	HookOn();
	return result;
}

// CHookApp

BEGIN_MESSAGE_MAP(CHookApp, CWinApp)
END_MESSAGE_MAP()


// CHookApp 构造

CHookApp::CHookApp()
{
	// TODO: 在此处添加构造代码,
	// 将所有重要的初始化放置在 InitInstance 中
}


// 唯一的一个 CHookApp 对象

CHookApp theApp;


//在dll实例化中获得一些参数
BOOL CHookApp::InitInstance()
{
	CWinApp::InitInstance();

	//获得dll 实例,进程句柄
	hinst=::AfxGetInstanceHandle();
	DWORD dwPid=::GetCurrentProcessId();
	hProcess=OpenProcess(PROCESS_ALL_ACCESS,0,dwPid); 
	//调用注射函数
	Inject();
	return TRUE;
}

//鼠标钩子过程,什么也不做,目录是注入dll到程序中
LRESULT CALLBACK MouseProc(int nCode,WPARAM wParam,LPARAM lParam)
{
	return CallNextHookEx(hhk,nCode,wParam,lParam);
}

//鼠标钩子安装函数:
BOOL InstallHook()
{

	hhk=::SetWindowsHookEx(WH_MOUSE,MouseProc,hinst,0);

    return true;
}

//卸载鼠标钩子函数
void UninstallHook()
{
	if (hhk!=NULL)
	{
		::UnhookWindowsHookEx(hhk);
	}
	HookOff();//记得恢复原函数入口
}

//dll退出时
int CHookApp::ExitInstance()
{
	HookOff();//记得恢复原函数入口
	return CWinApp::ExitInstance();
}


 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值