从零开始学习破解(第一天)

最近闲来无事,饭也吃饱了。

ps:我一般就是记个随笔,不要当作教程来看,我会比较详细的记录研究过程以及遇到的问题,所以,可能中间有些东西会写错了,后面修改,也可能写错了我自己也不知道,欢迎指正。如果要动手,尽量看完再动手,默认所有人都有最基本的判断力。

准备搞搞研究研究破解相关的东西,首先声明,只做研究,不做坏坏的事情。

首先呢,了解到,破解和注入啥的有很大的相关性。

经过查资料,发现只要b把自己注入到其他进程中,就能做很多的事情。

那么下面,就尝试着写个dll,注入一下试试看。

vs新建工程,选择动态库,写上以下代码,没几行就不贴代码了。(图片点击可以放大)

从零开始学习破解(第一天)插图1

然后尝试一下,怎么注入呢,下载个工具试试效果。

工具直接搜索注入工具就有了。

试试注入到vs中看看效果。

从零开始学习破解(第一天)插图3
从零开始学习破解(第一天)插图5

从下面的提示图标可以看出来,这个提示框已经是vs进程的了,图标都变了。

但是这个工具感觉不好用,我dll修改东西的时候老是提示我,文件被占用,又无法卸载dll。

那个注出按钮一点就崩溃。

所以咱们自己写个注入工具吧。

经过百度和到处ctrl+c以及之前研究键盘hook

新建一个控制台程序,代码如下。

// mxInject.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。//includeincludeinclude"tlhelp32.h"includedefine DLLPath "DLL的存放位置"intInject(intpid){HANDLEhprocess=OpenProcess(PROCESS_ALL_ACCESS,false,pid);if(!hprocess){std::cout<<"can not get handle"<<std::endl;return1;}SIZE_TPathSize=(strlen(DLLPath)+1)*sizeof(TCHAR);LPVOIDStartAddress=VirtualAllocEx(hprocess,NULL,PathSize,MEM_COMMIT,PAGE_READWRITE);if(!StartAddress){std::cout<<"开辟内存失败"<<std::endl;return1;}if(!WriteProcessMemory(hprocess,StartAddress,DLLPath,PathSize,NULL)){std::cout<<"无法写入DLL路径"<<std::endl;return1;}PTHREAD_START_ROUTINEpfnStartAddress=(PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("kernel32.dll"),"LoadLibraryA");if(!pfnStartAddress){std::cout<<"无法获取函数地址"<<std::endl;return1;}HANDLEhThread=CreateRemoteThreadEx(hprocess,NULL,NULL,pfnStartAddress,StartAddress,NULL,NULL,NULL);if(!hThread){std::cout<<"创建线程失败"<<std::endl;return1;}//WaitForSingleObject(hThread, INFINITE);//等待DLL结束std::cout<<"注入成功!n";CloseHandle(hThread);CloseHandle(hprocess);return0;}BOOLEjectDll(DWORDdwPID,LPCTSTRszDllName){BOOLbMore=FALSE,bFound=FALSE;HANDLEhSnapshot,hProcess,hThread;HMODULEhModule=NULL;MODULEENTRY32me={sizeof(me)};LPTHREAD_START_ROUTINEpThreadProc;hSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,dwPID);bMore=Module32First(hSnapshot,&me);for(;bMore;bMore=Module32Next(hSnapshot,&me)){if(!_tcsicmp((LPCTSTR)me.szModule,szDllName)||!_tcsicmp((LPCTSTR)me.szExePath,szDllName)){bFound=TRUE;break;}}if(!bFound){CloseHandle(hSnapshot);returnFALSE;}if(!(hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwPID))){_tprintf("OpenProcess(%d) failed!!! [%d]n,",dwPID,GetLastError());returnFALSE;}hModule=GetModuleHandle("Kernel32.dll");pThreadProc=(LPTHREAD_START_ROUTINE)GetProcAddress(hModule,"FreeLibrary");hThread=CreateRemoteThread(hProcess,NULL,0,pThreadProc,me.modBaseAddr,0,NULL);WaitForSingleObject(hThread,INFINITE);CloseHandle(hThread);CloseHandle(hProcess);CloseHandle(hSnapshot);returnTRUE;}LRESULTCALLBACKCallBackProc_keyboard(intnCode,WPARAMwParam,LPARAMlParam){if(nCode!=HC_ACTION){returnCallNextHookEx(0,nCode,wParam,lParam);}if(wParam==WM_KEYDOWN||wParam==WM_KEYUP){PKBDLLHOOKSTRUCThookStruct=(PKBDLLHOOKSTRUCT)lParam;if(hookStruct->vkCode==VK_F3){if(wParam==WM_KEYDOWN){HWNDhwnd=GetForegroundWindow();DWORDdwPID,dwTid;dwTid=GetWindowThreadProcessId(hwnd,&dwPID);printf("开始注入%dn",dwPID);Inject(dwPID);printf("注入%d结束n",dwPID);}return1;}if(hookStruct->vkCode==VK_F4){if(wParam==WM_KEYDOWN){HWNDhwnd=GetForegroundWindow();DWORDdwPID,dwTid;dwTid=GetWindowThreadProcessId(hwnd,&dwPID);printf("开始卸载dll%dn",dwPID);EjectDll(dwPID,"remotecall.dll");printf("dll卸载%d结束n",dwPID);}return1;}}returnCallNextHookEx(0,nCode,wParam,lParam);}intmain(){SetWindowsHookEx(WH_KEYBOARD_LL,CallBackProc_keyboard,GetModuleHandle(nullptr),0);MSGmsg;while(GetMessage(&msg,NULL,0,0)){TranslateMessage(&msg);DispatchMessage(&msg);}return0;}

