Windows编程学习笔记(一)(Windows黑客编程技术详解第2、3章)

基础技术
1.运行单一实例:防止病毒木马多次运行,增加暴露风险。
原理:利用CreatMutex()函数创建一个实例,若创建成功,切GetLastError()获取的返回码为ERROR_ALREADY_EXISTS,则表明该命名的互斥对象已存在,程序重复运行,否则,则是首次运行。
2.DLL延迟加载:先执行程序,到调用DLL之前,将嵌入在程序中的DLL文件释放出来,从而程序可以继续执行。通过这种方式,程序编写者只需发送给用户一个可执行文件(exe),减少DLL丢失的风险。
原理:在VS开发环境中进行设置。
3.资源释放:使程序变得简洁,例如只有一个可执行文件(exe)。
原理:(1)获取资源FindResource()(2)确定资源大小SizeofResource()(3)将资源加载到内存LoadResource()(4)锁定资源(获取起始地址)LockResource()(5)将资源保存为文件(释放)
注入技术
目的:为了方便修改目标进程空间的数据;为了戴上目标进程的“面具”进行伪装。
方式和原理:
1.全局钩子注入:SetWindowsHookEx()。在DLL项目中设置全局钩子,监控系统进程间的通讯,一旦进程有消息发送到消息队列中,DLL就会自动加载进该进程。由于进程的地址空间是相互独立的,发生对应事件的进程无法调用其他进程的钩子函数,因此全局钩子要设立在DLL中。回调函数的参数和返回值固定。
2.远线程注入:OpenProcess()、VirtualAllocEx()、WriteProcessMemory()、CreateRemoteThread()。通过调用CreateRemoteThread()函数,该函数在另一个进程的虚拟地址空间中创建运行的线程。两个重要参数,一个是LoadLibrary(),一个是DLL路径字符串。借助LoadLibrary()加载DLL。
3.突破Session0的远线程注入:远线程注入的CreateRemoteThread()函数在Session0层无法创建线程,因此采用更为底层的ZwCreateThreadEx()函数创建线程,该函数需要自行在代码中声明,且64位与32位系统下函数声明并不一致。特别的,对于高权限进程,需要对程序进行提权,OpenProcess()才会成功(直到最后我也没成功我也很绝望)。
4.APC(Asynchronous Procedure Call,异步过程调用)注入:每个线程都会维护一个APC队列,队列中的APC函数只有在线程处于可警告的状态时才会执行,其调用顺序为先进先出。为了确保能够执行插入的APC,应当向进程中的所有线程插入APC函数,当其中一个线程的函数被唤醒,DLL就会被注入。
编程中的问题和bug
1.LRESULT:一种数据类型,long result,表示返回的长整型数据结果
2.lParam 和 wParam 是宏定义,一般在消息函数中带这两个类型的参数,通常用来存储窗口消息的参数。
wParam 通常用来存储小段信息,如标志, lParam 通常用于存储消息所需的对象
3.HINSTANCE 是“句柄型”数据类型。相当于装入到了内存的资源的ID。HINSTANCE对应的资源是instance.句柄实际上是一个 无符号长整数。但它是“句柄型”,所以你不能把它当成真的无符号长整数,拿来派别的用处,例如,不能拿来做四则运算。HINSTANCE常出现在 API 程序
4.GetModuleHandle():获取已经载入进程空间的模块句柄。参数:
LPCTSTR lpModuleName为需要获取句柄的模块名。(.dll或.exe文件),若无后缀,默认为.dll。不必指定所在模块路径,若需指定,则需用反斜杠\。模块名必须与当前映射到调用进程空间的模板名一致。不会获取使用标志LOAD_LIBRARY_AS_DATAFILE加载的模块句柄。
5.错误 MSB6006 “CL.exe”已退出,代码为2。解决方式:编写需要返回值的函数没有返回,增加“return”之后就可以正常编译。
6.共享数据段:
(1)#pragma data_seg()一般用于DLL中。也就是说,在DLL中定义一个共享的,有名字的数据段。
最关键的是:这个数据段中的全局变量可以被多个进程共享。否则多个进程之间无法共享DLL中的全局变量。
(2)共享数据必须初始化,否则微软编译器会把没有初始化的数据放到普通的未初始化数据段中而不是放在shared中,从而导致多个进程之间的共享行为失败。
7.DWORD:全称Double Word,是指注册表的键值,每个word为2个字节的长度,DWORD 双字即为4个字节,每个字节是8位,共32位。
8.LPVOID:L = Long,P = Pointer,VOID = *void,32位的无类型的指针,在使用的时候再强制转换成需要的类型。
9.LPTHREAD_START_ROUTINE:函数指针,指向一个函数,该函数通知宿主某个线程已开始执行。
10.VS生成DLL没有产生lib的解决方法:使用vs生成DLL时,没有产生lib,一般发生在我们自己创建的DLL项目中,产生这个问题的主要原因是没有导出类。
导出DLL标记有两种方法,只要采用其中一种就可以解决。
(1)添加def文件
在工程上右键 -> 添加 -> 新建项 -> 选"模块定义文件(.def)" -> 随便输入个名字 -> 添加
(2)导出类
11.C4273: dll 链接不一致问题:参考https://jingyan.baidu.com/album/cd4c29795ee2d8756e6e601f.html?picindex=8
12.c++中\是一种转义字符,他表示一个\,就像\n表示回车一样。
所以C++中的路径名:D:\matcom45\doc\users_themes\m.dat

应为:
CString filename=_T(“D:\matcom45\doc\users\_themes\m.dat”);或
CStringfilename=_T(“D:/matcom45/doc/users/_themes/m.dat”);
"./"加不加都一样,就是指当前目录
"…/"表示当前目录的上级目录,即当前的父目录。
13.PROCESSENTRY32:用来存放快照进程信息的一个结构体。(存放进程信息和调用成员输出进程信息)。
Process32First指向第一个进程信息,并将进程信息抽取到PROCESSENTRY32中。用 Process32Next指向下一条进程信息。
14.LoadLibraryA使用LPCSTR 作为参数类型,它即为窄字符串(A代表ANSI)
LoadLibraryW使用LPCWSTR 作为参数类型,它即为宽字符串(W代表WIDEN)
15.dll项目找不到“xxx.lib”错误(LINK1104):检查下dll项目代码实现文件(.cpp文件)是否#include对应导出函数的头文件
16.RtlZeroMemory():把一块内存空间填O,因为结构中有的一些地方不填O且又不初始化,里面的数据可能是拉级数据。
17.C、C++变量为什么要初始化:一个变量光定义的话,只会为它分配一个内存空间,但是具体的数值是不确定的,如果你不初始化(也就是赋初值),你拿什么去参与的运算操作,不得而知,运算的结果肯定要有问题。
18.do…while(FALSE)的好处:解决循环里的多级嵌套问题

你可能感兴趣的:(Windows)