F3注入 F4卸载。测试一下。

从零开始学习破解(第一天)插图7
从零开始学习破解(第一天)插图9

完全没有问题。

既然已经可以打入敌人内部了,那么应该可以修改点内存啥的,就是怎么找内存呢。

从网上找资料,发现可以根据偏移来查找。

为了测试方便,咱们写个程序用来破解吧。

vs新建MFC工程,基于对话框,拖个控件。

从零开始学习破解(第一天)插图11

写个onok

从零开始学习破解(第一天)插图13
voidCloginDlg::OnBnClickedOk(){CStringstr;GetDlgItemText(IDC_EDIT1,str);if(str!=_T("123")){MessageBox("密码错误");return;}// TODO: 在此添加控件通知处理程序代码CDialogEx::OnOK();}

运行效果如下

从零开始学习破解(第一天)插图15

然后试试能不能破解。

下载个ce工具,这个全名叫Cheat Engine 直接百度就可以了。

从零开始学习破解(第一天)插图17

扫描一下,发现不是绿色的,人家说绿色的才行。

而且这个好像也不准。

忽然发现代码中用的是字符串,这里用的是数值,修改成字符串再试试,

从零开始学习破解(第一天)插图19

搜索出来两个,确认框点掉,发现就剩下一个了。

从零开始学习破解(第一天)插图21

说明第二个就是咱们申请的临时变量。CString str;

第一个应该是控件中保存数据的变量,测试一下。

从零开始学习破解(第一天)插图23

修改输入框内容,发现这个就跟着变化,这么就说明,这个变量是控件的变量,用来保存控件数据的,不过这好像也没啥用啊。

需要有固定偏移,咱们用的都是动态申请的,所以搞个全局变量应该就好了,试试看。

增加全局变量int m_nCount;

并修改代码,记录密码错误的次数。

从零开始学习破解(第一天)插图25

点击几次确定,然后搜索(别忘记了,修改成4字节的,因为这次咱们用的是int)

从零开始学习破解(第一天)插图27

太多了,再点两下试试看。

从零开始学习破解(第一天)插图29

这次就只剩下1个了,并且是绿色的

从零开始学习破解(第一天)插图31

再点击两下,发现确实变化了。

从零开始学习破解(第一天)插图33

那么记录下这个地址

login.exe+0xBB3B58

下面去修改dll代码

intOnInit(){MessageBox(0,"成功潜入敌人内部!","报告主人",NULL);HANDLEhand=GetModuleHandle("login.exe");if(!hand){MessageBox(0,"查找主句柄失败!","报告主人",NULL);return0;}intnoffset=0XBB3B58;int*pCount=(int*)((DWORD)hand+noffset);*pCount=15;return0;}

然后再F3注入试试看。

可以看到这个值变成15了。

从零开始学习破解(第一天)插图35

点击确定,也提示的16次

从零开始学习破解(第一天)插图37

到这里第一步算是完成了,我们实现了进入敌人内部,并修改敌人的内存数据。

参考链接:残阳血:C++ DLL注入微信实现自动接收、发送消息

原创文章 从零开始学习破解(第一天),版权所有
如若转载,请注明出处:https://www.itxiaozhan.cn/20221156.html

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注